Merge "Revert "Use headers library for libvibrator""
diff --git a/OWNERS b/OWNERS
index 9989bf0..7f523a2 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,5 +1,7 @@
+chz@google.com
 elaurent@google.com
 etalvala@google.com
+hkuang@google.com
 lajos@google.com
 marcone@google.com
 
diff --git a/apex/Android.bp b/apex/Android.bp
index 6ba9cb9..bf91bf7 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -32,15 +32,21 @@
                 "liboggextractor",
                 "libwavextractor",
             ],
+            // Transcoding service only run with primary ABI.
+            binaries: [
+                "mediatranscoding",
+            ],
         },
     },
     // JNI
     native_shared_libs: ["libmediaparser-jni"],
     compile_multilib: "both",
     prebuilts: [
-        "mediaextractor.policy",
         "code_coverage.policy",
+        "com.android.media-mediatranscoding.rc",
         "crash_dump.policy",
+        "mediaextractor.policy",
+        "media-linker-config",
     ],
     key: "com.android.media.key",
     certificate: ":com.android.media.certificate",
@@ -62,9 +68,6 @@
     name: "com.android.media",
     manifest: "manifest.json",
     defaults: ["com.android.media-defaults"],
-    prebuilts: [
-        "media-linker-config",
-    ],
 }
 
 linker_config {
@@ -89,6 +92,9 @@
     binaries: [
         "mediaswcodec",
     ],
+    native_shared_libs: [
+        "libstagefright_foundation",
+    ],
     prebuilts: [
         "com.android.media.swcodec-mediaswcodec.rc",
         "com.android.media.swcodec-ld.config.txt",
@@ -97,7 +103,6 @@
         "crash_dump.policy",
         "mediaswcodec.xml",
     ],
-    use_vendor: true,
     key: "com.android.media.swcodec.key",
     certificate: ":com.android.media.swcodec.certificate",
 
@@ -115,6 +120,13 @@
 }
 
 prebuilt_etc {
+    name: "com.android.media-mediatranscoding.rc",
+    src: "mediatranscoding.rc",
+    filename: "init.rc",
+    installable: false,
+}
+
+prebuilt_etc {
     name: "com.android.media.swcodec-mediaswcodec.rc",
     src: "mediaswcodec.rc",
     filename: "init.rc",
diff --git a/apex/manifest.json b/apex/manifest.json
index f1f69f4..b7d8fc8 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,4 +1,10 @@
 {
   "name": "com.android.media",
-  "version": 309999900
+  "version": 309999900,
+  "requireNativeLibs": [
+    "libandroid.so",
+    "libbinder_ndk.so",
+    "libmediandk.so",
+    ":sphal"
+  ]
 }
diff --git a/apex/mediatranscoding.rc b/apex/mediatranscoding.rc
new file mode 100644
index 0000000..fa4acf8
--- /dev/null
+++ b/apex/mediatranscoding.rc
@@ -0,0 +1,10 @@
+# media.transcoding service is defined on com.android.media apex which goes back
+# to API29, but we only want it started on API31+ devices. So we declare it as
+# "disabled" and start it explicitly on boot.
+service media.transcoding /apex/com.android.media/bin/mediatranscoding
+    class main
+    user media
+    group media
+    ioprio rt 4
+    task_profiles ProcessCapacityHigh HighPerformance
+    disabled
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 08c88ce..dd652c7 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -1367,31 +1367,11 @@
                 it->second.isSequenceCompleted = true;
             }
 
-            if (it->second.isSequenceCompleted && hasCallback) {
-                auto cbIt = mSequenceCallbackMap.find(sequenceId);
-                CallbackHolder cbh = cbIt->second;
-
-                // send seq complete callback
-                sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
-                msg->setPointer(kContextKey, cbh.mContext);
-                msg->setObject(kSessionSpKey, cbh.mSession);
-                msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
-                msg->setInt32(kSequenceIdKey, sequenceId);
-                msg->setInt64(kFrameNumberKey, lastFrameNumber);
-
-                // Clear the session sp before we send out the message
-                // This will guarantee the rare case where the message is processed
-                // before cbh goes out of scope and causing we call the session
-                // destructor while holding device lock
-                cbh.mSession.clear();
-                postSessionMsgAndCleanup(msg);
-            }
         }
 
         if (it->second.isSequenceCompleted && it->second.isInflightCompleted) {
-            if (mSequenceCallbackMap.find(sequenceId) != mSequenceCallbackMap.end()) {
-                mSequenceCallbackMap.erase(sequenceId);
-            }
+            sendCaptureSequenceCompletedLocked(sequenceId, lastFrameNumber);
+
             it = mSequenceLastFrameNumberMap.erase(it);
             ALOGV("%s: Remove holder for sequenceId %d", __FUNCTION__, sequenceId);
         } else {
@@ -1418,13 +1398,7 @@
                 lastCompletedRegularFrameNumber);
         if (lastFrameNumber <= lastCompletedRegularFrameNumber) {
             if (it->second.isSequenceCompleted) {
-                // Check if there is callback for this sequence
-                // This should not happen because we always register callback (with nullptr inside)
-                if (mSequenceCallbackMap.count(sequenceId) == 0) {
-                    ALOGW("No callback found for sequenceId %d", sequenceId);
-                } else {
-                    mSequenceCallbackMap.erase(sequenceId);
-                }
+                sendCaptureSequenceCompletedLocked(sequenceId, lastFrameNumber);
 
                 it = mSequenceLastFrameNumberMap.erase(it);
                 ALOGV("%s: Remove holder for sequenceId %d", __FUNCTION__, sequenceId);
@@ -1715,5 +1689,33 @@
     return ret;
 }
 
+void
+CameraDevice::sendCaptureSequenceCompletedLocked(int sequenceId, int64_t lastFrameNumber) {
+    auto cbIt = mSequenceCallbackMap.find(sequenceId);
+    if (cbIt != mSequenceCallbackMap.end()) {
+        CallbackHolder cbh = cbIt->second;
+        mSequenceCallbackMap.erase(cbIt);
+
+        // send seq complete callback
+        sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
+        msg->setPointer(kContextKey, cbh.mContext);
+        msg->setObject(kSessionSpKey, cbh.mSession);
+        msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
+        msg->setInt32(kSequenceIdKey, sequenceId);
+        msg->setInt64(kFrameNumberKey, lastFrameNumber);
+
+        // Clear the session sp before we send out the message
+        // This will guarantee the rare case where the message is processed
+        // before cbh goes out of scope and causing we call the session
+        // destructor while holding device lock
+        cbh.mSession.clear();
+        postSessionMsgAndCleanup(msg);
+    } else {
+        // Check if there is callback for this sequence
+        // This should not happen because we always register callback (with nullptr inside)
+        ALOGW("No callback found for sequenceId %d", sequenceId);
+    }
+}
+
 } // namespace acam
 } // namespace android
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 125e6e3..344d964 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -354,6 +354,7 @@
     void checkRepeatingSequenceCompleteLocked(const int sequenceId, const int64_t lastFrameNumber);
     void checkAndFireSequenceCompleteLocked();
     void removeCompletedCallbackHolderLocked(int64_t lastCompletedRegularFrameNumber);
+    void sendCaptureSequenceCompletedLocked(int sequenceId, int64_t lastFrameNumber);
 
     // Misc variables
     int32_t mShadingMapSize[2];   // const after constructor
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 2d54bd1..c7c3dd5 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -816,7 +816,7 @@
      * </ul></p>
      *
      * <p>This control is only effective if ACAMERA_CONTROL_MODE is AUTO.</p>
-     * <p>When set to the ON mode, the camera device's auto-white balance
+     * <p>When set to the AUTO mode, the camera device's auto-white balance
      * routine is enabled, overriding the application's selected
      * ACAMERA_COLOR_CORRECTION_TRANSFORM, ACAMERA_COLOR_CORRECTION_GAINS and
      * ACAMERA_COLOR_CORRECTION_MODE. Note that when ACAMERA_CONTROL_AE_MODE
@@ -1957,7 +1957,10 @@
      * explicitly set ACAMERA_CONTROL_ZOOM_RATIO, its value defaults to 1.0.</p>
      * <p>One limitation of controlling zoom using zoomRatio is that the ACAMERA_SCALER_CROP_REGION
      * must only be used for letterboxing or pillarboxing of the sensor active array, and no
-     * FREEFORM cropping can be used with ACAMERA_CONTROL_ZOOM_RATIO other than 1.0.</p>
+     * FREEFORM cropping can be used with ACAMERA_CONTROL_ZOOM_RATIO other than 1.0. If
+     * ACAMERA_CONTROL_ZOOM_RATIO is not 1.0, and ACAMERA_SCALER_CROP_REGION is set to be
+     * windowboxing, the camera framework will override the ACAMERA_SCALER_CROP_REGION to be
+     * the active array.</p>
      *
      * @see ACAMERA_CONTROL_AE_REGIONS
      * @see ACAMERA_CONTROL_ZOOM_RATIO
@@ -3651,7 +3654,9 @@
      * </ol>
      * </li>
      * <li>Setting ACAMERA_CONTROL_ZOOM_RATIO to values different than 1.0 and
-     * ACAMERA_SCALER_CROP_REGION to be windowboxing at the same time is undefined behavior.</li>
+     * ACAMERA_SCALER_CROP_REGION to be windowboxing at the same time are not supported. In this
+     * case, the camera framework will override the ACAMERA_SCALER_CROP_REGION to be the active
+     * array.</li>
      * </ul>
      * <p>LEGACY capability devices will only support CENTER_ONLY cropping.</p>
      *
@@ -8517,10 +8522,10 @@
      * respective color channel provided in
      * ACAMERA_SENSOR_TEST_PATTERN_DATA.</p>
      * <p>For example:</p>
-     * <pre><code>android.testPatternData = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0]
+     * <pre><code>android.control.testPatternData = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0]
      * </code></pre>
      * <p>All green pixels are 100% green. All red/blue pixels are black.</p>
-     * <pre><code>android.testPatternData = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0]
+     * <pre><code>android.control.testPatternData = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0]
      * </code></pre>
      * <p>All red pixels are 100% red. Only the odd green pixels
      * are 100% green. All blue pixels are 100% black.</p>
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index f4b8164..e000633 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -272,7 +272,7 @@
 status_t SimplePlayer::onPrepare() {
     CHECK_EQ(mState, UNPREPARED);
 
-    mExtractor = new NuMediaExtractor;
+    mExtractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
 
     status_t err = mExtractor->setDataSource(
             NULL /* httpService */, mPath.c_str());
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index c26e0b9..33c4663 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -79,7 +79,7 @@
 
     static int64_t kTimeout = 500ll;
 
-    sp<NuMediaExtractor> extractor = new NuMediaExtractor;
+    sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
     if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
         fprintf(stderr, "unable to instantiate extractor.\n");
         return 1;
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
index b894545..ca058ab 100644
--- a/cmds/stagefright/mediafilter.cpp
+++ b/cmds/stagefright/mediafilter.cpp
@@ -319,7 +319,8 @@
 
     static int64_t kTimeout = 500ll;
 
-    sp<NuMediaExtractor> extractor = new NuMediaExtractor;
+    sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
+
     if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
         fprintf(stderr, "unable to instantiate extractor.\n");
         return 1;
diff --git a/cmds/stagefright/muxer.cpp b/cmds/stagefright/muxer.cpp
index 4a83a4a..bc7e41e 100644
--- a/cmds/stagefright/muxer.cpp
+++ b/cmds/stagefright/muxer.cpp
@@ -62,7 +62,7 @@
         int trimEndTimeMs,
         int rotationDegrees,
         MediaMuxer::OutputFormat container = MediaMuxer::OUTPUT_FORMAT_MPEG_4) {
-    sp<NuMediaExtractor> extractor = new NuMediaExtractor;
+    sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
     if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
         fprintf(stderr, "unable to instantiate extractor. %s\n", path);
         return 1;
diff --git a/drm/TEST_MAPPING b/drm/TEST_MAPPING
index 9f6a532..aa8a7d8 100644
--- a/drm/TEST_MAPPING
+++ b/drm/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "presubmit": [
+  "presubmit-large": [
     // The following tests validate codec and drm path.
     {
       "name": "GtsMediaTestCases",
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 1700a95..55a32ae 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -11,7 +11,7 @@
 
 }
 
-cc_library_shared {
+cc_library {
     name: "libmediadrm",
 
     srcs: [
diff --git a/drm/libmediadrm/fuzzer/Android.bp b/drm/libmediadrm/fuzzer/Android.bp
new file mode 100644
index 0000000..6f2d054
--- /dev/null
+++ b/drm/libmediadrm/fuzzer/Android.bp
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_fuzz {
+    name: "mediadrm_fuzzer",
+    srcs: [
+        "mediadrm_fuzzer.cpp",
+    ],
+    static_libs: [
+        "libmediadrm",
+        "liblog",
+        "resourcemanager_aidl_interface-ndk_platform",
+    ],
+    header_libs: [
+        "libmedia_headers",
+        "libmediadrm_headers",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+        "libbinder_ndk",
+        "libcutils",
+        "libdl",
+        "libmedia",
+        "libmediadrmmetrics_lite",
+        "libmediametrics#1",
+        "libmediautils",
+        "libstagefright_foundation",
+        "android.hardware.drm@1.0",
+        "android.hardware.drm@1.1",
+        "android.hardware.drm@1.2",
+        "android.hardware.drm@1.3",
+        "libhidlallocatorutils",
+        "libhidlbase",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 155276,
+    },
+}
diff --git a/drm/libmediadrm/fuzzer/README.md b/drm/libmediadrm/fuzzer/README.md
new file mode 100644
index 0000000..3c95cd7
--- /dev/null
+++ b/drm/libmediadrm/fuzzer/README.md
@@ -0,0 +1,56 @@
+# Fuzzer for libmediadrm
+
+## Plugin Design Considerations
+The fuzzer plugin for libmediadrm is designed based on the understanding of the
+library and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+libmediadrm supports the following parameters:
+1. Security Level (parameter name: `securityLevel`)
+2. Mime Type (parameter name: `mimeType`)
+3. Key Type (parameter name: `keyType`)
+4. Crypto Mode (parameter name: `cryptoMode`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `securityLevel` | 0.`DrmPlugin::kSecurityLevelUnknown` 1.`DrmPlugin::kSecurityLevelMax` 2.`DrmPlugin::kSecurityLevelSwSecureCrypto` 3.`DrmPlugin::kSecurityLevelSwSecureDecode`  4.`DrmPlugin::kSecurityLevelHwSecureCrypto` 5.`DrmPlugin::kSecurityLevelHwSecureDecode` 6.`DrmPlugin::kSecurityLevelHwSecureAll`| Value obtained from FuzzedDataProvider in the range 0 to 6|
+| `mimeType` | 0.`video/mp4` 1.`video/mpeg` 2.`video/x-flv` 3.`video/mj2` 4.`video/3gp2` 5.`video/3gpp` 6.`video/3gpp2` 7.`audio/mp4` 8.`audio/mpeg` 9.`audio/aac` 10.`audio/3gp2` 11.`audio/3gpp` 12.`audio/3gpp2` 13.`video/unknown`| Value obtained from FuzzedDataProvider in the range 0 to 13|
+| `keyType` | 0.`DrmPlugin::kKeyType_Offline` 1.`DrmPlugin::kKeyType_Streaming` 2.`DrmPlugin::kKeyType_Release` | Value obtained from FuzzedDataProvider in the range 0 to 2|
+| `cryptoMode` | 0.`CryptoPlugin::kMode_Unencrypted` 1.`CryptoPlugin::kMode_AES_CTR` 2.`CryptoPlugin::kMode_AES_WV` 3.`CryptoPlugin::kMode_AES_CBC` | Value obtained from FuzzedDataProvider in the range 0 to 3|
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the drm module.
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build mediadrm_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) mediadrm_fuzzer
+```
+#### Steps to run
+Create a directory CORPUS_DIR
+```
+  $ adb shell mkdir CORPUS_DIR
+```
+To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/${TARGET_ARCH}/mediadrm_fuzzer/mediadrm_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp b/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
new file mode 100644
index 0000000..8df0477
--- /dev/null
+++ b/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
@@ -0,0 +1,458 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include <binder/MemoryDealer.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <mediadrm/CryptoHal.h>
+#include <mediadrm/DrmHal.h>
+#include <utils/String8.h>
+#include "fuzzer/FuzzedDataProvider.h"
+
+#define AES_BLOCK_SIZE 16
+#define UNUSED_PARAM __attribute__((unused))
+
+using namespace std;
+using namespace android;
+using android::hardware::fromHeap;
+using ::android::os::PersistableBundle;
+using drm::V1_0::BufferType;
+
+enum {
+    INVALID_UUID = 0,
+    PSSH_BOX_UUID,
+    CLEARKEY_UUID,
+};
+
+static const uint8_t kInvalidUUID[16] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
+                                         0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};
+
+static const uint8_t kCommonPsshBoxUUID[16] = {0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02,
+                                               0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B};
+
+static const uint8_t kClearKeyUUID[16] = {0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
+                                          0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
+
+static const uint32_t kUUID[] = {INVALID_UUID, PSSH_BOX_UUID, CLEARKEY_UUID};
+
+const DrmPlugin::SecurityLevel kSecurityLevel[] = {
+    DrmPlugin::kSecurityLevelUnknown,        DrmPlugin::kSecurityLevelMax,
+    DrmPlugin::kSecurityLevelSwSecureCrypto, DrmPlugin::kSecurityLevelSwSecureDecode,
+    DrmPlugin::kSecurityLevelHwSecureCrypto, DrmPlugin::kSecurityLevelHwSecureDecode,
+    DrmPlugin::kSecurityLevelHwSecureAll};
+
+const char *kMimeType[] = {"video/mp4",   "video/mpeg",    "video/x-flv",  "video/mj2",
+                           "video/3gp2",  "video/3gpp",    "video/3gpp2",  "audio/mp4",
+                           "audio/mpeg",  "audio/aac",     "audio/3gp2",   "audio/3gpp",
+                           "audio/3gpp2", "video/unknown", "audio/unknown"};
+
+const DrmPlugin::KeyType kKeyType[] = {DrmPlugin::kKeyType_Offline, DrmPlugin::kKeyType_Streaming,
+                                       DrmPlugin::kKeyType_Release};
+
+const CryptoPlugin::Mode kCryptoMode[] = {CryptoPlugin::kMode_Unencrypted,
+                                          CryptoPlugin::kMode_AES_CTR, CryptoPlugin::kMode_AES_WV,
+                                          CryptoPlugin::kMode_AES_CBC};
+
+const char *kCipherAlgorithm[] = {"AES/CBC/NoPadding", ""};
+const char *kMacAlgorithm[] = {"HmacSHA256", ""};
+const char *kRSAAlgorithm[] = {"RSASSA-PSS-SHA1", ""};
+const size_t kNumSecurityLevel = size(kSecurityLevel);
+const size_t kNumMimeType = size(kMimeType);
+const size_t kNumKeyType = size(kKeyType);
+const size_t kNumCryptoMode = size(kCryptoMode);
+const size_t kNumUUID = size(kUUID);
+const size_t kMaxStringLength = 100;
+const size_t kMaxSubSamples = 10;
+const size_t kMaxNumBytes = 1000;
+
+struct DrmListener : virtual public IDrmClient {
+   public:
+    void sendEvent(DrmPlugin::EventType eventType UNUSED_PARAM,
+                   const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM,
+                   const hardware::hidl_vec<uint8_t> &data UNUSED_PARAM) override {}
+
+    void sendExpirationUpdate(const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM,
+                              int64_t expiryTimeInMS UNUSED_PARAM) override {}
+
+    void sendKeysChange(const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM,
+                        const std::vector<DrmKeyStatus> &keyStatusList UNUSED_PARAM,
+                        bool hasNewUsableKey UNUSED_PARAM) override {}
+
+    void sendSessionLostState(const hardware::hidl_vec<uint8_t> &) override {}
+    DrmListener() {}
+
+   private:
+    DISALLOW_EVIL_CONSTRUCTORS(DrmListener);
+};
+
+class DrmFuzzer {
+   public:
+    void process(const uint8_t *data, size_t size);
+
+   private:
+    void invokeDrm(const uint8_t *data, size_t size);
+    bool initDrm();
+    void invokeDrmCreatePlugin();
+    void invokeDrmOpenSession();
+    void invokeDrmSetListener();
+    void invokeDrmSetAlgorithmAPI();
+    void invokeDrmPropertyAPI();
+    void invokeDrmDecryptEncryptAPI(const uint8_t *data, size_t size);
+    void invokeDrmSecureStopAPI();
+    void invokeDrmOfflineLicenseAPI();
+    void invokeDrmCloseSession();
+    void invokeDrmDestroyPlugin();
+    void invokeCrypto(const uint8_t *data);
+    bool initCrypto();
+    void invokeCryptoCreatePlugin();
+    void invokeCryptoDecrypt(const uint8_t *data);
+    void invokeCryptoDestroyPlugin();
+    sp<DrmHal> mDrm = nullptr;
+    sp<CryptoHal> mCrypto = nullptr;
+    Vector<uint8_t> mSessionId = {};
+    FuzzedDataProvider *mFuzzedDataProvider = nullptr;
+};
+
+bool DrmFuzzer::initDrm() {
+    mDrm = new DrmHal();
+    if (!mDrm) {
+        return false;
+    }
+    return true;
+}
+
+void DrmFuzzer::invokeDrmCreatePlugin() {
+    mDrm->initCheck();
+    String8 packageName(mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str());
+    uint32_t uuidEnum = kUUID[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumUUID - 1)];
+    switch (uuidEnum) {
+        case INVALID_UUID:
+            mDrm->createPlugin(kInvalidUUID, packageName);
+            break;
+        case PSSH_BOX_UUID:
+            mDrm->createPlugin(kCommonPsshBoxUUID, packageName);
+            break;
+        case CLEARKEY_UUID:
+            mDrm->createPlugin(kClearKeyUUID, packageName);
+            break;
+        default:
+            break;
+    }
+}
+
+void DrmFuzzer::invokeDrmDestroyPlugin() { mDrm->destroyPlugin(); }
+
+void DrmFuzzer::invokeDrmOpenSession() {
+    DrmPlugin::SecurityLevel securityLevel;
+    bool shouldPassRandomSecurityLevel = mFuzzedDataProvider->ConsumeBool();
+    if (shouldPassRandomSecurityLevel) {
+        securityLevel =
+            static_cast<DrmPlugin::SecurityLevel>(mFuzzedDataProvider->ConsumeIntegral<size_t>());
+    } else {
+        securityLevel = kSecurityLevel[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+            0, kNumSecurityLevel - 1)];
+    }
+    mDrm->openSession(securityLevel, mSessionId);
+}
+
+void DrmFuzzer::invokeDrmCloseSession() { mDrm->closeSession(mSessionId); }
+
+void DrmFuzzer::invokeDrmSetListener() {
+    sp<DrmListener> listener = new DrmListener();
+    mDrm->setListener(listener);
+}
+
+void DrmFuzzer::invokeDrmSetAlgorithmAPI() {
+    mDrm->setCipherAlgorithm(mSessionId,
+                             String8(kCipherAlgorithm[mFuzzedDataProvider->ConsumeBool()]));
+    mDrm->setMacAlgorithm(mSessionId, String8(kMacAlgorithm[mFuzzedDataProvider->ConsumeBool()]));
+}
+
+void DrmFuzzer::invokeDrmPropertyAPI() {
+    mDrm->setPropertyString(String8("property"), String8("value"));
+    String8 stringValue;
+    mDrm->getPropertyString(String8("property"), stringValue);
+    Vector<uint8_t> value = {};
+    mDrm->setPropertyByteArray(String8("property"), value);
+    Vector<uint8_t> byteValue;
+    mDrm->getPropertyByteArray(String8("property"), byteValue);
+}
+
+void DrmFuzzer::invokeDrmDecryptEncryptAPI(const uint8_t *data, size_t size) {
+    uint32_t openSessions = 0;
+    uint32_t maxSessions = 0;
+    mDrm->getNumberOfSessions(&openSessions, &maxSessions);
+
+    DrmPlugin::HdcpLevel connected;
+    DrmPlugin::HdcpLevel max;
+    mDrm->getHdcpLevels(&connected, &max);
+
+    DrmPlugin::SecurityLevel securityLevel;
+    mDrm->getSecurityLevel(mSessionId, &securityLevel);
+
+    // isCryptoSchemeSupported() shall fill isSupported
+    bool isSupported;
+    String8 mimeType(
+        kMimeType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumMimeType - 1)]);
+    mDrm->isCryptoSchemeSupported(kClearKeyUUID, mimeType, securityLevel, &isSupported);
+
+    // getProvisionRequest() shall fill legacyRequest and legacyDefaultUrl
+    String8 certificateType(
+        mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str());
+    String8 certAuthority(mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str());
+    Vector<uint8_t> legacyRequest = {};
+    String8 legacyDefaultUrl;
+    mDrm->getProvisionRequest(certificateType, certAuthority, legacyRequest, legacyDefaultUrl);
+
+    // provideProvisionResponse() shall fill certificate and wrappedKey
+    Vector<uint8_t> provisionResponse = {};
+    Vector<uint8_t> certificate = {};
+    Vector<uint8_t> wrappedKey = {};
+    mDrm->provideProvisionResponse(provisionResponse, certificate, wrappedKey);
+
+    // getKeyRequest() shall fill keyRequest, defaultUrl and keyRequestType
+    Vector<uint8_t> initData = {};
+    initData.appendArray(data, size);
+    DrmPlugin::KeyType keyType;
+    bool shouldPassRandomKeyType = mFuzzedDataProvider->ConsumeBool();
+    if (shouldPassRandomKeyType) {
+        keyType = static_cast<DrmPlugin::KeyType>(mFuzzedDataProvider->ConsumeIntegral<size_t>());
+    } else {
+        keyType = kKeyType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumKeyType - 1)];
+    }
+    KeyedVector<String8, String8> mdOptionalParameters = {};
+    Vector<uint8_t> keyRequest = {};
+    String8 defaultUrl;
+    DrmPlugin::KeyRequestType keyRequestType;
+    mDrm->getKeyRequest(mSessionId, initData, mimeType, keyType, mdOptionalParameters, keyRequest,
+                        defaultUrl, &keyRequestType);
+
+    // provideKeyResponse() shall fill keySetId
+    Vector<uint8_t> keyResponse = {};
+    keyResponse.appendArray(data, size);
+    Vector<uint8_t> keySetId = {};
+    mDrm->provideKeyResponse(mSessionId, keyResponse, keySetId);
+
+    // restoreKeys
+    mDrm->restoreKeys(mSessionId, keySetId);
+
+    // queryKeyStatus() shall fill infoMap
+    KeyedVector<String8, String8> infoMap = {};
+    mDrm->queryKeyStatus(mSessionId, infoMap);
+
+    // decrypt() shall fill outputVec
+    Vector<uint8_t> keyIdVec = {};
+    keyIdVec.appendArray(data, size);
+
+    Vector<uint8_t> inputVec = {};
+    inputVec.appendArray(data, size);
+
+    Vector<uint8_t> ivVec = {};
+    ivVec.appendArray(data, size);
+
+    Vector<uint8_t> outputVec = {};
+    mDrm->decrypt(mSessionId, keyIdVec, inputVec, ivVec, outputVec);
+
+    // encrypt() shall fill outputVec
+    mDrm->encrypt(mSessionId, keyIdVec, inputVec, ivVec, outputVec);
+
+    // sign() shall fill signature
+    Vector<uint8_t> message = {};
+    message.appendArray(data, size);
+    Vector<uint8_t> signature = {};
+    mDrm->sign(mSessionId, keyIdVec, message, signature);
+
+    // verify() shall fill match
+    bool match;
+    mDrm->verify(mSessionId, keyIdVec, message, signature, match);
+
+    // signRSA() shall fill signature
+    mDrm->signRSA(mSessionId, String8(kRSAAlgorithm[mFuzzedDataProvider->ConsumeBool()]), message,
+                  wrappedKey, signature);
+
+    mDrm->removeKeys(mSessionId);
+}
+
+void DrmFuzzer::invokeDrmSecureStopAPI() {
+    // getSecureStops() shall fill secureStops
+    List<Vector<uint8_t>> secureStops = {};
+    mDrm->getSecureStops(secureStops);
+
+    // getSecureStopIds() shall fill secureStopIds
+    List<Vector<uint8_t>> secureStopIds = {};
+    mDrm->getSecureStopIds(secureStopIds);
+
+    // getSecureStop() shall fill secureStop
+    Vector<uint8_t> ssid = {};
+    Vector<uint8_t> secureStop = {};
+    mDrm->getSecureStop(ssid, secureStop);
+
+    mDrm->removeSecureStop(ssid);
+
+    mDrm->releaseSecureStops(ssid);
+
+    mDrm->removeAllSecureStops();
+}
+
+void DrmFuzzer::invokeDrmOfflineLicenseAPI() {
+    // getOfflineLicenseKeySetIds() shall keySetIds
+    List<Vector<uint8_t>> keySetIds = {};
+    mDrm->getOfflineLicenseKeySetIds(keySetIds);
+
+    // getOfflineLicenseState() shall fill state
+    Vector<uint8_t> const keySetIdOfflineLicense = {};
+    DrmPlugin::OfflineLicenseState state;
+    mDrm->getOfflineLicenseState(keySetIdOfflineLicense, &state);
+
+    mDrm->removeOfflineLicense(keySetIdOfflineLicense);
+}
+
+bool DrmFuzzer::initCrypto() {
+    mCrypto = new CryptoHal();
+    if (!mCrypto) {
+        return false;
+    }
+    return true;
+}
+
+void DrmFuzzer::invokeCryptoCreatePlugin() {
+    mCrypto->initCheck();
+
+    mCrypto->isCryptoSchemeSupported(kClearKeyUUID);
+    mCrypto->createPlugin(kClearKeyUUID, NULL, 0);
+}
+
+void DrmFuzzer::invokeCryptoDestroyPlugin() { mCrypto->destroyPlugin(); }
+
+void DrmFuzzer::invokeCryptoDecrypt(const uint8_t *data) {
+    mCrypto->requiresSecureDecoderComponent(
+        kMimeType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumMimeType - 1)]);
+
+    uint32_t width = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+    uint32_t height = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+    mCrypto->notifyResolution(width, height);
+
+    mCrypto->setMediaDrmSession(mSessionId);
+
+    const CryptoPlugin::Pattern pattern = {0, 0};
+
+    size_t totalSize = 0;
+    size_t numSubSamples = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(1, kMaxSubSamples);
+
+    CryptoPlugin::SubSample subSamples[numSubSamples];
+
+    for (size_t i = 0; i < numSubSamples; ++i) {
+        uint32_t clearBytes =
+            mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxNumBytes);
+        uint32_t encryptedBytes =
+            mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxNumBytes);
+        subSamples[i].mNumBytesOfClearData = clearBytes;
+        subSamples[i].mNumBytesOfEncryptedData = encryptedBytes;
+        totalSize += subSamples[i].mNumBytesOfClearData;
+        totalSize += subSamples[i].mNumBytesOfEncryptedData;
+    }
+
+    size_t heapSize = totalSize * 2;
+    sp<MemoryDealer> dealer = new MemoryDealer(heapSize, "DrmFuzzerMemory");
+    if (!dealer) {
+        return;
+    }
+
+    sp<HidlMemory> heap = fromHeap(dealer->getMemoryHeap());
+    if (!heap) {
+        return;
+    }
+    int heapSeqNum = mCrypto->setHeap(heap);
+    if (heapSeqNum < 0) {
+        return;
+    }
+
+    const size_t segmentIndex = 0;
+    const uint8_t keyId[AES_BLOCK_SIZE] = {};
+    memcpy((void *)keyId, data, AES_BLOCK_SIZE);
+
+    const uint8_t iv[AES_BLOCK_SIZE] = {};
+    memset((void *)iv, 0, AES_BLOCK_SIZE);
+
+    const SharedBuffer sourceBuffer = {.bufferId = segmentIndex, .offset = 0, .size = totalSize};
+
+    const DestinationBuffer destBuffer = {
+        .type = BufferType::SHARED_MEMORY,
+        {.bufferId = segmentIndex, .offset = totalSize, .size = totalSize},
+        .secureMemory = nullptr};
+
+    const uint64_t offset = 0;
+    AString *errorDetailMsg = nullptr;
+    CryptoPlugin::Mode mode;
+    bool shouldPassRandomCryptoMode = mFuzzedDataProvider->ConsumeBool();
+    if (shouldPassRandomCryptoMode) {
+        mode = static_cast<CryptoPlugin::Mode>(mFuzzedDataProvider->ConsumeIntegral<size_t>());
+    } else {
+        mode =
+            kCryptoMode[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumCryptoMode - 1)];
+    }
+    mCrypto->decrypt(keyId, iv, mode, pattern, sourceBuffer, offset, subSamples, numSubSamples,
+                     destBuffer, errorDetailMsg);
+
+    if (heapSeqNum >= 0) {
+        mCrypto->unsetHeap(heapSeqNum);
+    }
+    heap.clear();
+}
+
+void DrmFuzzer::invokeDrm(const uint8_t *data, size_t size) {
+    if (!initDrm()) {
+        return;
+    }
+    invokeDrmCreatePlugin();
+    invokeDrmOpenSession();
+    invokeDrmSetAlgorithmAPI();
+    invokeDrmSetListener();
+    invokeDrmPropertyAPI();
+    invokeDrmDecryptEncryptAPI(data, size);
+    invokeDrmSecureStopAPI();
+    invokeDrmOfflineLicenseAPI();
+    invokeDrmCloseSession();
+    invokeDrmDestroyPlugin();
+}
+
+void DrmFuzzer::invokeCrypto(const uint8_t *data) {
+    if (!initCrypto()) {
+        return;
+    }
+    invokeCryptoCreatePlugin();
+    invokeCryptoDecrypt(data);
+    invokeCryptoDestroyPlugin();
+}
+
+void DrmFuzzer::process(const uint8_t *data, size_t size) {
+    mFuzzedDataProvider = new FuzzedDataProvider(data, size);
+    invokeDrm(data, size);
+    invokeCrypto(data);
+    delete mFuzzedDataProvider;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    if (size < AES_BLOCK_SIZE) {
+        return 0;
+    }
+    DrmFuzzer drmFuzzer;
+    drmFuzzer.process(data, size);
+    return 0;
+}
diff --git a/include/media/MicrophoneInfo.h b/include/media/MicrophoneInfo.h
index e89401a..a5045b9 100644
--- a/include/media/MicrophoneInfo.h
+++ b/include/media/MicrophoneInfo.h
@@ -208,6 +208,21 @@
     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
 
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
index 50facfb..80e0924 100644
--- a/media/TEST_MAPPING
+++ b/media/TEST_MAPPING
@@ -1,6 +1,6 @@
 // for frameworks/av/media
 {
-    "presubmit": [
+    "presubmit-large": [
         // runs whenever we change something in this tree
         {
             "name": "CtsMediaTestCases",
@@ -17,7 +17,9 @@
                     "include-filter": "android.media.cts.DecodeEditEncodeTest"
                 }
             ]
-        },
+        }
+    ],
+    "presubmit": [
         {
             "name": "GtsMediaTestCases",
             "options" : [
diff --git a/media/bufferpool/2.0/AccessorImpl.cpp b/media/bufferpool/2.0/AccessorImpl.cpp
index 6111fea..1d2562e 100644
--- a/media/bufferpool/2.0/AccessorImpl.cpp
+++ b/media/bufferpool/2.0/AccessorImpl.cpp
@@ -39,6 +39,8 @@
 
     static constexpr size_t kMinAllocBytesForEviction = 1024*1024*15;
     static constexpr size_t kMinBufferCountForEviction = 25;
+    static constexpr size_t kMaxUnusedBufferCount = 64;
+    static constexpr size_t kUnusedBufferCountTarget = kMaxUnusedBufferCount - 16;
 
     static constexpr nsecs_t kEvictGranularityNs = 1000000000; // 1 sec
     static constexpr nsecs_t kEvictDurationNs = 5000000000; // 5 secs
@@ -724,9 +726,11 @@
 }
 
 void Accessor::Impl::BufferPool::cleanUp(bool clearCache) {
-    if (clearCache || mTimestampUs > mLastCleanUpUs + kCleanUpDurationUs) {
+    if (clearCache || mTimestampUs > mLastCleanUpUs + kCleanUpDurationUs ||
+            mStats.buffersNotInUse() > kMaxUnusedBufferCount) {
         mLastCleanUpUs = mTimestampUs;
-        if (mTimestampUs > mLastLogUs + kLogDurationUs) {
+        if (mTimestampUs > mLastLogUs + kLogDurationUs ||
+                mStats.buffersNotInUse() > kMaxUnusedBufferCount) {
             mLastLogUs = mTimestampUs;
             ALOGD("bufferpool2 %p : %zu(%zu size) total buffers - "
                   "%zu(%zu size) used buffers - %zu/%zu (recycle/alloc) - "
@@ -737,8 +741,9 @@
                   mStats.mTotalFetches, mStats.mTotalTransfers);
         }
         for (auto freeIt = mFreeBuffers.begin(); freeIt != mFreeBuffers.end();) {
-            if (!clearCache && (mStats.mSizeCached < kMinAllocBytesForEviction
-                    || mBuffers.size() < kMinBufferCountForEviction)) {
+            if (!clearCache && mStats.buffersNotInUse() <= kUnusedBufferCountTarget &&
+                    (mStats.mSizeCached < kMinAllocBytesForEviction ||
+                     mBuffers.size() < kMinBufferCountForEviction)) {
                 break;
             }
             auto it = mBuffers.find(*freeIt);
diff --git a/media/bufferpool/2.0/AccessorImpl.h b/media/bufferpool/2.0/AccessorImpl.h
index cd1b4d0..3d39941 100644
--- a/media/bufferpool/2.0/AccessorImpl.h
+++ b/media/bufferpool/2.0/AccessorImpl.h
@@ -193,6 +193,12 @@
                 : mSizeCached(0), mBuffersCached(0), mSizeInUse(0), mBuffersInUse(0),
                   mTotalAllocations(0), mTotalRecycles(0), mTotalTransfers(0), mTotalFetches(0) {}
 
+            /// # of currently unused buffers
+            size_t buffersNotInUse() const {
+                ALOG_ASSERT(mBuffersCached >= mBuffersInUse);
+                return mBuffersCached - mBuffersInUse;
+            }
+
             /// A new buffer is allocated on an allocation request.
             void onBufferAllocated(size_t allocSize) {
                 mSizeCached += allocSize;
diff --git a/media/bufferpool/2.0/BufferPoolClient.cpp b/media/bufferpool/2.0/BufferPoolClient.cpp
index 342fef6..9308b81 100644
--- a/media/bufferpool/2.0/BufferPoolClient.cpp
+++ b/media/bufferpool/2.0/BufferPoolClient.cpp
@@ -32,6 +32,8 @@
 static constexpr int64_t kReceiveTimeoutUs = 1000000; // 100ms
 static constexpr int kPostMaxRetry = 3;
 static constexpr int kCacheTtlUs = 1000000; // TODO: tune
+static constexpr size_t kMaxCachedBufferCount = 64;
+static constexpr size_t kCachedBufferCountTarget = kMaxCachedBufferCount - 16;
 
 class BufferPoolClient::Impl
         : public std::enable_shared_from_this<BufferPoolClient::Impl> {
@@ -136,6 +138,10 @@
             --mActive;
             mLastChangeUs = getTimestampNow();
         }
+
+        int cachedBufferCount() const {
+            return mBuffers.size() - mActive;
+        }
     } mCache;
 
     // FMQ - release notifier
@@ -668,10 +674,12 @@
 // should have mCache.mLock
 void BufferPoolClient::Impl::evictCaches(bool clearCache) {
     int64_t now = getTimestampNow();
-    if (now >= mLastEvictCacheUs + kCacheTtlUs || clearCache) {
+    if (now >= mLastEvictCacheUs + kCacheTtlUs ||
+            clearCache || mCache.cachedBufferCount() > kMaxCachedBufferCount) {
         size_t evicted = 0;
         for (auto it = mCache.mBuffers.begin(); it != mCache.mBuffers.end();) {
-            if (!it->second->hasCache() && (it->second->expire() || clearCache)) {
+            if (!it->second->hasCache() && (it->second->expire() ||
+                        clearCache || mCache.cachedBufferCount() > kCachedBufferCountTarget)) {
                 it = mCache.mBuffers.erase(it);
                 ++evicted;
             } else {
diff --git a/media/bufferpool/2.0/tests/Android.bp b/media/bufferpool/2.0/tests/Android.bp
index 8492939..56bda89 100644
--- a/media/bufferpool/2.0/tests/Android.bp
+++ b/media/bufferpool/2.0/tests/Android.bp
@@ -25,7 +25,7 @@
     static_libs: [
         "android.hardware.media.bufferpool@2.0",
         "libcutils",
-        "libstagefright_bufferpool@2.0",
+        "libstagefright_bufferpool@2.0.1",
     ],
     shared_libs: [
         "libfmq",
@@ -44,10 +44,30 @@
     static_libs: [
         "android.hardware.media.bufferpool@2.0",
         "libcutils",
-        "libstagefright_bufferpool@2.0",
+        "libstagefright_bufferpool@2.0.1",
     ],
     shared_libs: [
         "libfmq",
     ],
     compile_multilib: "both",
 }
+
+cc_test {
+    name: "VtsVndkHidlBufferpoolV2_0TargetCondTest",
+    test_suites: ["device-tests"],
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "allocator.cpp",
+        "cond.cpp",
+    ],
+    static_libs: [
+        "android.hardware.media.bufferpool@2.0",
+        "libcutils",
+        "libstagefright_bufferpool@2.0.1",
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "libfmq",
+    ],
+    compile_multilib: "both",
+}
diff --git a/media/bufferpool/2.0/tests/allocator.cpp b/media/bufferpool/2.0/tests/allocator.cpp
index 843f7ea..25b08ef 100644
--- a/media/bufferpool/2.0/tests/allocator.cpp
+++ b/media/bufferpool/2.0/tests/allocator.cpp
@@ -120,6 +120,24 @@
 
 }
 
+void IpcMutex::init() {
+  pthread_mutexattr_t mattr;
+  pthread_mutexattr_init(&mattr);
+  pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
+  pthread_mutex_init(&lock, &mattr);
+  pthread_mutexattr_destroy(&mattr);
+
+  pthread_condattr_t cattr;
+  pthread_condattr_init(&cattr);
+  pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
+  pthread_cond_init(&cond, &cattr);
+  pthread_condattr_destroy(&cattr);
+}
+
+IpcMutex *IpcMutex::Import(void *pMutex) {
+  return reinterpret_cast<IpcMutex *>(pMutex);
+}
+
 
 ResultStatus TestBufferPoolAllocator::allocate(
     const std::vector<uint8_t> &params,
@@ -201,9 +219,33 @@
   return false;
 }
 
+bool TestBufferPoolAllocator::MapMemoryForMutex(const native_handle_t *handle, void **mem) {
+  if (!HandleAshmem::isValid(handle)) {
+    return false;
+  }
+  const HandleAshmem *o = static_cast<const HandleAshmem*>(handle);
+  *mem = mmap(
+      NULL, o->size(), PROT_READ|PROT_WRITE, MAP_SHARED, o->ashmemFd(), 0);
+  if (*mem == MAP_FAILED || *mem == nullptr) {
+    return false;
+  }
+  return true;
+}
+
+bool TestBufferPoolAllocator::UnmapMemoryForMutex(void *mem) {
+  munmap(mem, sizeof(IpcMutex));
+  return true;
+}
+
 void getTestAllocatorParams(std::vector<uint8_t> *params) {
   constexpr static int kAllocationSize = 1024 * 10;
   Params ashmemParams(kAllocationSize);
 
   params->assign(ashmemParams.array, ashmemParams.array + sizeof(ashmemParams));
 }
+
+void getIpcMutexParams(std::vector<uint8_t> *params) {
+  Params ashmemParams(sizeof(IpcMutex));
+
+  params->assign(ashmemParams.array, ashmemParams.array + sizeof(ashmemParams));
+}
diff --git a/media/bufferpool/2.0/tests/allocator.h b/media/bufferpool/2.0/tests/allocator.h
index 5281dc3..862d1a5 100644
--- a/media/bufferpool/2.0/tests/allocator.h
+++ b/media/bufferpool/2.0/tests/allocator.h
@@ -17,6 +17,7 @@
 #ifndef VNDK_HIDL_BUFFERPOOL_V2_0_ALLOCATOR_H
 #define VNDK_HIDL_BUFFERPOOL_V2_0_ALLOCATOR_H
 
+#include <pthread.h>
 #include <bufferpool/BufferPoolTypes.h>
 
 using android::hardware::media::bufferpool::V2_0::ResultStatus;
@@ -25,6 +26,17 @@
 using android::hardware::media::bufferpool::V2_0::implementation::
     BufferPoolAllocator;
 
+struct IpcMutex {
+  pthread_mutex_t lock;
+  pthread_cond_t cond;
+  int counter = 0;
+  bool signalled = false;
+
+  void init();
+
+  static IpcMutex *Import(void *mem);
+};
+
 // buffer allocator for the tests
 class TestBufferPoolAllocator : public BufferPoolAllocator {
  public:
@@ -43,9 +55,14 @@
 
   static bool Verify(const native_handle_t *handle, const unsigned char val);
 
+  static bool MapMemoryForMutex(const native_handle_t *handle, void **mem);
+
+  static bool UnmapMemoryForMutex(void *mem);
 };
 
 // retrieve buffer allocator paramters
 void getTestAllocatorParams(std::vector<uint8_t> *params);
 
+void getIpcMutexParams(std::vector<uint8_t> *params);
+
 #endif  // VNDK_HIDL_BUFFERPOOL_V2_0_ALLOCATOR_H
diff --git a/media/bufferpool/2.0/tests/cond.cpp b/media/bufferpool/2.0/tests/cond.cpp
new file mode 100644
index 0000000..21beea8
--- /dev/null
+++ b/media/bufferpool/2.0/tests/cond.cpp
@@ -0,0 +1,269 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "buffferpool_unit_test"
+
+#include <gtest/gtest.h>
+
+#include <android-base/logging.h>
+#include <binder/ProcessState.h>
+#include <bufferpool/ClientManager.h>
+#include <errno.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+#include <hidl/Status.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <iostream>
+#include <memory>
+#include <vector>
+#include "allocator.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::hidl_handle;
+using android::hardware::media::bufferpool::V2_0::IClientManager;
+using android::hardware::media::bufferpool::V2_0::ResultStatus;
+using android::hardware::media::bufferpool::V2_0::implementation::BufferId;
+using android::hardware::media::bufferpool::V2_0::implementation::ClientManager;
+using android::hardware::media::bufferpool::V2_0::implementation::ConnectionId;
+using android::hardware::media::bufferpool::V2_0::implementation::TransactionId;
+using android::hardware::media::bufferpool::BufferPoolData;
+
+namespace {
+
+// communication message types between processes.
+enum PipeCommand : int32_t {
+    INIT_OK = 0,
+    INIT_ERROR,
+    SEND,
+    RECEIVE_OK,
+    RECEIVE_ERROR,
+};
+
+// communication message between processes.
+union PipeMessage {
+    struct  {
+        int32_t command;
+        BufferId bufferId;
+        ConnectionId connectionId;
+        TransactionId transactionId;
+        int64_t  timestampUs;
+    } data;
+    char array[0];
+};
+
+constexpr int kSignalInt = 200;
+
+// media.bufferpool test setup
+class BufferpoolMultiTest : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+    ResultStatus status;
+    mReceiverPid = -1;
+    mConnectionValid = false;
+
+    ASSERT_TRUE(pipe(mCommandPipeFds) == 0);
+    ASSERT_TRUE(pipe(mResultPipeFds) == 0);
+
+    mReceiverPid = fork();
+    ASSERT_TRUE(mReceiverPid >= 0);
+
+    if (mReceiverPid == 0) {
+      doReceiver();
+      // In order to ignore gtest behaviour, wait for being killed from
+      // tearDown
+      pause();
+    }
+
+    mManager = ClientManager::getInstance();
+    ASSERT_NE(mManager, nullptr);
+
+    mAllocator = std::make_shared<TestBufferPoolAllocator>();
+    ASSERT_TRUE((bool)mAllocator);
+
+    status = mManager->create(mAllocator, &mConnectionId);
+    ASSERT_TRUE(status == ResultStatus::OK);
+    mConnectionValid = true;
+  }
+
+  virtual void TearDown() override {
+    if (mReceiverPid > 0) {
+      kill(mReceiverPid, SIGKILL);
+      int wstatus;
+      wait(&wstatus);
+    }
+
+    if (mConnectionValid) {
+      mManager->close(mConnectionId);
+    }
+  }
+
+ protected:
+  static void description(const std::string& description) {
+    RecordProperty("description", description);
+  }
+
+  android::sp<ClientManager> mManager;
+  std::shared_ptr<BufferPoolAllocator> mAllocator;
+  bool mConnectionValid;
+  ConnectionId mConnectionId;
+  pid_t mReceiverPid;
+  int mCommandPipeFds[2];
+  int mResultPipeFds[2];
+
+  bool sendMessage(int *pipes, const PipeMessage &message) {
+    int ret = write(pipes[1], message.array, sizeof(PipeMessage));
+    return ret == sizeof(PipeMessage);
+  }
+
+  bool receiveMessage(int *pipes, PipeMessage *message) {
+    int ret = read(pipes[0], message->array, sizeof(PipeMessage));
+    return ret == sizeof(PipeMessage);
+  }
+
+  void doReceiver() {
+    configureRpcThreadpool(1, false);
+    PipeMessage message;
+    mManager = ClientManager::getInstance();
+    if (!mManager) {
+      message.data.command = PipeCommand::INIT_ERROR;
+      sendMessage(mResultPipeFds, message);
+      return;
+    }
+    android::status_t status = mManager->registerAsService();
+    if (status != android::OK) {
+      message.data.command = PipeCommand::INIT_ERROR;
+      sendMessage(mResultPipeFds, message);
+      return;
+    }
+    message.data.command = PipeCommand::INIT_OK;
+    sendMessage(mResultPipeFds, message);
+
+    int val = 0;
+    receiveMessage(mCommandPipeFds, &message);
+    {
+      native_handle_t *rhandle = nullptr;
+      std::shared_ptr<BufferPoolData> rbuffer;
+      void *mem = nullptr;
+      IpcMutex *mutex = nullptr;
+      ResultStatus status = mManager->receive(
+          message.data.connectionId, message.data.transactionId,
+          message.data.bufferId, message.data.timestampUs, &rhandle, &rbuffer);
+      mManager->close(message.data.connectionId);
+      if (status != ResultStatus::OK) {
+          message.data.command = PipeCommand::RECEIVE_ERROR;
+          sendMessage(mResultPipeFds, message);
+          return;
+      }
+      if (!TestBufferPoolAllocator::MapMemoryForMutex(rhandle, &mem)) {
+          message.data.command = PipeCommand::RECEIVE_ERROR;
+          sendMessage(mResultPipeFds, message);
+          return;
+      }
+      mutex = IpcMutex::Import(mem);
+      pthread_mutex_lock(&(mutex->lock));
+      while (mutex->signalled != true) {
+          pthread_cond_wait(&(mutex->cond), &(mutex->lock));
+      }
+      val = mutex->counter;
+      pthread_mutex_unlock(&(mutex->lock));
+
+      (void)TestBufferPoolAllocator::UnmapMemoryForMutex(mem);
+      if (rhandle) {
+        native_handle_close(rhandle);
+        native_handle_delete(rhandle);
+      }
+    }
+    if (val == kSignalInt) {
+      message.data.command = PipeCommand::RECEIVE_OK;
+    } else {
+      message.data.command = PipeCommand::RECEIVE_ERROR;
+    }
+    sendMessage(mResultPipeFds, message);
+  }
+};
+
+// Buffer transfer test between processes.
+TEST_F(BufferpoolMultiTest, TransferBuffer) {
+  ResultStatus status;
+  PipeMessage message;
+
+  ASSERT_TRUE(receiveMessage(mResultPipeFds, &message));
+
+  android::sp<IClientManager> receiver = IClientManager::getService();
+  ConnectionId receiverId;
+  ASSERT_TRUE((bool)receiver);
+
+  status = mManager->registerSender(receiver, mConnectionId, &receiverId);
+  ASSERT_TRUE(status == ResultStatus::OK);
+  {
+    native_handle_t *shandle = nullptr;
+    std::shared_ptr<BufferPoolData> sbuffer;
+    TransactionId transactionId;
+    int64_t postUs;
+    std::vector<uint8_t> vecParams;
+    void *mem = nullptr;
+    IpcMutex *mutex = nullptr;
+
+    getIpcMutexParams(&vecParams);
+    status = mManager->allocate(mConnectionId, vecParams, &shandle, &sbuffer);
+    ASSERT_TRUE(status == ResultStatus::OK);
+
+    ASSERT_TRUE(TestBufferPoolAllocator::MapMemoryForMutex(shandle, &mem));
+
+    mutex = new(mem) IpcMutex();
+    mutex->init();
+
+    status = mManager->postSend(receiverId, sbuffer, &transactionId, &postUs);
+    ASSERT_TRUE(status == ResultStatus::OK);
+
+    message.data.command = PipeCommand::SEND;
+    message.data.bufferId = sbuffer->mId;
+    message.data.connectionId = receiverId;
+    message.data.transactionId = transactionId;
+    message.data.timestampUs = postUs;
+    sendMessage(mCommandPipeFds, message);
+    for (int i=0; i < 200000000; ++i) {
+      // no-op in order to ensure
+      // pthread_cond_wait is called before pthread_cond_signal
+    }
+    pthread_mutex_lock(&(mutex->lock));
+    mutex->counter = kSignalInt;
+    mutex->signalled = true;
+    pthread_cond_signal(&(mutex->cond));
+    pthread_mutex_unlock(&(mutex->lock));
+    (void)TestBufferPoolAllocator::UnmapMemoryForMutex(mem);
+    if (shandle) {
+      native_handle_close(shandle);
+      native_handle_delete(shandle);
+    }
+  }
+  EXPECT_TRUE(receiveMessage(mResultPipeFds, &message));
+  EXPECT_TRUE(message.data.command == PipeCommand::RECEIVE_OK);
+}
+
+}  // anonymous namespace
+
+int main(int argc, char** argv) {
+  android::hardware::details::setTrebleTestingOverride(true);
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  LOG(INFO) << "Test result = " << status;
+  return status;
+}
diff --git a/media/bufferpool/2.0/tests/multi.cpp b/media/bufferpool/2.0/tests/multi.cpp
index b40838e..43b0a8c 100644
--- a/media/bufferpool/2.0/tests/multi.cpp
+++ b/media/bufferpool/2.0/tests/multi.cpp
@@ -161,11 +161,18 @@
           message.data.bufferId, message.data.timestampUs, &rhandle, &rbuffer);
       mManager->close(message.data.connectionId);
       if (status != ResultStatus::OK) {
-        if (!TestBufferPoolAllocator::Verify(rhandle, 0x77)) {
-          message.data.command = PipeCommand::RECEIVE_ERROR;
-          sendMessage(mResultPipeFds, message);
-          return;
-        }
+        message.data.command = PipeCommand::RECEIVE_ERROR;
+        sendMessage(mResultPipeFds, message);
+        return;
+      }
+      if (!TestBufferPoolAllocator::Verify(rhandle, 0x77)) {
+        message.data.command = PipeCommand::RECEIVE_ERROR;
+        sendMessage(mResultPipeFds, message);
+        return;
+      }
+      if (rhandle) {
+        native_handle_close(rhandle);
+        native_handle_delete(rhandle);
       }
     }
     message.data.command = PipeCommand::RECEIVE_OK;
@@ -198,6 +205,10 @@
     ASSERT_TRUE(status == ResultStatus::OK);
 
     ASSERT_TRUE(TestBufferPoolAllocator::Fill(shandle, 0x77));
+    if (shandle) {
+        native_handle_close(shandle);
+        native_handle_delete(shandle);
+    }
 
     status = mManager->postSend(receiverId, sbuffer, &transactionId, &postUs);
     ASSERT_TRUE(status == ResultStatus::OK);
@@ -210,6 +221,7 @@
     sendMessage(mCommandPipeFds, message);
   }
   EXPECT_TRUE(receiveMessage(mResultPipeFds, &message));
+  EXPECT_TRUE(message.data.command == PipeCommand::RECEIVE_OK);
 }
 
 }  // anonymous namespace
diff --git a/media/bufferpool/2.0/tests/single.cpp b/media/bufferpool/2.0/tests/single.cpp
index 777edcf..1e9027b 100644
--- a/media/bufferpool/2.0/tests/single.cpp
+++ b/media/bufferpool/2.0/tests/single.cpp
@@ -102,6 +102,10 @@
   for (int i = 0; i < kNumAllocationTest; ++i) {
     status = mManager->allocate(mConnectionId, vecParams, &allocHandle, &buffer[i]);
     ASSERT_TRUE(status == ResultStatus::OK);
+    if (allocHandle) {
+      native_handle_close(allocHandle);
+      native_handle_delete(allocHandle);
+    }
   }
   for (int i = 0; i < kNumAllocationTest; ++i) {
     for (int j = i + 1; j < kNumAllocationTest; ++j) {
@@ -125,6 +129,10 @@
     status = mManager->allocate(mConnectionId, vecParams, &allocHandle, &buffer);
     ASSERT_TRUE(status == ResultStatus::OK);
     bid[i] = buffer->mId;
+    if (allocHandle) {
+      native_handle_close(allocHandle);
+      native_handle_delete(allocHandle);
+    }
   }
   for (int i = 1; i < kNumRecycleTest; ++i) {
     ASSERT_TRUE(bid[i - 1] == bid[i]);
@@ -154,6 +162,15 @@
                              &recvHandle, &rbuffer);
   EXPECT_TRUE(status == ResultStatus::OK);
   ASSERT_TRUE(TestBufferPoolAllocator::Verify(recvHandle, 0x77));
+
+  if (allocHandle) {
+    native_handle_close(allocHandle);
+    native_handle_delete(allocHandle);
+  }
+  if (recvHandle) {
+    native_handle_close(recvHandle);
+    native_handle_delete(recvHandle);
+  }
 }
 
 }  // anonymous namespace
diff --git a/media/codec2/TEST_MAPPING b/media/codec2/TEST_MAPPING
index fca3477..6ac4210 100644
--- a/media/codec2/TEST_MAPPING
+++ b/media/codec2/TEST_MAPPING
@@ -4,7 +4,9 @@
     // { "name": "codec2_core_param_test"},
     // TODO(b/155516524)
     // { "name": "codec2_vndk_interface_test"},
-    { "name": "codec2_vndk_test"},
+    { "name": "codec2_vndk_test"}
+  ],
+  "presubmit-large": [
     {
       "name": "CtsMediaTestCases",
       "options": [
diff --git a/media/codec2/components/aac/Android.bp b/media/codec2/components/aac/Android.bp
index 9eca585..50495a9 100644
--- a/media/codec2/components/aac/Android.bp
+++ b/media/codec2/components/aac/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_aacdec",
     defaults: [
         "libcodec2_soft-defaults",
@@ -15,7 +15,7 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_aacenc",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/aac/C2SoftAacDec.cpp b/media/codec2/components/aac/C2SoftAacDec.cpp
index 677f316..f3341ab 100644
--- a/media/codec2/components/aac/C2SoftAacDec.cpp
+++ b/media/codec2/components/aac/C2SoftAacDec.cpp
@@ -1061,11 +1061,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftAacDecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/aac/C2SoftAacEnc.cpp b/media/codec2/components/aac/C2SoftAacEnc.cpp
index 2e85915..ea76cbb 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.cpp
+++ b/media/codec2/components/aac/C2SoftAacEnc.cpp
@@ -692,11 +692,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftAacEncFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/amr_nb_wb/Android.bp b/media/codec2/components/amr_nb_wb/Android.bp
index ce25bc9..b09a505 100644
--- a/media/codec2/components/amr_nb_wb/Android.bp
+++ b/media/codec2/components/amr_nb_wb/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_amrnbdec",
     defaults: [
         "libcodec2_soft-defaults",
@@ -21,7 +21,7 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_amrwbdec",
     defaults: [
         "libcodec2_soft-defaults",
@@ -40,7 +40,7 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_amrnbenc",
     defaults: [
         "libcodec2_soft-defaults",
@@ -58,7 +58,7 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_amrwbenc",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
index f7943be..c08e02b 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
@@ -420,11 +420,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftAMRDecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp
index e2d8cb6..bb63e1f 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrNbEnc.cpp
@@ -337,11 +337,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftAmrNbEncFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp
index 84ae4b7..84728ae 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrWbEnc.cpp
@@ -411,11 +411,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftAmrWbEncFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/aom/Android.bp b/media/codec2/components/aom/Android.bp
index 61dbd4c..fcc4552 100644
--- a/media/codec2/components/aom/Android.bp
+++ b/media/codec2/components/aom/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_av1dec_aom",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/aom/C2SoftAomDec.cpp b/media/codec2/components/aom/C2SoftAomDec.cpp
index 9ba3b697..c08cd59 100644
--- a/media/codec2/components/aom/C2SoftAomDec.cpp
+++ b/media/codec2/components/aom/C2SoftAomDec.cpp
@@ -800,11 +800,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftAomFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/avc/Android.bp b/media/codec2/components/avc/Android.bp
index 4021444..9f8bc68 100644
--- a/media/codec2/components/avc/Android.bp
+++ b/media/codec2/components/avc/Android.bp
@@ -1,9 +1,10 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_avcdec",
     defaults: [
         "libcodec2_soft-defaults",
         "libcodec2_soft_sanitize_signed-defaults",
-   ],
+        "libcodec2_soft_sanitize_cfi-defaults",
+    ],
 
     static_libs: ["libavcdec"],
 
@@ -15,12 +16,13 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_avcenc",
     defaults: [
         "libcodec2_soft-defaults",
         "libcodec2_soft_sanitize_signed-defaults",
-   ],
+        "libcodec2_soft_sanitize_cfi-defaults",
+    ],
 
     static_libs: ["libavcenc"],
 
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index 3afd670..0207311 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -1049,11 +1049,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftAvcDecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index ab93ce3..cfaeb66 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -1756,11 +1756,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftAvcEncFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/base/Android.bp b/media/codec2/components/base/Android.bp
index f10835f..0c8f4a4 100644
--- a/media/codec2/components/base/Android.bp
+++ b/media/codec2/components/base/Android.bp
@@ -1,6 +1,6 @@
 // DO NOT DEPEND ON THIS DIRECTLY
 // use libcodec2_soft-defaults instead
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_common",
     defaults: ["libcodec2-impl-defaults"],
     vendor_available: true,
@@ -20,7 +20,7 @@
 
     shared_libs: [
         "libcutils", // for properties
-        "liblog",    // for ALOG
+        "liblog", // for ALOG
         "libsfplugin_ccodec_utils", // for ImageCopy
         "libstagefright_foundation", // for Mutexed
     ],
@@ -38,7 +38,7 @@
 
 filegroup {
     name: "codec2_soft_exports",
-    srcs: [ "exports.lds" ],
+    srcs: ["exports.lds"],
 }
 
 // public dependency for software codec implementation
@@ -91,12 +91,25 @@
         misc_undefined: [
             "signed-integer-overflow",
         ],
+    },
+}
+
+cc_defaults {
+    name: "libcodec2_soft_sanitize_cfi-defaults",
+
+    sanitize: {
         cfi: true,
+        config: {
+            cfi_assembly_support: true,
+        },
+        diag: {
+            cfi: true,
+        },
     },
 }
 
 // TEMP: used by cheets2 project - remove when no longer used
-cc_library_shared {
+cc_library {
     name: "libcodec2_simple_component",
     vendor_available: true,
 
@@ -131,4 +144,3 @@
 
     ldflags: ["-Wl,-Bsymbolic"],
 }
-
diff --git a/media/codec2/components/flac/Android.bp b/media/codec2/components/flac/Android.bp
index 48cc51b..603c412 100644
--- a/media/codec2/components/flac/Android.bp
+++ b/media/codec2/components/flac/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_flacdec",
     defaults: [
         "libcodec2_soft-defaults",
@@ -14,7 +14,7 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_flacenc",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/flac/C2SoftFlacDec.cpp b/media/codec2/components/flac/C2SoftFlacDec.cpp
index 4039b9b..e70c289 100644
--- a/media/codec2/components/flac/C2SoftFlacDec.cpp
+++ b/media/codec2/components/flac/C2SoftFlacDec.cpp
@@ -367,11 +367,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftFlacDecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.cpp b/media/codec2/components/flac/C2SoftFlacEnc.cpp
index 72910c5..6fead3a 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.cpp
+++ b/media/codec2/components/flac/C2SoftFlacEnc.cpp
@@ -482,11 +482,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftFlacEncFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/g711/Android.bp b/media/codec2/components/g711/Android.bp
index 0101b1a..c39df7b 100644
--- a/media/codec2/components/g711/Android.bp
+++ b/media/codec2/components/g711/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_g711alawdec",
     defaults: [
         "libcodec2_soft-defaults",
@@ -14,7 +14,7 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_g711mlawdec",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/g711/C2SoftG711Dec.cpp b/media/codec2/components/g711/C2SoftG711Dec.cpp
index 7f9c34e..f9299af 100644
--- a/media/codec2/components/g711/C2SoftG711Dec.cpp
+++ b/media/codec2/components/g711/C2SoftG711Dec.cpp
@@ -259,11 +259,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftG711DecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/gav1/Android.bp b/media/codec2/components/gav1/Android.bp
index f374089..32aa98d 100644
--- a/media/codec2/components/gav1/Android.bp
+++ b/media/codec2/components/gav1/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_av1dec_gav1",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index a1929e7..76345ae 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -770,11 +770,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory *CreateCodec2Factory() {
   ALOGV("in %s", __func__);
   return new ::android::C2SoftGav1Factory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory *factory) {
   ALOGV("in %s", __func__);
   delete factory;
diff --git a/media/codec2/components/gsm/Android.bp b/media/codec2/components/gsm/Android.bp
index 9330c01..7f54af8 100644
--- a/media/codec2/components/gsm/Android.bp
+++ b/media/codec2/components/gsm/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_gsmdec",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/gsm/C2SoftGsmDec.cpp b/media/codec2/components/gsm/C2SoftGsmDec.cpp
index 287cfc6..977677d 100644
--- a/media/codec2/components/gsm/C2SoftGsmDec.cpp
+++ b/media/codec2/components/gsm/C2SoftGsmDec.cpp
@@ -294,11 +294,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftGSMDecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/hevc/Android.bp b/media/codec2/components/hevc/Android.bp
index 369bd78..2858212 100644
--- a/media/codec2/components/hevc/Android.bp
+++ b/media/codec2/components/hevc/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_hevcdec",
     defaults: [
         "libcodec2_soft-defaults",
@@ -11,7 +11,7 @@
 
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_hevcenc",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index 23104dc..56dd26b 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -1048,11 +1048,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftHevcDecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index c2d2540..436a2c4 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -1078,11 +1078,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftHevcEncFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/mp3/Android.bp b/media/codec2/components/mp3/Android.bp
index 66665ed..b4fb1b0 100644
--- a/media/codec2/components/mp3/Android.bp
+++ b/media/codec2/components/mp3/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_mp3dec",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/mp3/C2SoftMp3Dec.cpp b/media/codec2/components/mp3/C2SoftMp3Dec.cpp
index 5ba7e3d..7137767 100644
--- a/media/codec2/components/mp3/C2SoftMp3Dec.cpp
+++ b/media/codec2/components/mp3/C2SoftMp3Dec.cpp
@@ -539,11 +539,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftMp3DecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/mpeg2/Android.bp b/media/codec2/components/mpeg2/Android.bp
index 841f0a9..666e697 100644
--- a/media/codec2/components/mpeg2/Android.bp
+++ b/media/codec2/components/mpeg2/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_mpeg2dec",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index 55dd475..82c061a 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -1113,11 +1113,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftMpeg2DecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/mpeg4_h263/Android.bp b/media/codec2/components/mpeg4_h263/Android.bp
index 41e4f44..0673709 100644
--- a/media/codec2/components/mpeg4_h263/Android.bp
+++ b/media/codec2/components/mpeg4_h263/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_mpeg4dec",
     defaults: [
         "libcodec2_soft-defaults",
@@ -15,7 +15,7 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_h263dec",
     defaults: [
         "libcodec2_soft-defaults",
@@ -31,7 +31,7 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_mpeg4enc",
     defaults: [
         "libcodec2_soft-defaults",
@@ -49,7 +49,7 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_h263enc",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
index 13cc0ec..a7cc037 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
@@ -747,11 +747,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftMpeg4DecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
index 54c8c47..e1cc6b3 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
@@ -652,11 +652,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftMpeg4EncFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/opus/Android.bp b/media/codec2/components/opus/Android.bp
index 0ed141b..32e2bf8 100644
--- a/media/codec2/components/opus/Android.bp
+++ b/media/codec2/components/opus/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_opusdec",
     defaults: [
         "libcodec2_soft-defaults",
@@ -9,7 +9,7 @@
 
     shared_libs: ["libopus"],
 }
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_opusenc",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/opus/C2SoftOpusDec.cpp b/media/codec2/components/opus/C2SoftOpusDec.cpp
index b7c1556..d4987c0 100644
--- a/media/codec2/components/opus/C2SoftOpusDec.cpp
+++ b/media/codec2/components/opus/C2SoftOpusDec.cpp
@@ -473,11 +473,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftOpusDecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/opus/C2SoftOpusEnc.cpp b/media/codec2/components/opus/C2SoftOpusEnc.cpp
index 70d1965..b47275f 100644
--- a/media/codec2/components/opus/C2SoftOpusEnc.cpp
+++ b/media/codec2/components/opus/C2SoftOpusEnc.cpp
@@ -626,11 +626,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftOpusEncFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/raw/Android.bp b/media/codec2/components/raw/Android.bp
index dc944da..d4fb8f8 100644
--- a/media/codec2/components/raw/Android.bp
+++ b/media/codec2/components/raw/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_rawdec",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/raw/C2SoftRawDec.cpp b/media/codec2/components/raw/C2SoftRawDec.cpp
index 7b6f21a..31ca705 100644
--- a/media/codec2/components/raw/C2SoftRawDec.cpp
+++ b/media/codec2/components/raw/C2SoftRawDec.cpp
@@ -215,11 +215,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftRawDecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/vorbis/Android.bp b/media/codec2/components/vorbis/Android.bp
index bc1c380..ff1183f 100644
--- a/media/codec2/components/vorbis/Android.bp
+++ b/media/codec2/components/vorbis/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_vorbisdec",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/vorbis/C2SoftVorbisDec.cpp b/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
index d3b6e31..899fe9b 100644
--- a/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
+++ b/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
@@ -359,10 +359,6 @@
     }
     memcpy(&numPageFrames, data + inSize - sizeof(numPageFrames), sizeof(numPageFrames));
     inSize -= sizeof(numPageFrames);
-    if (inSize == 0) {
-        // empty buffer, ignore
-        return;
-    }
     if (numPageFrames >= 0) {
         mNumFramesLeftOnPage = numPageFrames;
     }
@@ -413,7 +409,7 @@
                 mState,  reinterpret_cast<int16_t *> (wView.data()),
                 kMaxNumSamplesPerChannel);
         if (numFrames < 0) {
-            ALOGD("vorbis_dsp_pcmout returned %d frames", numFrames);
+            ALOGD("vorbis_dsp_pcmout returned %d", numFrames);
             numFrames = 0;
         }
     }
@@ -481,11 +477,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftVorbisDecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/vpx/Android.bp b/media/codec2/components/vpx/Android.bp
index 34f5753..72178aa 100644
--- a/media/codec2/components/vpx/Android.bp
+++ b/media/codec2/components/vpx/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_vp9dec",
     defaults: [
         "libcodec2_soft-defaults",
@@ -14,7 +14,7 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_vp8dec",
     defaults: [
         "libcodec2_soft-defaults",
@@ -26,7 +26,7 @@
     shared_libs: ["libvpx"],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_vp9enc",
     defaults: [
         "libcodec2_soft-defaults",
@@ -43,7 +43,7 @@
     cflags: ["-DVP9"],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_vp8enc",
     defaults: [
         "libcodec2_soft-defaults",
diff --git a/media/codec2/components/vpx/C2SoftVp8Enc.cpp b/media/codec2/components/vpx/C2SoftVp8Enc.cpp
index f18f5d0..049ec38 100644
--- a/media/codec2/components/vpx/C2SoftVp8Enc.cpp
+++ b/media/codec2/components/vpx/C2SoftVp8Enc.cpp
@@ -101,11 +101,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftVp8EncFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/vpx/C2SoftVp9Enc.cpp b/media/codec2/components/vpx/C2SoftVp9Enc.cpp
index 740dbda..6401521 100644
--- a/media/codec2/components/vpx/C2SoftVp9Enc.cpp
+++ b/media/codec2/components/vpx/C2SoftVp9Enc.cpp
@@ -131,11 +131,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftVp9EncFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.cpp b/media/codec2/components/vpx/C2SoftVpxDec.cpp
index 91238e8..2953d90 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxDec.cpp
@@ -948,11 +948,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftVpxFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/components/xaac/Android.bp b/media/codec2/components/xaac/Android.bp
index 7795cc1..9b7e2de 100644
--- a/media/codec2/components/xaac/Android.bp
+++ b/media/codec2/components/xaac/Android.bp
@@ -1,8 +1,9 @@
-cc_library_shared {
+cc_library {
     name: "libcodec2_soft_xaacdec",
     defaults: [
         "libcodec2_soft-defaults",
         "libcodec2_soft_sanitize_all-defaults",
+	"libcodec2_soft_sanitize_cfi-defaults",
     ],
 
     srcs: ["C2SoftXaacDec.cpp"],
diff --git a/media/codec2/components/xaac/C2SoftXaacDec.cpp b/media/codec2/components/xaac/C2SoftXaacDec.cpp
index 951d058..6deafda 100644
--- a/media/codec2/components/xaac/C2SoftXaacDec.cpp
+++ b/media/codec2/components/xaac/C2SoftXaacDec.cpp
@@ -1600,11 +1600,13 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
     ALOGV("in %s", __func__);
     return new ::android::C2SoftXaacDecFactory();
 }
 
+__attribute__((cfi_canonical_jump_table))
 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
     ALOGV("in %s", __func__);
     delete factory;
diff --git a/media/codec2/core/Android.bp b/media/codec2/core/Android.bp
index 33fafa7..beeadb8 100644
--- a/media/codec2/core/Android.bp
+++ b/media/codec2/core/Android.bp
@@ -5,7 +5,7 @@
     export_include_dirs: ["include"],
 }
 
-cc_library_shared {
+cc_library {
     name: "libcodec2",
     vendor_available: true,
     min_sdk_version: "29",
diff --git a/media/codec2/fuzzer/Android.bp b/media/codec2/fuzzer/Android.bp
new file mode 100644
index 0000000..2de400d
--- /dev/null
+++ b/media/codec2/fuzzer/Android.bp
@@ -0,0 +1,333 @@
+/*
+ * 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.
+ *
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_defaults {
+    name: "C2Fuzzer-defaults",
+
+    srcs: [
+        "C2Fuzzer.cpp",
+    ],
+
+    static_libs: [
+        "liblog",
+        "libion",
+        "libfmq",
+        "libbase",
+        "libutils",
+        "libcutils",
+        "libcodec2",
+        "libhidlbase",
+        "libdmabufheap",
+        "libcodec2_vndk",
+        "libnativewindow",
+        "libcodec2_soft_common",
+        "libsfplugin_ccodec_utils",
+        "libstagefright_foundation",
+        "libstagefright_bufferpool@2.0.1",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.media.bufferpool@2.0",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.allocator@3.0",
+        "android.hardware.graphics.bufferqueue@2.0",
+    ],
+
+    shared_libs: [
+        "libui",
+        "libdl",
+        "libbinder",
+        "libhardware",
+        "libvndksupport",
+        "libprocessgroup",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerAvcDec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.avc.decoder\"",
+    ],
+
+    static_libs: [
+        "libavcdec",
+        "libcodec2_soft_avcdec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerHevcDec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.hevc.decoder\"",
+    ],
+
+    static_libs: [
+        "libhevcdec",
+        "libcodec2_soft_hevcdec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerMpeg2Dec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.mpeg2.decoder\"",
+    ],
+
+    static_libs: [
+        "libmpeg2dec",
+        "libcodec2_soft_mpeg2dec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerMpeg4Dec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.mpeg4.decoder\"",
+    ],
+
+    static_libs: [
+        "libstagefright_m4vh263dec",
+        "libcodec2_soft_mpeg4dec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerH263Dec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.h263.decoder\"",
+    ],
+
+    static_libs: [
+        "libstagefright_m4vh263dec",
+        "libcodec2_soft_h263dec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerVp8Dec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.vp8.decoder\"",
+    ],
+
+    static_libs: [
+        "libvpx",
+        "libcodec2_soft_vp8dec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerVp9Dec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.vp9.decoder\"",
+    ],
+
+    static_libs: [
+        "libvpx",
+        "libcodec2_soft_vp9dec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerAacDec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.aac.decoder\"",
+    ],
+
+    static_libs: [
+        "libFraunhoferAAC",
+        "libcodec2_soft_aacdec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerAmrnbDec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.amrnb.decoder\"",
+    ],
+
+    static_libs: [
+        "libstagefright_amrnbdec",
+        "libstagefright_amrwbdec",
+        "libstagefright_amrnb_common",
+        "libcodec2_soft_amrnbdec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerAmrwbDec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.amrwb.decoder\"",
+    ],
+
+    static_libs: [
+        "libstagefright_amrnbdec",
+        "libstagefright_amrwbdec",
+        "libstagefright_amrnb_common",
+        "libcodec2_soft_amrwbdec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerFlacDec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.flac.decoder\"",
+    ],
+
+    static_libs: [
+        "libFLAC",
+        "libstagefright_flacdec",
+        "libcodec2_soft_flacdec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerG711AlawDec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.g711.alaw.decoder\"",
+    ],
+
+    static_libs: [
+        "codecs_g711dec",
+        "libcodec2_soft_g711alawdec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerG711MlawDec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.g711.mlaw.decoder\"",
+    ],
+
+    static_libs: [
+        "codecs_g711dec",
+        "libcodec2_soft_g711mlawdec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerGsmDec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.gsm.decoder\"",
+    ],
+
+    static_libs: [
+        "libgsm",
+        "libcodec2_soft_gsmdec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerMp3Dec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.mp3.decoder\"",
+    ],
+
+    static_libs: [
+        "libstagefright_mp3dec",
+        "libcodec2_soft_mp3dec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerOpusDec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.opus.decoder\"",
+    ],
+
+    static_libs: [
+        "libopus",
+        "libcodec2_soft_opusdec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerRawDec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.raw.decoder\"",
+    ],
+
+    static_libs: [
+        "libcodec2_soft_rawdec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerVorbisDec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.vorbis.decoder\"",
+    ],
+
+    static_libs: [
+        "libvorbisidec",
+        "libcodec2_soft_vorbisdec",
+    ],
+}
+
+cc_fuzz {
+    name: "C2FuzzerXaacDec",
+    defaults: ["C2Fuzzer-defaults"],
+
+    cflags: [
+        "-DC2COMPONENTNAME=\"c2.android.xaac.decoder\"",
+    ],
+
+    static_libs: [
+        "libxaacdec",
+        "libcodec2_soft_xaacdec",
+    ],
+}
diff --git a/media/codec2/fuzzer/C2Fuzzer.cpp b/media/codec2/fuzzer/C2Fuzzer.cpp
new file mode 100644
index 0000000..71956a2
--- /dev/null
+++ b/media/codec2/fuzzer/C2Fuzzer.cpp
@@ -0,0 +1,318 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <stdio.h>
+
+#include <C2Fuzzer.h>
+
+using namespace android;
+
+class LinearBuffer : public C2Buffer {
+ public:
+  explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
+      : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
+
+  explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block, size_t size)
+      : C2Buffer({block->share(block->offset(), size, ::C2Fence())}) {}
+};
+
+/**
+ * Handle Callback functions onWorkDone_nb(), onTripped_nb(), onError_nb() for C2 Components
+ */
+struct CodecListener : public C2Component::Listener {
+ public:
+  CodecListener(const std::function<void(std::weak_ptr<C2Component> comp,
+                                         std::list<std::unique_ptr<C2Work>>& workItems)>
+                    fn = nullptr)
+      : callBack(fn) {}
+  virtual void onWorkDone_nb(const std::weak_ptr<C2Component> comp,
+                             std::list<std::unique_ptr<C2Work>> workItems) {
+    if (callBack) {
+      callBack(comp, workItems);
+    }
+  }
+
+  virtual void onTripped_nb(const std::weak_ptr<C2Component> comp,
+                            const std::vector<std::shared_ptr<C2SettingResult>> settingResults) {
+    (void)comp;
+    (void)settingResults;
+  }
+
+  virtual void onError_nb(const std::weak_ptr<C2Component> comp, uint32_t errorCode) {
+    (void)comp;
+    (void)errorCode;
+  }
+
+  std::function<void(std::weak_ptr<C2Component> comp,
+                     std::list<std::unique_ptr<C2Work>>& workItems)> callBack;
+};
+
+/**
+ * Buffer source implementations to identify a frame and its size
+ */
+bool Codec2Fuzzer::BufferSource::searchForMarker() {
+  while (true) {
+    if (isMarker()) {
+      return true;
+    }
+    --mReadIndex;
+    if (mReadIndex > mSize) {
+      break;
+    }
+  }
+  return false;
+}
+
+void Codec2Fuzzer::BufferSource::parse() {
+  bool isFrameAvailable = true;
+  size_t bytesRemaining = mSize;
+  while (isFrameAvailable) {
+    isFrameAvailable = searchForMarker();
+    if (isFrameAvailable) {
+      size_t location = mReadIndex + kMarkerSize;
+      bool isCSD = isCSDMarker(location);
+      location += kMarkerSuffixSize;
+      uint8_t* framePtr = const_cast<uint8_t*>(&mData[location]);
+      size_t frameSize = bytesRemaining - location;
+      uint32_t flags = 0;
+      if (mFrameList.empty()) {
+        flags |= C2FrameData::FLAG_END_OF_STREAM;
+      } else if (isCSD) {
+        flags |= C2FrameData::FLAG_CODEC_CONFIG;
+      }
+      mFrameList.emplace_back(std::make_tuple(framePtr, frameSize, flags));
+      bytesRemaining -= (frameSize + kMarkerSize + kMarkerSuffixSize);
+      --mReadIndex;
+    }
+  }
+  if (mFrameList.empty()) {
+    /**
+     * Scenario where input data does not contain the custom frame markers.
+     * Hence feed the entire data as single frame.
+     */
+    mFrameList.emplace_back(
+        std::make_tuple(const_cast<uint8_t*>(mData), 0, C2FrameData::FLAG_END_OF_STREAM));
+    mFrameList.emplace_back(
+        std::make_tuple(const_cast<uint8_t*>(mData), mSize, C2FrameData::FLAG_CODEC_CONFIG));
+  }
+}
+
+FrameData Codec2Fuzzer::BufferSource::getFrame() {
+  FrameData frame = mFrameList.back();
+  mFrameList.pop_back();
+  return frame;
+}
+
+void Codec2Fuzzer::handleWorkDone(std::weak_ptr<C2Component> comp,
+                                  std::list<std::unique_ptr<C2Work>>& workItems) {
+  (void)comp;
+  for (std::unique_ptr<C2Work>& work : workItems) {
+    if (!work->worklets.empty()) {
+      if (work->worklets.front()->output.flags != C2FrameData::FLAG_INCOMPLETE) {
+        mEos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
+        work->input.buffers.clear();
+        work->worklets.clear();
+        {
+          std::unique_lock<std::mutex> lock(mQueueLock);
+          mWorkQueue.push_back(std::move(work));
+          mQueueCondition.notify_all();
+        }
+        if (mEos) {
+          {
+            std::lock_guard<std::mutex> waitForDecodeComplete(mDecodeCompleteMutex);
+          }
+          mConditionalVariable.notify_one();
+        }
+      }
+    }
+  }
+}
+
+bool Codec2Fuzzer::initDecoder() {
+  std::vector<std::tuple<C2String, C2ComponentFactory::CreateCodec2FactoryFunc,
+        C2ComponentFactory::DestroyCodec2FactoryFunc>> codec2FactoryFunc;
+
+  codec2FactoryFunc.emplace_back(std::make_tuple(C2COMPONENTNAME,
+                                                &CreateCodec2Factory,
+                                                &DestroyCodec2Factory));
+
+  std::shared_ptr<C2ComponentStore> componentStore = GetTestComponentStore(codec2FactoryFunc);
+  if (!componentStore) {
+    return false;
+  }
+
+  std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
+  if (!allocatorStore) {
+    return false;
+  }
+
+  c2_status_t status =
+      allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator);
+  if (status != C2_OK) {
+    return false;
+  }
+
+  mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, ++mBlockPoolId);
+  if (!mLinearPool) {
+    return false;
+  }
+
+  for (int32_t i = 0; i < kNumberOfC2WorkItems; ++i) {
+    mWorkQueue.emplace_back(new C2Work);
+  }
+
+  status = componentStore->createComponent(C2COMPONENTNAME, &mComponent);
+  if (status != C2_OK) {
+    return false;
+  }
+
+  status = componentStore->createInterface(C2COMPONENTNAME, &mInterface);
+  if (status != C2_OK) {
+    return false;
+  }
+
+  C2ComponentKindSetting kind;
+  C2ComponentDomainSetting domain;
+  status = mInterface->query_vb({&kind, &domain}, {}, C2_MAY_BLOCK, nullptr);
+  if (status != C2_OK) {
+    return false;
+  }
+
+  std::vector<C2Param*> configParams;
+  if (domain.value == DOMAIN_VIDEO) {
+    C2StreamPictureSizeInfo::input inputSize(0u, kWidthOfVideo, kHeightOfVideo);
+    configParams.push_back(&inputSize);
+  } else if (domain.value == DOMAIN_AUDIO) {
+    C2StreamSampleRateInfo::output sampleRateInfo(0u, kSamplingRateOfAudio);
+    C2StreamChannelCountInfo::output channelCountInfo(0u, kChannelsOfAudio);
+    configParams.push_back(&sampleRateInfo);
+    configParams.push_back(&channelCountInfo);
+  }
+
+  mListener.reset(new CodecListener(
+      [this](std::weak_ptr<C2Component> comp, std::list<std::unique_ptr<C2Work>>& workItems) {
+        handleWorkDone(comp, workItems);
+      }));
+  if (!mListener) {
+    return false;
+  }
+
+  status = mComponent->setListener_vb(mListener, C2_DONT_BLOCK);
+  if (status != C2_OK) {
+    return false;
+  }
+
+  std::vector<std::unique_ptr<C2SettingResult>> failures;
+  componentStore->config_sm(configParams, &failures);
+  if (failures.size() != 0) {
+    return false;
+  }
+
+  status = mComponent->start();
+  if (status != C2_OK) {
+    return false;
+  }
+
+  return true;
+}
+
+void Codec2Fuzzer::deInitDecoder() {
+  mComponent->stop();
+  mComponent->reset();
+  mComponent->release();
+  mComponent = nullptr;
+}
+
+void Codec2Fuzzer::decodeFrames(const uint8_t* data, size_t size) {
+  mBufferSource = new BufferSource(data, size);
+  if (!mBufferSource) {
+    return;
+  }
+  mBufferSource->parse();
+  c2_status_t status = C2_OK;
+  size_t numFrames = 0;
+  while (!mBufferSource->isEos()) {
+    uint8_t* frame = nullptr;
+    size_t frameSize = 0;
+    FrameData frameData = mBufferSource->getFrame();
+    frame = std::get<0>(frameData);
+    frameSize = std::get<1>(frameData);
+
+    std::unique_ptr<C2Work> work;
+    {
+      std::unique_lock<std::mutex> lock(mQueueLock);
+      if (mWorkQueue.empty()) mQueueCondition.wait_for(lock, kC2FuzzerTimeOut);
+      if (!mWorkQueue.empty()) {
+        work.swap(mWorkQueue.front());
+        mWorkQueue.pop_front();
+      } else {
+        return;
+      }
+    }
+
+    work->input.flags = (C2FrameData::flags_t)std::get<2>(frameData);
+    work->input.ordinal.timestamp = 0;
+    work->input.ordinal.frameIndex = ++numFrames;
+    work->input.buffers.clear();
+    int32_t alignedSize = C2FUZZER_ALIGN(frameSize, PAGE_SIZE);
+
+    std::shared_ptr<C2LinearBlock> block;
+    status = mLinearPool->fetchLinearBlock(
+        alignedSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+    if (status != C2_OK || block == nullptr) {
+      return;
+    }
+
+    C2WriteView view = block->map().get();
+    if (view.error() != C2_OK) {
+      return;
+    }
+    memcpy(view.base(), frame, frameSize);
+    work->input.buffers.emplace_back(new LinearBuffer(block, frameSize));
+    work->worklets.clear();
+    work->worklets.emplace_back(new C2Worklet);
+
+    std::list<std::unique_ptr<C2Work>> items;
+    items.push_back(std::move(work));
+    status = mComponent->queue_nb(&items);
+    if (status != C2_OK) {
+      return;
+    }
+  }
+  std::unique_lock<std::mutex> waitForDecodeComplete(mDecodeCompleteMutex);
+  mConditionalVariable.wait_for(waitForDecodeComplete, kC2FuzzerTimeOut, [this] { return mEos; });
+  std::list<std::unique_ptr<C2Work>> c2flushedWorks;
+  mComponent->flush_sm(C2Component::FLUSH_COMPONENT, &c2flushedWorks);
+  delete mBufferSource;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  if (size < 1) {
+    return 0;
+  }
+  Codec2Fuzzer* codec = new Codec2Fuzzer();
+  if (!codec) {
+    return 0;
+  }
+  if (codec->initDecoder()) {
+    codec->decodeFrames(data, size);
+  }
+  delete codec;
+  return 0;
+}
diff --git a/media/codec2/fuzzer/C2Fuzzer.h b/media/codec2/fuzzer/C2Fuzzer.h
new file mode 100644
index 0000000..2efad50
--- /dev/null
+++ b/media/codec2/fuzzer/C2Fuzzer.h
@@ -0,0 +1,114 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#ifndef __C2FUZZER_H__
+#define __C2FUZZER_H__
+
+#include <C2AllocatorIon.h>
+#include <C2Buffer.h>
+#include <C2BufferPriv.h>
+#include <C2Component.h>
+#include <C2Config.h>
+#include <C2PlatformSupport.h>
+
+using namespace std::chrono_literals;
+
+extern "C" ::C2ComponentFactory* CreateCodec2Factory();
+extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory);
+
+namespace android {
+
+#define C2FUZZER_ALIGN(_sz, _align) (((_sz) + ((_align)-1)) & ~((_align)-1))
+
+constexpr std::chrono::milliseconds kC2FuzzerTimeOut = 5000ms;
+constexpr int32_t kNumberOfC2WorkItems = 8;
+constexpr uint32_t kWidthOfVideo = 3840;
+constexpr uint32_t kHeightOfVideo = 2160;
+constexpr uint32_t kSamplingRateOfAudio = 48000;
+constexpr uint32_t kChannelsOfAudio = 8;
+
+typedef std::tuple<uint8_t*, size_t, uint32_t> FrameData;
+
+class Codec2Fuzzer {
+ public:
+  Codec2Fuzzer() = default;
+  ~Codec2Fuzzer() { deInitDecoder(); }
+  bool initDecoder();
+  void deInitDecoder();
+  void decodeFrames(const uint8_t* data, size_t size);
+
+  void handleWorkDone(std::weak_ptr<C2Component> comp,
+                      std::list<std::unique_ptr<C2Work>>& workItems);
+
+ private:
+  class BufferSource {
+   public:
+    BufferSource(const uint8_t* data, size_t size)
+        : mData(data), mSize(size), mReadIndex(size - kMarkerSize) {}
+    ~BufferSource() {
+      mData = nullptr;
+      mSize = 0;
+      mReadIndex = 0;
+      mFrameList.clear();
+    }
+    bool isEos() { return mFrameList.empty(); }
+    void parse();
+    FrameData getFrame();
+
+   private:
+    bool isMarker() { return (memcmp(&mData[mReadIndex], kMarker, kMarkerSize) == 0); }
+
+    bool isCSDMarker(size_t position) {
+      return (memcmp(&mData[position], kCsdMarkerSuffix, kMarkerSuffixSize) == 0);
+    }
+
+    bool searchForMarker();
+
+    const uint8_t* mData = nullptr;
+    size_t mSize = 0;
+    size_t mReadIndex = 0;
+    std::vector<FrameData> mFrameList;
+    static constexpr uint8_t kMarker[] = "_MARK";
+    static constexpr uint8_t kCsdMarkerSuffix[] = "_H_";
+    static constexpr uint8_t kFrameMarkerSuffix[] = "_F_";
+    // All markers should be 5 bytes long ( sizeof '_MARK' which is 5)
+    static constexpr size_t kMarkerSize = (sizeof(kMarker) - 1);
+    // All marker types should be 3 bytes long ('_H_', '_F_')
+    static constexpr size_t kMarkerSuffixSize = 3;
+  };
+
+  BufferSource* mBufferSource;
+  bool mEos = false;
+  C2BlockPool::local_id_t mBlockPoolId;
+
+  std::shared_ptr<C2BlockPool> mLinearPool;
+  std::shared_ptr<C2Allocator> mLinearAllocator;
+  std::shared_ptr<C2Component::Listener> mListener;
+  std::shared_ptr<C2Component> mComponent;
+  std::shared_ptr<C2ComponentInterface> mInterface;
+  std::mutex mQueueLock;
+  std::condition_variable mQueueCondition;
+  std::list<std::unique_ptr<C2Work>> mWorkQueue;
+  std::mutex mDecodeCompleteMutex;
+  std::condition_variable mConditionalVariable;
+};
+
+}  // namespace android
+
+#endif  // __C2FUZZER_H__
diff --git a/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp b/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
index fb1c291..47ceed5 100644
--- a/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
@@ -73,9 +73,10 @@
             ASSERT_NE(listener, nullptr);
 
             // Create component from all known services
-            component =
-                    mClient->CreateComponentByName(listTraits[i].name.c_str(), listener, &mClient);
-            ASSERT_NE(component, nullptr)
+            const c2_status_t status =
+                    android::Codec2Client::CreateComponentByName(
+                            listTraits[i].name.c_str(), listener, &component, &mClient);
+            ASSERT_EQ(status, C2_OK)
                     << "Create component failed for " << listTraits[i].name.c_str();
         }
     }
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 12ed725..b520c17 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
@@ -734,7 +734,7 @@
             }
             if (timestampMax < timestamp) timestampMax = timestamp;
         }
-        timestampOffset = timestampMax;
+        timestampOffset = timestampMax + 33333;
         eleInfo.close();
 
         // Reset Total frames before second decode loop
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 4650672..341a577 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -1008,6 +1008,8 @@
                 std::scoped_lock lock{key2IndexMutex};
                 key2Index[key] = index; // update last known client index
                 return C2_OK;
+            } else if (status == C2_NO_MEMORY) {
+                return C2_NO_MEMORY;
             } else if (status == C2_TRANSACTION_FAILED) {
                 LOG(WARNING) << "\"" << key << "\" failed for service \""
                              << client->getName()
@@ -1028,24 +1030,23 @@
     return status; // return the last status from a valid client
 }
 
-std::shared_ptr<Codec2Client::Component>
-        Codec2Client::CreateComponentByName(
+c2_status_t Codec2Client::CreateComponentByName(
         const char* componentName,
         const std::shared_ptr<Listener>& listener,
+        std::shared_ptr<Component>* component,
         std::shared_ptr<Codec2Client>* owner,
         size_t numberOfAttempts) {
     std::string key{"create:"};
     key.append(componentName);
-    std::shared_ptr<Component> component;
     c2_status_t status = ForAllServices(
             key,
             numberOfAttempts,
-            [owner, &component, componentName, &listener](
+            [owner, component, componentName, &listener](
                     const std::shared_ptr<Codec2Client> &client)
                         -> c2_status_t {
                 c2_status_t status = client->createComponent(componentName,
                                                              listener,
-                                                             &component);
+                                                             component);
                 if (status == C2_OK) {
                     if (owner) {
                         *owner = client;
@@ -1064,7 +1065,7 @@
                    << "\" from all known services. "
                       "Last returned status = " << status << ".";
     }
-    return component;
+    return status;
 }
 
 std::shared_ptr<Codec2Client::Interface>
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index ffd194a..bbb2b96 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -200,9 +200,10 @@
     // Try to create a component with a given name from all known
     // IComponentStore services. numberOfAttempts determines the number of times
     // to retry the HIDL call if the transaction fails.
-    static std::shared_ptr<Component> CreateComponentByName(
+    static c2_status_t CreateComponentByName(
             char const* componentName,
             std::shared_ptr<Listener> const& listener,
+            std::shared_ptr<Component>* component,
             std::shared_ptr<Codec2Client>* owner = nullptr,
             size_t numberOfAttempts = 10);
 
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 9c1df71..5de4d7f 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -247,15 +247,20 @@
             return NO_INIT;
         }
 
-        size_t numSlots = 4;
-        constexpr OMX_U32 kPortIndexInput = 0;
+        size_t numSlots = 16;
+        // WORKAROUND: having more slots improve performance while consuming
+        // more memory. This is a temporary workaround to reduce memory for
+        // larger-than-4K scenario.
+        if (mWidth * mHeight > 4096 * 2340) {
+            constexpr OMX_U32 kPortIndexInput = 0;
 
-        OMX_PARAM_PORTDEFINITIONTYPE param;
-        param.nPortIndex = kPortIndexInput;
-        status_t err = mNode->getParameter(OMX_IndexParamPortDefinition,
-                                           &param, sizeof(param));
-        if (err == OK) {
-            numSlots = param.nBufferCountActual;
+            OMX_PARAM_PORTDEFINITIONTYPE param;
+            param.nPortIndex = kPortIndexInput;
+            status_t err = mNode->getParameter(OMX_IndexParamPortDefinition,
+                                               &param, sizeof(param));
+            if (err == OK) {
+                numSlots = param.nBufferCountActual;
+            }
         }
 
         for (size_t i = 0; i < numSlots; ++i) {
@@ -645,17 +650,18 @@
                 std::make_shared<Codec2ClientInterfaceWrapper>(client));
     }
 
-    std::shared_ptr<Codec2Client::Component> comp =
-            Codec2Client::CreateComponentByName(
+    std::shared_ptr<Codec2Client::Component> comp;
+    c2_status_t status = Codec2Client::CreateComponentByName(
             componentName.c_str(),
             mClientListener,
+            &comp,
             &client);
-    if (!comp) {
-        ALOGE("Failed Create component: %s", componentName.c_str());
+    if (status != C2_OK) {
+        ALOGE("Failed Create component: %s, error=%d", componentName.c_str(), status);
         Mutexed<State>::Locked state(mState);
         state->set(RELEASED);
         state.unlock();
-        mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
+        mCallback->onError((status == C2_NO_MEMORY ? NO_MEMORY : UNKNOWN_ERROR), ACTION_CODE_FATAL);
         state.lock();
         return;
     }
@@ -967,6 +973,7 @@
                 C2AndroidMemoryUsage androidUsage(C2MemoryUsage(usage.value));
                 config->mISConfig->mUsage = androidUsage.asGrallocUsage();
             }
+            config->mInputFormat->setInt64("android._C2MemoryUsage", usage.value);
         }
 
         // NOTE: we don't blindly use client specified input size if specified as clients
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 3ef454b..8c1e712 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1300,54 +1300,30 @@
                 return a.capacity < b.capacity;
             });
 
-    {
-        Mutexed<std::list<sp<ABuffer>>>::Locked configs(mFlushedConfigs);
-        if (!configs->empty()) {
-            while (!configs->empty()) {
-                sp<ABuffer> config = configs->front();
-                configs->pop_front();
-                // Find the smallest input buffer that can fit the config.
-                auto i = std::find_if(
-                        clientInputBuffers.begin(),
-                        clientInputBuffers.end(),
-                        [cfgSize = config->size()](const ClientInputBuffer& b) {
-                            return b.capacity >= cfgSize;
-                        });
-                if (i == clientInputBuffers.end()) {
-                    ALOGW("[%s] no input buffer large enough for the config "
-                          "(%zu bytes)",
-                          mName, config->size());
-                    return NO_MEMORY;
-                }
-                sp<MediaCodecBuffer> buffer = i->buffer;
-                memcpy(buffer->base(), config->data(), config->size());
-                buffer->setRange(0, config->size());
-                buffer->meta()->clear();
-                buffer->meta()->setInt64("timeUs", 0);
-                buffer->meta()->setInt32("csd", 1);
-                if (queueInputBufferInternal(buffer) != OK) {
-                    ALOGW("[%s] Error while queueing a flushed config",
-                          mName);
-                    return UNKNOWN_ERROR;
-                }
-                clientInputBuffers.erase(i);
-            }
-        } else if (oStreamFormat.value == C2BufferData::LINEAR &&
-                   (!prepend || prepend.value == PREPEND_HEADER_TO_NONE)) {
-            sp<MediaCodecBuffer> buffer = clientInputBuffers.front().buffer;
-            // WORKAROUND: Some apps expect CSD available without queueing
-            //             any input. Queue an empty buffer to get the CSD.
-            buffer->setRange(0, 0);
-            buffer->meta()->clear();
-            buffer->meta()->setInt64("timeUs", 0);
-            if (queueInputBufferInternal(buffer) != OK) {
-                ALOGW("[%s] Error while queueing an empty buffer to get CSD",
-                      mName);
-                return UNKNOWN_ERROR;
-            }
-            clientInputBuffers.pop_front();
+    std::list<std::unique_ptr<C2Work>> flushedConfigs;
+    mFlushedConfigs.lock()->swap(flushedConfigs);
+    if (!flushedConfigs.empty()) {
+        err = mComponent->queue(&flushedConfigs);
+        if (err != C2_OK) {
+            ALOGW("[%s] Error while queueing a flushed config", mName);
+            return UNKNOWN_ERROR;
         }
     }
+    if (oStreamFormat.value == C2BufferData::LINEAR &&
+            (!prepend || prepend.value == PREPEND_HEADER_TO_NONE)) {
+        sp<MediaCodecBuffer> buffer = clientInputBuffers.front().buffer;
+        // WORKAROUND: Some apps expect CSD available without queueing
+        //             any input. Queue an empty buffer to get the CSD.
+        buffer->setRange(0, 0);
+        buffer->meta()->clear();
+        buffer->meta()->setInt64("timeUs", 0);
+        if (queueInputBufferInternal(buffer) != OK) {
+            ALOGW("[%s] Error while queueing an empty buffer to get CSD",
+                  mName);
+            return UNKNOWN_ERROR;
+        }
+        clientInputBuffers.pop_front();
+    }
 
     for (const ClientInputBuffer& clientInputBuffer: clientInputBuffers) {
         mCallback->onInputBufferAvailable(
@@ -1396,27 +1372,36 @@
 
 void CCodecBufferChannel::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
     ALOGV("[%s] flush", mName);
-    {
-        Mutexed<std::list<sp<ABuffer>>>::Locked configs(mFlushedConfigs);
-        for (const std::unique_ptr<C2Work> &work : flushedWork) {
-            if (!(work->input.flags & C2FrameData::FLAG_CODEC_CONFIG)) {
-                continue;
-            }
-            if (work->input.buffers.empty()
-                    || work->input.buffers.front()->data().linearBlocks().empty()) {
-                ALOGD("[%s] no linear codec config data found", mName);
-                continue;
-            }
-            C2ReadView view =
-                    work->input.buffers.front()->data().linearBlocks().front().map().get();
-            if (view.error() != C2_OK) {
-                ALOGD("[%s] failed to map flushed codec config data: %d", mName, view.error());
-                continue;
-            }
-            configs->push_back(ABuffer::CreateAsCopy(view.data(), view.capacity()));
-            ALOGV("[%s] stashed flushed codec config data (size=%u)", mName, view.capacity());
+    std::list<std::unique_ptr<C2Work>> configs;
+    for (const std::unique_ptr<C2Work> &work : flushedWork) {
+        if (!(work->input.flags & C2FrameData::FLAG_CODEC_CONFIG)) {
+            continue;
         }
+        if (work->input.buffers.empty()
+                || work->input.buffers.front() == nullptr
+                || work->input.buffers.front()->data().linearBlocks().empty()) {
+            ALOGD("[%s] no linear codec config data found", mName);
+            continue;
+        }
+        std::unique_ptr<C2Work> copy(new C2Work);
+        copy->input.flags = C2FrameData::flags_t(work->input.flags | C2FrameData::FLAG_DROP_FRAME);
+        copy->input.ordinal = work->input.ordinal;
+        copy->input.buffers.insert(
+                copy->input.buffers.begin(),
+                work->input.buffers.begin(),
+                work->input.buffers.end());
+        for (const std::unique_ptr<C2Param> &param : work->input.configUpdate) {
+            copy->input.configUpdate.push_back(C2Param::Copy(*param));
+        }
+        copy->input.infoBuffers.insert(
+                copy->input.infoBuffers.begin(),
+                work->input.infoBuffers.begin(),
+                work->input.infoBuffers.end());
+        copy->worklets.emplace_back(new C2Worklet);
+        configs.push_back(std::move(copy));
+        ALOGV("[%s] stashed flushed codec config data", mName);
     }
+    mFlushedConfigs.lock()->swap(configs);
     {
         Mutexed<Input>::Locked input(mInput);
         input->buffers->flush();
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index 046c5c3..e2c9aaa 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -277,7 +277,7 @@
         uint32_t outputDelay;
     };
     Mutexed<Output> mOutput;
-    Mutexed<std::list<sp<ABuffer>>> mFlushedConfigs;
+    Mutexed<std::list<std::unique_ptr<C2Work>>> mFlushedConfigs;
 
     std::atomic_uint64_t mFrameIndex;
     std::atomic_uint64_t mFirstValidFrameIndex;
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index 692da58..dd28b6a 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -96,6 +96,9 @@
                 int32_t vstride = int32_t(offsetDelta / stride);
                 newFormat->setInt32(KEY_SLICE_HEIGHT, vstride);
                 ALOGD("[%s] updating vstride = %d", mName, vstride);
+                buffer->setRange(
+                        img->mPlane[0].mOffset,
+                        buffer->size() - img->mPlane[0].mOffset);
             }
         }
         setFormat(newFormat);
@@ -804,8 +807,9 @@
         capacity = kMaxLinearBufferSize;
     }
 
-    // TODO: read usage from intf
-    C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
+    int64_t usageValue = 0;
+    (void)format->findInt64("android._C2MemoryUsage", &usageValue);
+    C2MemoryUsage usage{usageValue | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE};
     std::shared_ptr<C2LinearBlock> block;
 
     c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
@@ -1037,8 +1041,9 @@
 }
 
 sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
-    // TODO: read usage from intf
-    C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
+    int64_t usageValue = 0;
+    (void)mFormat->findInt64("android._C2MemoryUsage", &usageValue);
+    C2MemoryUsage usage{usageValue | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE};
     return AllocateGraphicBuffer(
             mPool, mFormat, HAL_PIXEL_FORMAT_YV12, usage, mLocalBufferPool);
 }
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 25e7da9..5072323 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "Codec2Buffer"
 #include <utils/Log.h>
 
+#include <android-base/properties.h>
 #include <android/hardware/cas/native/1.0/types.h>
 #include <android/hardware/drm/1.0/types.h>
 #include <hidlmemory/FrameworkUtils.h>
@@ -276,20 +277,22 @@
                             int32_t planeSize = 0;
                             for (uint32_t i = 0; i < layout.numPlanes; ++i) {
                                 const C2PlaneInfo &plane = layout.planes[i];
-                                ssize_t minOffset = plane.minOffset(mWidth, mHeight);
-                                ssize_t maxOffset = plane.maxOffset(mWidth, mHeight);
+                                int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
+                                ssize_t minOffset = plane.minOffset(
+                                        mWidth / plane.colSampling, mHeight / plane.rowSampling);
+                                ssize_t maxOffset = plane.maxOffset(
+                                        mWidth / plane.colSampling, mHeight / plane.rowSampling);
                                 if (minPtr > mView.data()[i] + minOffset) {
                                     minPtr = mView.data()[i] + minOffset;
                                 }
                                 if (maxPtr < mView.data()[i] + maxOffset) {
                                     maxPtr = mView.data()[i] + maxOffset;
                                 }
-                                planeSize += std::abs(plane.rowInc) * align(mHeight, 64)
-                                        / plane.rowSampling / plane.colSampling
-                                        * divUp(mAllocatedDepth, 8u);
+                                planeSize += planeStride * divUp(mAllocatedDepth, 8u)
+                                        * align(mHeight, 64) / plane.rowSampling;
                             }
 
-                            if ((maxPtr - minPtr + 1) <= planeSize) {
+                            if (minPtr == mView.data()[0] && (maxPtr - minPtr + 1) <= planeSize) {
                                 // FIXME: this is risky as reading/writing data out of bound results
                                 //        in an undefined behavior, but gralloc does assume a
                                 //        contiguous mapping
@@ -578,7 +581,23 @@
 }
 
 std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
-#ifndef __LP64__
+#ifdef __LP64__
+    static std::once_flag s_checkOnce;
+    static bool s_64bitonly {false};
+    std::call_once(s_checkOnce, [&](){
+        const std::string abi32list =
+        ::android::base::GetProperty("ro.product.cpu.abilist32", "");
+        if (abi32list.empty()) {
+            s_64bitonly = true;
+        }
+    });
+
+    if (!s_64bitonly) {
+        ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object");
+        return nullptr;
+    }
+#endif
+
     VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
     ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
     if (buffer == nullptr) {
@@ -611,10 +630,6 @@
     }
     return C2Buffer::CreateGraphicBuffer(
             block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
-#else
-    ALOGE("GraphicMetadataBuffer does not work on 64-bit arch");
-    return nullptr;
-#endif
 }
 
 // ConstGraphicBlockBuffer
diff --git a/media/codec2/sfplugin/InputSurfaceWrapper.h b/media/codec2/sfplugin/InputSurfaceWrapper.h
index bb35763..479acb1 100644
--- a/media/codec2/sfplugin/InputSurfaceWrapper.h
+++ b/media/codec2/sfplugin/InputSurfaceWrapper.h
@@ -61,24 +61,24 @@
     /// Input Surface configuration
     struct Config {
         // IN PARAMS (GBS)
-        float mMinFps; // minimum fps (repeat frame to achieve this)
-        float mMaxFps; // max fps (via frame drop)
-        float mCaptureFps; // capture fps
-        float mCodedFps;   // coded fps
-        bool mSuspended; // suspended
-        int64_t mTimeOffsetUs; // time offset (input => codec)
-        int64_t mSuspendAtUs; // suspend/resume time
-        int64_t mStartAtUs; // start time
-        bool mStopped; // stopped
-        int64_t mStopAtUs; // stop time
+        float mMinFps = 0.0; // minimum fps (repeat frame to achieve this)
+        float mMaxFps = 0.0; // max fps (via frame drop)
+        float mCaptureFps = 0.0; // capture fps
+        float mCodedFps = 0.0;   // coded fps
+        bool mSuspended = false; // suspended
+        int64_t mTimeOffsetUs = 0; // time offset (input => codec)
+        int64_t mSuspendAtUs = 0; // suspend/resume time
+        int64_t mStartAtUs = 0; // start time
+        bool mStopped = false; // stopped
+        int64_t mStopAtUs = 0; // stop time
 
         // OUT PARAMS (GBS)
-        int64_t mInputDelayUs; // delay between encoder input and surface input
+        int64_t mInputDelayUs = 0; // delay between encoder input and surface input
 
         // IN PARAMS (CODEC WRAPPER)
-        float mFixedAdjustedFps; // fixed fps via PTS manipulation
-        float mMinAdjustedFps; // minimum fps via PTS manipulation
-        uint64_t mUsage; // consumer usage
+        float mFixedAdjustedFps = 0.0; // fixed fps via PTS manipulation
+        float mMinAdjustedFps = 0.0; // minimum fps via PTS manipulation
+        uint64_t mUsage = 0; // consumer usage
     };
 
     /**
diff --git a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
index 5bee605..ad8f6e5 100644
--- a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
+++ b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
@@ -18,22 +18,31 @@
 
 #include <gtest/gtest.h>
 
+#include <media/stagefright/foundation/AString.h>
 #include <media/stagefright/MediaCodecConstants.h>
 
+#include <C2BlockInternal.h>
 #include <C2PlatformSupport.h>
 
 namespace android {
 
+static std::shared_ptr<RawGraphicOutputBuffers> GetRawGraphicOutputBuffers(
+        int32_t width, int32_t height) {
+    std::shared_ptr<RawGraphicOutputBuffers> buffers =
+        std::make_shared<RawGraphicOutputBuffers>("test");
+    sp<AMessage> format{new AMessage};
+    format->setInt32(KEY_WIDTH, width);
+    format->setInt32(KEY_HEIGHT, height);
+    buffers->setFormat(format);
+    return buffers;
+}
+
 TEST(RawGraphicOutputBuffersTest, ChangeNumSlots) {
     constexpr int32_t kWidth = 3840;
     constexpr int32_t kHeight = 2160;
 
     std::shared_ptr<RawGraphicOutputBuffers> buffers =
-        std::make_shared<RawGraphicOutputBuffers>("test");
-    sp<AMessage> format{new AMessage};
-    format->setInt32("width", kWidth);
-    format->setInt32("height", kHeight);
-    buffers->setFormat(format);
+        GetRawGraphicOutputBuffers(kWidth, kHeight);
 
     std::shared_ptr<C2BlockPool> pool;
     ASSERT_EQ(OK, GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, nullptr, &pool));
@@ -96,4 +105,435 @@
     }
 }
 
+class TestGraphicAllocation : public C2GraphicAllocation {
+public:
+    TestGraphicAllocation(
+            uint32_t width,
+            uint32_t height,
+            const C2PlanarLayout &layout,
+            size_t capacity,
+            std::vector<size_t> offsets)
+        : C2GraphicAllocation(width, height),
+          mLayout(layout),
+          mMemory(capacity, 0xAA),
+          mOffsets(offsets) {
+    }
+
+    c2_status_t map(
+            C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
+            C2PlanarLayout *layout, uint8_t **addr) override {
+        (void)rect;
+        (void)usage;
+        (void)fence;
+        *layout = mLayout;
+        for (size_t i = 0; i < mLayout.numPlanes; ++i) {
+            addr[i] = mMemory.data() + mOffsets[i];
+        }
+        return C2_OK;
+    }
+
+    c2_status_t unmap(uint8_t **, C2Rect, C2Fence *) override { return C2_OK; }
+
+    C2Allocator::id_t getAllocatorId() const override { return -1; }
+
+    const C2Handle *handle() const override { return nullptr; }
+
+    bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override {
+        return other.get() == this;
+    }
+
+private:
+    C2PlanarLayout mLayout;
+    std::vector<uint8_t> mMemory;
+    std::vector<uint8_t *> mAddr;
+    std::vector<size_t> mOffsets;
+};
+
+class LayoutTest : public ::testing::TestWithParam<std::tuple<bool, std::string, bool, int32_t>> {
+private:
+    static C2PlanarLayout YUVPlanarLayout(int32_t stride) {
+        C2PlanarLayout layout = {
+            C2PlanarLayout::TYPE_YUV,
+            3,  /* numPlanes */
+            3,  /* rootPlanes */
+            {},  /* planes --- to be filled below */
+        };
+        layout.planes[C2PlanarLayout::PLANE_Y] = {
+            C2PlaneInfo::CHANNEL_Y,
+            1,  /* colInc */
+            stride,  /* rowInc */
+            1,  /* colSampling */
+            1,  /* rowSampling */
+            8,  /* allocatedDepth */
+            8,  /* bitDepth */
+            0,  /* rightShift */
+            C2PlaneInfo::NATIVE,
+            C2PlanarLayout::PLANE_Y,  /* rootIx */
+            0,  /* offset */
+        };
+        layout.planes[C2PlanarLayout::PLANE_U] = {
+            C2PlaneInfo::CHANNEL_CB,
+            1,  /* colInc */
+            stride / 2,  /* rowInc */
+            2,  /* colSampling */
+            2,  /* rowSampling */
+            8,  /* allocatedDepth */
+            8,  /* bitDepth */
+            0,  /* rightShift */
+            C2PlaneInfo::NATIVE,
+            C2PlanarLayout::PLANE_U,  /* rootIx */
+            0,  /* offset */
+        };
+        layout.planes[C2PlanarLayout::PLANE_V] = {
+            C2PlaneInfo::CHANNEL_CR,
+            1,  /* colInc */
+            stride / 2,  /* rowInc */
+            2,  /* colSampling */
+            2,  /* rowSampling */
+            8,  /* allocatedDepth */
+            8,  /* bitDepth */
+            0,  /* rightShift */
+            C2PlaneInfo::NATIVE,
+            C2PlanarLayout::PLANE_V,  /* rootIx */
+            0,  /* offset */
+        };
+        return layout;
+    }
+
+    static C2PlanarLayout YUVSemiPlanarLayout(int32_t stride) {
+        C2PlanarLayout layout = {
+            C2PlanarLayout::TYPE_YUV,
+            3,  /* numPlanes */
+            2,  /* rootPlanes */
+            {},  /* planes --- to be filled below */
+        };
+        layout.planes[C2PlanarLayout::PLANE_Y] = {
+            C2PlaneInfo::CHANNEL_Y,
+            1,  /* colInc */
+            stride,  /* rowInc */
+            1,  /* colSampling */
+            1,  /* rowSampling */
+            8,  /* allocatedDepth */
+            8,  /* bitDepth */
+            0,  /* rightShift */
+            C2PlaneInfo::NATIVE,
+            C2PlanarLayout::PLANE_Y,  /* rootIx */
+            0,  /* offset */
+        };
+        layout.planes[C2PlanarLayout::PLANE_U] = {
+            C2PlaneInfo::CHANNEL_CB,
+            2,  /* colInc */
+            stride,  /* rowInc */
+            2,  /* colSampling */
+            2,  /* rowSampling */
+            8,  /* allocatedDepth */
+            8,  /* bitDepth */
+            0,  /* rightShift */
+            C2PlaneInfo::NATIVE,
+            C2PlanarLayout::PLANE_U,  /* rootIx */
+            0,  /* offset */
+        };
+        layout.planes[C2PlanarLayout::PLANE_V] = {
+            C2PlaneInfo::CHANNEL_CR,
+            2,  /* colInc */
+            stride,  /* rowInc */
+            2,  /* colSampling */
+            2,  /* rowSampling */
+            8,  /* allocatedDepth */
+            8,  /* bitDepth */
+            0,  /* rightShift */
+            C2PlaneInfo::NATIVE,
+            C2PlanarLayout::PLANE_U,  /* rootIx */
+            1,  /* offset */
+        };
+        return layout;
+    }
+
+    static C2PlanarLayout YVUSemiPlanarLayout(int32_t stride) {
+        C2PlanarLayout layout = {
+            C2PlanarLayout::TYPE_YUV,
+            3,  /* numPlanes */
+            2,  /* rootPlanes */
+            {},  /* planes --- to be filled below */
+        };
+        layout.planes[C2PlanarLayout::PLANE_Y] = {
+            C2PlaneInfo::CHANNEL_Y,
+            1,  /* colInc */
+            stride,  /* rowInc */
+            1,  /* colSampling */
+            1,  /* rowSampling */
+            8,  /* allocatedDepth */
+            8,  /* bitDepth */
+            0,  /* rightShift */
+            C2PlaneInfo::NATIVE,
+            C2PlanarLayout::PLANE_Y,  /* rootIx */
+            0,  /* offset */
+        };
+        layout.planes[C2PlanarLayout::PLANE_U] = {
+            C2PlaneInfo::CHANNEL_CB,
+            2,  /* colInc */
+            stride,  /* rowInc */
+            2,  /* colSampling */
+            2,  /* rowSampling */
+            8,  /* allocatedDepth */
+            8,  /* bitDepth */
+            0,  /* rightShift */
+            C2PlaneInfo::NATIVE,
+            C2PlanarLayout::PLANE_V,  /* rootIx */
+            1,  /* offset */
+        };
+        layout.planes[C2PlanarLayout::PLANE_V] = {
+            C2PlaneInfo::CHANNEL_CR,
+            2,  /* colInc */
+            stride,  /* rowInc */
+            2,  /* colSampling */
+            2,  /* rowSampling */
+            8,  /* allocatedDepth */
+            8,  /* bitDepth */
+            0,  /* rightShift */
+            C2PlaneInfo::NATIVE,
+            C2PlanarLayout::PLANE_V,  /* rootIx */
+            0,  /* offset */
+        };
+        return layout;
+    }
+
+    static std::shared_ptr<C2GraphicBlock> CreateGraphicBlock(
+            uint32_t width,
+            uint32_t height,
+            const C2PlanarLayout &layout,
+            size_t capacity,
+            std::vector<size_t> offsets) {
+        std::shared_ptr<C2GraphicAllocation> alloc = std::make_shared<TestGraphicAllocation>(
+                width,
+                height,
+                layout,
+                capacity,
+                offsets);
+
+        return _C2BlockFactory::CreateGraphicBlock(alloc);
+    }
+
+    static constexpr uint8_t GetPixelValue(uint8_t value, uint32_t row, uint32_t col) {
+        return (uint32_t(value) * row + col) & 0xFF;
+    }
+
+    static void FillPlane(C2GraphicView &view, size_t index, uint8_t value) {
+        C2PlanarLayout layout = view.layout();
+
+        uint8_t *rowPtr = view.data()[index];
+        C2PlaneInfo plane = layout.planes[index];
+        for (uint32_t row = 0; row < view.height() / plane.rowSampling; ++row) {
+            uint8_t *colPtr = rowPtr;
+            for (uint32_t col = 0; col < view.width() / plane.colSampling; ++col) {
+                *colPtr = GetPixelValue(value, row, col);
+                colPtr += plane.colInc;
+            }
+            rowPtr += plane.rowInc;
+        }
+    }
+
+    static void FillBlock(const std::shared_ptr<C2GraphicBlock> &block) {
+        C2GraphicView view = block->map().get();
+
+        FillPlane(view, C2PlanarLayout::PLANE_Y, 'Y');
+        FillPlane(view, C2PlanarLayout::PLANE_U, 'U');
+        FillPlane(view, C2PlanarLayout::PLANE_V, 'V');
+    }
+
+    static bool VerifyPlane(
+            const MediaImage2 *mediaImage,
+            const uint8_t *base,
+            uint32_t index,
+            uint8_t value,
+            std::string *errorMsg) {
+        *errorMsg = "";
+        MediaImage2::PlaneInfo plane = mediaImage->mPlane[index];
+        const uint8_t *rowPtr = base + plane.mOffset;
+        for (uint32_t row = 0; row < mediaImage->mHeight / plane.mVertSubsampling; ++row) {
+            const uint8_t *colPtr = rowPtr;
+            for (uint32_t col = 0; col < mediaImage->mWidth / plane.mHorizSubsampling; ++col) {
+                if (GetPixelValue(value, row, col) != *colPtr) {
+                    *errorMsg = AStringPrintf("row=%u col=%u expected=%02x actual=%02x",
+                            row, col, GetPixelValue(value, row, col), *colPtr).c_str();
+                    return false;
+                }
+                colPtr += plane.mColInc;
+            }
+            rowPtr += plane.mRowInc;
+        }
+        return true;
+    }
+
+public:
+    static constexpr int32_t kWidth = 320;
+    static constexpr int32_t kHeight = 240;
+    static constexpr int32_t kGapLength = kWidth * kHeight * 10;
+
+    static std::shared_ptr<C2Buffer> CreateAndFillBufferFromParam(const ParamType &param) {
+        bool contiguous = std::get<0>(param);
+        std::string planeOrderStr = std::get<1>(param);
+        bool planar = std::get<2>(param);
+        int32_t stride = std::get<3>(param);
+
+        C2PlanarLayout::plane_index_t planeOrder[3];
+        C2PlanarLayout layout;
+
+        if (planeOrderStr.size() != 3) {
+            return nullptr;
+        }
+        for (size_t i = 0; i < 3; ++i) {
+            C2PlanarLayout::plane_index_t planeIndex;
+            switch (planeOrderStr[i]) {
+                case 'Y': planeIndex = C2PlanarLayout::PLANE_Y; break;
+                case 'U': planeIndex = C2PlanarLayout::PLANE_U; break;
+                case 'V': planeIndex = C2PlanarLayout::PLANE_V; break;
+                default:  return nullptr;
+            }
+            planeOrder[i] = planeIndex;
+        }
+
+        if (planar) {
+            layout = YUVPlanarLayout(stride);
+        } else {  // semi-planar
+            for (size_t i = 0; i < 3; ++i) {
+                if (planeOrder[i] == C2PlanarLayout::PLANE_U) {
+                    layout = YUVSemiPlanarLayout(stride);
+                    break;
+                }
+                if (planeOrder[i] == C2PlanarLayout::PLANE_V) {
+                    layout = YVUSemiPlanarLayout(stride);
+                    break;
+                }
+            }
+        }
+
+        size_t yPlaneSize = stride * kHeight;
+        size_t uvPlaneSize = stride * kHeight / 4;
+        size_t capacity = yPlaneSize + uvPlaneSize * 2;
+        std::vector<size_t> offsets(3);
+
+        if (!contiguous) {
+            if (planar) {
+                capacity += kGapLength * 2;
+            } else {  // semi-planar
+                capacity += kGapLength;
+            }
+        }
+
+        offsets[planeOrder[0]] = 0;
+        size_t planeSize = (planeOrder[0] == C2PlanarLayout::PLANE_Y) ? yPlaneSize : uvPlaneSize;
+        for (size_t i = 1; i < 3; ++i) {
+            offsets[planeOrder[i]] = offsets[planeOrder[i - 1]] + planeSize;
+            if (!contiguous) {
+                offsets[planeOrder[i]] += kGapLength;
+            }
+            planeSize = (planeOrder[i] == C2PlanarLayout::PLANE_Y) ? yPlaneSize : uvPlaneSize;
+            if (!planar  // semi-planar
+                    && planeOrder[i - 1] != C2PlanarLayout::PLANE_Y
+                    && planeOrder[i] != C2PlanarLayout::PLANE_Y) {
+                offsets[planeOrder[i]] = offsets[planeOrder[i - 1]] + 1;
+                planeSize = uvPlaneSize * 2 - 1;
+            }
+        }
+
+        std::shared_ptr<C2GraphicBlock> block = CreateGraphicBlock(
+                kWidth,
+                kHeight,
+                layout,
+                capacity,
+                offsets);
+        FillBlock(block);
+        return C2Buffer::CreateGraphicBuffer(
+                block->share(block->crop(), C2Fence()));
+    }
+
+    static bool VerifyClientBuffer(
+            const sp<MediaCodecBuffer> &buffer, std::string *errorMsg) {
+        *errorMsg = "";
+        sp<ABuffer> imageData;
+        if (!buffer->format()->findBuffer("image-data", &imageData)) {
+            *errorMsg = "Missing image data";
+            return false;
+        }
+        MediaImage2 *mediaImage = (MediaImage2 *)imageData->data();
+        if (mediaImage->mType != MediaImage2::MEDIA_IMAGE_TYPE_YUV) {
+            *errorMsg = AStringPrintf("Unexpected type: %d", mediaImage->mType).c_str();
+            return false;
+        }
+        std::string planeErrorMsg;
+        if (!VerifyPlane(mediaImage, buffer->base(), MediaImage2::Y, 'Y', &planeErrorMsg)) {
+            *errorMsg = "Y plane does not match: " + planeErrorMsg;
+            return false;
+        }
+        if (!VerifyPlane(mediaImage, buffer->base(), MediaImage2::U, 'U', &planeErrorMsg)) {
+            *errorMsg = "U plane does not match: " + planeErrorMsg;
+            return false;
+        }
+        if (!VerifyPlane(mediaImage, buffer->base(), MediaImage2::V, 'V', &planeErrorMsg)) {
+            *errorMsg = "V plane does not match: " + planeErrorMsg;
+            return false;
+        }
+
+        int32_t width, height, stride;
+        buffer->format()->findInt32(KEY_WIDTH, &width);
+        buffer->format()->findInt32(KEY_HEIGHT, &height);
+        buffer->format()->findInt32(KEY_STRIDE, &stride);
+
+        MediaImage2 legacyYLayout = {
+            MediaImage2::MEDIA_IMAGE_TYPE_Y,
+            1,  // mNumPlanes
+            uint32_t(width),
+            uint32_t(height),
+            8,
+            8,
+            {},  // mPlane
+        };
+        legacyYLayout.mPlane[MediaImage2::Y] = {
+            0,  // mOffset
+            1,  // mColInc
+            stride,  // mRowInc
+            1,  // mHorizSubsampling
+            1,  // mVertSubsampling
+        };
+        if (!VerifyPlane(&legacyYLayout, buffer->data(), MediaImage2::Y, 'Y', &planeErrorMsg)) {
+            *errorMsg = "Y plane by legacy layout does not match: " + planeErrorMsg;
+            return false;
+        }
+        return true;
+    }
+
+};
+
+TEST_P(LayoutTest, VerifyLayout) {
+    std::shared_ptr<RawGraphicOutputBuffers> buffers =
+        GetRawGraphicOutputBuffers(kWidth, kHeight);
+
+    std::shared_ptr<C2Buffer> c2Buffer = CreateAndFillBufferFromParam(GetParam());
+    ASSERT_NE(nullptr, c2Buffer);
+    sp<MediaCodecBuffer> clientBuffer;
+    size_t index;
+    ASSERT_EQ(OK, buffers->registerBuffer(c2Buffer, &index, &clientBuffer));
+    ASSERT_NE(nullptr, clientBuffer);
+    std::string errorMsg;
+    ASSERT_TRUE(VerifyClientBuffer(clientBuffer, &errorMsg)) << errorMsg;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        RawGraphicOutputBuffersTest,
+        LayoutTest,
+        ::testing::Combine(
+            ::testing::Bool(),  /* contiguous */
+            ::testing::Values("YUV", "YVU", "UVY", "VUY"),
+            ::testing::Bool(),  /* planar */
+            ::testing::Values(320, 512)),
+        [](const ::testing::TestParamInfo<LayoutTest::ParamType> &info) {
+            std::string contiguous = std::get<0>(info.param) ? "Contiguous" : "Noncontiguous";
+            std::string planar = std::get<2>(info.param) ? "Planar" : "SemiPlanar";
+            return contiguous
+                    + std::get<1>(info.param)
+                    + planar
+                    + std::to_string(std::get<3>(info.param));
+        });
+
 } // namespace android
diff --git a/media/codec2/sfplugin/utils/Android.bp b/media/codec2/sfplugin/utils/Android.bp
index 6287221..e7dc92a 100644
--- a/media/codec2/sfplugin/utils/Android.bp
+++ b/media/codec2/sfplugin/utils/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "libsfplugin_ccodec_utils",
     vendor_available: true,
     min_sdk_version: "29",
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index 60f4736..19afccf 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -13,7 +13,7 @@
 
 // !!!DO NOT DEPEND ON THIS SHARED LIBRARY DIRECTLY!!!
 // use libcodec2-impl-defaults instead
-cc_library_shared {
+cc_library {
     name: "libcodec2_vndk",
     vendor_available: true,
     min_sdk_version: "29",
diff --git a/media/codec2/vndk/C2DmaBufAllocator.cpp b/media/codec2/vndk/C2DmaBufAllocator.cpp
index 59e82e2..750aa31 100644
--- a/media/codec2/vndk/C2DmaBufAllocator.cpp
+++ b/media/codec2/vndk/C2DmaBufAllocator.cpp
@@ -315,8 +315,8 @@
         if (mUsageMapper) {
             res = mUsageMapper(usage, capacity, heap_name, flags);
         } else {
-            // No system-uncached yet, so disabled for now
-            if (0 && !(usage.expected & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE)))
+            if (C2DmaBufAllocator::system_uncached_supported() &&
+                !(usage.expected & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE)))
                 *heap_name = "system-uncached";
             else
                 *heap_name = "system";
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 1e907c1..dee3bf6 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -622,6 +622,12 @@
             std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
     C2PlatformComponentStore();
 
+    // For testing only
+    C2PlatformComponentStore(
+            std::vector<std::tuple<C2String,
+                                   C2ComponentFactory::CreateCodec2FactoryFunc,
+                                   C2ComponentFactory::DestroyCodec2FactoryFunc>>);
+
     virtual ~C2PlatformComponentStore() override = default;
 
 private:
@@ -662,6 +668,24 @@
         }
 
         /**
+         * Creates an uninitialized component module.
+         * NOTE: For testing only
+         *
+         * \param name[in]  component name.
+         *
+         * \note Only used by ComponentLoader.
+         */
+        ComponentModule(
+                C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
+                C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
+            : mInit(C2_NO_INIT),
+              mLibHandle(nullptr),
+              createFactory(createFactory),
+              destroyFactory(destroyFactory),
+              mComponentFactory(nullptr) {
+        }
+
+        /**
          * Initializes a component module with a given library path. Must be called exactly once.
          *
          * \note Only used by ComponentLoader.
@@ -717,7 +741,13 @@
             std::lock_guard<std::mutex> lock(mMutex);
             std::shared_ptr<ComponentModule> localModule = mModule.lock();
             if (localModule == nullptr) {
-                localModule = std::make_shared<ComponentModule>();
+                if(mCreateFactory) {
+                    // For testing only
+                    localModule = std::make_shared<ComponentModule>(mCreateFactory,
+                                                                    mDestroyFactory);
+                } else {
+                    localModule = std::make_shared<ComponentModule>();
+                }
                 res = localModule->init(mLibPath);
                 if (res == C2_OK) {
                     mModule = localModule;
@@ -733,10 +763,22 @@
         ComponentLoader(std::string libPath)
             : mLibPath(libPath) {}
 
+        // For testing only
+        ComponentLoader(std::tuple<C2String,
+                          C2ComponentFactory::CreateCodec2FactoryFunc,
+                          C2ComponentFactory::DestroyCodec2FactoryFunc> func)
+            : mLibPath(std::get<0>(func)),
+              mCreateFactory(std::get<1>(func)),
+              mDestroyFactory(std::get<2>(func)) {}
+
     private:
         std::mutex mMutex; ///< mutex guarding the module
         std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
         std::string mLibPath; ///< library path
+
+        // For testing only
+        C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
+        C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
     };
 
     struct Interface : public C2InterfaceHelper {
@@ -780,7 +822,13 @@
                 };
 
                 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
-                    strncpy(me.set().m.heapName, "system", me.v.flexCount());
+                    long long usage = (long long)me.get().m.usage;
+                    if (C2DmaBufAllocator::system_uncached_supported() &&
+                        !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
+                        strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
+                    } else {
+                        strncpy(me.set().m.heapName, "system", me.v.flexCount());
+                    }
                     me.set().m.allocFlags = 0;
                     return C2R::Ok();
                 };
@@ -846,25 +894,33 @@
 
     std::shared_ptr<C2ReflectorHelper> mReflector;
     Interface mInterface;
+
+    // For testing only
+    std::vector<std::tuple<C2String,
+                          C2ComponentFactory::CreateCodec2FactoryFunc,
+                          C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
 };
 
 c2_status_t C2PlatformComponentStore::ComponentModule::init(
         std::string libPath) {
     ALOGV("in %s", __func__);
     ALOGV("loading dll");
-    mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
-    LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
-            "could not dlopen %s: %s", libPath.c_str(), dlerror());
 
-    createFactory =
-        (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
-    LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
-            "createFactory is null in %s", libPath.c_str());
+    if(!createFactory) {
+        mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
+        LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
+                "could not dlopen %s: %s", libPath.c_str(), dlerror());
 
-    destroyFactory =
-        (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
-    LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
-            "destroyFactory is null in %s", libPath.c_str());
+        createFactory =
+            (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
+        LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
+                "createFactory is null in %s", libPath.c_str());
+
+        destroyFactory =
+            (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
+        LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
+                "destroyFactory is null in %s", libPath.c_str());
+    }
 
     mComponentFactory = createFactory();
     if (mComponentFactory == nullptr) {
@@ -1065,6 +1121,22 @@
     emplace("libcodec2_soft_vp8enc.so");
     emplace("libcodec2_soft_vp9dec.so");
     emplace("libcodec2_soft_vp9enc.so");
+
+}
+
+// For testing only
+C2PlatformComponentStore::C2PlatformComponentStore(
+    std::vector<std::tuple<C2String,
+                C2ComponentFactory::CreateCodec2FactoryFunc,
+                C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
+    : mVisited(false),
+      mReflector(std::make_shared<C2ReflectorHelper>()),
+      mInterface(mReflector),
+      mCodec2FactoryFuncs(funcs) {
+
+    for(auto const& func: mCodec2FactoryFuncs) {
+        mComponents.emplace(std::get<0>(func), func);
+    }
 }
 
 c2_status_t C2PlatformComponentStore::copyBuffer(
@@ -1184,4 +1256,11 @@
     return store;
 }
 
+// For testing only
+std::shared_ptr<C2ComponentStore> GetTestComponentStore(
+        std::vector<std::tuple<C2String,
+        C2ComponentFactory::CreateCodec2FactoryFunc,
+        C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
+    return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
+}
 } // namespace android
diff --git a/media/codec2/vndk/include/C2DmaBufAllocator.h b/media/codec2/vndk/include/C2DmaBufAllocator.h
index abb8307..d84c8c6 100644
--- a/media/codec2/vndk/include/C2DmaBufAllocator.h
+++ b/media/codec2/vndk/include/C2DmaBufAllocator.h
@@ -84,6 +84,16 @@
     void setUsageMapper(const UsageMapperFn& mapper, uint64_t minUsage, uint64_t maxUsage,
                         uint64_t blockSize);
 
+    static bool system_uncached_supported(void) {
+        static int cached_result = -1;
+
+        if (cached_result == -1) {
+            struct stat buffer;
+            cached_result = (stat("/dev/dma_heap/system-uncached", &buffer) == 0);
+        }
+        return (cached_result == 1);
+    };
+
    private:
     c2_status_t mInit;
     BufferAllocator mBufferAllocator;
diff --git a/media/codec2/vndk/include/C2PlatformSupport.h b/media/codec2/vndk/include/C2PlatformSupport.h
index 4814494..6d351c2 100644
--- a/media/codec2/vndk/include/C2PlatformSupport.h
+++ b/media/codec2/vndk/include/C2PlatformSupport.h
@@ -144,6 +144,15 @@
 std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore();
 
 /**
+ * Returns the platform component store.
+ * NOTE: For testing only
+ * \retval nullptr if the platform component store could not be obtained
+ */
+std::shared_ptr<C2ComponentStore> GetTestComponentStore(
+        std::vector<std::tuple<C2String, C2ComponentFactory::CreateCodec2FactoryFunc,
+        C2ComponentFactory::DestroyCodec2FactoryFunc>>);
+
+/**
  * Sets the preferred component store in this process for the sole purpose of accessing its
  * interface. If this is not called, the default IComponentStore HAL (if exists) is the preferred
  * store for this purpose. If the default IComponentStore HAL is not present, the platform
diff --git a/media/codecs/amrwb/dec/src/wb_syn_filt.cpp b/media/codecs/amrwb/dec/src/wb_syn_filt.cpp
index d960322..f12828d 100644
--- a/media/codecs/amrwb/dec/src/wb_syn_filt.cpp
+++ b/media/codecs/amrwb/dec/src/wb_syn_filt.cpp
@@ -181,12 +181,14 @@
         L_tmp4  = fxp_mac_16by16(yy[(i<<2)+3  - j], a[j], L_tmp4);
 
         L_tmp1 = shl_int32(L_tmp1, 4);
+        L_tmp1 = L_tmp1 == INT32_MIN ? INT32_MIN + 1 : L_tmp1;
 
         y[(i<<2)] = yy[(i<<2)] = amr_wb_round(-L_tmp1);
 
         L_tmp2  = fxp_mac_16by16(yy[(i<<2)], a[1], L_tmp2);
 
         L_tmp2 = shl_int32(L_tmp2, 4);
+        L_tmp2 = L_tmp2 == INT32_MIN ? INT32_MIN + 1 : L_tmp2;
 
         y[(i<<2)+1] = yy[(i<<2)+1] = amr_wb_round(-L_tmp2);
 
@@ -197,12 +199,14 @@
         L_tmp3  = fxp_mac_16by16(yy[(i<<2) + 1], a[1], L_tmp3);
 
         L_tmp3 = shl_int32(L_tmp3, 4);
+        L_tmp3 = L_tmp3 == INT32_MIN ? INT32_MIN + 1 : L_tmp3;
 
         y[(i<<2)+2] = yy[(i<<2)+2] = amr_wb_round(-L_tmp3);
 
         L_tmp4  = fxp_mac_16by16(yy[(i<<2)+2], a[1], L_tmp4);
 
         L_tmp4 = shl_int32(L_tmp4, 4);
+        L_tmp4 = L_tmp4 == INT32_MIN ? INT32_MIN + 1 : L_tmp4;
 
         y[(i<<2)+3] = yy[(i<<2)+3] = amr_wb_round(-L_tmp4);
     }
diff --git a/media/codecs/g711/decoder/Android.bp b/media/codecs/g711/decoder/Android.bp
index efff60b..51f4c38 100644
--- a/media/codecs/g711/decoder/Android.bp
+++ b/media/codecs/g711/decoder/Android.bp
@@ -35,7 +35,13 @@
         ],
         cfi: true,
     },
-    apex_available: ["com.android.media.swcodec"],
+
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media.swcodec",
+        "test_com.android.media.swcodec",
+    ],
+
     min_sdk_version: "29",
 
     target: {
diff --git a/media/codecs/m4v_h263/dec/src/vop.cpp b/media/codecs/m4v_h263/dec/src/vop.cpp
index 335846c..7b32498 100644
--- a/media/codecs/m4v_h263/dec/src/vop.cpp
+++ b/media/codecs/m4v_h263/dec/src/vop.cpp
@@ -497,6 +497,13 @@
                 }
                 while ((qmat[*(zigzag_inv+i)] != 0) && (++i < 64));
 
+                /* qmatrix must have at least one non-zero value, which means
+                   i would be non-zero in valid cases */
+                if (i == 0)
+                {
+                    return PV_FAIL;
+                }
+
                 for (j = i; j < 64; j++)
                     qmat[*(zigzag_inv+j)] = qmat[*(zigzag_inv+i-1)];
             }
@@ -520,6 +527,13 @@
                 }
                 while ((qmat[*(zigzag_inv+i)] != 0) && (++i < 64));
 
+                /* qmatrix must have at least one non-zero value, which means
+                   i would be non-zero in valid cases */
+                if (i == 0)
+                {
+                    return PV_FAIL;
+                }
+
                 for (j = i; j < 64; j++)
                     qmat[*(zigzag_inv+j)] = qmat[*(zigzag_inv+i-1)];
             }
diff --git a/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
index 7ab8f45..30e4fda 100644
--- a/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
+++ b/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
@@ -491,6 +491,9 @@
     }
     for (i = 0; i < encParams->nLayers; i++)
     {
+        if (encOption->encHeight[i] == 0 || encOption->encWidth[i] == 0 ||
+                encOption->encHeight[i] % 16 != 0 || encOption->encWidth[i] % 16 != 0)
+            goto CLEAN_UP;
         encParams->LayerHeight[i] = encOption->encHeight[i];
         encParams->LayerWidth[i] = encOption->encWidth[i];
     }
diff --git a/media/codecs/mp3dec/Android.bp b/media/codecs/mp3dec/Android.bp
index 1acf0a6..f84da21 100644
--- a/media/codecs/mp3dec/Android.bp
+++ b/media/codecs/mp3dec/Android.bp
@@ -1,3 +1,18 @@
+cc_library_headers {
+    name: "libstagefright_mp3dec_headers",
+    vendor_available: true,
+    min_sdk_version: "29",
+    host_supported:true,
+    export_include_dirs: [
+        "include",
+        "src",
+    ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media.swcodec",
+    ],
+}
+
 cc_library_static {
     name: "libstagefright_mp3dec",
     vendor_available: true,
@@ -65,10 +80,8 @@
 
     include_dirs: ["frameworks/av/media/libstagefright/include"],
 
-    export_include_dirs: [
-        "include",
-        "src",
-    ],
+    header_libs: ["libstagefright_mp3dec_headers"],
+    export_header_lib_headers: ["libstagefright_mp3dec_headers"],
 
     cflags: [
         "-DOSCL_UNUSED_ARG(x)=(void)(x)",
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index 0617e88..ec7cb24 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -561,6 +561,8 @@
         AMediaFormat_setString(mFileMetadata,
                 AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC);
     }
+    mMaxBufferSize = getMaxBlockSize() * getChannels() * getOutputSampleSize();
+    AMediaFormat_setInt32(mTrackMetadata, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, mMaxBufferSize);
     return OK;
 }
 
@@ -568,8 +570,6 @@
 {
     CHECK(mGroup == NULL);
     mGroup = group;
-    mMaxBufferSize = getMaxBlockSize() * getChannels() * getOutputSampleSize();
-    AMediaFormat_setInt32(mTrackMetadata, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, mMaxBufferSize);
     mGroup->add_buffer(mMaxBufferSize);
 }
 
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index ded3d1a..444664c 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -80,13 +80,15 @@
 
     Vector<uint32_t> thumbnails;
     Vector<uint32_t> dimgRefs;
-    Vector<uint32_t> cdscRefs;
+    Vector<uint32_t> exifRefs;
+    Vector<uint32_t> xmpRefs;
     size_t nextTileIndex;
 };
 
-struct ExifItem {
+struct ExternalMetaItem {
     off64_t offset;
     size_t size;
+    bool isExif;
 };
 
 /////////////////////////////////////////////////////////////////////
@@ -482,7 +484,7 @@
 
     void apply(
             KeyedVector<uint32_t, ImageItem> &itemIdToItemMap,
-            KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const;
+            KeyedVector<uint32_t, ExternalMetaItem> &itemIdToMetaMap) const;
 
 private:
     uint32_t mItemId;
@@ -494,7 +496,7 @@
 
 void ItemReference::apply(
         KeyedVector<uint32_t, ImageItem> &itemIdToItemMap,
-        KeyedVector<uint32_t, ExifItem> &itemIdToExifMap) const {
+        KeyedVector<uint32_t, ExternalMetaItem> &itemIdToMetaMap) const {
     ALOGV("attach reference type 0x%x to item id %d)", type(), mItemId);
 
     switch(type()) {
@@ -556,15 +558,15 @@
         break;
     }
     case FOURCC("cdsc"): {
-        ssize_t itemIndex = itemIdToExifMap.indexOfKey(mItemId);
+        ssize_t metaIndex = itemIdToMetaMap.indexOfKey(mItemId);
 
-        // ignore non-exif block items
-        if (itemIndex < 0) {
+        // ignore non-meta items
+        if (metaIndex < 0) {
             return;
         }
 
         for (size_t i = 0; i < mRefs.size(); i++) {
-            itemIndex = itemIdToItemMap.indexOfKey(mRefs[i]);
+            ssize_t itemIndex = itemIdToItemMap.indexOfKey(mRefs[i]);
 
             // ignore non-image items
             if (itemIndex < 0) {
@@ -572,7 +574,11 @@
             }
             ALOGV("Image item id %d uses metadata item id %d", mRefs[i], mItemId);
             ImageItem &image = itemIdToItemMap.editValueAt(itemIndex);
-            image.cdscRefs.push_back(mItemId);
+            if (itemIdToMetaMap[metaIndex].isExif) {
+                image.exifRefs.push_back(mItemId);
+            } else {
+                image.xmpRefs.push_back(mItemId);
+            }
         }
         break;
     }
@@ -1065,7 +1071,21 @@
 struct ItemInfo {
     uint32_t itemId;
     uint32_t itemType;
+    String8 contentType;
     bool hidden;
+
+    bool isXmp() const {
+        return itemType == FOURCC("mime") && contentType == String8("application/rdf+xml");
+    }
+    bool isExif() const {
+        return itemType == FOURCC("Exif");
+    }
+    bool isGrid() const {
+        return itemType == FOURCC("grid");
+    }
+    bool isSample() const {
+        return itemType == FOURCC("av01") || itemType == FOURCC("hvc1");
+    }
 };
 
 struct InfeBox : public FullBox {
@@ -1155,6 +1175,7 @@
             if (!parseNullTerminatedString(&offset, &size, &content_type)) {
                 return ERROR_MALFORMED;
             }
+            itemInfo->contentType = content_type;
 
             // content_encoding is optional; can be omitted if would be empty
             if (size > 0) {
@@ -1175,18 +1196,18 @@
 
 struct IinfBox : public FullBox {
     IinfBox(DataSourceHelper *source, Vector<ItemInfo> *itemInfos) :
-        FullBox(source, FOURCC("iinf")), mItemInfos(itemInfos) {}
+        FullBox(source, FOURCC("iinf")), mItemInfos(itemInfos), mNeedIref(false) {}
 
     status_t parse(off64_t offset, size_t size);
 
-    bool hasFourCC(uint32_t type) { return mFourCCSeen.count(type) > 0; }
+    bool needIrefBox() { return mNeedIref; }
 
 protected:
     status_t onChunkData(uint32_t type, off64_t offset, size_t size) override;
 
 private:
     Vector<ItemInfo> *mItemInfos;
-    std::unordered_set<uint32_t> mFourCCSeen;
+    bool mNeedIref;
 };
 
 status_t IinfBox::parse(off64_t offset, size_t size) {
@@ -1233,7 +1254,7 @@
     status_t err = infeBox.parse(offset, size, &itemInfo);
     if (err == OK) {
         mItemInfos->push_back(itemInfo);
-        mFourCCSeen.insert(itemInfo.itemType);
+        mNeedIref |= (itemInfo.isExif() || itemInfo.isXmp() || itemInfo.isGrid());
     }
     // InfeBox parse returns ERROR_UNSUPPORTED if the box if an unsupported
     // version. Ignore this error as it's not fatal.
@@ -1323,7 +1344,7 @@
         return err;
     }
 
-    if (iinfBox.hasFourCC(FOURCC("grid")) || iinfBox.hasFourCC(FOURCC("Exif"))) {
+    if (iinfBox.needIrefBox()) {
         mRequiredBoxes.insert('iref');
     }
 
@@ -1399,12 +1420,9 @@
 
         // Only handle 3 types of items, all others are ignored:
         //   'grid': derived image from tiles
-        //   'hvc1': coded image (or tile)
-        //   'Exif': EXIF metadata
-        if (info.itemType != FOURCC("grid") &&
-            info.itemType != FOURCC("hvc1") &&
-            info.itemType != FOURCC("Exif") &&
-            info.itemType != FOURCC("av01")) {
+        //   'hvc1' or 'av01': coded image (or tile)
+        //   'Exif' or XMP: metadata
+        if (!info.isGrid() && !info.isSample() && !info.isExif() && !info.isXmp()) {
             continue;
         }
 
@@ -1427,15 +1445,18 @@
             return ERROR_MALFORMED;
         }
 
-        if (info.itemType == FOURCC("Exif")) {
-            // Only add if the Exif data is non-empty. The first 4 bytes contain
+        if (info.isExif() || info.isXmp()) {
+            // Only add if the meta is non-empty. For Exif, the first 4 bytes contain
             // the offset to TIFF header, which the Exif parser doesn't use.
-            if (size > 4) {
-                ExifItem exifItem = {
+            ALOGV("adding meta to mItemIdToMetaMap: isExif %d, offset %lld, size %lld",
+                    info.isExif(), (long long)offset, (long long)size);
+            if ((info.isExif() && size > 4) || (info.isXmp() && size > 0)) {
+                ExternalMetaItem metaItem = {
+                        .isExif = info.isExif(),
                         .offset = offset,
                         .size = size,
                 };
-                mItemIdToExifMap.add(info.itemId, exifItem);
+                mItemIdToMetaMap.add(info.itemId, metaItem);
             }
             continue;
         }
@@ -1470,7 +1491,7 @@
     }
 
     for (size_t i = 0; i < mItemReferences.size(); i++) {
-        mItemReferences[i]->apply(mItemIdToItemMap, mItemIdToExifMap);
+        mItemReferences[i]->apply(mItemIdToItemMap, mItemIdToMetaMap);
     }
 
     bool foundPrimary = false;
@@ -1747,11 +1768,11 @@
     }
 
     const ImageItem &image = mItemIdToItemMap[itemIndex];
-    if (image.cdscRefs.size() == 0) {
+    if (image.exifRefs.size() == 0) {
         return NAME_NOT_FOUND;
     }
 
-    ssize_t exifIndex = mItemIdToExifMap.indexOfKey(image.cdscRefs[0]);
+    ssize_t exifIndex = mItemIdToMetaMap.indexOfKey(image.exifRefs[0]);
     if (exifIndex < 0) {
         return NAME_NOT_FOUND;
     }
@@ -1759,7 +1780,7 @@
     // skip the first 4-byte of the offset to TIFF header
     uint32_t tiffOffset;
     if (!mDataSource->readAt(
-            mItemIdToExifMap[exifIndex].offset, &tiffOffset, 4)) {
+            mItemIdToMetaMap[exifIndex].offset, &tiffOffset, 4)) {
         return ERROR_IO;
     }
 
@@ -1772,16 +1793,43 @@
     // exif data. The size of the item should be > 4 for a non-empty exif (this
     // was already checked when the item was added). Also check that the tiff
     // header offset is valid.
-    if (mItemIdToExifMap[exifIndex].size <= 4 ||
-            tiffOffset > mItemIdToExifMap[exifIndex].size - 4) {
+    if (mItemIdToMetaMap[exifIndex].size <= 4 ||
+            tiffOffset > mItemIdToMetaMap[exifIndex].size - 4) {
         return ERROR_MALFORMED;
     }
 
     // Offset of 'Exif\0\0' relative to the beginning of 'Exif' item
     // (first 4-byte is the tiff header offset)
     uint32_t exifOffset = 4 + tiffOffset - 6;
-    *offset = mItemIdToExifMap[exifIndex].offset + exifOffset;
-    *size = mItemIdToExifMap[exifIndex].size - exifOffset;
+    *offset = mItemIdToMetaMap[exifIndex].offset + exifOffset;
+    *size = mItemIdToMetaMap[exifIndex].size - exifOffset;
+    return OK;
+}
+
+status_t ItemTable::getXmpOffsetAndSize(off64_t *offset, size_t *size) {
+    if (!mImageItemsValid) {
+        return INVALID_OPERATION;
+    }
+
+    ssize_t itemIndex = mItemIdToItemMap.indexOfKey(mPrimaryItemId);
+
+    // this should not happen, something's seriously wrong.
+    if (itemIndex < 0) {
+        return INVALID_OPERATION;
+    }
+
+    const ImageItem &image = mItemIdToItemMap[itemIndex];
+    if (image.xmpRefs.size() == 0) {
+        return NAME_NOT_FOUND;
+    }
+
+    ssize_t xmpIndex = mItemIdToMetaMap.indexOfKey(image.xmpRefs[0]);
+    if (xmpIndex < 0) {
+        return NAME_NOT_FOUND;
+    }
+
+    *offset = mItemIdToMetaMap[xmpIndex].offset;
+    *size = mItemIdToMetaMap[xmpIndex].size;
     return OK;
 }
 
diff --git a/media/extractors/mp4/ItemTable.h b/media/extractors/mp4/ItemTable.h
index b19dc18..62826b6 100644
--- a/media/extractors/mp4/ItemTable.h
+++ b/media/extractors/mp4/ItemTable.h
@@ -34,7 +34,7 @@
 
 struct AssociationEntry;
 struct ImageItem;
-struct ExifItem;
+struct ExternalMetaItem;
 struct ItemLoc;
 struct ItemInfo;
 struct ItemProperty;
@@ -59,6 +59,7 @@
     status_t getImageOffsetAndSize(
             uint32_t *itemIndex, off64_t *offset, size_t *size);
     status_t getExifOffsetAndSize(off64_t *offset, size_t *size);
+    status_t getXmpOffsetAndSize(off64_t *offset, size_t *size);
 
 protected:
     ~ItemTable();
@@ -84,7 +85,7 @@
     bool mImageItemsValid;
     uint32_t mCurrentItemIndex;
     KeyedVector<uint32_t, ImageItem> mItemIdToItemMap;
-    KeyedVector<uint32_t, ExifItem> mItemIdToExifMap;
+    KeyedVector<uint32_t, ExternalMetaItem> mItemIdToMetaMap;
     Vector<uint32_t> mDisplayables;
 
     status_t parseIlocBox(off64_t offset, size_t size);
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 7989d4b..221bf4f 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -681,6 +681,19 @@
             AMediaFormat_setInt64(mFileMetaData,
                     AMEDIAFORMAT_KEY_EXIF_SIZE, (int64_t)exifSize);
         }
+        off64_t xmpOffset;
+        size_t xmpSize;
+        if (mItemTable->getXmpOffsetAndSize(&xmpOffset, &xmpSize) == OK) {
+            // TODO(chz): b/175717339
+            // Use a hard-coded string here instead of named keys. The keys are available
+            // only on API 31+. The mp4 extractor is part of mainline and has min_sdk_version
+            // of 29. This hard-coded string can be replaced with the named constant once
+            // the mp4 extractor is built against API 31+.
+            AMediaFormat_setInt64(mFileMetaData,
+                    "xmp-offset" /*AMEDIAFORMAT_KEY_XMP_OFFSET*/, (int64_t)xmpOffset);
+            AMediaFormat_setInt64(mFileMetaData,
+                    "xmp-size" /*AMEDIAFORMAT_KEY_XMP_SIZE*/, (int64_t)xmpSize);
+        }
         for (uint32_t imageIndex = 0;
                 imageIndex < mItemTable->countImages(); imageIndex++) {
             AMediaFormat *meta = mItemTable->getImageMeta(imageIndex);
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index 62f0808..eb2246d 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -43,9 +43,6 @@
     long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
 }
 
-static constexpr int OGG_PAGE_FLAG_CONTINUED_PACKET = 1;
-static constexpr int OGG_PAGE_FLAG_END_OF_STREAM = 4;
-
 namespace android {
 
 struct OggSource : public MediaTrackHelper {
@@ -300,8 +297,7 @@
     AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
 
     *out = packet;
-    ALOGV("returning buffer %p, size %zu, length %zu",
-          packet, packet->size(), packet->range_length());
+    ALOGV("returning buffer %p", packet);
     return AMEDIA_OK;
 }
 
@@ -362,10 +358,10 @@
 
         if (!memcmp(signature, "OggS", 4)) {
             if (*pageOffset > startOffset) {
-                ALOGV("skipped %lld bytes of junk at %lld to reach next frame",
-                     (long long)(*pageOffset - startOffset), (long long)(startOffset));
+                ALOGV("skipped %lld bytes of junk to reach next frame",
+                     (long long)(*pageOffset - startOffset));
             }
-            ALOGV("found frame at %lld", (long long)(*pageOffset));
+
             return OK;
         }
 
@@ -633,8 +629,7 @@
     // Calculate timestamps by accumulating durations starting from the first sample of a page;
     // We assume that we only seek to page boundaries.
     AMediaFormat *meta = (*out)->meta_data();
-    if (AMediaFormat_getInt32(meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, &currentPageSamples) &&
-            (mCurrentPage.mFlags & OGG_PAGE_FLAG_END_OF_STREAM)) {
+    if (AMediaFormat_getInt32(meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, &currentPageSamples)) {
         // first packet in page
         if (mOffset == mFirstDataOffset) {
             currentPageSamples -= mStartGranulePosition;
@@ -817,7 +812,6 @@
             }
             buffer = tmp;
 
-            ALOGV("reading %zu bytes @ %zu", packetSize, size_t(dataOffset));
             ssize_t n = mSource->readAt(
                     dataOffset,
                     (uint8_t *)buffer->data() + buffer->range_length(),
@@ -836,9 +830,8 @@
 
             if (gotFullPacket) {
                 // We've just read the entire packet.
-                ALOGV("got full packet, size %zu", fullSize);
 
-                if (mFirstPacketInPage && (mCurrentPage.mFlags & OGG_PAGE_FLAG_END_OF_STREAM)) {
+                if (mFirstPacketInPage) {
                     AMediaFormat *meta = buffer->meta_data();
                     AMediaFormat_setInt32(
                             meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, mCurrentPageSamples);
@@ -871,9 +864,6 @@
             }
 
             // fall through, the buffer now contains the start of the packet.
-            ALOGV("have start of packet, getting rest");
-        } else {
-            ALOGV("moving to next page");
         }
 
         CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments);
@@ -909,10 +899,9 @@
         mNextLaceIndex = 0;
 
         if (buffer != NULL) {
-            if ((mCurrentPage.mFlags & OGG_PAGE_FLAG_CONTINUED_PACKET) == 0) {
+            if ((mCurrentPage.mFlags & 1) == 0) {
                 // This page does not continue the packet, i.e. the packet
                 // is already complete.
-                ALOGV("packet was already complete?!");
 
                 if (timeUs >= 0) {
                     AMediaFormat *meta = buffer->meta_data();
@@ -920,10 +909,8 @@
                 }
 
                 AMediaFormat *meta = buffer->meta_data();
-                if (mCurrentPage.mFlags & OGG_PAGE_FLAG_END_OF_STREAM) {
-                    AMediaFormat_setInt32(
-                            meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, mCurrentPageSamples);
-                }
+                AMediaFormat_setInt32(
+                        meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, mCurrentPageSamples);
                 mFirstPacketInPage = false;
 
                 *out = buffer;
@@ -942,7 +929,6 @@
     for (size_t i = 0; i < mNumHeaders; ++i) {
         // ignore timestamp for configuration packets
         if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != AMEDIA_OK) {
-            ALOGV("readNextPacket failed");
             return err;
         }
         ALOGV("read packet of size %zu\n", packet->range_length());
@@ -1022,10 +1008,6 @@
 
     size_t size = buffer->range_length();
 
-    if (size == 0) {
-        return 0;
-    }
-
     ogg_buffer buf;
     buf.data = (uint8_t *)data;
     buf.size = size;
diff --git a/media/libaaudio/Android.bp b/media/libaaudio/Android.bp
index e81ab06..7796ed5 100644
--- a/media/libaaudio/Android.bp
+++ b/media/libaaudio/Android.bp
@@ -32,6 +32,6 @@
 cc_library_headers {
     name: "libaaudio_headers",
     export_include_dirs: ["include"],
-    export_header_lib_headers: ["aaudio-aidl-cpp"],
-    header_libs: ["aaudio-aidl-cpp"],
+    export_shared_lib_headers: ["aaudio-aidl-cpp"],
+    shared_libs: ["aaudio-aidl-cpp"],
 }
diff --git a/media/libaaudio/src/binding/AAudioBinderAdapter.cpp b/media/libaaudio/src/binding/AAudioBinderAdapter.cpp
index 2b2fe6d..6e3a1c8 100644
--- a/media/libaaudio/src/binding/AAudioBinderAdapter.cpp
+++ b/media/libaaudio/src/binding/AAudioBinderAdapter.cpp
@@ -15,10 +15,12 @@
  */
 
 #include <binding/AAudioBinderAdapter.h>
+#include <media/AidlConversionUtil.h>
 #include <utility/AAudioUtilities.h>
 
 namespace aaudio {
 
+using android::aidl_utils::statusTFromBinderStatus;
 using android::binder::Status;
 
 AAudioBinderAdapter::AAudioBinderAdapter(IAAudioService* delegate)
@@ -36,7 +38,7 @@
                                           &params,
                                           &result);
     if (!status.isOk()) {
-        result = AAudioConvert_androidToAAudioResult(status.transactionError());
+        result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
     }
     config = params;
     return result;
@@ -46,7 +48,7 @@
     aaudio_result_t result;
     Status status = mDelegate->closeStream(streamHandle, &result);
     if (!status.isOk()) {
-        result = AAudioConvert_androidToAAudioResult(status.transactionError());
+        result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
     }
     return result;
 }
@@ -59,7 +61,7 @@
                                                     &endpoint,
                                                     &result);
     if (!status.isOk()) {
-        result = AAudioConvert_androidToAAudioResult(status.transactionError());
+        result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
     }
     endpointOut = std::move(endpoint);
     return result;
@@ -69,7 +71,7 @@
     aaudio_result_t result;
     Status status = mDelegate->startStream(streamHandle, &result);
     if (!status.isOk()) {
-        result = AAudioConvert_androidToAAudioResult(status.transactionError());
+        result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
     }
     return result;
 }
@@ -78,7 +80,7 @@
     aaudio_result_t result;
     Status status = mDelegate->pauseStream(streamHandle, &result);
     if (!status.isOk()) {
-        result = AAudioConvert_androidToAAudioResult(status.transactionError());
+        result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
     }
     return result;
 }
@@ -87,7 +89,7 @@
     aaudio_result_t result;
     Status status = mDelegate->stopStream(streamHandle, &result);
     if (!status.isOk()) {
-        result = AAudioConvert_androidToAAudioResult(status.transactionError());
+        result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
     }
     return result;
 }
@@ -96,7 +98,7 @@
     aaudio_result_t result;
     Status status = mDelegate->flushStream(streamHandle, &result);
     if (!status.isOk()) {
-        result = AAudioConvert_androidToAAudioResult(status.transactionError());
+        result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
     }
     return result;
 }
@@ -107,7 +109,7 @@
     aaudio_result_t result;
     Status status = mDelegate->registerAudioThread(streamHandle, clientThreadId, periodNanoseconds, &result);
     if (!status.isOk()) {
-        result = AAudioConvert_androidToAAudioResult(status.transactionError());
+        result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
     }
     return result;
 }
@@ -117,7 +119,7 @@
     aaudio_result_t result;
     Status status = mDelegate->unregisterAudioThread(streamHandle, clientThreadId, &result);
     if (!status.isOk()) {
-        result = AAudioConvert_androidToAAudioResult(status.transactionError());
+        result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
     }
     return result;
 }
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 57c4c16..431f0fa 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -171,7 +171,7 @@
     aaudio_result_t result = requestStart_l();
     if (result == AAUDIO_OK) {
         // We only call this for logging in "dumpsys audio". So ignore return code.
-        (void) mPlayerBase->start();
+        (void) mPlayerBase->startWithStatus(getDeviceId());
     }
     return result;
 }
@@ -221,7 +221,7 @@
     aaudio_result_t result = requestPause_l();
     if (result == AAUDIO_OK) {
         // We only call this for logging in "dumpsys audio". So ignore return code.
-        (void) mPlayerBase->pause();
+        (void) mPlayerBase->pauseWithStatus();
     }
     return result;
 }
@@ -251,7 +251,7 @@
     aaudio_result_t result = safeStop_l();
     if (result == AAUDIO_OK) {
         // We only call this for logging in "dumpsys audio". So ignore return code.
-        (void) mPlayerBase->stop();
+        (void) mPlayerBase->stopWithStatus();
     }
     return result;
 }
@@ -265,7 +265,7 @@
     aaudio_result_t result = safeStop_l();
     if (result == AAUDIO_OK) {
         // We only call this for logging in "dumpsys audio". So ignore return code.
-        (void) mPlayerBase->stop();
+        (void) mPlayerBase->stopWithStatus();
     }
     return result;
 }
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 1d036d0..af8ff19 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -558,7 +558,7 @@
         if (status < 0) { // a non-negative value is the volume shaper id.
             ALOGE("applyVolumeShaper() failed with status %d", status);
         }
-        return binder::Status::fromStatusT(status);
+        return aidl_utils::binderStatusFromStatusT(status);
     } else {
         ALOGD("applyVolumeShaper()"
                       " no AudioTrack for volume control from IPlayer");
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index f11f184..31c071e 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -117,56 +117,58 @@
 
 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;
-                default:
-                    break;
             }
             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;
-                default:
-                    break;
             }
             break;
-        default:
-            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;
-                default:
-                    break;
             }
             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;
-                default:
-                    break;
             }
             break;
-        default:
-            break;
     }
     return unexpected(BAD_VALUE);
 }
@@ -236,6 +238,14 @@
     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);
 }
@@ -268,8 +278,9 @@
     return std::string(legacy.c_str());
 }
 
-// The legacy enum is unnamed. Thus, we use int.
-ConversionResult<int> aidl2legacy_AudioPortConfigType(media::AudioPortConfigType aidl) {
+// The legacy enum is unnamed. Thus, we use int32_t.
+ConversionResult<int32_t> aidl2legacy_AudioPortConfigType_int32_t(
+        media::AudioPortConfigType aidl) {
     switch (aidl) {
         case media::AudioPortConfigType::SAMPLE_RATE:
             return AUDIO_PORT_CONFIG_SAMPLE_RATE;
@@ -285,8 +296,9 @@
     return unexpected(BAD_VALUE);
 }
 
-// The legacy enum is unnamed. Thus, we use int.
-ConversionResult<media::AudioPortConfigType> legacy2aidl_AudioPortConfigType(int legacy) {
+// The legacy enum is unnamed. Thus, we use int32_t.
+ConversionResult<media::AudioPortConfigType> legacy2aidl_int32_t_AudioPortConfigType(
+        int32_t legacy) {
     switch (legacy) {
         case AUDIO_PORT_CONFIG_SAMPLE_RATE:
             return media::AudioPortConfigType::SAMPLE_RATE;
@@ -304,7 +316,7 @@
 
 ConversionResult<unsigned int> aidl2legacy_int32_t_config_mask(int32_t aidl) {
     return convertBitmask<unsigned int, int32_t, int, media::AudioPortConfigType>(
-            aidl, aidl2legacy_AudioPortConfigType,
+            aidl, aidl2legacy_AudioPortConfigType_int32_t,
             // AudioPortConfigType enum is index-based.
             index2enum_index<media::AudioPortConfigType>,
             // AUDIO_PORT_CONFIG_* flags are mask-based.
@@ -313,7 +325,7 @@
 
 ConversionResult<int32_t> legacy2aidl_config_mask_int32_t(unsigned int legacy) {
     return convertBitmask<int32_t, unsigned int, media::AudioPortConfigType, int>(
-            legacy, legacy2aidl_AudioPortConfigType,
+            legacy, legacy2aidl_int32_t_AudioPortConfigType,
             // AUDIO_PORT_CONFIG_* flags are mask-based.
             index2enum_bitmask<unsigned>,
             // AudioPortConfigType enum is index-based.
@@ -355,9 +367,8 @@
             return AUDIO_INPUT_CONFIG_CHANGED;
         case media::AudioIoConfigEvent::CLIENT_STARTED:
             return AUDIO_CLIENT_STARTED;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<media::AudioIoConfigEvent> legacy2aidl_audio_io_config_event_AudioIoConfigEvent(
@@ -381,9 +392,8 @@
             return media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED;
         case AUDIO_CLIENT_STARTED:
             return media::AudioIoConfigEvent::CLIENT_STARTED;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<audio_port_role_t> aidl2legacy_AudioPortRole_audio_port_role_t(
@@ -395,9 +405,8 @@
             return AUDIO_PORT_ROLE_SOURCE;
         case media::AudioPortRole::SINK:
             return AUDIO_PORT_ROLE_SINK;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<media::AudioPortRole> legacy2aidl_audio_port_role_t_AudioPortRole(
@@ -409,9 +418,8 @@
             return media::AudioPortRole::SOURCE;
         case AUDIO_PORT_ROLE_SINK:
             return media::AudioPortRole::SINK;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<audio_port_type_t> aidl2legacy_AudioPortType_audio_port_type_t(
@@ -425,9 +433,8 @@
             return AUDIO_PORT_TYPE_MIX;
         case media::AudioPortType::SESSION:
             return AUDIO_PORT_TYPE_SESSION;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<media::AudioPortType> legacy2aidl_audio_port_type_t_AudioPortType(
@@ -441,9 +448,8 @@
             return media::AudioPortType::MIX;
         case AUDIO_PORT_TYPE_SESSION:
             return media::AudioPortType::SESSION;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<audio_format_t> aidl2legacy_AudioFormat_audio_format_t(
@@ -468,9 +474,8 @@
             return AUDIO_GAIN_MODE_CHANNELS;
         case media::AudioGainMode::RAMP:
             return AUDIO_GAIN_MODE_RAMP;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<media::AudioGainMode> legacy2aidl_audio_gain_mode_t_AudioGainMode(audio_gain_mode_t legacy) {
@@ -481,9 +486,8 @@
             return media::AudioGainMode::CHANNELS;
         case AUDIO_GAIN_MODE_RAMP:
             return media::AudioGainMode::RAMP;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl) {
@@ -495,7 +499,7 @@
             enumToMask_bitmask<audio_gain_mode_t, audio_gain_mode_t>);
 }
 
-ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_mask_int32_t(audio_gain_mode_t legacy) {
+ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy) {
     return convertBitmask<int32_t, audio_gain_mode_t, media::AudioGainMode, audio_gain_mode_t>(
             legacy, legacy2aidl_audio_gain_mode_t_AudioGainMode,
             // AUDIO_GAIN_MODE_* constants are mask-based.
@@ -540,7 +544,7 @@
         const audio_gain_config& legacy, audio_port_role_t role, audio_port_type_t type) {
     media::AudioGainConfig aidl;
     aidl.index = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.index));
-    aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_mask_int32_t(legacy.mode));
+    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_int32_t(legacy.channel_mask));
     const bool isInput = VALUE_OR_RETURN(direction(role, type)) == Direction::INPUT;
@@ -575,14 +579,15 @@
             return AUDIO_INPUT_FLAG_HW_AV_SYNC;
         case media::AudioInputFlags::DIRECT:
             return AUDIO_INPUT_FLAG_DIRECT;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<media::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 media::AudioInputFlags::FAST;
         case AUDIO_INPUT_FLAG_HW_HOTWORD:
@@ -599,9 +604,8 @@
             return media::AudioInputFlags::HW_AV_SYNC;
         case AUDIO_INPUT_FLAG_DIRECT:
             return media::AudioInputFlags::DIRECT;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
@@ -637,14 +641,17 @@
             return AUDIO_OUTPUT_FLAG_VOIP_RX;
         case media::AudioOutputFlags::INCALL_MUSIC:
             return AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
-        default:
-            return unexpected(BAD_VALUE);
+        case media::AudioOutputFlags::GAPLESS_OFFLOAD:
+            return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<media::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 media::AudioOutputFlags::DIRECT;
         case AUDIO_OUTPUT_FLAG_PRIMARY:
@@ -675,12 +682,14 @@
             return media::AudioOutputFlags::VOIP_RX;
         case AUDIO_OUTPUT_FLAG_INCALL_MUSIC:
             return media::AudioOutputFlags::INCALL_MUSIC;
-        default:
-            return unexpected(BAD_VALUE);
+        case AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD:
+            return media::AudioOutputFlags::GAPLESS_OFFLOAD;
     }
+    return unexpected(BAD_VALUE);
 }
 
-ConversionResult<audio_input_flags_t> aidl2legacy_audio_input_flags_mask(int32_t aidl) {
+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(
@@ -691,7 +700,8 @@
     return static_cast<audio_input_flags_t>(converted);
 }
 
-ConversionResult<int32_t> legacy2aidl_audio_input_flags_mask(audio_input_flags_t legacy) {
+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);
@@ -701,7 +711,8 @@
             enumToMask_index<int32_t, media::AudioInputFlags>);
 }
 
-ConversionResult<audio_output_flags_t> aidl2legacy_audio_output_flags_mask(int32_t aidl) {
+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,
@@ -711,7 +722,8 @@
             enumToMask_bitmask<audio_output_flags_t, audio_output_flags_t>);
 }
 
-ConversionResult<int32_t> legacy2aidl_audio_output_flags_mask(audio_output_flags_t legacy) {
+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);
@@ -728,13 +740,15 @@
     switch (dir) {
         case Direction::INPUT: {
             legacy.input = VALUE_OR_RETURN(
-                    aidl2legacy_audio_input_flags_mask(VALUE_OR_RETURN(UNION_GET(aidl, input))));
+                    aidl2legacy_int32_t_audio_input_flags_t_mask(
+                            VALUE_OR_RETURN(UNION_GET(aidl, input))));
         }
             break;
 
         case Direction::OUTPUT: {
             legacy.output = VALUE_OR_RETURN(
-                    aidl2legacy_audio_output_flags_mask(VALUE_OR_RETURN(UNION_GET(aidl, output))));
+                    aidl2legacy_int32_t_audio_output_flags_t_mask(
+                            VALUE_OR_RETURN(UNION_GET(aidl, output))));
         }
             break;
     }
@@ -750,17 +764,20 @@
     switch (dir) {
         case Direction::INPUT:
             UNION_SET(aidl, input,
-                      VALUE_OR_RETURN(legacy2aidl_audio_input_flags_mask(legacy.input)));
+                      VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(
+                              legacy.input)));
             break;
         case Direction::OUTPUT:
             UNION_SET(aidl, output,
-                      VALUE_OR_RETURN(legacy2aidl_audio_output_flags_mask(legacy.output)));
+                      VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(
+                              legacy.output)));
             break;
     }
     return aidl;
 }
 
-ConversionResult<audio_port_config_device_ext> aidl2legacy_AudioPortConfigDeviceExt(
+ConversionResult<audio_port_config_device_ext>
+aidl2legacy_AudioPortConfigDeviceExt_audio_port_config_device_ext(
         const media::AudioPortConfigDeviceExt& aidl) {
     audio_port_config_device_ext legacy;
     legacy.hw_module = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_module_handle_t(aidl.hwModule));
@@ -769,7 +786,8 @@
     return legacy;
 }
 
-ConversionResult<media::AudioPortConfigDeviceExt> legacy2aidl_AudioPortConfigDeviceExt(
+ConversionResult<media::AudioPortConfigDeviceExt>
+legacy2aidl_audio_port_config_device_ext_AudioPortConfigDeviceExt(
         const audio_port_config_device_ext& legacy) {
     media::AudioPortConfigDeviceExt aidl;
     aidl.hwModule = VALUE_OR_RETURN(legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
@@ -814,9 +832,8 @@
             return AUDIO_STREAM_PATCH;
         case media::AudioStreamType::CALL_ASSISTANT:
             return AUDIO_STREAM_CALL_ASSISTANT;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<media::AudioStreamType> legacy2aidl_audio_stream_type_t_AudioStreamType(
@@ -854,9 +871,8 @@
             return media::AudioStreamType::PATCH;
         case AUDIO_STREAM_CALL_ASSISTANT:
             return media::AudioStreamType::CALL_ASSISTANT;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<audio_source_t> aidl2legacy_AudioSourceType_audio_source_t(
@@ -893,9 +909,8 @@
             return AUDIO_SOURCE_FM_TUNER;
         case media::AudioSourceType::HOTWORD:
             return AUDIO_SOURCE_HOTWORD;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<media::AudioSourceType> legacy2aidl_audio_source_t_AudioSourceType(
@@ -931,9 +946,8 @@
             return media::AudioSourceType::FM_TUNER;
         case AUDIO_SOURCE_HOTWORD:
             return media::AudioSourceType::HOTWORD;
-        default:
-            return unexpected(BAD_VALUE);
     }
+    return unexpected(BAD_VALUE);
 }
 
 ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl) {
@@ -955,24 +969,21 @@
         case media::AudioPortRole::NONE:
             // Just verify that the union is empty.
             VALUE_OR_RETURN(UNION_GET(aidl, unspecified));
-            break;
+            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))));
-            break;
+            return legacy;
 
         case media::AudioPortRole::SINK:
             // This is not a bug. A SINK role corresponds to the source field.
             legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSourceType_audio_source_t(
                     VALUE_OR_RETURN(UNION_GET(aidl, source))));
-            break;
-
-        default:
-            LOG_ALWAYS_FATAL("Shouldn't get here");
+            return legacy;
     }
-    return legacy;
+    LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
 }
 
 ConversionResult<media::AudioPortConfigMixExtUseCase> legacy2aidl_AudioPortConfigMixExtUseCase(
@@ -982,21 +993,19 @@
     switch (role) {
         case AUDIO_PORT_ROLE_NONE:
             UNION_SET(aidl, unspecified, false);
-            break;
+            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)));
-            break;
+            return aidl;
         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_AudioSourceType(legacy.source)));
-            break;
-        default:
-            LOG_ALWAYS_FATAL("Shouldn't get here");
+            return aidl;
     }
-    return aidl;
+    LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
 }
 
 ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortConfigMixExt(
@@ -1017,14 +1026,16 @@
     return aidl;
 }
 
-ConversionResult<audio_port_config_session_ext> aidl2legacy_AudioPortConfigSessionExt(
+ConversionResult<audio_port_config_session_ext>
+aidl2legacy_AudioPortConfigSessionExt_audio_port_config_session_ext(
         const media::AudioPortConfigSessionExt& aidl) {
     audio_port_config_session_ext legacy;
     legacy.session = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl.session));
     return legacy;
 }
 
-ConversionResult<media::AudioPortConfigSessionExt> legacy2aidl_AudioPortConfigSessionExt(
+ConversionResult<media::AudioPortConfigSessionExt>
+legacy2aidl_audio_port_config_session_ext_AudioPortConfigSessionExt(
         const audio_port_config_session_ext& legacy) {
     media::AudioPortConfigSessionExt aidl;
     aidl.session = VALUE_OR_RETURN(legacy2aidl_audio_session_t_int32_t(legacy.session));
@@ -1042,23 +1053,24 @@
         case media::AudioPortType::NONE:
             // Just verify that the union is empty.
             VALUE_OR_RETURN(UNION_GET(aidl, unspecified));
-            break;
+            return legacy;
         case media::AudioPortType::DEVICE:
             legacy.device = VALUE_OR_RETURN(
-                    aidl2legacy_AudioPortConfigDeviceExt(VALUE_OR_RETURN(UNION_GET(aidl, device))));
-            break;
+                    aidl2legacy_AudioPortConfigDeviceExt_audio_port_config_device_ext(
+                            VALUE_OR_RETURN(UNION_GET(aidl, device))));
+            return legacy;
         case media::AudioPortType::MIX:
             legacy.mix = VALUE_OR_RETURN(
                     aidl2legacy_AudioPortConfigMixExt(VALUE_OR_RETURN(UNION_GET(aidl, mix)), role));
-            break;
+            return legacy;
         case media::AudioPortType::SESSION:
-            legacy.session = VALUE_OR_RETURN(aidl2legacy_AudioPortConfigSessionExt(
-                    VALUE_OR_RETURN(UNION_GET(aidl, session))));
-            break;
-        default:
-            LOG_ALWAYS_FATAL("Shouldn't get here");
+            legacy.session = VALUE_OR_RETURN(
+                    aidl2legacy_AudioPortConfigSessionExt_audio_port_config_session_ext(
+                            VALUE_OR_RETURN(UNION_GET(aidl, session))));
+            return legacy;
+
     }
-    return legacy;
+    LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
 }
 
 ConversionResult<media::AudioPortConfigExt> legacy2aidl_AudioPortConfigExt(
@@ -1068,23 +1080,25 @@
     switch (type) {
         case AUDIO_PORT_TYPE_NONE:
             UNION_SET(aidl, unspecified, false);
-            break;
+            return aidl;
         case AUDIO_PORT_TYPE_DEVICE:
             UNION_SET(aidl, device,
-                      VALUE_OR_RETURN(legacy2aidl_AudioPortConfigDeviceExt(legacy.device)));
-            break;
+                      VALUE_OR_RETURN(
+                        legacy2aidl_audio_port_config_device_ext_AudioPortConfigDeviceExt(
+                          legacy.device)));
+            return aidl;
         case AUDIO_PORT_TYPE_MIX:
             UNION_SET(aidl, mix,
                       VALUE_OR_RETURN(legacy2aidl_AudioPortConfigMixExt(legacy.mix, role)));
-            break;
+            return aidl;
         case AUDIO_PORT_TYPE_SESSION:
             UNION_SET(aidl, session,
-                      VALUE_OR_RETURN(legacy2aidl_AudioPortConfigSessionExt(legacy.session)));
-            break;
-        default:
-            LOG_ALWAYS_FATAL("Shouldn't get here");
+                      VALUE_OR_RETURN(
+                        legacy2aidl_audio_port_config_session_ext_AudioPortConfigSessionExt(
+                          legacy.session)));
+            return aidl;
     }
-    return aidl;
+    LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
 }
 
 ConversionResult<audio_port_config> aidl2legacy_AudioPortConfig_audio_port_config(
@@ -1223,7 +1237,8 @@
     return aidl;
 }
 
-ConversionResult<AudioClient> aidl2legacy_AudioClient(const media::AudioClient& aidl) {
+ConversionResult<AudioClient> aidl2legacy_AudioClient_AudioClient(
+        const media::AudioClient& aidl) {
     AudioClient legacy;
     legacy.clientUid = VALUE_OR_RETURN(aidl2legacy_int32_t_uid_t(aidl.clientUid));
     legacy.clientPid = VALUE_OR_RETURN(aidl2legacy_int32_t_pid_t(aidl.clientPid));
@@ -1232,7 +1247,8 @@
     return legacy;
 }
 
-ConversionResult<media::AudioClient> legacy2aidl_AudioClient(const AudioClient& legacy) {
+ConversionResult<media::AudioClient> legacy2aidl_AudioClient_AudioClient(
+        const AudioClient& legacy) {
     media::AudioClient aidl;
     aidl.clientUid = VALUE_OR_RETURN(legacy2aidl_uid_t_int32_t(legacy.clientUid));
     aidl.clientPid = VALUE_OR_RETURN(legacy2aidl_pid_t_int32_t(legacy.clientPid));
@@ -1660,7 +1676,7 @@
 }
 
 ConversionResult<AudioTimestamp>
-aidl2legacy_AudioTimestamp(const media::AudioTimestampInternal& aidl) {
+aidl2legacy_AudioTimestampInternal_AudioTimestamp(const media::AudioTimestampInternal& aidl) {
     AudioTimestamp legacy;
     legacy.mPosition = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.position));
     legacy.mTime.tv_sec = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sec));
@@ -1669,7 +1685,7 @@
 }
 
 ConversionResult<media::AudioTimestampInternal>
-legacy2aidl_AudioTimestamp(const AudioTimestamp& legacy) {
+legacy2aidl_AudioTimestamp_AudioTimestampInternal(const AudioTimestamp& legacy) {
     media::AudioTimestampInternal aidl;
     aidl.position = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.mPosition));
     aidl.sec = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.mTime.tv_sec));
@@ -1900,25 +1916,24 @@
         case media::AudioPortType::NONE:
             // Just verify that the union is empty.
             VALUE_OR_RETURN(UNION_GET(aidl, unspecified));
-            break;
+            return legacy;
         case media::AudioPortType::DEVICE:
             legacy.device = VALUE_OR_RETURN(
                     aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
                             VALUE_OR_RETURN(UNION_GET(aidl, device))));
-            break;
+            return legacy;
         case media::AudioPortType::MIX:
             legacy.mix = VALUE_OR_RETURN(
                     aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
                             VALUE_OR_RETURN(UNION_GET(aidl, mix))));
-            break;
+            return legacy;
         case media::AudioPortType::SESSION:
             legacy.session = VALUE_OR_RETURN(aidl2legacy_AudioPortSessionExt_audio_port_session_ext(
                     VALUE_OR_RETURN(UNION_GET(aidl, session))));
-            break;
-        default:
-            LOG_ALWAYS_FATAL("Shouldn't get here");
+            return legacy;
+
     }
-    return legacy;
+    LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
 }
 
 ConversionResult<media::AudioPortExt> legacy2aidl_AudioPortExt(
@@ -1927,25 +1942,23 @@
     switch (type) {
         case AUDIO_PORT_TYPE_NONE:
             UNION_SET(aidl, unspecified, false);
-            break;
+            return aidl;
         case AUDIO_PORT_TYPE_DEVICE:
             UNION_SET(aidl, device,
                       VALUE_OR_RETURN(
                               legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(legacy.device)));
-            break;
+            return aidl;
         case AUDIO_PORT_TYPE_MIX:
             UNION_SET(aidl, mix,
                       VALUE_OR_RETURN(legacy2aidl_audio_port_mix_ext_AudioPortMixExt(legacy.mix)));
-            break;
+            return aidl;
         case AUDIO_PORT_TYPE_SESSION:
             UNION_SET(aidl, session,
                       VALUE_OR_RETURN(legacy2aidl_audio_port_session_ext_AudioPortSessionExt(
                               legacy.session)));
-            break;
-        default:
-            LOG_ALWAYS_FATAL("Shouldn't get here");
+            return aidl;
     }
-    return aidl;
+    LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
 }
 
 ConversionResult<audio_profile>
@@ -2012,7 +2025,7 @@
 ConversionResult<media::AudioGain>
 legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy) {
     media::AudioGain aidl;
-    aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_mask_int32_t(legacy.mode));
+    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_int32_t(legacy.channel_mask));
     aidl.minValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_value));
@@ -2082,4 +2095,106 @@
     return aidl;
 }
 
+ConversionResult<audio_mode_t>
+aidl2legacy_AudioMode_audio_mode_t(media::AudioMode aidl) {
+    switch (aidl) {
+        case media::AudioMode::INVALID:
+            return AUDIO_MODE_INVALID;
+        case media::AudioMode::CURRENT:
+            return AUDIO_MODE_CURRENT;
+        case media::AudioMode::NORMAL:
+            return AUDIO_MODE_NORMAL;
+        case media::AudioMode::RINGTONE:
+            return AUDIO_MODE_RINGTONE;
+        case media::AudioMode::IN_CALL:
+            return AUDIO_MODE_IN_CALL;
+        case media::AudioMode::IN_COMMUNICATION:
+            return AUDIO_MODE_IN_COMMUNICATION;
+        case media::AudioMode::CALL_SCREEN:
+            return AUDIO_MODE_CALL_SCREEN;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<media::AudioMode>
+legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_MODE_INVALID:
+            return media::AudioMode::INVALID;
+        case AUDIO_MODE_CURRENT:
+            return media::AudioMode::CURRENT;
+        case AUDIO_MODE_NORMAL:
+            return media::AudioMode::NORMAL;
+        case AUDIO_MODE_RINGTONE:
+            return media::AudioMode::RINGTONE;
+        case AUDIO_MODE_IN_CALL:
+            return media::AudioMode::IN_CALL;
+        case AUDIO_MODE_IN_COMMUNICATION:
+            return media::AudioMode::IN_COMMUNICATION;
+        case AUDIO_MODE_CALL_SCREEN:
+            return media::AudioMode::CALL_SCREEN;
+        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) {
+        case media::AudioUniqueIdUse::UNSPECIFIED:
+            return AUDIO_UNIQUE_ID_USE_UNSPECIFIED;
+        case media::AudioUniqueIdUse::SESSION:
+            return AUDIO_UNIQUE_ID_USE_SESSION;
+        case media::AudioUniqueIdUse::MODULE:
+            return AUDIO_UNIQUE_ID_USE_MODULE;
+        case media::AudioUniqueIdUse::EFFECT:
+            return AUDIO_UNIQUE_ID_USE_EFFECT;
+        case media::AudioUniqueIdUse::PATCH:
+            return AUDIO_UNIQUE_ID_USE_PATCH;
+        case media::AudioUniqueIdUse::OUTPUT:
+            return AUDIO_UNIQUE_ID_USE_OUTPUT;
+        case media::AudioUniqueIdUse::INPUT:
+            return AUDIO_UNIQUE_ID_USE_INPUT;
+        case media::AudioUniqueIdUse::CLIENT:
+            return AUDIO_UNIQUE_ID_USE_CLIENT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<media::AudioUniqueIdUse>
+legacy2aidl_audio_unique_id_use_t_AudioUniqueIdUse(audio_unique_id_use_t legacy) {
+    switch (legacy) {
+        case AUDIO_UNIQUE_ID_USE_UNSPECIFIED:
+            return media::AudioUniqueIdUse::UNSPECIFIED;
+        case AUDIO_UNIQUE_ID_USE_SESSION:
+            return media::AudioUniqueIdUse::SESSION;
+        case AUDIO_UNIQUE_ID_USE_MODULE:
+            return media::AudioUniqueIdUse::MODULE;
+        case AUDIO_UNIQUE_ID_USE_EFFECT:
+            return media::AudioUniqueIdUse::EFFECT;
+        case AUDIO_UNIQUE_ID_USE_PATCH:
+            return media::AudioUniqueIdUse::PATCH;
+        case AUDIO_UNIQUE_ID_USE_OUTPUT:
+            return media::AudioUniqueIdUse::OUTPUT;
+        case AUDIO_UNIQUE_ID_USE_INPUT:
+            return media::AudioUniqueIdUse::INPUT;
+        case AUDIO_UNIQUE_ID_USE_CLIENT:
+            return media::AudioUniqueIdUse::CLIENT;
+        case AUDIO_UNIQUE_ID_USE_MAX:
+            break;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<volume_group_t>
+aidl2legacy_int32_t_volume_group_t(int32_t aidl) {
+    return convertReinterpret<volume_group_t>(aidl);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_volume_group_t_int32_t(volume_group_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
 }  // namespace android
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index fa67898..aa740a7 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -15,10 +15,12 @@
     ],
     static_libs: [
         "audioflinger-aidl-unstable-cpp",
+        "audiopolicy-aidl-unstable-cpp",
         "av-types-aidl-unstable-cpp",
     ],
     export_static_lib_headers: [
         "audioflinger-aidl-unstable-cpp",
+        "audiopolicy-aidl-unstable-cpp",
         "av-types-aidl-unstable-cpp",
     ],
     target: {
@@ -56,9 +58,10 @@
         "audioflinger-aidl-unstable-cpp",
         "capture_state_listener-aidl-cpp",
     ],
+    header_libs: ["libaudioclient_headers"],
 }
 
-cc_library_shared {
+cc_library {
     name: "libaudioclient",
 
     aidl: {
@@ -82,7 +85,6 @@
         "AudioTrackShared.cpp",
         "IAudioFlinger.cpp",
         "IAudioPolicyService.cpp",
-        "IAudioPolicyServiceClient.cpp",
         "ToneGenerator.cpp",
         "PlayerBase.cpp",
         "RecordingActivityTracker.cpp",
@@ -91,6 +93,7 @@
     shared_libs: [
         "audioclient-types-aidl-unstable-cpp",
         "audioflinger-aidl-unstable-cpp",
+        "audiopolicy-aidl-unstable-cpp",
         "av-types-aidl-unstable-cpp",
         "capture_state_listener-aidl-cpp",
         "libaudioclient_aidl_conversion",
@@ -113,6 +116,7 @@
     ],
     export_shared_lib_headers: [
         "audioflinger-aidl-unstable-cpp",
+        "audiopolicy-aidl-unstable-cpp",
         "libbinder",
     ],
 
@@ -347,7 +351,9 @@
         "aidl/android/media/OpenInputResponse.aidl",
         "aidl/android/media/OpenOutputRequest.aidl",
         "aidl/android/media/OpenOutputResponse.aidl",
+        "aidl/android/media/RenderPosition.aidl",
 
+        "aidl/android/media/IAudioFlingerService.aidl",
         "aidl/android/media/IAudioFlingerClient.aidl",
         "aidl/android/media/IAudioRecord.aidl",
         "aidl/android/media/IAudioTrack.aidl",
@@ -371,3 +377,29 @@
         },
     },
 }
+
+aidl_interface {
+    name: "audiopolicy-aidl",
+    unstable: true,
+    local_include_dir: "aidl",
+    host_supported: true,
+    vendor_available: true,
+    srcs: [
+        "aidl/android/media/RecordClientInfo.aidl",
+
+        "aidl/android/media/IAudioPolicyServiceClient.aidl",
+    ],
+    imports: [
+        "audioclient-types-aidl",
+    ],
+    double_loadable: true,
+    backend: {
+        cpp: {
+            min_sdk_version: "29",
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.media",
+            ],
+        },
+    },
+}
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index ae899c0..79ea1bb 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -30,7 +30,7 @@
 #include <utils/Log.h>
 
 namespace android {
-
+using aidl_utils::statusTFromBinderStatus;
 using binder::Status;
 
 namespace {
@@ -262,7 +262,7 @@
             bs = mIEffect->disable(&status);
         }
         if (!bs.isOk()) {
-            status = bs.transactionError();
+            status = statusTFromBinderStatus(bs);
         }
         if (status == NO_ERROR) {
             mEnabled = enabled;
@@ -303,7 +303,7 @@
 
     Status bs = mIEffect->command(cmdCode, data, *replySize, &response, &status);
     if (!bs.isOk()) {
-        status = bs.transactionError();
+        status = statusTFromBinderStatus(bs);
     }
     if (status == NO_ERROR) {
         memcpy(replyData, response.data(), response.size());
@@ -351,7 +351,7 @@
                                   &response,
                                   &status);
     if (!bs.isOk()) {
-        status = bs.transactionError();
+        status = statusTFromBinderStatus(bs);
         return status;
     }
     assert(response.size() == sizeof(int));
@@ -410,7 +410,7 @@
                                   &response,
                                   &status);
     if (!bs.isOk()) {
-        status = bs.transactionError();
+        status = statusTFromBinderStatus(bs);
     }
     return status;
 }
@@ -441,7 +441,7 @@
 
     Status bs = mIEffect->command(EFFECT_CMD_GET_PARAM, cmd, psize, &response, &status);
     if (!bs.isOk()) {
-        status = bs.transactionError();
+        status = statusTFromBinderStatus(bs);
         return status;
     }
     memcpy(param, response.data(), response.size());
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index f01b1d0..112cb67 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -47,6 +47,8 @@
 #define WAIT_PERIOD_MS          10
 
 namespace android {
+using aidl_utils::statusTFromBinderStatus;
+
 // ---------------------------------------------------------------------------
 
 // static
@@ -450,7 +452,7 @@
     mActive = true;
 
     if (!(flags & CBLK_INVALID)) {
-        status = mAudioRecord->start(event, triggerSession).transactionError();
+        status = statusTFromBinderStatus(mAudioRecord->start(event, triggerSession));
         if (status == DEAD_OBJECT) {
             flags |= CBLK_INVALID;
         }
@@ -1439,8 +1441,8 @@
         if (mActive) {
             // callback thread or sync event hasn't changed
             // FIXME this fails if we have a new AudioFlinger instance
-            result = mAudioRecord->start(
-                AudioSystem::SYNC_EVENT_SAME, AUDIO_SESSION_NONE).transactionError();
+            result = statusTFromBinderStatus(mAudioRecord->start(
+                AudioSystem::SYNC_EVENT_SAME, AUDIO_SESSION_NONE));
         }
         mFramesReadServerOffset = mFramesRead; // server resets to zero so we need an offset.
     }
@@ -1531,7 +1533,7 @@
 {
     AutoMutex lock(mLock);
     std::vector<media::MicrophoneInfoData> mics;
-    status_t status = mAudioRecord->getActiveMicrophones(&mics).transactionError();
+    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]);
@@ -1552,7 +1554,7 @@
         // the internal AudioRecord hasn't be created yet, so just stash the attribute.
         return OK;
     } else {
-        return mAudioRecord->setPreferredMicrophoneDirection(direction).transactionError();
+        return statusTFromBinderStatus(mAudioRecord->setPreferredMicrophoneDirection(direction));
     }
 }
 
@@ -1568,7 +1570,7 @@
         // the internal AudioRecord hasn't be created yet, so just stash the attribute.
         return OK;
     } else {
-        return mAudioRecord->setPreferredMicrophoneFieldDimension(zoom).transactionError();
+        return statusTFromBinderStatus(mAudioRecord->setPreferredMicrophoneFieldDimension(zoom));
     }
 }
 
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index d163feb..2187635 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -35,7 +35,7 @@
 
 #define VALUE_OR_RETURN_BINDER_STATUS(x) \
     ({ auto _tmp = (x); \
-       if (!_tmp.ok()) return Status::fromStatusT(_tmp.error()); \
+       if (!_tmp.ok()) return aidl_utils::binderStatusFromStatusT(_tmp.error()); \
        std::move(_tmp.value()); })
 
 // ----------------------------------------------------------------------------
@@ -53,6 +53,7 @@
 std::set<audio_error_callback> AudioSystem::gAudioErrorCallbacks;
 dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL;
 record_config_callback AudioSystem::gRecordConfigCallback = NULL;
+routing_callback AudioSystem::gRoutingCallback = NULL;
 
 // Required to be held while calling into gSoundTriggerCaptureStateListener.
 class CaptureStateListenerImpl;
@@ -71,7 +72,7 @@
             sp<IServiceManager> sm = defaultServiceManager();
             sp<IBinder> binder;
             do {
-                binder = sm->getService(String16("media.audio_flinger"));
+                binder = sm->getService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME));
                 if (binder != 0)
                     break;
                 ALOGW("AudioFlinger not published, waiting...");
@@ -83,7 +84,8 @@
                 reportNoError = true;
             }
             binder->linkToDeath(gAudioFlingerClient);
-            gAudioFlinger = interface_cast<IAudioFlinger>(binder);
+            gAudioFlinger = new AudioFlingerClientAdapter(
+                    interface_cast<media::IAudioFlingerService>(binder));
             LOG_ALWAYS_FATAL_IF(gAudioFlinger == 0);
             afc = gAudioFlingerClient;
             // Make sure callbacks can be received by gAudioFlingerClient
@@ -770,6 +772,12 @@
     gRecordConfigCallback = cb;
 }
 
+/*static*/ void AudioSystem::setRoutingCallback(routing_callback cb)
+{
+    Mutex::Autolock _l(gLock);
+    gRoutingCallback = cb;
+}
+
 // client singleton for AudioPolicyService binder interface
 // protected by gLockAPS
 sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
@@ -1187,18 +1195,18 @@
     return aps->setAllowedCapturePolicy(uid, flags);
 }
 
-bool AudioSystem::isOffloadSupported(const audio_offload_info_t& info)
+audio_offload_mode_t AudioSystem::getOffloadSupport(const audio_offload_info_t& info)
 {
-    ALOGV("isOffloadSupported()");
+    ALOGV("%s", __func__);
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
-    if (aps == 0) return false;
-    return aps->isOffloadSupported(info);
+    if (aps == 0) return AUDIO_OFFLOAD_NOT_SUPPORTED;
+    return aps->getOffloadSupport(info);
 }
 
 status_t AudioSystem::listAudioPorts(audio_port_role_t role,
                                      audio_port_type_t type,
                                      unsigned int *num_ports,
-                                     struct audio_port *ports,
+                                     struct audio_port_v7 *ports,
                                      unsigned int *generation)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
@@ -1206,7 +1214,7 @@
     return aps->listAudioPorts(role, type, num_ports, ports, generation);
 }
 
-status_t AudioSystem::getAudioPort(struct audio_port *port)
+status_t AudioSystem::getAudioPort(struct audio_port_v7 *port)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
@@ -1791,20 +1799,22 @@
 }
 
 
-void AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate()
+Status AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate()
 {
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) {
         mAudioPortCallbacks[i]->onAudioPortListUpdate();
     }
+    return Status::ok();
 }
 
-void AudioSystem::AudioPolicyServiceClient::onAudioPatchListUpdate()
+Status AudioSystem::AudioPolicyServiceClient::onAudioPatchListUpdate()
 {
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) {
         mAudioPortCallbacks[i]->onAudioPatchListUpdate();
     }
+    return Status::ok();
 }
 
 // ----------------------------------------------------------------------------
@@ -1838,20 +1848,26 @@
     return mAudioVolumeGroupCallback.size();
 }
 
-void AudioSystem::AudioPolicyServiceClient::onAudioVolumeGroupChanged(volume_group_t group,
-                                                                      int flags)
-{
+Status AudioSystem::AudioPolicyServiceClient::onAudioVolumeGroupChanged(int32_t group,
+                                                                        int32_t flags) {
+    volume_group_t groupLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+            aidl2legacy_int32_t_volume_group_t(group));
+    int flagsLegacy = VALUE_OR_RETURN_BINDER_STATUS(convertReinterpret<int>(flags));
+
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mAudioVolumeGroupCallback.size(); i++) {
-        mAudioVolumeGroupCallback[i]->onAudioVolumeGroupChanged(group, flags);
+        mAudioVolumeGroupCallback[i]->onAudioVolumeGroupChanged(groupLegacy, flagsLegacy);
     }
+    return Status::ok();
 }
 // ----------------------------------------------------------------------------
 
-void AudioSystem::AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate(
-        String8 regId, int32_t state)
-{
-    ALOGV("AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate(%s, %d)", regId.string(), state);
+Status AudioSystem::AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate(
+        const ::std::string& regId, int32_t state) {
+    ALOGV("AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate(%s, %d)", regId.c_str(), state);
+
+    String8 regIdLegacy = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_string_view_String8(regId));
+    int stateLegacy = VALUE_OR_RETURN_BINDER_STATUS(convertReinterpret<int>(state));
     dynamic_policy_callback cb = NULL;
     {
         Mutex::Autolock _l(AudioSystem::gLock);
@@ -1859,19 +1875,20 @@
     }
 
     if (cb != NULL) {
-        cb(DYNAMIC_POLICY_EVENT_MIX_STATE_UPDATE, regId, state);
+        cb(DYNAMIC_POLICY_EVENT_MIX_STATE_UPDATE, regIdLegacy, stateLegacy);
     }
+    return Status::ok();
 }
 
-void AudioSystem::AudioPolicyServiceClient::onRecordingConfigurationUpdate(
-                                                int event,
-                                                const record_client_info_t *clientInfo,
-                                                const audio_config_base_t *clientConfig,
-                                                std::vector<effect_descriptor_t> clientEffects,
-                                                const audio_config_base_t *deviceConfig,
-                                                std::vector<effect_descriptor_t> effects,
-                                                audio_patch_handle_t patchHandle,
-                                                audio_source_t source) {
+Status AudioSystem::AudioPolicyServiceClient::onRecordingConfigurationUpdate(
+        int32_t event,
+        const media::RecordClientInfo& clientInfo,
+        const media::AudioConfigBase& clientConfig,
+        const std::vector<media::EffectDescriptor>& clientEffects,
+        const media::AudioConfigBase& deviceConfig,
+        const std::vector<media::EffectDescriptor>& effects,
+        int32_t patchHandle,
+        media::AudioSourceType source) {
     record_config_callback cb = NULL;
     {
         Mutex::Autolock _l(AudioSystem::gLock);
@@ -1879,9 +1896,42 @@
     }
 
     if (cb != NULL) {
-        cb(event, clientInfo, clientConfig, clientEffects,
-           deviceConfig, effects, patchHandle, source);
+        int eventLegacy = VALUE_OR_RETURN_BINDER_STATUS(convertReinterpret<int>(event));
+        record_client_info_t clientInfoLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+                aidl2legacy_RecordClientInfo_record_client_info_t(clientInfo));
+        audio_config_base_t clientConfigLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+                aidl2legacy_AudioConfigBase_audio_config_base_t(clientConfig));
+        std::vector<effect_descriptor_t> clientEffectsLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+                convertContainer<std::vector<effect_descriptor_t>>(
+                        clientEffects,
+                        aidl2legacy_EffectDescriptor_effect_descriptor_t));
+        audio_config_base_t deviceConfigLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+                aidl2legacy_AudioConfigBase_audio_config_base_t(deviceConfig));
+        std::vector<effect_descriptor_t> effectsLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+                convertContainer<std::vector<effect_descriptor_t>>(
+                        effects,
+                        aidl2legacy_EffectDescriptor_effect_descriptor_t));
+        audio_patch_handle_t patchHandleLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+                aidl2legacy_int32_t_audio_patch_handle_t(patchHandle));
+        audio_source_t sourceLegacy = VALUE_OR_RETURN_BINDER_STATUS(
+                aidl2legacy_AudioSourceType_audio_source_t(source));
+        cb(eventLegacy, &clientInfoLegacy, &clientConfigLegacy, clientEffectsLegacy,
+           &deviceConfigLegacy, effectsLegacy, patchHandleLegacy, sourceLegacy);
     }
+    return Status::ok();
+}
+
+Status AudioSystem::AudioPolicyServiceClient::onRoutingUpdated() {
+    routing_callback cb = NULL;
+    {
+        Mutex::Autolock _l(AudioSystem::gLock);
+        cb = gRoutingCallback;
+    }
+
+    if (cb != NULL) {
+        cb();
+    }
+    return Status::ok();
 }
 
 void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused)
@@ -1903,4 +1953,28 @@
     ALOGW("AudioPolicyService server died!");
 }
 
+ConversionResult<record_client_info_t>
+aidl2legacy_RecordClientInfo_record_client_info_t(const media::RecordClientInfo& aidl) {
+    record_client_info_t legacy;
+    legacy.riid = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_unique_id_t(aidl.riid));
+    legacy.uid = VALUE_OR_RETURN(aidl2legacy_int32_t_uid_t(aidl.uid));
+    legacy.session = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl.session));
+    legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSourceType_audio_source_t(aidl.source));
+    legacy.port_id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.portId));
+    legacy.silenced = aidl.silenced;
+    return legacy;
+}
+
+ConversionResult<media::RecordClientInfo>
+legacy2aidl_record_client_info_t_RecordClientInfo(const record_client_info_t& legacy) {
+    media::RecordClientInfo aidl;
+    aidl.riid = VALUE_OR_RETURN(legacy2aidl_audio_unique_id_t_int32_t(legacy.riid));
+    aidl.uid = VALUE_OR_RETURN(legacy2aidl_uid_t_int32_t(legacy.uid));
+    aidl.session = VALUE_OR_RETURN(legacy2aidl_audio_session_t_int32_t(legacy.session));
+    aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSourceType(legacy.source));
+    aidl.portId = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.port_id));
+    aidl.silenced = legacy.silenced;
+    return aidl;
+}
+
 } // namespace android
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 8c53c5b..d4cbbc3 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1609,9 +1609,11 @@
 
     media::CreateTrackResponse response;
     status = audioFlinger->createTrack(VALUE_OR_FATAL(input.toAidl()), response);
-    IAudioFlinger::CreateTrackOutput output = VALUE_OR_FATAL(
-            IAudioFlinger::CreateTrackOutput::fromAidl(
-                    response));
+
+    IAudioFlinger::CreateTrackOutput output{};
+    if (status == NO_ERROR) {
+        output = VALUE_OR_FATAL(IAudioFlinger::CreateTrackOutput::fromAidl(response));
+    }
 
     if (status != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
         ALOGE("%s(%d): AudioFlinger could not create track, status: %d output %d",
@@ -2819,7 +2821,7 @@
         media::AudioTimestampInternal ts;
         mAudioTrack->getTimestamp(&ts, &status);
         if (status == OK) {
-            timestamp = VALUE_OR_FATAL(aidl2legacy_AudioTimestamp(ts));
+            timestamp = VALUE_OR_FATAL(aidl2legacy_AudioTimestampInternal_AudioTimestamp(ts));
         }
     } else {
         // read timestamp from shared memory
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 786af53..20124df 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -28,19 +28,41 @@
 
 namespace android {
 
+using aidl_utils::statusTFromBinderStatus;
+using binder::Status;
+
 #define MAX_ITEMS_PER_LIST 1024
 
+#define VALUE_OR_RETURN_BINDER(x)                                 \
+    ({                                                            \
+       auto _tmp = (x);                                           \
+       if (!_tmp.ok()) return Status::fromStatusT(_tmp.error());  \
+       std::move(_tmp.value()); \
+     })
+
+#define RETURN_STATUS_IF_ERROR(x)    \
+    {                                \
+       auto _tmp = (x);              \
+       if (_tmp != OK) return _tmp;  \
+    }
+
+#define RETURN_BINDER_IF_ERROR(x)                         \
+    {                                                     \
+       auto _tmp = (x);                                   \
+       if (_tmp != OK) return Status::fromStatusT(_tmp);  \
+    }
+
 ConversionResult<media::CreateTrackRequest> IAudioFlinger::CreateTrackInput::toAidl() const {
     media::CreateTrackRequest aidl;
     aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
     aidl.config = VALUE_OR_RETURN(legacy2aidl_audio_config_t_AudioConfig(config));
-    aidl.clientInfo = VALUE_OR_RETURN(legacy2aidl_AudioClient(clientInfo));
+    aidl.clientInfo = VALUE_OR_RETURN(legacy2aidl_AudioClient_AudioClient(clientInfo));
     aidl.sharedBuffer = VALUE_OR_RETURN(legacy2aidl_NullableIMemory_SharedFileRegion(sharedBuffer));
     aidl.notificationsPerBuffer = VALUE_OR_RETURN(convertIntegral<int32_t>(notificationsPerBuffer));
     aidl.speed = speed;
     aidl.audioTrackCallback = audioTrackCallback;
     aidl.opPackageName = opPackageName;
-    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_output_flags_mask(flags));
+    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
     aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(frameCount));
     aidl.notificationFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(notificationFrameCount));
     aidl.selectedDeviceId = VALUE_OR_RETURN(
@@ -54,14 +76,14 @@
     IAudioFlinger::CreateTrackInput legacy;
     legacy.attr = VALUE_OR_RETURN(aidl2legacy_AudioAttributesInternal_audio_attributes_t(aidl.attr));
     legacy.config = VALUE_OR_RETURN(aidl2legacy_AudioConfig_audio_config_t(aidl.config));
-    legacy.clientInfo = VALUE_OR_RETURN(aidl2legacy_AudioClient(aidl.clientInfo));
+    legacy.clientInfo = VALUE_OR_RETURN(aidl2legacy_AudioClient_AudioClient(aidl.clientInfo));
     legacy.sharedBuffer = VALUE_OR_RETURN(aidl2legacy_NullableSharedFileRegion_IMemory(aidl.sharedBuffer));
     legacy.notificationsPerBuffer = VALUE_OR_RETURN(
             convertIntegral<uint32_t>(aidl.notificationsPerBuffer));
     legacy.speed = aidl.speed;
     legacy.audioTrackCallback = aidl.audioTrackCallback;
     legacy.opPackageName = aidl.opPackageName;
-    legacy.flags = VALUE_OR_RETURN(aidl2legacy_audio_output_flags_mask(aidl.flags));
+    legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_output_flags_t_mask(aidl.flags));
     legacy.frameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCount));
     legacy.notificationFrameCount = VALUE_OR_RETURN(
             convertIntegral<size_t>(aidl.notificationFrameCount));
@@ -74,7 +96,7 @@
 ConversionResult<media::CreateTrackResponse>
 IAudioFlinger::CreateTrackOutput::toAidl() const {
     media::CreateTrackResponse aidl;
-    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_output_flags_mask(flags));
+    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
     aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(frameCount));
     aidl.notificationFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(notificationFrameCount));
     aidl.selectedDeviceId = VALUE_OR_RETURN(
@@ -94,7 +116,7 @@
 IAudioFlinger::CreateTrackOutput::fromAidl(
         const media::CreateTrackResponse& aidl) {
     IAudioFlinger::CreateTrackOutput legacy;
-    legacy.flags = VALUE_OR_RETURN(aidl2legacy_audio_output_flags_mask(aidl.flags));
+    legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_output_flags_t_mask(aidl.flags));
     legacy.frameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCount));
     legacy.notificationFrameCount = VALUE_OR_RETURN(
             convertIntegral<size_t>(aidl.notificationFrameCount));
@@ -116,10 +138,10 @@
     media::CreateRecordRequest aidl;
     aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
     aidl.config = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(config));
-    aidl.clientInfo = VALUE_OR_RETURN(legacy2aidl_AudioClient(clientInfo));
+    aidl.clientInfo = VALUE_OR_RETURN(legacy2aidl_AudioClient_AudioClient(clientInfo));
     aidl.opPackageName = VALUE_OR_RETURN(legacy2aidl_String16_string(opPackageName));
     aidl.riid = VALUE_OR_RETURN(legacy2aidl_audio_unique_id_t_int32_t(riid));
-    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_input_flags_mask(flags));
+    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
     aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(frameCount));
     aidl.notificationFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(notificationFrameCount));
     aidl.selectedDeviceId = VALUE_OR_RETURN(
@@ -134,10 +156,10 @@
     IAudioFlinger::CreateRecordInput legacy;
     legacy.attr = VALUE_OR_RETURN(aidl2legacy_AudioAttributesInternal_audio_attributes_t(aidl.attr));
     legacy.config = VALUE_OR_RETURN(aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.config));
-    legacy.clientInfo = VALUE_OR_RETURN(aidl2legacy_AudioClient(aidl.clientInfo));
+    legacy.clientInfo = VALUE_OR_RETURN(aidl2legacy_AudioClient_AudioClient(aidl.clientInfo));
     legacy.opPackageName = VALUE_OR_RETURN(aidl2legacy_string_view_String16(aidl.opPackageName));
     legacy.riid = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_unique_id_t(aidl.riid));
-    legacy.flags = VALUE_OR_RETURN(aidl2legacy_audio_input_flags_mask(aidl.flags));
+    legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_input_flags_t_mask(aidl.flags));
     legacy.frameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCount));
     legacy.notificationFrameCount = VALUE_OR_RETURN(
             convertIntegral<size_t>(aidl.notificationFrameCount));
@@ -150,7 +172,7 @@
 ConversionResult<media::CreateRecordResponse>
 IAudioFlinger::CreateRecordOutput::toAidl() const {
     media::CreateRecordResponse aidl;
-    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_input_flags_mask(flags));
+    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
     aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(frameCount));
     aidl.notificationFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(notificationFrameCount));
     aidl.selectedDeviceId = VALUE_OR_RETURN(
@@ -169,7 +191,7 @@
 IAudioFlinger::CreateRecordOutput::fromAidl(
         const media::CreateRecordResponse& aidl) {
     IAudioFlinger::CreateRecordOutput legacy;
-    legacy.flags = VALUE_OR_RETURN(aidl2legacy_audio_input_flags_mask(aidl.flags));
+    legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_input_flags_t_mask(aidl.flags));
     legacy.frameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCount));
     legacy.notificationFrameCount = VALUE_OR_RETURN(
             convertIntegral<size_t>(aidl.notificationFrameCount));
@@ -185,1275 +207,975 @@
     return legacy;
 }
 
-class BpAudioFlinger : public BpInterface<IAudioFlinger>
-{
-public:
-    explicit BpAudioFlinger(const sp<IBinder>& impl)
-        : BpInterface<IAudioFlinger>(impl)
-    {
-    }
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// AudioFlingerClientAdapter
 
-    virtual status_t createTrack(const media::CreateTrackRequest& input,
-                                 media::CreateTrackResponse& output)
-    {
-        Parcel data, reply;
-        status_t status;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeParcelable(input);
+AudioFlingerClientAdapter::AudioFlingerClientAdapter(
+        const sp<media::IAudioFlingerService> delegate) : mDelegate(delegate) {}
 
-        status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
-        if (lStatus != NO_ERROR) {
-            ALOGE("createTrack transaction error %d", lStatus);
-            return DEAD_OBJECT;
-        }
-        status = reply.readInt32();
-        if (status != NO_ERROR) {
-            ALOGE("createTrack returned error %d", status);
-            return status;
-        }
-        output.readFromParcel(&reply);
-        if (output.audioTrack == 0) {
-            ALOGE("createTrack returned an NULL IAudioTrack with status OK");
-            return DEAD_OBJECT;
-        }
-        return OK;
-    }
-
-    virtual status_t createRecord(const media::CreateRecordRequest& input,
-                                  media::CreateRecordResponse& output)
-    {
-        Parcel data, reply;
-        status_t status;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-
-        data.writeParcelable(input);
-
-        status_t lStatus = remote()->transact(CREATE_RECORD, data, &reply);
-        if (lStatus != NO_ERROR) {
-            ALOGE("createRecord transaction error %d", lStatus);
-            return DEAD_OBJECT;
-        }
-        status = reply.readInt32();
-        if (status != NO_ERROR) {
-            ALOGE("createRecord returned error %d", status);
-            return status;
-        }
-
-        output.readFromParcel(&reply);
-        if (output.audioRecord == 0) {
-            ALOGE("createRecord returned a NULL IAudioRecord with status OK");
-            return DEAD_OBJECT;
-        }
-        return OK;
-    }
-
-    virtual uint32_t sampleRate(audio_io_handle_t ioHandle) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) ioHandle);
-        remote()->transact(SAMPLE_RATE, data, &reply);
-        return reply.readInt32();
-    }
-
-    // RESERVED for channelCount()
-
-    virtual audio_format_t format(audio_io_handle_t output) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) output);
-        remote()->transact(FORMAT, data, &reply);
-        return (audio_format_t) reply.readInt32();
-    }
-
-    virtual size_t frameCount(audio_io_handle_t ioHandle) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) ioHandle);
-        remote()->transact(FRAME_COUNT, data, &reply);
-        return reply.readInt64();
-    }
-
-    virtual uint32_t latency(audio_io_handle_t output) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) output);
-        remote()->transact(LATENCY, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual status_t setMasterVolume(float value)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeFloat(value);
-        remote()->transact(SET_MASTER_VOLUME, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual status_t setMasterMute(bool muted)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(muted);
-        remote()->transact(SET_MASTER_MUTE, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual float masterVolume() const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        remote()->transact(MASTER_VOLUME, data, &reply);
-        return reply.readFloat();
-    }
-
-    virtual bool masterMute() const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        remote()->transact(MASTER_MUTE, data, &reply);
-        return reply.readInt32();
-    }
-
-    status_t setMasterBalance(float balance) override
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeFloat(balance);
-        status_t status = remote()->transact(SET_MASTER_BALANCE, data, &reply);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        return reply.readInt32();
-    }
-
-    status_t getMasterBalance(float *balance) const override
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        status_t status = remote()->transact(GET_MASTER_BALANCE, data, &reply);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        status = (status_t)reply.readInt32();
-        if (status != NO_ERROR) {
-            return status;
-        }
-        *balance = reply.readFloat();
-        return NO_ERROR;
-    }
-
-    virtual status_t setStreamVolume(audio_stream_type_t stream, float value,
-            audio_io_handle_t output)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) stream);
-        data.writeFloat(value);
-        data.writeInt32((int32_t) output);
-        remote()->transact(SET_STREAM_VOLUME, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual status_t setStreamMute(audio_stream_type_t stream, bool muted)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) stream);
-        data.writeInt32(muted);
-        remote()->transact(SET_STREAM_MUTE, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual float streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) stream);
-        data.writeInt32((int32_t) output);
-        remote()->transact(STREAM_VOLUME, data, &reply);
-        return reply.readFloat();
-    }
-
-    virtual bool streamMute(audio_stream_type_t stream) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) stream);
-        remote()->transact(STREAM_MUTE, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual status_t setMode(audio_mode_t mode)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(mode);
-        remote()->transact(SET_MODE, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual status_t setMicMute(bool state)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(state);
-        remote()->transact(SET_MIC_MUTE, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual bool getMicMute() const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        remote()->transact(GET_MIC_MUTE, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(portId);
-        data.writeInt32(silenced ? 1 : 0);
-        remote()->transact(SET_RECORD_SILENCED, data, &reply);
-    }
-
-    virtual status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) ioHandle);
-        data.writeString8(keyValuePairs);
-        remote()->transact(SET_PARAMETERS, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) ioHandle);
-        data.writeString8(keys);
-        remote()->transact(GET_PARAMETERS, data, &reply);
-        return reply.readString8();
-    }
-
-    virtual void registerClient(const sp<media::IAudioFlingerClient>& client)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(client));
-        remote()->transact(REGISTER_CLIENT, data, &reply);
-    }
-
-    virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
-            audio_channel_mask_t channelMask) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(sampleRate);
-        data.writeInt32(format);
-        data.writeInt32(channelMask);
-        remote()->transact(GET_INPUTBUFFERSIZE, data, &reply);
-        return reply.readInt64();
-    }
-
-    virtual status_t openOutput(const media::OpenOutputRequest& request,
-                                media::OpenOutputResponse* response)
-    {
-        status_t status;
-        Parcel data, reply;
-        return data.writeParcelable(request)
-                ?: remote()->transact(OPEN_OUTPUT, data, &reply)
-                ?: data.readInt32(&status)
-                ?: status
-                ?: data.readParcelable(response);
-    }
-
-    virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
-            audio_io_handle_t output2)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) output1);
-        data.writeInt32((int32_t) output2);
-        remote()->transact(OPEN_DUPLICATE_OUTPUT, data, &reply);
-        return (audio_io_handle_t) reply.readInt32();
-    }
-
-    virtual status_t closeOutput(audio_io_handle_t output)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) output);
-        remote()->transact(CLOSE_OUTPUT, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual status_t suspendOutput(audio_io_handle_t output)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) output);
-        remote()->transact(SUSPEND_OUTPUT, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual status_t restoreOutput(audio_io_handle_t output)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) output);
-        remote()->transact(RESTORE_OUTPUT, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual status_t openInput(const media::OpenInputRequest& request,
-                               media::OpenInputResponse* response)
-    {
-        Parcel data, reply;
-        status_t status;
-        return data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor())
-            ?: data.writeParcelable(request)
-            ?: remote()->transact(OPEN_INPUT, data, &reply)
-            ?: reply.readInt32(&status)
-            ?: status
-            ?: reply.readParcelable(response);
-    }
-
-    virtual status_t closeInput(int input)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(input);
-        remote()->transact(CLOSE_INPUT, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual status_t invalidateStream(audio_stream_type_t stream)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) stream);
-        remote()->transact(INVALIDATE_STREAM, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual status_t setVoiceVolume(float volume)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeFloat(volume);
-        remote()->transact(SET_VOICE_VOLUME, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
-            audio_io_handle_t output) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) output);
-        remote()->transact(GET_RENDER_POSITION, data, &reply);
-        status_t status = reply.readInt32();
-        if (status == NO_ERROR) {
-            uint32_t tmp = reply.readInt32();
-            if (halFrames != NULL) {
-                *halFrames = tmp;
-            }
-            tmp = reply.readInt32();
-            if (dspFrames != NULL) {
-                *dspFrames = tmp;
-            }
-        }
-        return status;
-    }
-
-    virtual uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) ioHandle);
-        status_t status = remote()->transact(GET_INPUT_FRAMES_LOST, data, &reply);
-        if (status != NO_ERROR) {
-            return 0;
-        }
-        return (uint32_t) reply.readInt32();
-    }
-
-    virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) use);
-        status_t status = remote()->transact(NEW_AUDIO_UNIQUE_ID, data, &reply);
-        audio_unique_id_t id = AUDIO_UNIQUE_ID_ALLOCATE;
-        if (status == NO_ERROR) {
-            id = reply.readInt32();
-        }
-        return id;
-    }
-
-    void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid) override
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(audioSession);
-        data.writeInt32((int32_t)pid);
-        data.writeInt32((int32_t)uid);
-        remote()->transact(ACQUIRE_AUDIO_SESSION_ID, data, &reply);
-    }
-
-    virtual void releaseAudioSessionId(audio_session_t audioSession, int pid)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(audioSession);
-        data.writeInt32(pid);
-        remote()->transact(RELEASE_AUDIO_SESSION_ID, data, &reply);
-    }
-
-    virtual status_t queryNumberEffects(uint32_t *numEffects) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        status_t status = remote()->transact(QUERY_NUM_EFFECTS, data, &reply);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        status = reply.readInt32();
-        if (status != NO_ERROR) {
-            return status;
-        }
-        if (numEffects != NULL) {
-            *numEffects = (uint32_t)reply.readInt32();
-        }
-        return NO_ERROR;
-    }
-
-    virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor) const
-    {
-        if (pDescriptor == NULL) {
-            return BAD_VALUE;
-        }
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(index);
-        status_t status = remote()->transact(QUERY_EFFECT, data, &reply);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        status = reply.readInt32();
-        if (status != NO_ERROR) {
-            return status;
-        }
-        reply.read(pDescriptor, sizeof(effect_descriptor_t));
-        return NO_ERROR;
-    }
-
-    virtual status_t getEffectDescriptor(const effect_uuid_t *pUuid,
-                                         const effect_uuid_t *pType,
-                                         uint32_t preferredTypeFlag,
-                                         effect_descriptor_t *pDescriptor) const
-    {
-        if (pUuid == NULL || pType == NULL || pDescriptor == NULL) {
-            return BAD_VALUE;
-        }
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.write(pUuid, sizeof(effect_uuid_t));
-        data.write(pType, sizeof(effect_uuid_t));
-        data.writeUint32(preferredTypeFlag);
-        status_t status = remote()->transact(GET_EFFECT_DESCRIPTOR, data, &reply);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        status = reply.readInt32();
-        if (status != NO_ERROR) {
-            return status;
-        }
-        reply.read(pDescriptor, sizeof(effect_descriptor_t));
-        return NO_ERROR;
-    }
-
-    virtual status_t createEffect(const media::CreateEffectRequest& request,
-                                  media::CreateEffectResponse* response)
-    {
-        Parcel data, reply;
-        sp<media::IEffect> effect;
-        if (response == nullptr) {
-            return BAD_VALUE;
-        }
-        status_t status;
-        status_t lStatus = data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor())
-                           ?: data.writeParcelable(request)
-                           ?: remote()->transact(CREATE_EFFECT, data, &reply)
-                           ?: reply.readInt32(&status)
-                           ?: reply.readParcelable(response)
-                           ?: status;
-        if (lStatus != NO_ERROR) {
-            ALOGE("createEffect error: %s", strerror(-lStatus));
-        }
-        return lStatus;
-    }
-
-    virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
-            audio_io_handle_t dstOutput)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(session);
-        data.writeInt32((int32_t) srcOutput);
-        data.writeInt32((int32_t) dstOutput);
-        remote()->transact(MOVE_EFFECTS, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual void setEffectSuspended(int effectId,
-                                    audio_session_t sessionId,
-                                    bool suspended)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(effectId);
-        data.writeInt32(sessionId);
-        data.writeInt32(suspended ? 1 : 0);
-        remote()->transact(SET_EFFECT_SUSPENDED, data, &reply);
-    }
-
-    virtual audio_module_handle_t loadHwModule(const char *name)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeCString(name);
-        remote()->transact(LOAD_HW_MODULE, data, &reply);
-        return (audio_module_handle_t) reply.readInt32();
-    }
-
-    virtual uint32_t getPrimaryOutputSamplingRate()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        remote()->transact(GET_PRIMARY_OUTPUT_SAMPLING_RATE, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual size_t getPrimaryOutputFrameCount()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        remote()->transact(GET_PRIMARY_OUTPUT_FRAME_COUNT, data, &reply);
-        return reply.readInt64();
-    }
-
-    virtual status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) override
-    {
-        Parcel data, reply;
-
-        static_assert(NO_ERROR == 0, "NO_ERROR must be 0");
-        return data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor())
-                ?: data.writeInt32((int) isLowRamDevice)
-                ?: data.writeInt64(totalMemory)
-                ?: remote()->transact(SET_LOW_RAM_DEVICE, data, &reply)
-                ?: reply.readInt32();
-    }
-
-    virtual status_t listAudioPorts(unsigned int *num_ports,
-                                    struct audio_port *ports)
-    {
-        if (num_ports == NULL || *num_ports == 0 || ports == NULL) {
-            return BAD_VALUE;
-        }
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(*num_ports);
-        status_t status = remote()->transact(LIST_AUDIO_PORTS, data, &reply);
-        if (status != NO_ERROR ||
-                (status = (status_t)reply.readInt32()) != NO_ERROR) {
-            return status;
-        }
-        *num_ports = (unsigned int)reply.readInt32();
-        reply.read(ports, *num_ports * sizeof(struct audio_port));
-        return status;
-    }
-    virtual status_t getAudioPort(struct audio_port_v7 *port)
-    {
-        if (port == nullptr) {
-            return BAD_VALUE;
-        }
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.write(port, sizeof(struct audio_port_v7));
-        status_t status = remote()->transact(GET_AUDIO_PORT, data, &reply);
-        if (status != NO_ERROR ||
-                (status = (status_t)reply.readInt32()) != NO_ERROR) {
-            return status;
-        }
-        reply.read(port, sizeof(struct audio_port));
-        return status;
-    }
-    virtual status_t createAudioPatch(const struct audio_patch *patch,
-                                       audio_patch_handle_t *handle)
-    {
-        if (patch == NULL || handle == NULL) {
-            return BAD_VALUE;
-        }
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.write(patch, sizeof(struct audio_patch));
-        data.write(handle, sizeof(audio_patch_handle_t));
-        status_t status = remote()->transact(CREATE_AUDIO_PATCH, data, &reply);
-        if (status != NO_ERROR ||
-                (status = (status_t)reply.readInt32()) != NO_ERROR) {
-            return status;
-        }
-        reply.read(handle, sizeof(audio_patch_handle_t));
-        return status;
-    }
-    virtual status_t releaseAudioPatch(audio_patch_handle_t handle)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.write(&handle, sizeof(audio_patch_handle_t));
-        status_t status = remote()->transact(RELEASE_AUDIO_PATCH, data, &reply);
-        if (status != NO_ERROR) {
-            status = (status_t)reply.readInt32();
-        }
-        return status;
-    }
-    virtual status_t listAudioPatches(unsigned int *num_patches,
-                                      struct audio_patch *patches)
-    {
-        if (num_patches == NULL || *num_patches == 0 || patches == NULL) {
-            return BAD_VALUE;
-        }
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(*num_patches);
-        status_t status = remote()->transact(LIST_AUDIO_PATCHES, data, &reply);
-        if (status != NO_ERROR ||
-                (status = (status_t)reply.readInt32()) != NO_ERROR) {
-            return status;
-        }
-        *num_patches = (unsigned int)reply.readInt32();
-        reply.read(patches, *num_patches * sizeof(struct audio_patch));
-        return status;
-    }
-    virtual status_t setAudioPortConfig(const struct audio_port_config *config)
-    {
-        if (config == NULL) {
-            return BAD_VALUE;
-        }
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.write(config, sizeof(struct audio_port_config));
-        status_t status = remote()->transact(SET_AUDIO_PORT_CONFIG, data, &reply);
-        if (status != NO_ERROR) {
-            status = (status_t)reply.readInt32();
-        }
-        return status;
-    }
-    virtual audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(sessionId);
-        status_t status = remote()->transact(GET_AUDIO_HW_SYNC_FOR_SESSION, data, &reply);
-        if (status != NO_ERROR) {
-            return AUDIO_HW_SYNC_INVALID;
-        }
-        return (audio_hw_sync_t)reply.readInt32();
-    }
-    virtual status_t systemReady()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        return remote()->transact(SYSTEM_READY, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-    virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) ioHandle);
-        status_t status = remote()->transact(FRAME_COUNT_HAL, data, &reply);
-        if (status != NO_ERROR) {
-            return 0;
-        }
-        return reply.readInt64();
-    }
-    virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        status_t status = remote()->transact(GET_MICROPHONES, data, &reply);
-        if (status != NO_ERROR ||
-                (status = (status_t)reply.readInt32()) != NO_ERROR) {
-            return status;
-        }
-        status = reply.readParcelableVector(microphones);
-        return status;
-    }
-    virtual status_t setAudioHalPids(const std::vector<pid_t>& pids)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(pids.size());
-        for (auto pid : pids) {
-            data.writeInt32(pid);
-        }
-        status_t status = remote()->transact(SET_AUDIO_HAL_PIDS, data, &reply);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        return static_cast <status_t> (reply.readInt32());
-    }
-};
-
-IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
-
-// ----------------------------------------------------------------------
-
-status_t BnAudioFlinger::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch (code) {
-        case CREATE_TRACK: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-
-            media::CreateTrackRequest input;
-            if (data.readParcelable(&input) != NO_ERROR) {
-                reply->writeInt32(DEAD_OBJECT);
-                return NO_ERROR;
-            }
-
-            status_t status;
-            media::CreateTrackResponse output;
-
-            status = createTrack(input, output);
-
-            LOG_ALWAYS_FATAL_IF((output.audioTrack != 0) != (status == NO_ERROR));
-            reply->writeInt32(status);
-            if (status != NO_ERROR) {
-                return NO_ERROR;
-            }
-            output.writeToParcel(reply);
-            return NO_ERROR;
-        } break;
-        case CREATE_RECORD: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-
-            media::CreateRecordRequest input;
-            if (data.readParcelable(&input) != NO_ERROR) {
-                reply->writeInt32(DEAD_OBJECT);
-                return NO_ERROR;
-            }
-
-            status_t status;
-            media::CreateRecordResponse output;
-
-            status = createRecord(input, output);
-
-            LOG_ALWAYS_FATAL_IF((output.audioRecord != 0) != (status == NO_ERROR));
-            reply->writeInt32(status);
-            if (status != NO_ERROR) {
-                return NO_ERROR;
-            }
-            output.writeToParcel(reply);
-            return NO_ERROR;
-        } break;
-        case SAMPLE_RATE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( sampleRate((audio_io_handle_t) data.readInt32()) );
-            return NO_ERROR;
-        } break;
-
-        // RESERVED for channelCount()
-
-        case FORMAT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( format((audio_io_handle_t) data.readInt32()) );
-            return NO_ERROR;
-        } break;
-        case FRAME_COUNT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt64( frameCount((audio_io_handle_t) data.readInt32()) );
-            return NO_ERROR;
-        } break;
-        case LATENCY: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( latency((audio_io_handle_t) data.readInt32()) );
-            return NO_ERROR;
-        } break;
-        case SET_MASTER_VOLUME: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( setMasterVolume(data.readFloat()) );
-            return NO_ERROR;
-        } break;
-        case SET_MASTER_MUTE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( setMasterMute(data.readInt32()) );
-            return NO_ERROR;
-        } break;
-        case MASTER_VOLUME: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeFloat( masterVolume() );
-            return NO_ERROR;
-        } break;
-        case MASTER_MUTE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( masterMute() );
-            return NO_ERROR;
-        } break;
-        case SET_MASTER_BALANCE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( setMasterBalance(data.readFloat()) );
-            return NO_ERROR;
-        } break;
-        case GET_MASTER_BALANCE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            float f;
-            const status_t status = getMasterBalance(&f);
-            reply->writeInt32((int32_t)status);
-            if (status == NO_ERROR) {
-                (void)reply->writeFloat(f);
-            }
-            return NO_ERROR;
-        } break;
-        case SET_STREAM_VOLUME: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int stream = data.readInt32();
-            float volume = data.readFloat();
-            audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
-            reply->writeInt32( setStreamVolume((audio_stream_type_t) stream, volume, output) );
-            return NO_ERROR;
-        } break;
-        case SET_STREAM_MUTE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int stream = data.readInt32();
-            reply->writeInt32( setStreamMute((audio_stream_type_t) stream, data.readInt32()) );
-            return NO_ERROR;
-        } break;
-        case STREAM_VOLUME: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int stream = data.readInt32();
-            int output = data.readInt32();
-            reply->writeFloat( streamVolume((audio_stream_type_t) stream, output) );
-            return NO_ERROR;
-        } break;
-        case STREAM_MUTE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int stream = data.readInt32();
-            reply->writeInt32( streamMute((audio_stream_type_t) stream) );
-            return NO_ERROR;
-        } break;
-        case SET_MODE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            audio_mode_t mode = (audio_mode_t) data.readInt32();
-            reply->writeInt32( setMode(mode) );
-            return NO_ERROR;
-        } break;
-        case SET_MIC_MUTE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int state = data.readInt32();
-            reply->writeInt32( setMicMute(state) );
-            return NO_ERROR;
-        } break;
-        case GET_MIC_MUTE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( getMicMute() );
-            return NO_ERROR;
-        } break;
-        case SET_RECORD_SILENCED: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            audio_port_handle_t portId = data.readInt32();
-            bool silenced = data.readInt32() == 1;
-            setRecordSilenced(portId, silenced);
-            return NO_ERROR;
-        } break;
-        case SET_PARAMETERS: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            audio_io_handle_t ioHandle = (audio_io_handle_t) data.readInt32();
-            String8 keyValuePairs(data.readString8());
-            reply->writeInt32(setParameters(ioHandle, keyValuePairs));
-            return NO_ERROR;
-        } break;
-        case GET_PARAMETERS: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            audio_io_handle_t ioHandle = (audio_io_handle_t) data.readInt32();
-            String8 keys(data.readString8());
-            reply->writeString8(getParameters(ioHandle, keys));
-            return NO_ERROR;
-        } break;
-
-        case REGISTER_CLIENT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            sp<media::IAudioFlingerClient> client = interface_cast<media::IAudioFlingerClient>(
-                    data.readStrongBinder());
-            registerClient(client);
-            return NO_ERROR;
-        } break;
-        case GET_INPUTBUFFERSIZE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            uint32_t sampleRate = data.readInt32();
-            audio_format_t format = (audio_format_t) data.readInt32();
-            audio_channel_mask_t channelMask = (audio_channel_mask_t) data.readInt32();
-            reply->writeInt64( getInputBufferSize(sampleRate, format, channelMask) );
-            return NO_ERROR;
-        } break;
-        case OPEN_OUTPUT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            status_t status;
-            media::OpenOutputRequest request;
-            media::OpenOutputResponse response;
-            return data.readParcelable(&request)
-                ?: (status = openOutput(request, &response), OK)
-                ?: reply->writeInt32(status)
-                ?: reply->writeParcelable(response);
-        } break;
-        case OPEN_DUPLICATE_OUTPUT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            audio_io_handle_t output1 = (audio_io_handle_t) data.readInt32();
-            audio_io_handle_t output2 = (audio_io_handle_t) data.readInt32();
-            reply->writeInt32((int32_t) openDuplicateOutput(output1, output2));
-            return NO_ERROR;
-        } break;
-        case CLOSE_OUTPUT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32(closeOutput((audio_io_handle_t) data.readInt32()));
-            return NO_ERROR;
-        } break;
-        case SUSPEND_OUTPUT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32(suspendOutput((audio_io_handle_t) data.readInt32()));
-            return NO_ERROR;
-        } break;
-        case RESTORE_OUTPUT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32(restoreOutput((audio_io_handle_t) data.readInt32()));
-            return NO_ERROR;
-        } break;
-        case OPEN_INPUT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            media::OpenInputRequest request;
-            media::OpenInputResponse response;
-            status_t status;
-            return data.readParcelable(&request)
-                ?: (status = openInput(request, &response), OK)
-                ?: reply->writeInt32(status)
-                ?: reply->writeParcelable(response);
-        } break;
-        case CLOSE_INPUT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32(closeInput((audio_io_handle_t) data.readInt32()));
-            return NO_ERROR;
-        } break;
-        case INVALIDATE_STREAM: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            audio_stream_type_t stream = (audio_stream_type_t) data.readInt32();
-            reply->writeInt32(invalidateStream(stream));
-            return NO_ERROR;
-        } break;
-        case SET_VOICE_VOLUME: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            float volume = data.readFloat();
-            reply->writeInt32( setVoiceVolume(volume) );
-            return NO_ERROR;
-        } break;
-        case GET_RENDER_POSITION: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
-            uint32_t halFrames = 0;
-            uint32_t dspFrames = 0;
-            status_t status = getRenderPosition(&halFrames, &dspFrames, output);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->writeInt32(halFrames);
-                reply->writeInt32(dspFrames);
-            }
-            return NO_ERROR;
-        }
-        case GET_INPUT_FRAMES_LOST: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            audio_io_handle_t ioHandle = (audio_io_handle_t) data.readInt32();
-            reply->writeInt32((int32_t) getInputFramesLost(ioHandle));
-            return NO_ERROR;
-        } break;
-        case NEW_AUDIO_UNIQUE_ID: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32(newAudioUniqueId((audio_unique_id_use_t) data.readInt32()));
-            return NO_ERROR;
-        } break;
-        case ACQUIRE_AUDIO_SESSION_ID: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            audio_session_t audioSession = (audio_session_t) data.readInt32();
-            const pid_t pid = (pid_t)data.readInt32();
-            const uid_t uid = (uid_t)data.readInt32();
-            acquireAudioSessionId(audioSession, pid, uid);
-            return NO_ERROR;
-        } break;
-        case RELEASE_AUDIO_SESSION_ID: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            audio_session_t audioSession = (audio_session_t) data.readInt32();
-            int pid = data.readInt32();
-            releaseAudioSessionId(audioSession, pid);
-            return NO_ERROR;
-        } break;
-        case QUERY_NUM_EFFECTS: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            uint32_t numEffects = 0;
-            status_t status = queryNumberEffects(&numEffects);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->writeInt32((int32_t)numEffects);
-            }
-            return NO_ERROR;
-        }
-        case QUERY_EFFECT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            effect_descriptor_t desc = {};
-            status_t status = queryEffect(data.readInt32(), &desc);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->write(&desc, sizeof(effect_descriptor_t));
-            }
-            return NO_ERROR;
-        }
-        case GET_EFFECT_DESCRIPTOR: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            effect_uuid_t uuid = {};
-            if (data.read(&uuid, sizeof(effect_uuid_t)) != NO_ERROR) {
-                android_errorWriteLog(0x534e4554, "139417189");
-            }
-            effect_uuid_t type = {};
-            if (data.read(&type, sizeof(effect_uuid_t)) != NO_ERROR) {
-                android_errorWriteLog(0x534e4554, "139417189");
-            }
-            uint32_t preferredTypeFlag = data.readUint32();
-            effect_descriptor_t desc = {};
-            status_t status = getEffectDescriptor(&uuid, &type, preferredTypeFlag, &desc);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->write(&desc, sizeof(effect_descriptor_t));
-            }
-            return NO_ERROR;
-        }
-        case CREATE_EFFECT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-
-            media::CreateEffectRequest request;
-            media::CreateEffectResponse response;
-
-            return data.readParcelable(&request)
-                ?: reply->writeInt32(createEffect(request, &response))
-                ?: reply->writeParcelable(response);
-        } break;
-        case MOVE_EFFECTS: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            audio_session_t session = (audio_session_t) data.readInt32();
-            audio_io_handle_t srcOutput = (audio_io_handle_t) data.readInt32();
-            audio_io_handle_t dstOutput = (audio_io_handle_t) data.readInt32();
-            reply->writeInt32(moveEffects(session, srcOutput, dstOutput));
-            return NO_ERROR;
-        } break;
-        case SET_EFFECT_SUSPENDED: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int effectId = data.readInt32();
-            audio_session_t sessionId = (audio_session_t) data.readInt32();
-            bool suspended = data.readInt32() == 1;
-            setEffectSuspended(effectId, sessionId, suspended);
-            return NO_ERROR;
-        } break;
-        case LOAD_HW_MODULE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32(loadHwModule(data.readCString()));
-            return NO_ERROR;
-        } break;
-        case GET_PRIMARY_OUTPUT_SAMPLING_RATE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32(getPrimaryOutputSamplingRate());
-            return NO_ERROR;
-        } break;
-        case GET_PRIMARY_OUTPUT_FRAME_COUNT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt64(getPrimaryOutputFrameCount());
-            return NO_ERROR;
-        } break;
-        case SET_LOW_RAM_DEVICE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int32_t isLowRamDevice;
-            int64_t totalMemory;
-            const status_t status =
-                    data.readInt32(&isLowRamDevice) ?:
-                    data.readInt64(&totalMemory) ?:
-                    setLowRamDevice(isLowRamDevice != 0, totalMemory);
-            (void)reply->writeInt32(status);
-            return NO_ERROR;
-        } break;
-        case LIST_AUDIO_PORTS: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            unsigned int numPortsReq = data.readInt32();
-            if (numPortsReq > MAX_ITEMS_PER_LIST) {
-                numPortsReq = MAX_ITEMS_PER_LIST;
-            }
-            unsigned int numPorts = numPortsReq;
-            struct audio_port *ports =
-                    (struct audio_port *)calloc(numPortsReq,
-                                                           sizeof(struct audio_port));
-            if (ports == NULL) {
-                reply->writeInt32(NO_MEMORY);
-                reply->writeInt32(0);
-                return NO_ERROR;
-            }
-            status_t status = listAudioPorts(&numPorts, ports);
-            reply->writeInt32(status);
-            reply->writeInt32(numPorts);
-            if (status == NO_ERROR) {
-                if (numPortsReq > numPorts) {
-                    numPortsReq = numPorts;
-                }
-                reply->write(ports, numPortsReq * sizeof(struct audio_port));
-            }
-            free(ports);
-            return NO_ERROR;
-        } break;
-        case GET_AUDIO_PORT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            struct audio_port_v7 port = {};
-            status_t status = data.read(&port, sizeof(struct audio_port));
-            if (status != NO_ERROR) {
-                ALOGE("b/23905951");
-                return status;
-            }
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->write(&port, sizeof(struct audio_port_v7));
-            }
-            return NO_ERROR;
-        } break;
-        case CREATE_AUDIO_PATCH: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            struct audio_patch patch;
-            status_t status = data.read(&patch, sizeof(struct audio_patch));
-            if (status != NO_ERROR) {
-                return status;
-            }
-            audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
-            status = data.read(&handle, sizeof(audio_patch_handle_t));
-            if (status != NO_ERROR) {
-                ALOGE("b/23905951");
-                return status;
-            }
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->write(&handle, sizeof(audio_patch_handle_t));
-            }
-            return NO_ERROR;
-        } break;
-        case RELEASE_AUDIO_PATCH: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            audio_patch_handle_t handle;
-            data.read(&handle, sizeof(audio_patch_handle_t));
-            status_t status = releaseAudioPatch(handle);
-            reply->writeInt32(status);
-            return NO_ERROR;
-        } break;
-        case LIST_AUDIO_PATCHES: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            unsigned int numPatchesReq = data.readInt32();
-            if (numPatchesReq > MAX_ITEMS_PER_LIST) {
-                numPatchesReq = MAX_ITEMS_PER_LIST;
-            }
-            unsigned int numPatches = numPatchesReq;
-            struct audio_patch *patches =
-                    (struct audio_patch *)calloc(numPatchesReq,
-                                                 sizeof(struct audio_patch));
-            if (patches == NULL) {
-                reply->writeInt32(NO_MEMORY);
-                reply->writeInt32(0);
-                return NO_ERROR;
-            }
-            status_t status = listAudioPatches(&numPatches, patches);
-            reply->writeInt32(status);
-            reply->writeInt32(numPatches);
-            if (status == NO_ERROR) {
-                if (numPatchesReq > numPatches) {
-                    numPatchesReq = numPatches;
-                }
-                reply->write(patches, numPatchesReq * sizeof(struct audio_patch));
-            }
-            free(patches);
-            return NO_ERROR;
-        } break;
-        case SET_AUDIO_PORT_CONFIG: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            struct audio_port_config config;
-            status_t status = data.read(&config, sizeof(struct audio_port_config));
-            if (status != NO_ERROR) {
-                return status;
-            }
-            reply->writeInt32(status);
-            return NO_ERROR;
-        } break;
-        case GET_AUDIO_HW_SYNC_FOR_SESSION: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32(getAudioHwSyncForSession((audio_session_t) data.readInt32()));
-            return NO_ERROR;
-        } break;
-        case SYSTEM_READY: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            systemReady();
-            return NO_ERROR;
-        } break;
-        case FRAME_COUNT_HAL: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt64( frameCountHAL((audio_io_handle_t) data.readInt32()) );
-            return NO_ERROR;
-        } break;
-        case GET_MICROPHONES: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            std::vector<media::MicrophoneInfo> microphones;
-            status_t status = getMicrophones(&microphones);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->writeParcelableVector(microphones);
-            }
-            return NO_ERROR;
-        }
-        case SET_AUDIO_HAL_PIDS: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            std::vector<pid_t> pids;
-            int32_t size;
-            status_t status = data.readInt32(&size);
-            if (status != NO_ERROR) {
-                return status;
-            }
-            if (size < 0) {
-                return BAD_VALUE;
-            }
-            if (size > MAX_ITEMS_PER_LIST) {
-                size = MAX_ITEMS_PER_LIST;
-            }
-            for (int32_t i = 0; i < size; i++) {
-                int32_t pid;
-                status =  data.readInt32(&pid);
-                if (status != NO_ERROR) {
-                    return status;
-                }
-                pids.push_back(pid);
-            }
-            reply->writeInt32(setAudioHalPids(pids));
-            return NO_ERROR;
-        }
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
+status_t AudioFlingerClientAdapter::createTrack(const media::CreateTrackRequest& input,
+                                                media::CreateTrackResponse& output) {
+    return statusTFromBinderStatus(mDelegate->createTrack(input, &output));
 }
 
-// ----------------------------------------------------------------------------
+status_t AudioFlingerClientAdapter::createRecord(const media::CreateRecordRequest& input,
+                                                 media::CreateRecordResponse& output) {
+    return statusTFromBinderStatus(mDelegate->createRecord(input, &output));
+}
+
+uint32_t AudioFlingerClientAdapter::sampleRate(audio_io_handle_t ioHandle) const {
+    auto result = [&]() -> ConversionResult<uint32_t> {
+        int32_t ioHandleAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(ioHandle));
+        int32_t aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->sampleRate(ioHandleAidl, &aidlRet)));
+        return convertIntegral<uint32_t>(aidlRet);
+    }();
+    // Failure is ignored.
+    return result.value_or(0);
+}
+
+audio_format_t AudioFlingerClientAdapter::format(audio_io_handle_t output) const {
+    auto result = [&]() -> ConversionResult<audio_format_t> {
+        int32_t outputAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(output));
+        media::audio::common::AudioFormat aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->format(outputAidl, &aidlRet)));
+        return aidl2legacy_AudioFormat_audio_format_t(aidlRet);
+    }();
+    return result.value_or(AUDIO_FORMAT_INVALID);
+}
+
+size_t AudioFlingerClientAdapter::frameCount(audio_io_handle_t ioHandle) const {
+    auto result = [&]() -> ConversionResult<size_t> {
+        int32_t ioHandleAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(ioHandle));
+        int64_t aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->frameCount(ioHandleAidl, &aidlRet)));
+        return convertIntegral<size_t>(aidlRet);
+    }();
+    // Failure is ignored.
+    return result.value_or(0);
+}
+
+uint32_t AudioFlingerClientAdapter::latency(audio_io_handle_t output) const {
+    auto result = [&]() -> ConversionResult<uint32_t> {
+        int32_t outputAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(output));
+        int32_t aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->latency(outputAidl, &aidlRet)));
+        return convertIntegral<uint32_t>(aidlRet);
+    }();
+    // Failure is ignored.
+    return result.value_or(0);
+}
+
+status_t AudioFlingerClientAdapter::setMasterVolume(float value) {
+    return statusTFromBinderStatus(mDelegate->setMasterVolume(value));
+}
+
+status_t AudioFlingerClientAdapter::setMasterMute(bool muted) {
+    return statusTFromBinderStatus(mDelegate->setMasterMute(muted));
+}
+
+float AudioFlingerClientAdapter::masterVolume() const {
+    auto result = [&]() -> ConversionResult<float> {
+        float aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->masterVolume(&aidlRet)));
+        return aidlRet;
+    }();
+    // Failure is ignored.
+    return result.value_or(0.f);
+}
+
+bool AudioFlingerClientAdapter::masterMute() const {
+    auto result = [&]() -> ConversionResult<bool> {
+        bool aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->masterMute(&aidlRet)));
+        return aidlRet;
+    }();
+    // Failure is ignored.
+    return result.value_or(false);
+}
+
+status_t AudioFlingerClientAdapter::setMasterBalance(float balance) {
+    return statusTFromBinderStatus(mDelegate->setMasterBalance(balance));
+}
+
+status_t AudioFlingerClientAdapter::getMasterBalance(float* balance) const{
+    return statusTFromBinderStatus(mDelegate->getMasterBalance(balance));
+}
+
+status_t AudioFlingerClientAdapter::setStreamVolume(audio_stream_type_t stream, float value,
+                                                    audio_io_handle_t output) {
+    media::AudioStreamType streamAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_stream_type_t_AudioStreamType(stream));
+    int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+    return statusTFromBinderStatus(mDelegate->setStreamVolume(streamAidl, value, outputAidl));
+}
+
+status_t AudioFlingerClientAdapter::setStreamMute(audio_stream_type_t stream, bool muted) {
+    media::AudioStreamType streamAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_stream_type_t_AudioStreamType(stream));
+    return statusTFromBinderStatus(mDelegate->setStreamMute(streamAidl, muted));
+}
+
+float AudioFlingerClientAdapter::streamVolume(audio_stream_type_t stream,
+                                              audio_io_handle_t output) const {
+    auto result = [&]() -> ConversionResult<float> {
+        media::AudioStreamType streamAidl = VALUE_OR_RETURN_STATUS(
+                legacy2aidl_audio_stream_type_t_AudioStreamType(stream));
+        int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+        float aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(
+                mDelegate->streamVolume(streamAidl, outputAidl, &aidlRet)));
+        return aidlRet;
+    }();
+    // Failure is ignored.
+    return result.value_or(0.f);
+}
+
+bool AudioFlingerClientAdapter::streamMute(audio_stream_type_t stream) const {
+    auto result = [&]() -> ConversionResult<bool> {
+        media::AudioStreamType streamAidl = VALUE_OR_RETURN_STATUS(
+                legacy2aidl_audio_stream_type_t_AudioStreamType(stream));
+        bool aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(
+                mDelegate->streamMute(streamAidl, &aidlRet)));
+        return aidlRet;
+    }();
+    // Failure is ignored.
+    return result.value_or(false);
+}
+
+status_t AudioFlingerClientAdapter::setMode(audio_mode_t mode) {
+    media::AudioMode modeAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_mode_t_AudioMode(mode));
+    return statusTFromBinderStatus(mDelegate->setMode(modeAidl));
+}
+
+status_t AudioFlingerClientAdapter::setMicMute(bool state) {
+    return statusTFromBinderStatus(mDelegate->setMicMute(state));
+}
+
+bool AudioFlingerClientAdapter::getMicMute() const {
+    auto result = [&]() -> ConversionResult<bool> {
+        bool aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(
+                mDelegate->getMicMute(&aidlRet)));
+        return aidlRet;
+    }();
+    // Failure is ignored.
+    return result.value_or(false);
+}
+
+void AudioFlingerClientAdapter::setRecordSilenced(audio_port_handle_t portId, bool silenced) {
+    auto result = [&]() -> status_t {
+        int32_t portIdAidl = VALUE_OR_RETURN_STATUS(
+                legacy2aidl_audio_port_handle_t_int32_t(portId));
+        return statusTFromBinderStatus(mDelegate->setRecordSilenced(portIdAidl, silenced));
+    }();
+    // Failure is ignored.
+    (void) result;
+}
+
+status_t AudioFlingerClientAdapter::setParameters(audio_io_handle_t ioHandle,
+                                                  const String8& keyValuePairs) {
+    int32_t ioHandleAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(ioHandle));
+    std::string keyValuePairsAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_String8_string(keyValuePairs));
+    return statusTFromBinderStatus(mDelegate->setParameters(ioHandleAidl, keyValuePairsAidl));
+}
+
+String8 AudioFlingerClientAdapter::getParameters(audio_io_handle_t ioHandle, const String8& keys)
+const {
+    auto result = [&]() -> ConversionResult<String8> {
+        int32_t ioHandleAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(ioHandle));
+        std::string keysAidl = VALUE_OR_RETURN(legacy2aidl_String8_string(keys));
+        std::string aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(
+                mDelegate->getParameters(ioHandleAidl, keysAidl, &aidlRet)));
+        return aidl2legacy_string_view_String8(aidlRet);
+    }();
+    // Failure is ignored.
+    return result.value_or(String8());
+}
+
+void AudioFlingerClientAdapter::registerClient(const sp<media::IAudioFlingerClient>& client) {
+    mDelegate->registerClient(client);
+    // Failure is ignored.
+}
+
+size_t AudioFlingerClientAdapter::getInputBufferSize(uint32_t sampleRate, audio_format_t format,
+                                                     audio_channel_mask_t channelMask) const {
+    auto result = [&]() -> ConversionResult<size_t> {
+        int32_t sampleRateAidl = VALUE_OR_RETURN(convertIntegral<int32_t>(sampleRate));
+        media::audio::common::AudioFormat formatAidl = VALUE_OR_RETURN(
+                legacy2aidl_audio_format_t_AudioFormat(format));
+        int32_t channelMaskAidl = VALUE_OR_RETURN(
+                legacy2aidl_audio_channel_mask_t_int32_t(channelMask));
+        int64_t aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(
+                mDelegate->getInputBufferSize(sampleRateAidl, formatAidl, channelMaskAidl,
+                                              &aidlRet)));
+        return convertIntegral<size_t>(aidlRet);
+    }();
+    // Failure is ignored.
+    return result.value_or(0);
+}
+
+status_t AudioFlingerClientAdapter::openOutput(const media::OpenOutputRequest& request,
+                                               media::OpenOutputResponse* response) {
+    return statusTFromBinderStatus(mDelegate->openOutput(request, response));
+}
+
+audio_io_handle_t AudioFlingerClientAdapter::openDuplicateOutput(audio_io_handle_t output1,
+                                                                 audio_io_handle_t output2) {
+    auto result = [&]() -> ConversionResult<audio_io_handle_t> {
+        int32_t output1Aidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(output1));
+        int32_t output2Aidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(output2));
+        int32_t aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(
+                mDelegate->openDuplicateOutput(output1Aidl, output2Aidl, &aidlRet)));
+        return aidl2legacy_int32_t_audio_io_handle_t(aidlRet);
+    }();
+    // Failure is ignored.
+    return result.value_or(0);
+}
+
+status_t AudioFlingerClientAdapter::closeOutput(audio_io_handle_t output) {
+    int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+    return statusTFromBinderStatus(mDelegate->closeOutput(outputAidl));
+}
+
+status_t AudioFlingerClientAdapter::suspendOutput(audio_io_handle_t output) {
+    int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+    return statusTFromBinderStatus(mDelegate->suspendOutput(outputAidl));
+}
+
+status_t AudioFlingerClientAdapter::restoreOutput(audio_io_handle_t output) {
+    int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+    return statusTFromBinderStatus(mDelegate->restoreOutput(outputAidl));
+}
+
+status_t AudioFlingerClientAdapter::openInput(const media::OpenInputRequest& request,
+                                              media::OpenInputResponse* response) {
+    return statusTFromBinderStatus(mDelegate->openInput(request, response));
+}
+
+status_t AudioFlingerClientAdapter::closeInput(audio_io_handle_t input) {
+    int32_t inputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(input));
+    return statusTFromBinderStatus(mDelegate->closeInput(inputAidl));
+}
+
+status_t AudioFlingerClientAdapter::invalidateStream(audio_stream_type_t stream) {
+    media::AudioStreamType streamAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_stream_type_t_AudioStreamType(stream));
+    return statusTFromBinderStatus(mDelegate->invalidateStream(streamAidl));
+}
+
+status_t AudioFlingerClientAdapter::setVoiceVolume(float volume) {
+    return statusTFromBinderStatus(mDelegate->setVoiceVolume(volume));
+}
+
+status_t AudioFlingerClientAdapter::getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames,
+                                                      audio_io_handle_t output) const {
+    int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+    media::RenderPosition aidlRet;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+            mDelegate->getRenderPosition(outputAidl, &aidlRet)));
+    if (halFrames != nullptr) {
+        *halFrames = VALUE_OR_RETURN_STATUS(convertIntegral<uint32_t>(aidlRet.halFrames));
+    }
+    if (dspFrames != nullptr) {
+        *dspFrames = VALUE_OR_RETURN_STATUS(convertIntegral<uint32_t>(aidlRet.dspFrames));
+    }
+    return OK;
+}
+
+uint32_t AudioFlingerClientAdapter::getInputFramesLost(audio_io_handle_t ioHandle) const {
+    auto result = [&]() -> ConversionResult<uint32_t> {
+        int32_t ioHandleAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(ioHandle));
+        int32_t aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(
+                mDelegate->getInputFramesLost(ioHandleAidl, &aidlRet)));
+        return convertIntegral<uint32_t>(aidlRet);
+    }();
+    // Failure is ignored.
+    return result.value_or(0);
+}
+
+audio_unique_id_t AudioFlingerClientAdapter::newAudioUniqueId(audio_unique_id_use_t use) {
+    auto result = [&]() -> ConversionResult<audio_unique_id_t> {
+        media::AudioUniqueIdUse useAidl = VALUE_OR_RETURN(
+                legacy2aidl_audio_unique_id_use_t_AudioUniqueIdUse(use));
+        int32_t aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(
+                mDelegate->newAudioUniqueId(useAidl, &aidlRet)));
+        return aidl2legacy_int32_t_audio_unique_id_t(aidlRet);
+    }();
+    return result.value_or(AUDIO_UNIQUE_ID_ALLOCATE);
+}
+
+void AudioFlingerClientAdapter::acquireAudioSessionId(audio_session_t audioSession, pid_t pid,
+                                                      uid_t uid) {
+    [&]() -> status_t {
+        int32_t audioSessionAidl = VALUE_OR_RETURN_STATUS(
+                legacy2aidl_audio_session_t_int32_t(audioSession));
+        int32_t pidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(pid));
+        int32_t uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(uid));
+        return statusTFromBinderStatus(
+                mDelegate->acquireAudioSessionId(audioSessionAidl, pidAidl, uidAidl));
+    }();
+    // Failure is ignored.
+}
+
+void AudioFlingerClientAdapter::releaseAudioSessionId(audio_session_t audioSession, pid_t pid) {
+    [&]() -> status_t {
+        int32_t audioSessionAidl = VALUE_OR_RETURN_STATUS(
+                legacy2aidl_audio_session_t_int32_t(audioSession));
+        int32_t pidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(pid));
+        return statusTFromBinderStatus(
+                mDelegate->releaseAudioSessionId(audioSessionAidl, pidAidl));
+    }();
+    // Failure is ignored.
+}
+
+status_t AudioFlingerClientAdapter::queryNumberEffects(uint32_t* numEffects) const {
+    int32_t aidlRet;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+            mDelegate->queryNumberEffects(&aidlRet)));
+    if (numEffects != nullptr) {
+        *numEffects = VALUE_OR_RETURN_STATUS(convertIntegral<uint32_t>(aidlRet));
+    }
+    return OK;
+}
+
+status_t
+AudioFlingerClientAdapter::queryEffect(uint32_t index, effect_descriptor_t* pDescriptor) const {
+    int32_t indexAidl = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(index));
+    media::EffectDescriptor aidlRet;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+            mDelegate->queryEffect(indexAidl, &aidlRet)));
+    if (pDescriptor != nullptr) {
+        *pDescriptor = VALUE_OR_RETURN_STATUS(
+                aidl2legacy_EffectDescriptor_effect_descriptor_t(aidlRet));
+    }
+    return OK;
+}
+
+status_t AudioFlingerClientAdapter::getEffectDescriptor(const effect_uuid_t* pEffectUUID,
+                                                        const effect_uuid_t* pTypeUUID,
+                                                        uint32_t preferredTypeFlag,
+                                                        effect_descriptor_t* pDescriptor) const {
+    media::AudioUuid effectUuidAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_uuid_t_AudioUuid(*pEffectUUID));
+    media::AudioUuid typeUuidAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_uuid_t_AudioUuid(*pTypeUUID));
+    int32_t preferredTypeFlagAidl = VALUE_OR_RETURN_STATUS(
+            convertReinterpret<int32_t>(preferredTypeFlag));
+    media::EffectDescriptor aidlRet;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+            mDelegate->getEffectDescriptor(effectUuidAidl, typeUuidAidl, preferredTypeFlagAidl,
+                                           &aidlRet)));
+    if (pDescriptor != nullptr) {
+        *pDescriptor = VALUE_OR_RETURN_STATUS(
+                aidl2legacy_EffectDescriptor_effect_descriptor_t(aidlRet));
+    }
+    return OK;
+}
+
+status_t AudioFlingerClientAdapter::createEffect(const media::CreateEffectRequest& request,
+                                                 media::CreateEffectResponse* response) {
+    return statusTFromBinderStatus(mDelegate->createEffect(request, response));
+}
+
+status_t
+AudioFlingerClientAdapter::moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
+                                       audio_io_handle_t dstOutput) {
+    int32_t sessionAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_session_t_int32_t(session));
+    int32_t srcOutputAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_io_handle_t_int32_t(srcOutput));
+    int32_t dstOutputAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_io_handle_t_int32_t(dstOutput));
+    return statusTFromBinderStatus(
+            mDelegate->moveEffects(sessionAidl, srcOutputAidl, dstOutputAidl));
+}
+
+void AudioFlingerClientAdapter::setEffectSuspended(int effectId,
+                                                   audio_session_t sessionId,
+                                                   bool suspended) {
+    [&]() -> status_t {
+        int32_t effectIdAidl = VALUE_OR_RETURN_STATUS(convertReinterpret<int32_t>(effectId));
+        int32_t sessionIdAidl = VALUE_OR_RETURN_STATUS(
+                legacy2aidl_audio_session_t_int32_t(sessionId));
+        return statusTFromBinderStatus(
+                mDelegate->setEffectSuspended(effectIdAidl, sessionIdAidl, suspended));
+    }();
+    // Failure is ignored.
+}
+
+audio_module_handle_t AudioFlingerClientAdapter::loadHwModule(const char* name) {
+    auto result = [&]() -> ConversionResult<audio_module_handle_t> {
+        std::string nameAidl(name);
+        int32_t aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(
+                mDelegate->loadHwModule(nameAidl, &aidlRet)));
+        return aidl2legacy_int32_t_audio_module_handle_t(aidlRet);
+    }();
+    // Failure is ignored.
+    return result.value_or(0);
+}
+
+uint32_t AudioFlingerClientAdapter::getPrimaryOutputSamplingRate() {
+    auto result = [&]() -> ConversionResult<uint32_t> {
+        int32_t aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(
+                mDelegate->getPrimaryOutputSamplingRate(&aidlRet)));
+        return convertIntegral<uint32_t>(aidlRet);
+    }();
+    // Failure is ignored.
+    return result.value_or(0);
+}
+
+size_t AudioFlingerClientAdapter::getPrimaryOutputFrameCount() {
+    auto result = [&]() -> ConversionResult<size_t> {
+        int64_t aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(
+                mDelegate->getPrimaryOutputFrameCount(&aidlRet)));
+        return convertIntegral<size_t>(aidlRet);
+    }();
+    // Failure is ignored.
+    return result.value_or(0);
+}
+
+status_t AudioFlingerClientAdapter::setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) {
+    return statusTFromBinderStatus(mDelegate->setLowRamDevice(isLowRamDevice, totalMemory));
+}
+
+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;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+            mDelegate->getAudioPort(portAidl, &aidlRet)));
+    *port = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPort_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));
+    int32_t aidlRet;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+            mDelegate->createAudioPatch(patchAidl, &aidlRet)));
+    if (handle != nullptr) {
+        *handle = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_patch_handle_t(aidlRet));
+    }
+    return OK;
+}
+
+status_t AudioFlingerClientAdapter::releaseAudioPatch(audio_patch_handle_t handle) {
+    int32_t handleAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_patch_handle_t_int32_t(handle));
+    return statusTFromBinderStatus(mDelegate->releaseAudioPatch(handleAidl));
+}
+
+status_t AudioFlingerClientAdapter::listAudioPatches(unsigned int* num_patches,
+                                                     struct audio_patch* patches) {
+    std::vector<media::AudioPatch> 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);
+}
+
+status_t AudioFlingerClientAdapter::setAudioPortConfig(const struct audio_port_config* config) {
+    media::AudioPortConfig configAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_port_config_AudioPortConfig(*config));
+    return statusTFromBinderStatus(mDelegate->setAudioPortConfig(configAidl));
+}
+
+audio_hw_sync_t AudioFlingerClientAdapter::getAudioHwSyncForSession(audio_session_t sessionId) {
+    auto result = [&]() -> ConversionResult<audio_hw_sync_t> {
+        int32_t sessionIdAidl = VALUE_OR_RETURN(legacy2aidl_audio_session_t_int32_t(sessionId));
+        int32_t aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(
+                mDelegate->getAudioHwSyncForSession(sessionIdAidl, &aidlRet)));
+        return aidl2legacy_int32_t_audio_hw_sync_t(aidlRet);
+    }();
+    return result.value_or(AUDIO_HW_SYNC_INVALID);
+}
+
+status_t AudioFlingerClientAdapter::systemReady() {
+    return statusTFromBinderStatus(mDelegate->systemReady());
+}
+
+size_t AudioFlingerClientAdapter::frameCountHAL(audio_io_handle_t ioHandle) const {
+    auto result = [&]() -> ConversionResult<size_t> {
+        int32_t ioHandleAidl = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(ioHandle));
+        int64_t aidlRet;
+        RETURN_IF_ERROR(statusTFromBinderStatus(
+                mDelegate->frameCountHAL(ioHandleAidl, &aidlRet)));
+        return convertIntegral<size_t>(aidlRet);
+    }();
+    // Failure is ignored.
+    return result.value_or(0);
+}
+
+status_t
+AudioFlingerClientAdapter::getMicrophones(std::vector<media::MicrophoneInfo>* microphones) {
+    std::vector<media::MicrophoneInfoData> 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));
+    }
+    return OK;
+}
+
+status_t AudioFlingerClientAdapter::setAudioHalPids(const std::vector<pid_t>& pids) {
+    std::vector<int32_t> pidsAidl = VALUE_OR_RETURN_STATUS(
+            convertContainer<std::vector<int32_t>>(pids, legacy2aidl_pid_t_int32_t));
+    return statusTFromBinderStatus(mDelegate->setAudioHalPids(pidsAidl));
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// AudioFlingerServerAdapter
+AudioFlingerServerAdapter::AudioFlingerServerAdapter(
+        const sp<AudioFlingerServerAdapter::Delegate>& delegate) : mDelegate(delegate) {}
+
+status_t AudioFlingerServerAdapter::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                               uint32_t flags) {
+    return mDelegate->onPreTransact(static_cast<Delegate::TransactionCode>(code), data, flags)
+           ?: BnAudioFlingerService::onTransact(code, data, reply, flags);
+}
+
+status_t AudioFlingerServerAdapter::dump(int fd, const Vector<String16>& args) {
+    return mDelegate->dump(fd, args);
+}
+
+Status AudioFlingerServerAdapter::createTrack(const media::CreateTrackRequest& request,
+                                              media::CreateTrackResponse* _aidl_return) {
+    return Status::fromStatusT(mDelegate->createTrack(request, *_aidl_return));
+}
+
+Status AudioFlingerServerAdapter::createRecord(const media::CreateRecordRequest& request,
+                                               media::CreateRecordResponse* _aidl_return) {
+    return Status::fromStatusT(mDelegate->createRecord(request, *_aidl_return));
+}
+
+Status AudioFlingerServerAdapter::sampleRate(int32_t ioHandle, int32_t* _aidl_return) {
+    audio_io_handle_t ioHandleLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(ioHandle));
+    *_aidl_return = VALUE_OR_RETURN_BINDER(
+            convertIntegral<int32_t>(mDelegate->sampleRate(ioHandleLegacy)));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::format(int32_t output,
+                                         media::audio::common::AudioFormat* _aidl_return) {
+    audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(output));
+    *_aidl_return = VALUE_OR_RETURN_BINDER(
+            legacy2aidl_audio_format_t_AudioFormat(mDelegate->format(outputLegacy)));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::frameCount(int32_t ioHandle, int64_t* _aidl_return) {
+    audio_io_handle_t ioHandleLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(ioHandle));
+    *_aidl_return = VALUE_OR_RETURN_BINDER(
+            convertIntegral<int64_t>(mDelegate->frameCount(ioHandleLegacy)));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::latency(int32_t output, int32_t* _aidl_return) {
+    audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(output));
+    *_aidl_return = VALUE_OR_RETURN_BINDER(
+            convertIntegral<int32_t>(mDelegate->latency(outputLegacy)));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::setMasterVolume(float value) {
+    return Status::fromStatusT(mDelegate->setMasterVolume(value));
+}
+
+Status AudioFlingerServerAdapter::setMasterMute(bool muted) {
+    return Status::fromStatusT(mDelegate->setMasterMute(muted));
+}
+
+Status AudioFlingerServerAdapter::masterVolume(float* _aidl_return) {
+    *_aidl_return = mDelegate->masterVolume();
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::masterMute(bool* _aidl_return) {
+    *_aidl_return = mDelegate->masterMute();
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::setMasterBalance(float balance) {
+    return Status::fromStatusT(mDelegate->setMasterBalance(balance));
+}
+
+Status AudioFlingerServerAdapter::getMasterBalance(float* _aidl_return) {
+    return Status::fromStatusT(mDelegate->getMasterBalance(_aidl_return));
+}
+
+Status AudioFlingerServerAdapter::setStreamVolume(media::AudioStreamType stream, float value,
+                                                  int32_t output) {
+    audio_stream_type_t streamLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_AudioStreamType_audio_stream_type_t(stream));
+    audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(output));
+    return Status::fromStatusT(mDelegate->setStreamVolume(streamLegacy, value, outputLegacy));
+}
+
+Status AudioFlingerServerAdapter::setStreamMute(media::AudioStreamType stream, bool muted) {
+    audio_stream_type_t streamLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_AudioStreamType_audio_stream_type_t(stream));
+    return Status::fromStatusT(mDelegate->setStreamMute(streamLegacy, muted));
+}
+
+Status AudioFlingerServerAdapter::streamVolume(media::AudioStreamType stream, int32_t output,
+                                               float* _aidl_return) {
+    audio_stream_type_t streamLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_AudioStreamType_audio_stream_type_t(stream));
+    audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(output));
+    *_aidl_return = mDelegate->streamVolume(streamLegacy, outputLegacy);
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::streamMute(media::AudioStreamType stream, bool* _aidl_return) {
+    audio_stream_type_t streamLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_AudioStreamType_audio_stream_type_t(stream));
+    *_aidl_return = mDelegate->streamMute(streamLegacy);
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::setMode(media::AudioMode mode) {
+    audio_mode_t modeLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioMode_audio_mode_t(mode));
+    return Status::fromStatusT(mDelegate->setMode(modeLegacy));
+}
+
+Status AudioFlingerServerAdapter::setMicMute(bool state) {
+    return Status::fromStatusT(mDelegate->setMicMute(state));
+}
+
+Status AudioFlingerServerAdapter::getMicMute(bool* _aidl_return) {
+    *_aidl_return = mDelegate->getMicMute();
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::setRecordSilenced(int32_t portId, bool silenced) {
+    audio_port_handle_t portIdLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_port_handle_t(portId));
+    mDelegate->setRecordSilenced(portIdLegacy, silenced);
+    return Status::ok();
+}
+
+Status
+AudioFlingerServerAdapter::setParameters(int32_t ioHandle, const std::string& keyValuePairs) {
+    audio_io_handle_t ioHandleLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(ioHandle));
+    String8 keyValuePairsLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_string_view_String8(keyValuePairs));
+    return Status::fromStatusT(mDelegate->setParameters(ioHandleLegacy, keyValuePairsLegacy));
+}
+
+Status AudioFlingerServerAdapter::getParameters(int32_t ioHandle, const std::string& keys,
+                                                std::string* _aidl_return) {
+    audio_io_handle_t ioHandleLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(ioHandle));
+    String8 keysLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_string_view_String8(keys));
+    *_aidl_return = VALUE_OR_RETURN_BINDER(
+            legacy2aidl_String8_string(mDelegate->getParameters(ioHandleLegacy, keysLegacy)));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::registerClient(const sp<media::IAudioFlingerClient>& client) {
+    mDelegate->registerClient(client);
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::getInputBufferSize(int32_t sampleRate,
+                                                     media::audio::common::AudioFormat format,
+                                                     int32_t channelMask, int64_t* _aidl_return) {
+    uint32_t sampleRateLegacy = VALUE_OR_RETURN_BINDER(convertIntegral<uint32_t>(sampleRate));
+    audio_format_t formatLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_AudioFormat_audio_format_t(format));
+    audio_channel_mask_t channelMaskLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_channel_mask_t(channelMask));
+    size_t size = mDelegate->getInputBufferSize(sampleRateLegacy, formatLegacy, channelMaskLegacy);
+    *_aidl_return = VALUE_OR_RETURN_BINDER(convertIntegral<int64_t>(size));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::openOutput(const media::OpenOutputRequest& request,
+                                             media::OpenOutputResponse* _aidl_return) {
+    return Status::fromStatusT(mDelegate->openOutput(request, _aidl_return));
+}
+
+Status AudioFlingerServerAdapter::openDuplicateOutput(int32_t output1, int32_t output2,
+                                                      int32_t* _aidl_return) {
+    audio_io_handle_t output1Legacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(output1));
+    audio_io_handle_t output2Legacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(output2));
+    audio_io_handle_t result = mDelegate->openDuplicateOutput(output1Legacy, output2Legacy);
+    *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_io_handle_t_int32_t(result));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::closeOutput(int32_t output) {
+    audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(output));
+    return Status::fromStatusT(mDelegate->closeOutput(outputLegacy));
+}
+
+Status AudioFlingerServerAdapter::suspendOutput(int32_t output) {
+    audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(output));
+    return Status::fromStatusT(mDelegate->suspendOutput(outputLegacy));
+}
+
+Status AudioFlingerServerAdapter::restoreOutput(int32_t output) {
+    audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(output));
+    return Status::fromStatusT(mDelegate->restoreOutput(outputLegacy));
+}
+
+Status AudioFlingerServerAdapter::openInput(const media::OpenInputRequest& request,
+                                            media::OpenInputResponse* _aidl_return) {
+    return Status::fromStatusT(mDelegate->openInput(request, _aidl_return));
+}
+
+Status AudioFlingerServerAdapter::closeInput(int32_t input) {
+    audio_io_handle_t inputLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(input));
+    return Status::fromStatusT(mDelegate->closeInput(inputLegacy));
+}
+
+Status AudioFlingerServerAdapter::invalidateStream(media::AudioStreamType stream) {
+    audio_stream_type_t streamLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_AudioStreamType_audio_stream_type_t(stream));
+    return Status::fromStatusT(mDelegate->invalidateStream(streamLegacy));
+}
+
+Status AudioFlingerServerAdapter::setVoiceVolume(float volume) {
+    return Status::fromStatusT(mDelegate->setVoiceVolume(volume));
+}
+
+Status
+AudioFlingerServerAdapter::getRenderPosition(int32_t output, media::RenderPosition* _aidl_return) {
+    audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(output));
+    uint32_t halFramesLegacy;
+    uint32_t dspFramesLegacy;
+    RETURN_BINDER_IF_ERROR(
+            mDelegate->getRenderPosition(&halFramesLegacy, &dspFramesLegacy, outputLegacy));
+    _aidl_return->halFrames = VALUE_OR_RETURN_BINDER(convertIntegral<int32_t>(halFramesLegacy));
+    _aidl_return->dspFrames = VALUE_OR_RETURN_BINDER(convertIntegral<int32_t>(dspFramesLegacy));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::getInputFramesLost(int32_t ioHandle, int32_t* _aidl_return) {
+    audio_io_handle_t ioHandleLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(ioHandle));
+    uint32_t result = mDelegate->getInputFramesLost(ioHandleLegacy);
+    *_aidl_return = VALUE_OR_RETURN_BINDER(convertIntegral<int32_t>(result));
+    return Status::ok();
+}
+
+Status
+AudioFlingerServerAdapter::newAudioUniqueId(media::AudioUniqueIdUse use, int32_t* _aidl_return) {
+    audio_unique_id_use_t useLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_AudioUniqueIdUse_audio_unique_id_use_t(use));
+    audio_unique_id_t result = mDelegate->newAudioUniqueId(useLegacy);
+    *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_unique_id_t_int32_t(result));
+    return Status::ok();
+}
+
+Status
+AudioFlingerServerAdapter::acquireAudioSessionId(int32_t audioSession, int32_t pid, int32_t uid) {
+    audio_session_t audioSessionLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_session_t(audioSession));
+    pid_t pidLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_int32_t_pid_t(pid));
+    uid_t uidLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_int32_t_uid_t(uid));
+    mDelegate->acquireAudioSessionId(audioSessionLegacy, pidLegacy, uidLegacy);
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::releaseAudioSessionId(int32_t audioSession, int32_t pid) {
+    audio_session_t audioSessionLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_session_t(audioSession));
+    pid_t pidLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_int32_t_pid_t(pid));
+    mDelegate->releaseAudioSessionId(audioSessionLegacy, pidLegacy);
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::queryNumberEffects(int32_t* _aidl_return) {
+    uint32_t result;
+    RETURN_BINDER_IF_ERROR(mDelegate->queryNumberEffects(&result));
+    *_aidl_return = VALUE_OR_RETURN_BINDER(convertIntegral<uint32_t>(result));
+    return Status::ok();
+}
+
+Status
+AudioFlingerServerAdapter::queryEffect(int32_t index, media::EffectDescriptor* _aidl_return) {
+    uint32_t indexLegacy = VALUE_OR_RETURN_BINDER(convertIntegral<uint32_t>(index));
+    effect_descriptor_t result;
+    RETURN_BINDER_IF_ERROR(mDelegate->queryEffect(indexLegacy, &result));
+    *_aidl_return = VALUE_OR_RETURN_BINDER(
+            legacy2aidl_effect_descriptor_t_EffectDescriptor(result));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::getEffectDescriptor(const media::AudioUuid& effectUUID,
+                                                      const media::AudioUuid& typeUUID,
+                                                      int32_t preferredTypeFlag,
+                                                      media::EffectDescriptor* _aidl_return) {
+    effect_uuid_t effectUuidLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_AudioUuid_audio_uuid_t(effectUUID));
+    effect_uuid_t typeUuidLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_AudioUuid_audio_uuid_t(typeUUID));
+    uint32_t preferredTypeFlagLegacy = VALUE_OR_RETURN_BINDER(
+            convertReinterpret<uint32_t>(preferredTypeFlag));
+    effect_descriptor_t result;
+    RETURN_BINDER_IF_ERROR(mDelegate->getEffectDescriptor(&effectUuidLegacy, &typeUuidLegacy,
+                                                          preferredTypeFlagLegacy, &result));
+    *_aidl_return = VALUE_OR_RETURN_BINDER(
+            legacy2aidl_effect_descriptor_t_EffectDescriptor(result));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::createEffect(const media::CreateEffectRequest& request,
+                                               media::CreateEffectResponse* _aidl_return) {
+    return Status::fromStatusT(mDelegate->createEffect(request, _aidl_return));
+}
+
+Status
+AudioFlingerServerAdapter::moveEffects(int32_t session, int32_t srcOutput, int32_t dstOutput) {
+    audio_session_t sessionLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_session_t(session));
+    audio_io_handle_t srcOutputLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(srcOutput));
+    audio_io_handle_t dstOutputLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(dstOutput));
+    return Status::fromStatusT(
+            mDelegate->moveEffects(sessionLegacy, srcOutputLegacy, dstOutputLegacy));
+}
+
+Status AudioFlingerServerAdapter::setEffectSuspended(int32_t effectId, int32_t sessionId,
+                                                     bool suspended) {
+    int effectIdLegacy = VALUE_OR_RETURN_BINDER(convertReinterpret<int>(effectId));
+    audio_session_t sessionIdLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_session_t(sessionId));
+    mDelegate->setEffectSuspended(effectIdLegacy, sessionIdLegacy, suspended);
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::loadHwModule(const std::string& name, int32_t* _aidl_return) {
+    audio_module_handle_t result = mDelegate->loadHwModule(name.c_str());
+    *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_module_handle_t_int32_t(result));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::getPrimaryOutputSamplingRate(int32_t* _aidl_return) {
+    *_aidl_return = VALUE_OR_RETURN_BINDER(
+            convertIntegral<int32_t>(mDelegate->getPrimaryOutputSamplingRate()));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::getPrimaryOutputFrameCount(int64_t* _aidl_return) {
+    *_aidl_return = VALUE_OR_RETURN_BINDER(
+            convertIntegral<int64_t>(mDelegate->getPrimaryOutputFrameCount()));
+    return Status::ok();
+
+}
+
+Status AudioFlingerServerAdapter::setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) {
+    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));
+    RETURN_BINDER_IF_ERROR(mDelegate->getAudioPort(&portLegacy));
+    *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_port_v7_AudioPort(portLegacy));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::createAudioPatch(const media::AudioPatch& patch,
+                                                   int32_t* _aidl_return) {
+    audio_patch patchLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPatch_audio_patch(patch));
+    audio_patch_handle_t handleLegacy;
+    RETURN_BINDER_IF_ERROR(mDelegate->createAudioPatch(&patchLegacy, &handleLegacy));
+    *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_patch_handle_t_int32_t(handleLegacy));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::releaseAudioPatch(int32_t handle) {
+    audio_patch_handle_t handleLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_patch_handle_t(handle));
+    return Status::fromStatusT(mDelegate->releaseAudioPatch(handleLegacy));
+}
+
+Status AudioFlingerServerAdapter::listAudioPatches(int32_t maxCount,
+                            std::vector<media::AudioPatch>* _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]);
+    RETURN_BINDER_IF_ERROR(mDelegate->listAudioPatches(&count, patchesLegacy.get()));
+    RETURN_BINDER_IF_ERROR(convertRange(&patchesLegacy[0],
+                           &patchesLegacy[count],
+                           std::back_inserter(*_aidl_return),
+                           legacy2aidl_audio_patch_AudioPatch));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::setAudioPortConfig(const media::AudioPortConfig& config) {
+    audio_port_config configLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_AudioPortConfig_audio_port_config(config));
+    return Status::fromStatusT(mDelegate->setAudioPortConfig(&configLegacy));
+}
+
+Status AudioFlingerServerAdapter::getAudioHwSyncForSession(int32_t sessionId,
+                                                           int32_t* _aidl_return) {
+    audio_session_t sessionIdLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_session_t(sessionId));
+    audio_hw_sync_t result = mDelegate->getAudioHwSyncForSession(sessionIdLegacy);
+    *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_hw_sync_t_int32_t(result));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::systemReady() {
+    return Status::fromStatusT(mDelegate->systemReady());
+}
+
+Status AudioFlingerServerAdapter::frameCountHAL(int32_t ioHandle, int64_t* _aidl_return) {
+    audio_io_handle_t ioHandleLegacy = VALUE_OR_RETURN_BINDER(
+            aidl2legacy_int32_t_audio_io_handle_t(ioHandle));
+    size_t result = mDelegate->frameCountHAL(ioHandleLegacy);
+    *_aidl_return = VALUE_OR_RETURN_BINDER(convertIntegral<int64_t>(result));
+    return Status::ok();
+}
+
+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));
+    return Status::ok();
+}
+
+Status AudioFlingerServerAdapter::setAudioHalPids(const std::vector<int32_t>& pids) {
+    std::vector<pid_t> pidsLegacy = VALUE_OR_RETURN_BINDER(
+            convertContainer<std::vector<pid_t>>(pids, aidl2legacy_int32_t_pid_t));
+    RETURN_BINDER_IF_ERROR(mDelegate->setAudioHalPids(pidsLegacy));
+    return Status::ok();
+}
 
 } // namespace android
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 4132244..0849e61 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -69,7 +69,7 @@
     QUERY_DEFAULT_PRE_PROCESSING,
     SET_EFFECT_ENABLED,
     IS_STREAM_ACTIVE_REMOTELY,
-    IS_OFFLOAD_SUPPORTED,
+    GET_OFFLOAD_MODE_SUPPORTED,
     IS_DIRECT_OUTPUT_SUPPORTED,
     LIST_AUDIO_PORTS,
     GET_AUDIO_PORT,
@@ -666,13 +666,13 @@
         return reply.readInt32();
     }
 
-    virtual bool isOffloadSupported(const audio_offload_info_t& info)
+    virtual audio_offload_mode_t getOffloadSupport(const audio_offload_info_t& info)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.write(&info, sizeof(audio_offload_info_t));
-        remote()->transact(IS_OFFLOAD_SUPPORTED, data, &reply);
-        return reply.readInt32();
+        remote()->transact(GET_OFFLOAD_MODE_SUPPORTED, data, &reply);
+        return static_cast<audio_offload_mode_t>(reply.readInt32());
     }
 
     virtual bool isDirectOutputSupported(const audio_config_base_t& config,
@@ -688,7 +688,7 @@
     virtual status_t listAudioPorts(audio_port_role_t role,
                                     audio_port_type_t type,
                                     unsigned int *num_ports,
-                                    struct audio_port *ports,
+                                    struct audio_port_v7 *ports,
                                     unsigned int *generation)
     {
         if (num_ports == NULL || (*num_ports != 0 && ports == NULL) ||
@@ -711,27 +711,27 @@
                 numPortsReq = *num_ports;
             }
             if (numPortsReq > 0) {
-                reply.read(ports, numPortsReq * sizeof(struct audio_port));
+                reply.read(ports, numPortsReq * sizeof(struct audio_port_v7));
             }
             *generation = reply.readInt32();
         }
         return status;
     }
 
-    virtual status_t getAudioPort(struct audio_port *port)
+    virtual status_t getAudioPort(struct audio_port_v7 *port)
     {
         if (port == NULL) {
             return BAD_VALUE;
         }
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
-        data.write(port, sizeof(struct audio_port));
+        data.write(port, sizeof(struct audio_port_v7));
         status_t status = remote()->transact(GET_AUDIO_PORT, data, &reply);
         if (status != NO_ERROR ||
                 (status = (status_t)reply.readInt32()) != NO_ERROR) {
             return status;
         }
-        reply.read(port, sizeof(struct audio_port));
+        reply.read(port, sizeof(struct audio_port_v7));
         return status;
     }
 
@@ -810,7 +810,7 @@
         return status;
     }
 
-    virtual void registerClient(const sp<IAudioPolicyServiceClient>& client)
+    virtual void registerClient(const sp<media::IAudioPolicyServiceClient>& client)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -1591,6 +1591,7 @@
         case REGISTER_EFFECT:
         case UNREGISTER_EFFECT:
         case SET_EFFECT_ENABLED:
+        case GET_STRATEGY_FOR_STREAM:
         case GET_OUTPUT_FOR_ATTR:
         case MOVE_EFFECTS_TO_IO:
             ALOGW("%s: transaction %d received from PID %d",
@@ -1619,6 +1620,14 @@
         case INIT_STREAM_VOLUME:
         case SET_STREAM_VOLUME:
         case SET_VOLUME_ATTRIBUTES:
+        case GET_STREAM_VOLUME:
+        case GET_VOLUME_ATTRIBUTES:
+        case GET_MIN_VOLUME_FOR_ATTRIBUTES:
+        case GET_MAX_VOLUME_FOR_ATTRIBUTES:
+        case IS_STREAM_ACTIVE:
+        case IS_STREAM_ACTIVE_REMOTELY:
+        case IS_SOURCE_ACTIVE:
+        case GET_DEVICES_FOR_STREAM:
         case REGISTER_POLICY_MIXES:
         case SET_MASTER_MONO:
         case GET_SURROUND_FORMATS:
@@ -2140,12 +2149,11 @@
             return status;
         }
 
-        case IS_OFFLOAD_SUPPORTED: {
+        case GET_OFFLOAD_MODE_SUPPORTED: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_offload_info_t info = {};
             data.read(&info, sizeof(audio_offload_info_t));
-            bool isSupported = isOffloadSupported(info);
-            reply->writeInt32(isSupported);
+            reply->writeInt32(static_cast<int32_t>(getOffloadSupport(info)));
             return NO_ERROR;
         }
 
@@ -2174,8 +2182,8 @@
                 numPortsReq = MAX_ITEMS_PER_LIST;
             }
             unsigned int numPorts = numPortsReq;
-            struct audio_port *ports =
-                    (struct audio_port *)calloc(numPortsReq, sizeof(struct audio_port));
+            struct audio_port_v7 *ports =
+                    (struct audio_port_v7 *)calloc(numPortsReq, sizeof(struct audio_port_v7));
             if (ports == NULL) {
                 reply->writeInt32(NO_MEMORY);
                 reply->writeInt32(0);
@@ -2190,7 +2198,7 @@
                 if (numPortsReq > numPorts) {
                     numPortsReq = numPorts;
                 }
-                reply->write(ports, numPortsReq * sizeof(struct audio_port));
+                reply->write(ports, numPortsReq * sizeof(struct audio_port_v7));
                 reply->writeInt32(generation);
             }
             free(ports);
@@ -2199,8 +2207,8 @@
 
         case GET_AUDIO_PORT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            struct audio_port port = {};
-            status_t status = data.read(&port, sizeof(struct audio_port));
+            struct audio_port_v7 port = {};
+            status_t status = data.read(&port, sizeof(struct audio_port_v7));
             if (status != NO_ERROR) {
                 ALOGE("b/23912202");
                 return status;
@@ -2211,7 +2219,7 @@
             }
             reply->writeInt32(status);
             if (status == NO_ERROR) {
-                reply->write(&port, sizeof(struct audio_port));
+                reply->write(&port, sizeof(struct audio_port_v7));
             }
             return NO_ERROR;
         }
@@ -2296,8 +2304,8 @@
 
         case REGISTER_CLIENT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>(
-                    data.readStrongBinder());
+            sp<media::IAudioPolicyServiceClient> client =
+                    interface_cast<media::IAudioPolicyServiceClient>(data.readStrongBinder());
             registerClient(client);
             return NO_ERROR;
         } break;
diff --git a/media/libaudioclient/IAudioPolicyServiceClient.cpp b/media/libaudioclient/IAudioPolicyServiceClient.cpp
deleted file mode 100644
index 0f9580c..0000000
--- a/media/libaudioclient/IAudioPolicyServiceClient.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2009 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 "IAudioPolicyServiceClient"
-#include <utils/Log.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-
-#include <media/IAudioPolicyServiceClient.h>
-#include <media/AudioSystem.h>
-
-namespace android {
-
-enum {
-    PORT_LIST_UPDATE = IBinder::FIRST_CALL_TRANSACTION,
-    PATCH_LIST_UPDATE,
-    MIX_STATE_UPDATE,
-    RECORDING_CONFIGURATION_UPDATE,
-    VOLUME_GROUP_CHANGED,
-};
-
-// ----------------------------------------------------------------------
-inline void readAudioConfigBaseFromParcel(const Parcel& data, audio_config_base_t *config) {
-    config->sample_rate = data.readUint32();
-    config->channel_mask = (audio_channel_mask_t) data.readInt32();
-    config->format = (audio_format_t) data.readInt32();
-}
-
-inline void writeAudioConfigBaseToParcel(Parcel& data, const audio_config_base_t *config)
-{
-    data.writeUint32(config->sample_rate);
-    data.writeInt32((int32_t) config->channel_mask);
-    data.writeInt32((int32_t) config->format);
-}
-
-inline void readRecordClientInfoFromParcel(const Parcel& data, record_client_info_t *clientInfo) {
-    clientInfo->riid = (audio_unique_id_t) data.readInt32();
-    clientInfo->uid = (uid_t) data.readUint32();
-    clientInfo->session = (audio_session_t) data.readInt32();
-    clientInfo->source = (audio_source_t) data.readInt32();
-    data.read(&clientInfo->port_id, sizeof(audio_port_handle_t));
-    clientInfo->silenced = data.readBool();
-}
-
-inline void writeRecordClientInfoToParcel(Parcel& data, const record_client_info_t *clientInfo) {
-    data.writeInt32((int32_t) clientInfo->riid);
-    data.writeUint32((uint32_t) clientInfo->uid);
-    data.writeInt32((int32_t) clientInfo->session);
-    data.writeInt32((int32_t) clientInfo->source);
-    data.write(&clientInfo->port_id, sizeof(audio_port_handle_t));
-    data.writeBool(clientInfo->silenced);
-}
-
-inline void readEffectVectorFromParcel(const Parcel& data,
-                                       std::vector<effect_descriptor_t> *effects) {
-    int32_t numEffects = data.readInt32();
-    for (int32_t i = 0; i < numEffects; i++) {
-        effect_descriptor_t effect;
-        if (data.read(&effect, sizeof(effect_descriptor_t)) != NO_ERROR) {
-            break;
-        }
-        (*effects).push_back(effect);
-    }
-}
-
-inline void writeEffectVectorToParcel(Parcel& data, std::vector<effect_descriptor_t> effects) {
-    data.writeUint32((uint32_t) effects.size());
-    for (const auto& effect : effects) {
-        if (data.write(&effect, sizeof(effect_descriptor_t)) != NO_ERROR) {
-            break;
-        }
-    }
-}
-
-// ----------------------------------------------------------------------
-class BpAudioPolicyServiceClient : public BpInterface<IAudioPolicyServiceClient>
-{
-public:
-    explicit BpAudioPolicyServiceClient(const sp<IBinder>& impl)
-        : BpInterface<IAudioPolicyServiceClient>(impl)
-    {
-    }
-
-    void onAudioPortListUpdate()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
-        remote()->transact(PORT_LIST_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-
-    void onAudioPatchListUpdate()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
-        remote()->transact(PATCH_LIST_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-
-    void onAudioVolumeGroupChanged(volume_group_t group, int flags)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
-        data.writeUint32(group);
-        data.writeInt32(flags);
-        remote()->transact(VOLUME_GROUP_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-
-    void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
-        data.writeString8(regId);
-        data.writeInt32(state);
-        remote()->transact(MIX_STATE_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-
-    void onRecordingConfigurationUpdate(int event,
-                                        const record_client_info_t *clientInfo,
-                                        const audio_config_base_t *clientConfig,
-                                        std::vector<effect_descriptor_t> clientEffects,
-                                        const audio_config_base_t *deviceConfig,
-                                        std::vector<effect_descriptor_t> effects,
-                                        audio_patch_handle_t patchHandle,
-                                        audio_source_t source) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
-        data.writeInt32(event);
-        writeRecordClientInfoToParcel(data, clientInfo);
-        writeAudioConfigBaseToParcel(data, clientConfig);
-        writeEffectVectorToParcel(data, clientEffects);
-        writeAudioConfigBaseToParcel(data, deviceConfig);
-        writeEffectVectorToParcel(data, effects);
-        data.writeInt32(patchHandle);
-        data.writeInt32((int32_t) source);
-        remote()->transact(RECORDING_CONFIGURATION_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-};
-
-IMPLEMENT_META_INTERFACE(AudioPolicyServiceClient, "android.media.IAudioPolicyServiceClient");
-
-// ----------------------------------------------------------------------
-
-status_t BnAudioPolicyServiceClient::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch (code) {
-    case PORT_LIST_UPDATE: {
-            CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
-            onAudioPortListUpdate();
-            return NO_ERROR;
-        } break;
-    case PATCH_LIST_UPDATE: {
-            CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
-            onAudioPatchListUpdate();
-            return NO_ERROR;
-        } break;
-    case VOLUME_GROUP_CHANGED: {
-            CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
-            volume_group_t group = static_cast<volume_group_t>(data.readUint32());
-            int flags = data.readInt32();
-            onAudioVolumeGroupChanged(group, flags);
-            return NO_ERROR;
-        } break;
-    case MIX_STATE_UPDATE: {
-            CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
-            String8 regId = data.readString8();
-            int32_t state = data.readInt32();
-            onDynamicPolicyMixStateUpdate(regId, state);
-            return NO_ERROR;
-        } break;
-    case RECORDING_CONFIGURATION_UPDATE: {
-            CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
-            int event = (int) data.readInt32();
-            record_client_info_t clientInfo;
-            audio_config_base_t clientConfig;
-            audio_config_base_t deviceConfig;
-            readRecordClientInfoFromParcel(data, &clientInfo);
-            readAudioConfigBaseFromParcel(data, &clientConfig);
-            std::vector<effect_descriptor_t> clientEffects;
-            readEffectVectorFromParcel(data, &clientEffects);
-            readAudioConfigBaseFromParcel(data, &deviceConfig);
-            std::vector<effect_descriptor_t> effects;
-            readEffectVectorFromParcel(data, &effects);
-            audio_patch_handle_t patchHandle = (audio_patch_handle_t) data.readInt32();
-            audio_source_t source = (audio_source_t) data.readInt32();
-            onRecordingConfigurationUpdate(event, &clientInfo, &clientConfig, clientEffects,
-                                           &deviceConfig, effects, patchHandle, source);
-            return NO_ERROR;
-        } break;
-    default:
-        return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-} // namespace android
diff --git a/media/libaudioclient/PlayerBase.cpp b/media/libaudioclient/PlayerBase.cpp
index c443865..8793735 100644
--- a/media/libaudioclient/PlayerBase.cpp
+++ b/media/libaudioclient/PlayerBase.cpp
@@ -15,13 +15,14 @@
  */
 
 #include <binder/IServiceManager.h>
+#include <media/AidlConversionUtil.h>
 #include <media/PlayerBase.h>
 
 #define max(a, b) ((a) > (b) ? (a) : (b))
 #define min(a, b) ((a) < (b) ? (a) : (b))
 
 namespace android {
-
+using aidl_utils::binderStatusFromStatusT;
 using media::VolumeShaperConfiguration;
 using media::VolumeShaperOperation;
 
@@ -29,7 +30,8 @@
 PlayerBase::PlayerBase() : BnPlayer(),
         mPanMultiplierL(1.0f), mPanMultiplierR(1.0f),
         mVolumeMultiplierL(1.0f), mVolumeMultiplierR(1.0f),
-        mPIId(PLAYER_PIID_INVALID), mLastReportedEvent(PLAYER_STATE_UNKNOWN)
+        mPIId(PLAYER_PIID_INVALID), mLastReportedEvent(PLAYER_STATE_UNKNOWN),
+        mLastReportedDeviceId(AUDIO_PORT_HANDLE_NONE)
 {
     ALOGD("PlayerBase::PlayerBase()");
     // use checkService() to avoid blocking if audio service is not up yet
@@ -63,14 +65,26 @@
 }
 
 //------------------------------------------------------------------------------
-void PlayerBase::servicePlayerEvent(player_state_t event) {
+void PlayerBase::servicePlayerEvent(player_state_t event, audio_port_handle_t deviceId) {
     if (mAudioManager != 0) {
-        // only report state change
-        Mutex::Autolock _l(mPlayerStateLock);
-        if (event != mLastReportedEvent
-                && mPIId != PLAYER_PIID_INVALID) {
-            mLastReportedEvent = event;
-            mAudioManager->playerEvent(mPIId, event);
+        bool changed = false;
+        {
+            Mutex::Autolock _l(mDeviceIdLock);
+            changed = mLastReportedDeviceId != deviceId;
+            mLastReportedDeviceId = deviceId;
+        }
+
+        {
+            Mutex::Autolock _l(mPlayerStateLock);
+            // PLAYER_UPDATE_DEVICE_ID is not saved as an actual state, instead it is used to update
+            // device ID only.
+            if ((event != PLAYER_UPDATE_DEVICE_ID) && (event != mLastReportedEvent)) {
+                mLastReportedEvent = event;
+                changed = true;
+            }
+        }
+        if (changed && (mPIId != PLAYER_PIID_INVALID)) {
+            mAudioManager->playerEvent(mPIId, event, deviceId);
         }
     }
 }
@@ -83,14 +97,18 @@
 }
 
 //FIXME temporary method while some player state is outside of this class
-void PlayerBase::reportEvent(player_state_t event) {
-    servicePlayerEvent(event);
+void PlayerBase::reportEvent(player_state_t event, audio_port_handle_t deviceId) {
+    servicePlayerEvent(event, deviceId);
 }
 
-status_t PlayerBase::startWithStatus() {
+void PlayerBase::baseUpdateDeviceId(audio_port_handle_t deviceId) {
+    servicePlayerEvent(PLAYER_UPDATE_DEVICE_ID, deviceId);
+}
+
+status_t PlayerBase::startWithStatus(audio_port_handle_t deviceId) {
     status_t status = playerStart();
     if (status == NO_ERROR) {
-        servicePlayerEvent(PLAYER_STATE_STARTED);
+        servicePlayerEvent(PLAYER_STATE_STARTED, deviceId);
     } else {
         ALOGW("PlayerBase::start() error %d", status);
     }
@@ -100,18 +118,18 @@
 status_t PlayerBase::pauseWithStatus() {
     status_t status = playerPause();
     if (status == NO_ERROR) {
-        servicePlayerEvent(PLAYER_STATE_PAUSED);
+        servicePlayerEvent(PLAYER_STATE_PAUSED, AUDIO_PORT_HANDLE_NONE);
     } else {
         ALOGW("PlayerBase::pause() error %d", status);
     }
     return status;
 }
 
-
 status_t PlayerBase::stopWithStatus() {
     status_t status = playerStop();
+
     if (status == NO_ERROR) {
-        servicePlayerEvent(PLAYER_STATE_STOPPED);
+        servicePlayerEvent(PLAYER_STATE_STOPPED, AUDIO_PORT_HANDLE_NONE);
     } else {
         ALOGW("PlayerBase::stop() error %d", status);
     }
@@ -122,7 +140,12 @@
 // Implementation of IPlayer
 binder::Status PlayerBase::start() {
     ALOGD("PlayerBase::start() from IPlayer");
-    (void)startWithStatus();
+    audio_port_handle_t deviceId;
+    {
+        Mutex::Autolock _l(mDeviceIdLock);
+        deviceId = mLastReportedDeviceId;
+    }
+    (void)startWithStatus(deviceId);
     return binder::Status::ok();
 }
 
@@ -150,7 +173,7 @@
     if (status != NO_ERROR) {
         ALOGW("PlayerBase::setVolume() error %d", status);
     }
-    return binder::Status::fromStatusT(status);
+    return binderStatusFromStatusT(status);
 }
 
 binder::Status PlayerBase::setPan(float pan) {
@@ -170,7 +193,7 @@
     if (status != NO_ERROR) {
         ALOGW("PlayerBase::setPan() error %d", status);
     }
-    return binder::Status::fromStatusT(status);
+    return binderStatusFromStatusT(status);
 }
 
 binder::Status PlayerBase::setStartDelayMs(int32_t delayMs __unused) {
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index ee78a2d..c9f3ab9 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -17,6 +17,8 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ToneGenerator"
 
+#include <utility>
+
 #include <math.h>
 #include <utils/Log.h>
 #include <cutils/properties.h>
@@ -740,6 +742,11 @@
                         { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
           .repeatCnt = ToneGenerator::TONEGEN_INF,
           .repeatSegment = 0 },                              // TONE_JAPAN_RADIO_ACK
+        { .segments = { { .duration = 1000, .waveFreq = { 400, 0 }, 0, 0 },
+                        { .duration = 2000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_JAPAN_RINGTONE
         { .segments = { { .duration = 375, .waveFreq = { 400, 0 }, 0, 0 },
                         { .duration = 375, .waveFreq = { 0 }, 0, 0 },
                         { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
@@ -881,7 +888,7 @@
             TONE_SUP_RADIO_NOTAVAIL,     // TONE_SUP_RADIO_NOTAVAIL
             TONE_SUP_ERROR,              // TONE_SUP_ERROR
             TONE_SUP_CALL_WAITING,       // TONE_SUP_CALL_WAITING
-            TONE_SUP_RINGTONE            // TONE_SUP_RINGTONE
+            TONE_JAPAN_RINGTONE          // TONE_SUP_RINGTONE
         },
         {   // GB
             TONE_ANSI_DIAL,              // TONE_SUP_DIAL
@@ -979,7 +986,9 @@
 //        none
 //
 ////////////////////////////////////////////////////////////////////////////////
-ToneGenerator::ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava) {
+ToneGenerator::ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava,
+        std::string opPackageName)
+        : mOpPackageName(std::move(opPackageName)) {
 
     ALOGV("ToneGenerator constructor: streamType=%d, volume=%f", streamType, volume);
 
@@ -1250,7 +1259,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 bool ToneGenerator::initAudioTrack() {
     // Open audio track in mono, PCM 16bit, default sampling rate.
-    mpAudioTrack = new AudioTrack();
+    mpAudioTrack = new AudioTrack(mOpPackageName);
     ALOGV("AudioTrack(%p) created", mpAudioTrack.get());
 
     audio_attributes_t attr;
diff --git a/media/libaudioclient/TrackPlayerBase.cpp b/media/libaudioclient/TrackPlayerBase.cpp
index e571838..5c73756 100644
--- a/media/libaudioclient/TrackPlayerBase.cpp
+++ b/media/libaudioclient/TrackPlayerBase.cpp
@@ -17,7 +17,7 @@
 #include <media/TrackPlayerBase.h>
 
 namespace android {
-
+using aidl_utils::binderStatusFromStatusT;
 using media::VolumeShaper;
 
 //--------------------------------------------------------------------------------------------------
@@ -36,6 +36,10 @@
 void TrackPlayerBase::init(AudioTrack* pat, player_type_t playerType, audio_usage_t usage) {
     PlayerBase::init(playerType, usage);
     mAudioTrack = pat;
+    if (mAudioTrack != 0) {
+        mSelfAudioDeviceCallback = new SelfAudioDeviceCallback(*this);
+        mAudioTrack->addAudioDeviceCallback(mSelfAudioDeviceCallback);
+    }
 }
 
 void TrackPlayerBase::destroy() {
@@ -43,9 +47,23 @@
     baseDestroy();
 }
 
+TrackPlayerBase::SelfAudioDeviceCallback::SelfAudioDeviceCallback(PlayerBase& self) :
+    AudioSystem::AudioDeviceCallback(), mSelf(self) {
+}
+
+TrackPlayerBase::SelfAudioDeviceCallback::~SelfAudioDeviceCallback() {
+}
+
+void TrackPlayerBase::SelfAudioDeviceCallback::onAudioDeviceUpdate(audio_io_handle_t __unused,
+                                                                   audio_port_handle_t deviceId) {
+    mSelf.baseUpdateDeviceId(deviceId);
+}
+
 void TrackPlayerBase::doDestroy() {
     if (mAudioTrack != 0) {
         mAudioTrack->stop();
+        mAudioTrack->removeAudioDeviceCallback(mSelfAudioDeviceCallback);
+        mSelfAudioDeviceCallback.clear();
         // Note that there may still be another reference in post-unlock phase of SetPlayState
         mAudioTrack.clear();
     }
@@ -115,7 +133,7 @@
     status_t s = spConfiguration->readFromParcelable(configuration)
             ?: spOperation->readFromParcelable(operation);
     if (s != OK) {
-        return binder::Status::fromStatusT(s);
+        return binderStatusFromStatusT(s);
     }
 
     if (mAudioTrack != 0) {
@@ -124,7 +142,7 @@
         if (status < 0) { // a non-negative value is the volume shaper id.
             ALOGE("TrackPlayerBase::applyVolumeShaper() failed with status %d", status);
         }
-        return binder::Status::fromStatusT(status);
+        return binderStatusFromStatusT(status);
     } else {
         ALOGD("TrackPlayerBase::applyVolumeShaper()"
               " no AudioTrack for volume control from IPlayer");
diff --git a/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl b/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl
index cf11528..cebd8f0 100644
--- a/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl
@@ -35,4 +35,5 @@
     MMAP_NOIRQ       = 12,
     VOIP_RX          = 13,
     INCALL_MUSIC     = 14,
+    GAPLESS_OFFLOAD  = 15,
 }
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
new file mode 100644
index 0000000..e63f391
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.AudioMode;
+import android.media.AudioPatch;
+import android.media.AudioPort;
+import android.media.AudioPortConfig;
+import android.media.AudioStreamType;
+import android.media.AudioUniqueIdUse;
+import android.media.AudioUuid;
+import android.media.CreateEffectRequest;
+import android.media.CreateEffectResponse;
+import android.media.CreateRecordRequest;
+import android.media.CreateRecordResponse;
+import android.media.CreateTrackRequest;
+import android.media.CreateTrackResponse;
+import android.media.OpenInputRequest;
+import android.media.OpenInputResponse;
+import android.media.OpenOutputRequest;
+import android.media.OpenOutputResponse;
+import android.media.EffectDescriptor;
+import android.media.IAudioFlingerClient;
+import android.media.IAudioRecord;
+import android.media.IAudioTrack;
+import android.media.MicrophoneInfoData;
+import android.media.RenderPosition;
+import android.media.audio.common.AudioFormat;
+
+/**
+ * {@hide}
+ */
+interface IAudioFlingerService {
+    /**
+     * Creates an audio track and registers it with AudioFlinger, or null if the track cannot be
+     * created.
+     */
+    CreateTrackResponse createTrack(in CreateTrackRequest request);
+
+    CreateRecordResponse createRecord(in CreateRecordRequest request);
+
+    // FIXME Surprisingly, format/latency don't work for input handles
+
+    /**
+     * Queries the audio hardware state. This state never changes, and therefore can be cached.
+     */
+    int sampleRate(int /* audio_io_handle_t */ ioHandle);
+
+    AudioFormat format(int /* audio_io_handle_t */ output);
+
+    long frameCount(int /* audio_io_handle_t */ ioHandle);
+
+    /**
+     * Return the estimated latency in milliseconds.
+     */
+    int latency(int  /* audio_io_handle_t */ output);
+
+    /*
+     * Sets/gets the audio hardware state. This will probably be used by
+     * the preference panel, mostly.
+     */
+    void setMasterVolume(float value);
+    void setMasterMute(boolean muted);
+
+    float masterVolume();
+    boolean masterMute();
+
+    void setMasterBalance(float balance);
+    float getMasterBalance();
+
+    /*
+     * Set/gets stream type state. This will probably be used by
+     * the preference panel, mostly.
+     */
+    void setStreamVolume(AudioStreamType stream, float value, int /* audio_io_handle_t */ output);
+    void setStreamMute(AudioStreamType stream, boolean muted);
+    float streamVolume(AudioStreamType stream, int /* audio_io_handle_t */ output);
+    boolean streamMute(AudioStreamType stream);
+
+    // set audio mode.
+    void setMode(AudioMode mode);
+
+    // mic mute/state
+    void setMicMute(boolean state);
+    boolean getMicMute();
+    void setRecordSilenced(int /* audio_port_handle_t */ portId,
+                           boolean silenced);
+
+    void setParameters(int /* audio_io_handle_t */ ioHandle,
+                       @utf8InCpp String keyValuePairs);
+    @utf8InCpp String getParameters(int /* audio_io_handle_t */ ioHandle,
+                                    @utf8InCpp String keys);
+
+    // Register an object to receive audio input/output change and track notifications.
+    // For a given calling pid, AudioFlinger disregards any registrations after the first.
+    // Thus the IAudioFlingerClient must be a singleton per process.
+    void registerClient(IAudioFlingerClient client);
+
+    // Retrieve the audio recording buffer size in bytes.
+    // FIXME This API assumes a route, and so should be deprecated.
+    long getInputBufferSize(int sampleRate,
+                            AudioFormat format,
+                            int /* audio_channel_mask_t */ channelMask);
+
+    OpenOutputResponse openOutput(in OpenOutputRequest request);
+    int /* audio_io_handle_t */ openDuplicateOutput(int /* audio_io_handle_t */ output1,
+                                                    int /* audio_io_handle_t */ output2);
+    void closeOutput(int /* audio_io_handle_t */ output);
+    void suspendOutput(int /* audio_io_handle_t */ output);
+    void restoreOutput(int /* audio_io_handle_t */ output);
+
+    OpenInputResponse openInput(in OpenInputRequest request);
+    void closeInput(int /* audio_io_handle_t */ input);
+
+    void invalidateStream(AudioStreamType stream);
+
+    void setVoiceVolume(float volume);
+
+    RenderPosition getRenderPosition(int /* audio_io_handle_t */ output);
+
+    int getInputFramesLost(int /* audio_io_handle_t */ ioHandle);
+
+    int /* audio_unique_id_t */ newAudioUniqueId(AudioUniqueIdUse use);
+
+    void acquireAudioSessionId(int /* audio_session_t */ audioSession,
+                               int /* pid_t */ pid,
+                               int /* uid_t */ uid);
+    void releaseAudioSessionId(int /* audio_session_t */ audioSession,
+                               int /* pid_t */ pid);
+
+    int queryNumberEffects();
+
+    EffectDescriptor queryEffect(int index);
+
+    /** preferredTypeFlag is interpreted as a uint32_t with the "effect flag" format. */
+    EffectDescriptor getEffectDescriptor(in AudioUuid effectUUID,
+                                         in AudioUuid typeUUID,
+                                         int preferredTypeFlag);
+
+    CreateEffectResponse createEffect(in CreateEffectRequest request);
+
+    void moveEffects(int /* audio_session_t */ session,
+                     int /* audio_io_handle_t */ srcOutput,
+                     int /* audio_io_handle_t */ dstOutput);
+
+    void setEffectSuspended(int effectId,
+                            int /* audio_session_t */ sessionId,
+                            boolean suspended);
+
+    int /* audio_module_handle_t */ loadHwModule(@utf8InCpp String name);
+
+    // helpers for android.media.AudioManager.getProperty(), see description there for meaning
+    // FIXME move these APIs to AudioPolicy to permit a more accurate implementation
+    // that looks on primary device for a stream with fast flag, primary flag, or first one.
+    int getPrimaryOutputSamplingRate();
+    long getPrimaryOutputFrameCount();
+
+    // Intended for AudioService to inform AudioFlinger of device's low RAM attribute,
+    // and should be called at most once.  For a definition of what "low RAM" means, see
+    // android.app.ActivityManager.isLowRamDevice().  The totalMemory parameter
+    // is obtained from android.app.ActivityManager.MemoryInfo.totalMem.
+    void setLowRamDevice(boolean isLowRamDevice, long totalMemory);
+
+    /* Get attributes for a given audio port */
+    AudioPort getAudioPort(in AudioPort port);
+
+    /* Create an audio patch between several source and sink ports */
+    int /* audio_patch_handle_t */ createAudioPatch(in AudioPatch patch);
+
+    /* Release an audio patch */
+    void releaseAudioPatch(int /* audio_patch_handle_t */ handle);
+
+    /* List existing audio patches */
+    AudioPatch[] listAudioPatches(int maxCount);
+    /* Set audio port configuration */
+    void setAudioPortConfig(in AudioPortConfig config);
+
+    /* Get the HW synchronization source used for an audio session */
+    int /* audio_hw_sync_t */ getAudioHwSyncForSession(int /* audio_session_t */ sessionId);
+
+    /* Indicate JAVA services are ready (scheduling, power management ...) */
+    oneway void systemReady();
+
+    // Returns the number of frames per audio HAL buffer.
+    long frameCountHAL(int /* audio_io_handle_t */ ioHandle);
+
+    /* List available microphones and their characteristics */
+    MicrophoneInfoData[] getMicrophones();
+
+    void setAudioHalPids(in int[] /* pid_t[] */ pids);
+}
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl
new file mode 100644
index 0000000..a7782b8
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.AudioConfigBase;
+import android.media.AudioSourceType;
+import android.media.EffectDescriptor;
+import android.media.RecordClientInfo;
+
+/**
+ * {@hide}
+ */
+oneway interface IAudioPolicyServiceClient {
+    /** Notifies a change of volume group. */
+    void onAudioVolumeGroupChanged(int /* volume_group_t */ group,
+                                   int flags);
+    /** Notifies a change of audio port configuration. */
+    void onAudioPortListUpdate();
+    /** Notifies a change of audio patch configuration. */
+    void onAudioPatchListUpdate();
+    /** Notifies a change in the mixing state of a specific mix in a dynamic audio policy. */
+    void onDynamicPolicyMixStateUpdate(@utf8InCpp String regId,
+                                       int state);
+    /** Notifies a change of audio recording configuration. */
+    void onRecordingConfigurationUpdate(int event,
+                                        in RecordClientInfo clientInfo,
+                                        in AudioConfigBase clientConfig,
+                                        in EffectDescriptor[] clientEffects,
+                                        in AudioConfigBase deviceConfig,
+                                        in EffectDescriptor[] effects,
+                                        int /* audio_patch_handle_t */ patchHandle,
+                                        AudioSourceType source);
+     /** Notifies a change of audio routing */
+     void onRoutingUpdated();
+}
diff --git a/media/libaudioclient/aidl/android/media/RecordClientInfo.aidl b/media/libaudioclient/aidl/android/media/RecordClientInfo.aidl
new file mode 100644
index 0000000..3280460
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/RecordClientInfo.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.AudioSourceType;
+
+/**
+ * {@hide}
+ */
+parcelable RecordClientInfo {
+    /** Interpreted as audio_unique_id_t. */
+    int riid;
+    /** Interpreted as uid_t. */
+    int uid;
+    /** Interpreted as audio_session_t. */
+    int session;
+    AudioSourceType source;
+    /** Interpreted as audio_port_handle_t. */
+    int portId;
+    boolean silenced;
+}
diff --git a/media/libaudioclient/aidl/android/media/RenderPosition.aidl b/media/libaudioclient/aidl/android/media/RenderPosition.aidl
new file mode 100644
index 0000000..98dc17a
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/RenderPosition.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * {@hide}
+ */
+parcelable RenderPosition {
+    int halFrames;
+    int dspFrames;
+}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 2dc471b..56afe93 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -34,6 +34,7 @@
 #include <android/media/AudioIoConfigEvent.h>
 #include <android/media/AudioIoDescriptor.h>
 #include <android/media/AudioMixLatencyClass.h>
+#include <android/media/AudioMode.h>
 #include <android/media/AudioOutputFlags.h>
 #include <android/media/AudioPort.h>
 #include <android/media/AudioPortConfigType.h>
@@ -43,12 +44,14 @@
 #include <android/media/AudioPortSessionExt.h>
 #include <android/media/AudioProfile.h>
 #include <android/media/AudioTimestampInternal.h>
+#include <android/media/AudioUniqueIdUse.h>
 #include <android/media/EffectDescriptor.h>
 
 #include <android/media/SharedFileRegion.h>
 #include <binder/IMemory.h>
 #include <media/AidlConversionUtil.h>
 #include <media/AudioClient.h>
+#include <media/AudioCommonTypes.h>
 #include <media/AudioIoDescriptor.h>
 #include <media/AudioTimestamp.h>
 #include <system/audio_effect.h>
@@ -75,10 +78,15 @@
 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);
 
-// The legacy enum is unnamed. Thus, we use int.
-ConversionResult<int> aidl2legacy_AudioPortConfigType(media::AudioPortConfigType aidl);
-// The legacy enum is unnamed. Thus, we use int.
-ConversionResult<media::AudioPortConfigType> legacy2aidl_AudioPortConfigType(int 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);
+
+// The legacy enum is unnamed. Thus, we use int32_t.
+ConversionResult<int32_t> aidl2legacy_AudioPortConfigType_int32_t(
+        media::AudioPortConfigType aidl);
+// The legacy enum is unnamed. Thus, we use int32_t.
+ConversionResult<media::AudioPortConfigType> legacy2aidl_int32_t_AudioPortConfigType(
+        int32_t legacy);
 
 ConversionResult<unsigned int> aidl2legacy_int32_t_config_mask(int32_t aidl);
 ConversionResult<int32_t> legacy2aidl_config_mask_int32_t(unsigned int legacy);
@@ -124,7 +132,7 @@
 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_mask_int32_t(audio_gain_mode_t legacy);
+ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy);
 
 ConversionResult<audio_devices_t> aidl2legacy_int32_t_audio_devices_t(int32_t aidl);
 ConversionResult<int32_t> legacy2aidl_audio_devices_t_int32_t(audio_devices_t legacy);
@@ -144,20 +152,26 @@
 ConversionResult<media::AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
         audio_output_flags_t legacy);
 
-ConversionResult<audio_input_flags_t> aidl2legacy_audio_input_flags_mask(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_input_flags_mask(audio_input_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_audio_output_flags_mask(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_output_flags_mask(audio_output_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::AudioIoFlags& aidl, media::AudioPortRole role, media::AudioPortType type);
 ConversionResult<media::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
         const audio_io_flags& legacy, audio_port_role_t role, audio_port_type_t type);
 
-ConversionResult<audio_port_config_device_ext> aidl2legacy_AudioPortConfigDeviceExt(
+ConversionResult<audio_port_config_device_ext>
+aidl2legacy_AudioPortConfigDeviceExt_audio_port_config_device_ext(
         const media::AudioPortConfigDeviceExt& aidl);
-ConversionResult<media::AudioPortConfigDeviceExt> legacy2aidl_AudioPortConfigDeviceExt(
+ConversionResult<media::AudioPortConfigDeviceExt>
+legacy2aidl_audio_port_config_device_ext_AudioPortConfigDeviceExt(
         const audio_port_config_device_ext& legacy);
 
 ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
@@ -178,9 +192,11 @@
 ConversionResult<media::AudioPortConfigMixExt> legacy2aidl_AudioPortConfigMixExt(
         const audio_port_config_mix_ext& legacy, audio_port_role_t role);
 
-ConversionResult<audio_port_config_session_ext> aidl2legacy_AudioPortConfigSessionExt(
+ConversionResult<audio_port_config_session_ext>
+aidl2legacy_AudioPortConfigSessionExt_audio_port_config_session_ext(
         const media::AudioPortConfigSessionExt& aidl);
-ConversionResult<media::AudioPortConfigSessionExt> legacy2aidl_AudioPortConfigSessionExt(
+ConversionResult<media::AudioPortConfigSessionExt>
+legacy2aidl_audio_port_config_session_ext_AudioPortConfigSessionExt(
         const audio_port_config_session_ext& legacy);
 
 ConversionResult<audio_port_config> aidl2legacy_AudioPortConfig_audio_port_config(
@@ -199,8 +215,10 @@
 ConversionResult<media::AudioIoDescriptor> legacy2aidl_AudioIoDescriptor_AudioIoDescriptor(
         const sp<AudioIoDescriptor>& legacy);
 
-ConversionResult<AudioClient> aidl2legacy_AudioClient(const media::AudioClient& aidl);
-ConversionResult<media::AudioClient> legacy2aidl_AudioClient(const AudioClient& legacy);
+ConversionResult<AudioClient> aidl2legacy_AudioClient_AudioClient(
+        const media::AudioClient& aidl);
+ConversionResult<media::AudioClient> legacy2aidl_AudioClient_AudioClient(
+        const AudioClient& legacy);
 
 ConversionResult<audio_content_type_t>
 aidl2legacy_AudioContentType_audio_content_type_t(media::AudioContentType aidl);
@@ -258,9 +276,9 @@
 legacy2aidl_NullableIMemory_SharedFileRegion(const sp<IMemory>& legacy);
 
 ConversionResult<AudioTimestamp>
-aidl2legacy_AudioTimestamp(const media::AudioTimestampInternal& aidl);
+aidl2legacy_AudioTimestampInternal_AudioTimestamp(const media::AudioTimestampInternal& aidl);
 ConversionResult<media::AudioTimestampInternal>
-legacy2aidl_AudioTimestamp(const AudioTimestamp& legacy);
+legacy2aidl_AudioTimestamp_AudioTimestampInternal(const AudioTimestamp& legacy);
 
 ConversionResult<audio_uuid_t>
 aidl2legacy_AudioUuid_audio_uuid_t(const media::AudioUuid& aidl);
@@ -326,4 +344,19 @@
 ConversionResult<media::AudioPort>
 legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy);
 
+ConversionResult<audio_mode_t>
+aidl2legacy_AudioMode_audio_mode_t(media::AudioMode aidl);
+ConversionResult<media::AudioMode>
+legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy);
+
+ConversionResult<audio_unique_id_use_t>
+aidl2legacy_AudioUniqueIdUse_audio_unique_id_use_t(media::AudioUniqueIdUse aidl);
+ConversionResult<media::AudioUniqueIdUse>
+legacy2aidl_audio_unique_id_use_t_AudioUniqueIdUse(audio_unique_id_use_t legacy);
+
+ConversionResult<volume_group_t>
+aidl2legacy_int32_t_volume_group_t(int32_t aidl);
+ConversionResult<int32_t>
+legacy2aidl_volume_group_t_int32_t(volume_group_t legacy);
+
 }  // namespace android
diff --git a/media/libaudioclient/include/media/AidlConversionUtil.h b/media/libaudioclient/include/media/AidlConversionUtil.h
index 6bfb743..9453673 100644
--- a/media/libaudioclient/include/media/AidlConversionUtil.h
+++ b/media/libaudioclient/include/media/AidlConversionUtil.h
@@ -21,6 +21,7 @@
 #include <utility>
 
 #include <android-base/expected.h>
+#include <binder/Status.h>
 
 namespace android {
 
@@ -132,4 +133,98 @@
 #define UNION_SET(u, field, value) \
     (u).set<std::decay_t<decltype(u)>::Tag::field>(value)
 
+namespace aidl_utils {
+
+/**
+ * Return the equivalent Android status_t from a binder exception code.
+ *
+ * Generally one should use statusTFromBinderStatus() instead.
+ *
+ * Exception codes can be generated from a remote Java service exception, translate
+ * them for use on the Native side.
+ *
+ * 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) {
+    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;
+        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_TRANSACTION_FAILED: // Native - see error code
+        case Status::EX_SERVICE_SPECIFIC:  // Java ServiceSpecificException,
+                                           // rethrows in Java with integer error code
+            return UNKNOWN_ERROR;
+    }
+    return UNKNOWN_ERROR;
+}
+
+/**
+ * Return the equivalent Android status_t from a binder status.
+ *
+ * Used to handle errors from a AIDL method declaration
+ *
+ * [oneway] void method(type0 param0, ...)
+ *
+ * or the following (where return_type is not a status_t)
+ *
+ * return_type method(type0 param0, ...)
+ */
+static inline status_t statusTFromBinderStatus(const ::android::binder::Status &status) {
+    return status.isOk() ? OK // check OK,
+        : status.serviceSpecificErrorCode() // service-side error, not standard Java exception
+                                            // (fromServiceSpecificError)
+        ?: status.transactionError() // a native binder transaction error (fromStatusT)
+        ?: statusTFromExceptionCode(status.exceptionCode()); // a service-side error with a
+                                                    // standard Java exception (fromExceptionCode)
+}
+
+/**
+ * Return a binder::Status from native service status.
+ *
+ * This is used for methods not returning an explicit status_t,
+ * where Java callers expect an exception, not an integer return value.
+ */
+static inline ::android::binder::Status binderStatusFromStatusT(
+        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.
+    //  Exception codes and service specific errors map to nicer exceptions for
+    //  Java clients.
+
+    using namespace ::android::binder;
+    switch (status) {
+        case OK:
+            return Status::ok();
+        case PERMISSION_DENIED: // throw SecurityException on Java side
+            return Status::fromExceptionCode(Status::EX_SECURITY, emptyIfNull);
+        case BAD_VALUE: // throw IllegalArgumentException on Java side
+            return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, emptyIfNull);
+        case INVALID_OPERATION: // throw IllegalStateException on Java side
+            return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, emptyIfNull);
+    }
+
+    // A service specific error will not show on status.transactionError() so
+    // be sure to use statusTFromBinderStatus() for reliable error handling.
+
+    // throw a ServiceSpecificException.
+    return Status::fromServiceSpecificError(status, emptyIfNull);
+}
+
+} // namespace aidl_utils
+
 }  // namespace android
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index dfc1982..71b1e33 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -20,12 +20,13 @@
 #include <sys/types.h>
 
 #include <android/media/BnAudioFlingerClient.h>
+#include <android/media/BnAudioPolicyServiceClient.h>
+#include <media/AidlConversionUtil.h>
 #include <media/AudioDeviceTypeAddr.h>
 #include <media/AudioPolicy.h>
 #include <media/AudioProductStrategy.h>
 #include <media/AudioVolumeGroup.h>
 #include <media/AudioIoDescriptor.h>
-#include <media/IAudioPolicyServiceClient.h>
 #include <media/MicrophoneInfo.h>
 #include <set>
 #include <system/audio.h>
@@ -37,6 +38,23 @@
 
 namespace android {
 
+struct record_client_info {
+    audio_unique_id_t riid;
+    uid_t uid;
+    audio_session_t session;
+    audio_source_t source;
+    audio_port_handle_t port_id;
+    bool silenced;
+};
+
+typedef struct record_client_info record_client_info_t;
+
+// AIDL conversion functions.
+ConversionResult<record_client_info_t>
+aidl2legacy_RecordClientInfo_record_client_info_t(const media::RecordClientInfo& aidl);
+ConversionResult<media::RecordClientInfo>
+legacy2aidl_record_client_info_t_RecordClientInfo(const record_client_info_t& legacy);
+
 typedef void (*audio_error_callback)(status_t err);
 typedef void (*dynamic_policy_callback)(int event, String8 regId, int val);
 typedef void (*record_config_callback)(int event,
@@ -47,6 +65,7 @@
                                        std::vector<effect_descriptor_t> effects,
                                        audio_patch_handle_t patchHandle,
                                        audio_source_t source);
+typedef void (*routing_callback)();
 
 class IAudioFlinger;
 class IAudioPolicyService;
@@ -120,6 +139,7 @@
 
     static void setDynPolicyCallback(dynamic_policy_callback cb);
     static void setRecordConfigCallback(record_config_callback);
+    static void setRoutingCallback(routing_callback cb);
 
     // helper function to obtain AudioFlinger service handle
     static const sp<IAudioFlinger> get_audio_flinger();
@@ -319,9 +339,10 @@
 
     static status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags);
 
-    // Check if hw offload is possible for given format, stream type, sample rate,
-    // bit rate, duration, video and streaming or offload property is enabled
-    static bool isOffloadSupported(const audio_offload_info_t& info);
+    // Indicate if hw offload is possible for given format, stream type, sample rate,
+    // bit rate, duration, video and streaming or offload property is enabled and when possible
+    // if gapless transitions are supported.
+    static audio_offload_mode_t getOffloadSupport(const audio_offload_info_t& info);
 
     // check presence of audio flinger service.
     // returns NO_ERROR if binding to service succeeds, DEAD_OBJECT otherwise
@@ -331,11 +352,11 @@
     static status_t listAudioPorts(audio_port_role_t role,
                                    audio_port_type_t type,
                                    unsigned int *num_ports,
-                                   struct audio_port *ports,
+                                   struct audio_port_v7 *ports,
                                    unsigned int *generation);
 
     /* Get attributes for a given audio port */
-    static status_t getAudioPort(struct audio_port *port);
+    static status_t getAudioPort(struct audio_port_v7 *port);
 
     /* Create an audio patch between several source and sink ports */
     static status_t createAudioPatch(const struct audio_patch *patch,
@@ -579,7 +600,7 @@
     };
 
     class AudioPolicyServiceClient: public IBinder::DeathRecipient,
-                                    public BnAudioPolicyServiceClient
+                                    public media::BnAudioPolicyServiceClient
     {
     public:
         AudioPolicyServiceClient() {
@@ -597,18 +618,21 @@
         virtual void binderDied(const wp<IBinder>& who);
 
         // IAudioPolicyServiceClient
-        virtual void onAudioPortListUpdate();
-        virtual void onAudioPatchListUpdate();
-        virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags);
-        virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
-        virtual void onRecordingConfigurationUpdate(int event,
-                                                    const record_client_info_t *clientInfo,
-                                                    const audio_config_base_t *clientConfig,
-                                                    std::vector<effect_descriptor_t> clientEffects,
-                                                    const audio_config_base_t *deviceConfig,
-                                                    std::vector<effect_descriptor_t> effects,
-                                                    audio_patch_handle_t patchHandle,
-                                                    audio_source_t source);
+        binder::Status onAudioVolumeGroupChanged(int32_t group, int32_t flags) override;
+        binder::Status onAudioPortListUpdate() override;
+        binder::Status onAudioPatchListUpdate() override;
+        binder::Status onDynamicPolicyMixStateUpdate(const std::string& regId,
+                                                     int32_t state) override;
+        binder::Status onRecordingConfigurationUpdate(
+                int32_t event,
+                const media::RecordClientInfo& clientInfo,
+                const media::AudioConfigBase& clientConfig,
+                const std::vector<media::EffectDescriptor>& clientEffects,
+                const media::AudioConfigBase& deviceConfig,
+                const std::vector<media::EffectDescriptor>& effects,
+                int32_t patchHandle,
+                media::AudioSourceType source) override;
+        binder::Status onRoutingUpdated();
 
     private:
         Mutex                               mLock;
@@ -635,6 +659,7 @@
     static std::set<audio_error_callback> gAudioErrorCallbacks;
     static dynamic_policy_callback gDynPolicyCallback;
     static record_config_callback gRecordConfigCallback;
+    static routing_callback gRoutingCallback;
 
     static size_t gInBuffSize;
     // previous parameters for recording buffer size queries
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 911a34f..9a8014d 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -24,8 +24,6 @@
 #include <utils/RefBase.h>
 #include <utils/Errors.h>
 #include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <binder/Parcelable.h>
 #include <media/AidlConversion.h>
 #include <media/AudioClient.h>
 #include <media/DeviceDescriptorBase.h>
@@ -37,6 +35,8 @@
 #include <string>
 #include <vector>
 
+#include <android/media/BnAudioFlingerService.h>
+#include <android/media/BpAudioFlingerService.h>
 #include "android/media/CreateEffectRequest.h"
 #include "android/media/CreateEffectResponse.h"
 #include "android/media/CreateRecordRequest.h"
@@ -58,10 +58,11 @@
 
 // ----------------------------------------------------------------------------
 
-class IAudioFlinger : public IInterface
-{
+class IAudioFlinger : public RefBase {
 public:
-    DECLARE_META_INTERFACE(AudioFlinger);
+    static constexpr char DEFAULT_SERVICE_NAME[] = "media.audio_flinger";
+
+    virtual ~IAudioFlinger() = default;
 
     /* CreateTrackInput contains all input arguments sent by AudioTrack to AudioFlinger
      * when calling createTrack() including arguments that will be updated by AudioFlinger
@@ -162,7 +163,8 @@
         sp<media::IAudioRecord> audioRecord;
 
         ConversionResult<media::CreateRecordResponse> toAidl() const;
-        static ConversionResult<CreateRecordOutput> fromAidl(const media::CreateRecordResponse& aidl);
+        static ConversionResult<CreateRecordOutput>
+        fromAidl(const media::CreateRecordResponse& aidl);
     };
 
     /* create an audio track and registers it with AudioFlinger.
@@ -300,10 +302,6 @@
     // is obtained from android.app.ActivityManager.MemoryInfo.totalMem.
     virtual status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) = 0;
 
-    /* List available audio ports and their attributes */
-    virtual status_t listAudioPorts(unsigned int *num_ports,
-                                    struct audio_port *ports) = 0;
-
     /* Get attributes for a given audio port */
     virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
 
@@ -333,85 +331,284 @@
     virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
 
     virtual status_t setAudioHalPids(const std::vector<pid_t>& pids) = 0;
-
-protected:
-    enum {
-        CREATE_TRACK = IBinder::FIRST_CALL_TRANSACTION,
-        CREATE_RECORD,
-        SAMPLE_RATE,
-        RESERVED,   // obsolete, was CHANNEL_COUNT
-        FORMAT,
-        FRAME_COUNT,
-        LATENCY,
-        SET_MASTER_VOLUME,
-        SET_MASTER_MUTE,
-        MASTER_VOLUME,
-        MASTER_MUTE,
-        SET_STREAM_VOLUME,
-        SET_STREAM_MUTE,
-        STREAM_VOLUME,
-        STREAM_MUTE,
-        SET_MODE,
-        SET_MIC_MUTE,
-        GET_MIC_MUTE,
-        SET_RECORD_SILENCED,
-        SET_PARAMETERS,
-        GET_PARAMETERS,
-        REGISTER_CLIENT,
-        GET_INPUTBUFFERSIZE,
-        OPEN_OUTPUT,
-        OPEN_DUPLICATE_OUTPUT,
-        CLOSE_OUTPUT,
-        SUSPEND_OUTPUT,
-        RESTORE_OUTPUT,
-        OPEN_INPUT,
-        CLOSE_INPUT,
-        INVALIDATE_STREAM,
-        SET_VOICE_VOLUME,
-        GET_RENDER_POSITION,
-        GET_INPUT_FRAMES_LOST,
-        NEW_AUDIO_UNIQUE_ID,
-        ACQUIRE_AUDIO_SESSION_ID,
-        RELEASE_AUDIO_SESSION_ID,
-        QUERY_NUM_EFFECTS,
-        QUERY_EFFECT,
-        GET_EFFECT_DESCRIPTOR,
-        CREATE_EFFECT,
-        MOVE_EFFECTS,
-        LOAD_HW_MODULE,
-        GET_PRIMARY_OUTPUT_SAMPLING_RATE,
-        GET_PRIMARY_OUTPUT_FRAME_COUNT,
-        SET_LOW_RAM_DEVICE,
-        LIST_AUDIO_PORTS,
-        GET_AUDIO_PORT,
-        CREATE_AUDIO_PATCH,
-        RELEASE_AUDIO_PATCH,
-        LIST_AUDIO_PATCHES,
-        SET_AUDIO_PORT_CONFIG,
-        GET_AUDIO_HW_SYNC_FOR_SESSION,
-        SYSTEM_READY,
-        FRAME_COUNT_HAL,
-        GET_MICROPHONES,
-        SET_MASTER_BALANCE,
-        GET_MASTER_BALANCE,
-        SET_EFFECT_SUSPENDED,
-        SET_AUDIO_HAL_PIDS
-    };
 };
 
-
-// ----------------------------------------------------------------------------
-
-class BnAudioFlinger : public BnInterface<IAudioFlinger>
-{
+/**
+ * A client-side adapter, wrapping an IAudioFlingerService instance and presenting it as an
+ * IAudioFlinger. Intended to be used by legacy client code that was written against IAudioFlinger,
+ * before IAudioFlingerService was introduced as an AIDL service.
+ * New clients should not use this adapter, but rather IAudioFlingerService directly, via
+ * BpAudioFlingerService.
+ */
+class AudioFlingerClientAdapter : public IAudioFlinger {
 public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
+    explicit AudioFlingerClientAdapter(const sp<media::IAudioFlingerService> delegate);
+
+    status_t createTrack(const media::CreateTrackRequest& input,
+                         media::CreateTrackResponse& output) override;
+    status_t createRecord(const media::CreateRecordRequest& input,
+                          media::CreateRecordResponse& output) override;
+    uint32_t sampleRate(audio_io_handle_t ioHandle) const override;
+    audio_format_t format(audio_io_handle_t output) const override;
+    size_t frameCount(audio_io_handle_t ioHandle) const override;
+    uint32_t latency(audio_io_handle_t output) const override;
+    status_t setMasterVolume(float value) override;
+    status_t setMasterMute(bool muted) override;
+    float masterVolume() const override;
+    bool masterMute() const override;
+    status_t setMasterBalance(float balance) override;
+    status_t getMasterBalance(float* balance) const override;
+    status_t setStreamVolume(audio_stream_type_t stream, float value,
+                             audio_io_handle_t output) override;
+    status_t setStreamMute(audio_stream_type_t stream, bool muted) override;
+    float streamVolume(audio_stream_type_t stream,
+                       audio_io_handle_t output) const override;
+    bool streamMute(audio_stream_type_t stream) const override;
+    status_t setMode(audio_mode_t mode) override;
+    status_t setMicMute(bool state) override;
+    bool getMicMute() const override;
+    void setRecordSilenced(audio_port_handle_t portId, bool silenced) override;
+    status_t setParameters(audio_io_handle_t ioHandle,
+                           const String8& keyValuePairs) override;
+    String8 getParameters(audio_io_handle_t ioHandle, const String8& keys)
+    const override;
+    void registerClient(const sp<media::IAudioFlingerClient>& client) override;
+    size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
+                              audio_channel_mask_t channelMask) const override;
+    status_t openOutput(const media::OpenOutputRequest& request,
+                        media::OpenOutputResponse* response) override;
+    audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
+                                          audio_io_handle_t output2) override;
+    status_t closeOutput(audio_io_handle_t output) override;
+    status_t suspendOutput(audio_io_handle_t output) override;
+    status_t restoreOutput(audio_io_handle_t output) override;
+    status_t openInput(const media::OpenInputRequest& request,
+                       media::OpenInputResponse* response) override;
+    status_t closeInput(audio_io_handle_t input) override;
+    status_t invalidateStream(audio_stream_type_t stream) override;
+    status_t setVoiceVolume(float volume) override;
+    status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames,
+                               audio_io_handle_t output) const override;
+    uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const override;
+    audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) override;
+    void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid) override;
+    void releaseAudioSessionId(audio_session_t audioSession, pid_t pid) override;
+    status_t queryNumberEffects(uint32_t* numEffects) const override;
+    status_t queryEffect(uint32_t index, effect_descriptor_t* pDescriptor) const override;
+    status_t getEffectDescriptor(const effect_uuid_t* pEffectUUID,
+                                 const effect_uuid_t* pTypeUUID,
+                                 uint32_t preferredTypeFlag,
+                                 effect_descriptor_t* pDescriptor) const override;
+    status_t createEffect(const media::CreateEffectRequest& request,
+                          media::CreateEffectResponse* response) override;
+    status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
+                         audio_io_handle_t dstOutput) override;
+    void setEffectSuspended(int effectId,
+                            audio_session_t sessionId,
+                            bool suspended) override;
+    audio_module_handle_t loadHwModule(const char* name) override;
+    uint32_t getPrimaryOutputSamplingRate() override;
+    size_t getPrimaryOutputFrameCount() override;
+    status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) override;
+    status_t getAudioPort(struct audio_port_v7* port) override;
+    status_t createAudioPatch(const struct audio_patch* patch,
+                              audio_patch_handle_t* handle) override;
+    status_t releaseAudioPatch(audio_patch_handle_t handle) override;
+    status_t listAudioPatches(unsigned int* num_patches,
+                              struct audio_patch* patches) override;
+    status_t setAudioPortConfig(const struct audio_port_config* config) override;
+    audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId) override;
+    status_t systemReady() override;
+    size_t frameCountHAL(audio_io_handle_t ioHandle) const override;
+    status_t getMicrophones(std::vector<media::MicrophoneInfo>* microphones) override;
+    status_t setAudioHalPids(const std::vector<pid_t>& pids) override;
+
+private:
+    const sp<media::IAudioFlingerService> mDelegate;
 };
 
-// ----------------------------------------------------------------------------
+/**
+ * A server-side adapter, wrapping an IAudioFlinger instance and presenting it as an
+ * IAudioFlingerService. Intended to be used by legacy server code that was written against
+ * IAudioFlinger, before IAudioFlingerService was introduced as an AIDL service.
+ * New servers should not use this adapter, but rather implement IAudioFlingerService directly, via
+ * BnAudioFlingerService.
+ */
+class AudioFlingerServerAdapter : public media::BnAudioFlingerService {
+public:
+    using Status = binder::Status;
+
+    /**
+     * Legacy server should implement this interface in order to be wrapped.
+     */
+    class Delegate : public IAudioFlinger {
+    protected:
+        friend class AudioFlingerServerAdapter;
+
+        enum class TransactionCode {
+            CREATE_TRACK = media::BnAudioFlingerService::TRANSACTION_createTrack,
+            CREATE_RECORD = media::BnAudioFlingerService::TRANSACTION_createRecord,
+            SAMPLE_RATE = media::BnAudioFlingerService::TRANSACTION_sampleRate,
+            FORMAT = media::BnAudioFlingerService::TRANSACTION_format,
+            FRAME_COUNT = media::BnAudioFlingerService::TRANSACTION_frameCount,
+            LATENCY = media::BnAudioFlingerService::TRANSACTION_latency,
+            SET_MASTER_VOLUME = media::BnAudioFlingerService::TRANSACTION_setMasterVolume,
+            SET_MASTER_MUTE = media::BnAudioFlingerService::TRANSACTION_setMasterMute,
+            MASTER_VOLUME = media::BnAudioFlingerService::TRANSACTION_masterVolume,
+            MASTER_MUTE = media::BnAudioFlingerService::TRANSACTION_masterMute,
+            SET_STREAM_VOLUME = media::BnAudioFlingerService::TRANSACTION_setStreamVolume,
+            SET_STREAM_MUTE = media::BnAudioFlingerService::TRANSACTION_setStreamMute,
+            STREAM_VOLUME = media::BnAudioFlingerService::TRANSACTION_streamVolume,
+            STREAM_MUTE = media::BnAudioFlingerService::TRANSACTION_streamMute,
+            SET_MODE = media::BnAudioFlingerService::TRANSACTION_setMode,
+            SET_MIC_MUTE = media::BnAudioFlingerService::TRANSACTION_setMicMute,
+            GET_MIC_MUTE = media::BnAudioFlingerService::TRANSACTION_getMicMute,
+            SET_RECORD_SILENCED = media::BnAudioFlingerService::TRANSACTION_setRecordSilenced,
+            SET_PARAMETERS = media::BnAudioFlingerService::TRANSACTION_setParameters,
+            GET_PARAMETERS = media::BnAudioFlingerService::TRANSACTION_getParameters,
+            REGISTER_CLIENT = media::BnAudioFlingerService::TRANSACTION_registerClient,
+            GET_INPUTBUFFERSIZE = media::BnAudioFlingerService::TRANSACTION_getInputBufferSize,
+            OPEN_OUTPUT = media::BnAudioFlingerService::TRANSACTION_openOutput,
+            OPEN_DUPLICATE_OUTPUT = media::BnAudioFlingerService::TRANSACTION_openDuplicateOutput,
+            CLOSE_OUTPUT = media::BnAudioFlingerService::TRANSACTION_closeOutput,
+            SUSPEND_OUTPUT = media::BnAudioFlingerService::TRANSACTION_suspendOutput,
+            RESTORE_OUTPUT = media::BnAudioFlingerService::TRANSACTION_restoreOutput,
+            OPEN_INPUT = media::BnAudioFlingerService::TRANSACTION_openInput,
+            CLOSE_INPUT = media::BnAudioFlingerService::TRANSACTION_closeInput,
+            INVALIDATE_STREAM = media::BnAudioFlingerService::TRANSACTION_invalidateStream,
+            SET_VOICE_VOLUME = media::BnAudioFlingerService::TRANSACTION_setVoiceVolume,
+            GET_RENDER_POSITION = media::BnAudioFlingerService::TRANSACTION_getRenderPosition,
+            GET_INPUT_FRAMES_LOST = media::BnAudioFlingerService::TRANSACTION_getInputFramesLost,
+            NEW_AUDIO_UNIQUE_ID = media::BnAudioFlingerService::TRANSACTION_newAudioUniqueId,
+            ACQUIRE_AUDIO_SESSION_ID = media::BnAudioFlingerService::TRANSACTION_acquireAudioSessionId,
+            RELEASE_AUDIO_SESSION_ID = media::BnAudioFlingerService::TRANSACTION_releaseAudioSessionId,
+            QUERY_NUM_EFFECTS = media::BnAudioFlingerService::TRANSACTION_queryNumberEffects,
+            QUERY_EFFECT = media::BnAudioFlingerService::TRANSACTION_queryEffect,
+            GET_EFFECT_DESCRIPTOR = media::BnAudioFlingerService::TRANSACTION_getEffectDescriptor,
+            CREATE_EFFECT = media::BnAudioFlingerService::TRANSACTION_createEffect,
+            MOVE_EFFECTS = media::BnAudioFlingerService::TRANSACTION_moveEffects,
+            LOAD_HW_MODULE = media::BnAudioFlingerService::TRANSACTION_loadHwModule,
+            GET_PRIMARY_OUTPUT_SAMPLING_RATE = media::BnAudioFlingerService::TRANSACTION_getPrimaryOutputSamplingRate,
+            GET_PRIMARY_OUTPUT_FRAME_COUNT = media::BnAudioFlingerService::TRANSACTION_getPrimaryOutputFrameCount,
+            SET_LOW_RAM_DEVICE = media::BnAudioFlingerService::TRANSACTION_setLowRamDevice,
+            GET_AUDIO_PORT = media::BnAudioFlingerService::TRANSACTION_getAudioPort,
+            CREATE_AUDIO_PATCH = media::BnAudioFlingerService::TRANSACTION_createAudioPatch,
+            RELEASE_AUDIO_PATCH = media::BnAudioFlingerService::TRANSACTION_releaseAudioPatch,
+            LIST_AUDIO_PATCHES = media::BnAudioFlingerService::TRANSACTION_listAudioPatches,
+            SET_AUDIO_PORT_CONFIG = media::BnAudioFlingerService::TRANSACTION_setAudioPortConfig,
+            GET_AUDIO_HW_SYNC_FOR_SESSION = media::BnAudioFlingerService::TRANSACTION_getAudioHwSyncForSession,
+            SYSTEM_READY = media::BnAudioFlingerService::TRANSACTION_systemReady,
+            FRAME_COUNT_HAL = media::BnAudioFlingerService::TRANSACTION_frameCountHAL,
+            GET_MICROPHONES = media::BnAudioFlingerService::TRANSACTION_getMicrophones,
+            SET_MASTER_BALANCE = media::BnAudioFlingerService::TRANSACTION_setMasterBalance,
+            GET_MASTER_BALANCE = media::BnAudioFlingerService::TRANSACTION_getMasterBalance,
+            SET_EFFECT_SUSPENDED = media::BnAudioFlingerService::TRANSACTION_setEffectSuspended,
+            SET_AUDIO_HAL_PIDS = media::BnAudioFlingerService::TRANSACTION_setAudioHalPids,
+        };
+
+        /**
+         * And optional hook, called on every transaction, before unparceling the data and
+         * dispatching to the respective method. Useful for bulk operations, such as logging or
+         * permission checks.
+         * If an error status is returned, the transaction will return immediately and will not be
+         * processed.
+         */
+        virtual status_t onPreTransact(TransactionCode code, const Parcel& data, uint32_t flags) {
+            (void) code;
+            (void) data;
+            (void) flags;
+            return OK;
+        };
+
+        /**
+         * An optional hook for implementing diagnostics dumping.
+         */
+        virtual status_t dump(int fd, const Vector<String16>& args) {
+            (void) fd;
+            (void) args;
+            return OK;
+        }
+    };
+
+    explicit AudioFlingerServerAdapter(
+            const sp<AudioFlingerServerAdapter::Delegate>& delegate);
+
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
+    status_t dump(int fd, const Vector<String16>& args) override;
+
+    Status createTrack(const media::CreateTrackRequest& request,
+                       media::CreateTrackResponse* _aidl_return) override;
+    Status createRecord(const media::CreateRecordRequest& request,
+                        media::CreateRecordResponse* _aidl_return) override;
+    Status sampleRate(int32_t ioHandle, int32_t* _aidl_return) override;
+    Status format(int32_t output, media::audio::common::AudioFormat* _aidl_return) override;
+    Status frameCount(int32_t ioHandle, int64_t* _aidl_return) override;
+    Status latency(int32_t output, int32_t* _aidl_return) override;
+    Status setMasterVolume(float value) override;
+    Status setMasterMute(bool muted) override;
+    Status masterVolume(float* _aidl_return) override;
+    Status masterMute(bool* _aidl_return) override;
+    Status setMasterBalance(float balance) override;
+    Status getMasterBalance(float* _aidl_return) override;
+    Status setStreamVolume(media::AudioStreamType stream, float value, int32_t output) override;
+    Status setStreamMute(media::AudioStreamType stream, bool muted) override;
+    Status
+    streamVolume(media::AudioStreamType stream, int32_t output, float* _aidl_return) override;
+    Status streamMute(media::AudioStreamType stream, bool* _aidl_return) override;
+    Status setMode(media::AudioMode mode) override;
+    Status setMicMute(bool state) override;
+    Status getMicMute(bool* _aidl_return) override;
+    Status setRecordSilenced(int32_t portId, bool silenced) override;
+    Status setParameters(int32_t ioHandle, const std::string& keyValuePairs) override;
+    Status
+    getParameters(int32_t ioHandle, const std::string& keys, std::string* _aidl_return) override;
+    Status registerClient(const sp<media::IAudioFlingerClient>& client) override;
+    Status getInputBufferSize(int32_t sampleRate, media::audio::common::AudioFormat format,
+                              int32_t channelMask, int64_t* _aidl_return) override;
+    Status openOutput(const media::OpenOutputRequest& request,
+                      media::OpenOutputResponse* _aidl_return) override;
+    Status openDuplicateOutput(int32_t output1, int32_t output2, int32_t* _aidl_return) override;
+    Status closeOutput(int32_t output) override;
+    Status suspendOutput(int32_t output) override;
+    Status restoreOutput(int32_t output) override;
+    Status openInput(const media::OpenInputRequest& request,
+                     media::OpenInputResponse* _aidl_return) override;
+    Status closeInput(int32_t input) override;
+    Status invalidateStream(media::AudioStreamType stream) override;
+    Status setVoiceVolume(float volume) override;
+    Status getRenderPosition(int32_t output, media::RenderPosition* _aidl_return) override;
+    Status getInputFramesLost(int32_t ioHandle, int32_t* _aidl_return) override;
+    Status newAudioUniqueId(media::AudioUniqueIdUse use, int32_t* _aidl_return) override;
+    Status acquireAudioSessionId(int32_t audioSession, int32_t pid, int32_t uid) override;
+    Status releaseAudioSessionId(int32_t audioSession, int32_t pid) override;
+    Status queryNumberEffects(int32_t* _aidl_return) override;
+    Status queryEffect(int32_t index, media::EffectDescriptor* _aidl_return) override;
+    Status getEffectDescriptor(const media::AudioUuid& effectUUID, const media::AudioUuid& typeUUID,
+                               int32_t preferredTypeFlag,
+                               media::EffectDescriptor* _aidl_return) override;
+    Status createEffect(const media::CreateEffectRequest& request,
+                        media::CreateEffectResponse* _aidl_return) override;
+    Status moveEffects(int32_t session, int32_t srcOutput, int32_t dstOutput) override;
+    Status setEffectSuspended(int32_t effectId, int32_t sessionId, bool suspended) override;
+    Status loadHwModule(const std::string& name, int32_t* _aidl_return) override;
+    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 releaseAudioPatch(int32_t handle) override;
+    Status listAudioPatches(int32_t maxCount,
+                            std::vector<media::AudioPatch>* _aidl_return) override;
+    Status setAudioPortConfig(const media::AudioPortConfig& config) override;
+    Status getAudioHwSyncForSession(int32_t sessionId, int32_t* _aidl_return) override;
+    Status systemReady() override;
+    Status frameCountHAL(int32_t ioHandle, int64_t* _aidl_return) override;
+    Status getMicrophones(std::vector<media::MicrophoneInfoData>* _aidl_return) override;
+    Status setAudioHalPids(const std::vector<int32_t>& pids) override;
+
+private:
+    const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
+};
 
 }; // namespace android
 
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 837375d..3018364 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -20,14 +20,15 @@
 #include <stdint.h>
 #include <sys/types.h>
 #include <unistd.h>
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
+
+#include <android/media/IAudioPolicyServiceClient.h>
 #include <binder/IInterface.h>
 #include <media/AudioDeviceTypeAddr.h>
 #include <media/AudioSystem.h>
 #include <media/AudioPolicy.h>
-#include <media/IAudioPolicyServiceClient.h>
 #include <system/audio_policy.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
 #include <vector>
 
 namespace android {
@@ -150,7 +151,7 @@
     virtual status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags) = 0;
    // Check if offload is possible for given format, stream type, sample rate,
     // bit rate, duration, video and streaming or offload property is enabled
-    virtual bool isOffloadSupported(const audio_offload_info_t& info) = 0;
+    virtual audio_offload_mode_t getOffloadSupport(const audio_offload_info_t& info) = 0;
 
     // Check if direct playback is possible for given format, sample rate, channel mask and flags.
     virtual bool isDirectOutputSupported(const audio_config_base_t& config,
@@ -160,11 +161,11 @@
     virtual status_t listAudioPorts(audio_port_role_t role,
                                     audio_port_type_t type,
                                     unsigned int *num_ports,
-                                    struct audio_port *ports,
+                                    struct audio_port_v7 *ports,
                                     unsigned int *generation) = 0;
 
     /* Get attributes for a given audio port */
-    virtual status_t getAudioPort(struct audio_port *port) = 0;
+    virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
 
     /* Create an audio patch between several source and sink ports */
     virtual status_t createAudioPatch(const struct audio_patch *patch,
@@ -180,7 +181,7 @@
     /* Set audio port configuration */
     virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
 
-    virtual void registerClient(const sp<IAudioPolicyServiceClient>& client) = 0;
+    virtual void registerClient(const sp<media::IAudioPolicyServiceClient>& client) = 0;
 
     virtual void setAudioPortCallbacksEnabled(bool enabled) = 0;
 
diff --git a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
deleted file mode 100644
index 47b31ee..0000000
--- a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2009 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_IAUDIOPOLICYSERVICECLIENT_H
-#define ANDROID_IAUDIOPOLICYSERVICECLIENT_H
-
-#include <vector>
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <system/audio.h>
-#include <system/audio_effect.h>
-#include <media/AudioPolicy.h>
-#include <media/AudioVolumeGroup.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-struct record_client_info {
-    audio_unique_id_t riid;
-    uid_t uid;
-    audio_session_t session;
-    audio_source_t source;
-    audio_port_handle_t port_id;
-    bool silenced;
-};
-
-typedef struct record_client_info record_client_info_t;
-
-// ----------------------------------------------------------------------------
-
-class IAudioPolicyServiceClient : public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(AudioPolicyServiceClient);
-
-    // Notifies a change of volume group
-    virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags) = 0;
-    // Notifies a change of audio port configuration.
-    virtual void onAudioPortListUpdate() = 0;
-    // Notifies a change of audio patch configuration.
-    virtual void onAudioPatchListUpdate() = 0;
-    // Notifies a change in the mixing state of a specific mix in a dynamic audio policy
-    virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;
-    // Notifies a change of audio recording configuration
-    virtual void onRecordingConfigurationUpdate(int event,
-            const record_client_info_t *clientInfo,
-            const audio_config_base_t *clientConfig,
-            std::vector<effect_descriptor_t> clientEffects,
-            const audio_config_base_t *deviceConfig,
-            std::vector<effect_descriptor_t> effects,
-            audio_patch_handle_t patchHandle,
-            audio_source_t source) = 0;
-};
-
-
-// ----------------------------------------------------------------------------
-
-class BnAudioPolicyServiceClient : public BnInterface<IAudioPolicyServiceClient>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_IAUDIOPOLICYSERVICECLIENT_H
diff --git a/media/libaudioclient/include/media/PlayerBase.h b/media/libaudioclient/include/media/PlayerBase.h
index 4aad9b4..1a42b88 100644
--- a/media/libaudioclient/include/media/PlayerBase.h
+++ b/media/libaudioclient/include/media/PlayerBase.h
@@ -44,12 +44,14 @@
             const media::VolumeShaperConfiguration& configuration,
             const media::VolumeShaperOperation& operation) override;
 
-            status_t startWithStatus();
+            status_t startWithStatus(audio_port_handle_t deviceId);
             status_t pauseWithStatus();
             status_t stopWithStatus();
 
             //FIXME temporary method while some player state is outside of this class
-            void reportEvent(player_state_t event);
+            void reportEvent(player_state_t event, audio_port_handle_t deviceId);
+
+            void baseUpdateDeviceId(audio_port_handle_t deviceId);
 
 protected:
 
@@ -71,7 +73,7 @@
 
 private:
             // report events to AudioService
-            void servicePlayerEvent(player_state_t event);
+            void servicePlayerEvent(player_state_t event, audio_port_handle_t deviceId);
             void serviceReleasePlayer();
 
     // native interface to AudioService
@@ -83,6 +85,9 @@
     // Mutex for state reporting
     Mutex mPlayerStateLock;
     player_state_t mLastReportedEvent;
+
+    Mutex mDeviceIdLock;
+    audio_port_handle_t mLastReportedDeviceId;
 };
 
 } // namespace android
diff --git a/media/libaudioclient/include/media/ToneGenerator.h b/media/libaudioclient/include/media/ToneGenerator.h
index 04357a8..a575616 100644
--- a/media/libaudioclient/include/media/ToneGenerator.h
+++ b/media/libaudioclient/include/media/ToneGenerator.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_TONEGENERATOR_H_
 #define ANDROID_TONEGENERATOR_H_
 
+#include <string>
+
 #include <media/AudioSystem.h>
 #include <media/AudioTrack.h>
 #include <utils/Compat.h>
@@ -152,7 +154,8 @@
         NUM_SUP_TONES = LAST_SUP_TONE-FIRST_SUP_TONE+1
     };
 
-    ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava = false);
+    ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava = false,
+            std::string opPackageName = {});
     ~ToneGenerator();
 
     bool startTone(tone_type toneType, int durationMs = -1);
@@ -193,6 +196,7 @@
         TONE_JAPAN_DIAL,            // Dial tone: 400Hz, continuous
         TONE_JAPAN_BUSY,            // Busy tone: 400Hz, 500ms ON, 500ms OFF...
         TONE_JAPAN_RADIO_ACK,       // Radio path acknowlegment: 400Hz, 1s ON, 2s OFF...
+        TONE_JAPAN_RINGTONE,        // Ring Tone: 400 Hz repeated in a 1 s on, 2 s off pattern.
         // GB Supervisory tones
         TONE_GB_BUSY,               // Busy tone: 400 Hz, 375ms ON, 375ms OFF...
         TONE_GB_CONGESTION,         // Congestion Tone: 400 Hz, 400ms ON, 350ms OFF, 225ms ON, 525ms OFF...
@@ -343,6 +347,8 @@
     };
 
     KeyedVector<uint16_t, WaveGenerator *> mWaveGens;  // list of active wave generators.
+
+    std::string mOpPackageName;
 };
 
 }
diff --git a/media/libaudioclient/include/media/TrackPlayerBase.h b/media/libaudioclient/include/media/TrackPlayerBase.h
index 6d26e63..b40d1eb 100644
--- a/media/libaudioclient/include/media/TrackPlayerBase.h
+++ b/media/libaudioclient/include/media/TrackPlayerBase.h
@@ -53,8 +53,20 @@
             void doDestroy();
             status_t doSetVolume();
 
+            class SelfAudioDeviceCallback : public AudioSystem::AudioDeviceCallback {
+            public:
+                SelfAudioDeviceCallback(PlayerBase& self);
+                virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+                                                         audio_port_handle_t deviceId);
+            private:
+                virtual ~SelfAudioDeviceCallback();
+                PlayerBase& mSelf;
+            };
+
     // volume coming from the player volume API
     float mPlayerVolumeL, mPlayerVolumeR;
+
+   sp<SelfAudioDeviceCallback> mSelfAudioDeviceCallback;
 };
 
 } // namespace android
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index 350a780..21d18d3 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -7,6 +7,18 @@
 }
 
 cc_test {
+    name: "audio_aidl_status_tests",
+    defaults: ["libaudioclient_tests_defaults"],
+    srcs: ["audio_aidl_status_tests.cpp"],
+    shared_libs: [
+        "libaudioclient_aidl_conversion",
+        "libbinder",
+        "libcutils",
+        "libutils",
+    ],
+}
+
+cc_test {
     name: "test_create_audiotrack",
     defaults: ["libaudioclient_tests_defaults"],
     srcs: ["test_create_audiotrack.cpp",
diff --git a/media/libaudioclient/tests/audio_aidl_status_tests.cpp b/media/libaudioclient/tests/audio_aidl_status_tests.cpp
new file mode 100644
index 0000000..5517091
--- /dev/null
+++ b/media/libaudioclient/tests/audio_aidl_status_tests.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+#include <media/AidlConversionUtil.h>
+#include <utils/Errors.h>
+
+using namespace android;
+using namespace android::aidl_utils;
+using android::binder::Status;
+
+// Tests for statusTFromBinderStatus() and binderStatusFromStatusT().
+
+// STATUS_T_SMALL_VALUE_LIMIT is an arbitrary limit where we exhaustively check status_t errors.
+// It is known that this limit doesn't cover UNKNOWN_ERROR ~ INT32_MIN.
+constexpr status_t STATUS_T_SMALL_VALUE_LIMIT = -1000;
+
+// Small status values are preserved on round trip
+TEST(audio_aidl_status_tests, statusRoundTripSmallValues) {
+    for (status_t status = 0; status > STATUS_T_SMALL_VALUE_LIMIT; --status) {
+        ASSERT_EQ(status, statusTFromBinderStatus(binderStatusFromStatusT(status)));
+    }
+}
+
+// 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}) {
+        ASSERT_EQ(status, statusTFromBinderStatus(binderStatusFromStatusT(status)));
+    }
+}
+
+// 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().
+            }) {
+        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}) {
+        ASSERT_EQ(status, statusTFromBinderStatus(Status::fromStatusT(status)));
+    }
+}
+
+// Binder service specific errors show in status_t; these come fromServiceSpecificError().
+TEST(audio_aidl_status_tests, binderStatusServiceSpecificError) {
+    // fromServiceSpecificError() still stores exception code if status is 0.
+    for (status_t status = -1; status > STATUS_T_SMALL_VALUE_LIMIT; --status) {
+        ASSERT_EQ(status, statusTFromBinderStatus(Status::fromServiceSpecificError(status)));
+    }
+}
+
+// Binder status with message.
+TEST(audio_aidl_status_tests, binderStatusMessage) {
+    const String8 message("abcd");
+    for (status_t status = -1; status > STATUS_T_SMALL_VALUE_LIMIT; --status) {
+        const Status binderStatus = binderStatusFromStatusT(status, message.c_str());
+        ASSERT_EQ(status, statusTFromBinderStatus(binderStatus));
+        ASSERT_EQ(message, binderStatus.exceptionMessage());
+    }
+}
diff --git a/media/libaudiofoundation/AudioGain.cpp b/media/libaudiofoundation/AudioGain.cpp
index 56343d8..1dee938 100644
--- a/media/libaudiofoundation/AudioGain.cpp
+++ b/media/libaudiofoundation/AudioGain.cpp
@@ -140,7 +140,7 @@
     parcelable->useInChannelMask = mUseInChannelMask;
     parcelable->useForVolume = mUseForVolume;
     parcelable->mode = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_gain_mode_t_mask_int32_t(mGain.mode));
+            legacy2aidl_audio_gain_mode_t_int32_t_mask(mGain.mode));
     parcelable->channelMask = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_channel_mask_t_int32_t(mGain.channel_mask));
     parcelable->minValue = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(mGain.min_value));
diff --git a/media/libaudiofoundation/AudioPort.cpp b/media/libaudiofoundation/AudioPort.cpp
index 6b63675..20d8632 100644
--- a/media/libaudiofoundation/AudioPort.cpp
+++ b/media/libaudiofoundation/AudioPort.cpp
@@ -291,7 +291,7 @@
     parcelable->id = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(mId));
     parcelable->gain.index = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(mGain.index));
     parcelable->gain.mode = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_gain_mode_t_mask_int32_t(mGain.mode));
+            legacy2aidl_audio_gain_mode_t_int32_t_mask(mGain.mode));
     parcelable->gain.channelMask = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_channel_mask_t_int32_t(mGain.channel_mask));
     parcelable->gain.rampDurationMs = VALUE_OR_RETURN_STATUS(
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
index 3b47fed..65f7388 100644
--- a/media/libaudiofoundation/AudioProfile.cpp
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -355,4 +355,31 @@
     return convertContainer<std::vector<media::AudioProfile>>(legacy, legacy2aidl_AudioProfile);
 }
 
+AudioProfileVector intersectAudioProfiles(const AudioProfileVector& profiles1,
+                                          const AudioProfileVector& profiles2)
+{
+    std::map<audio_format_t, std::pair<ChannelMaskSet, SampleRateSet>> infos2;
+    for (const auto& profile : profiles2) {
+        infos2.emplace(profile->getFormat(),
+                std::make_pair(profile->getChannels(), profile->getSampleRates()));
+    }
+    AudioProfileVector profiles;
+    for (const auto& profile : profiles1) {
+        const auto it = infos2.find(profile->getFormat());
+        if (it == infos2.end()) {
+            continue;
+        }
+        ChannelMaskSet channelMasks = SetIntersection(profile->getChannels(), it->second.first);
+        if (channelMasks.empty()) {
+            continue;
+        }
+        SampleRateSet sampleRates = SetIntersection(profile->getSampleRates(), it->second.second);
+        if (sampleRates.empty()) {
+            continue;
+        }
+        profiles.push_back(new AudioProfile(profile->getFormat(), channelMasks, sampleRates));
+    }
+    return profiles;
+}
+
 } // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index aa7ca69..204b365 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -50,6 +50,15 @@
     return intersection;
 }
 
+template<typename T>
+static std::set<T> SetIntersection(const std::set<T>& a, const std::set<T> b) {
+    std::set<T> intersection;
+    std::set_intersection(a.begin(), a.end(),
+                          b.begin(), b.end(),
+                          std::inserter(intersection, intersection.begin()));
+    return intersection;
+}
+
 static inline ChannelMaskSet asInMask(const ChannelMaskSet& channelMasks) {
     ChannelMaskSet inMaskSet;
     for (const auto &channel : channelMasks) {
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
index 57592bc..5051233 100644
--- a/media/libaudiofoundation/include/media/AudioProfile.h
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -137,5 +137,7 @@
 ConversionResult<std::vector<media::AudioProfile>>
 legacy2aidl_AudioProfileVector(const AudioProfileVector& legacy);
 
+AudioProfileVector intersectAudioProfiles(const AudioProfileVector& profiles1,
+                                          const AudioProfileVector& profiles2);
 
 } // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index 77c2550..0108816 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -215,7 +215,7 @@
         const struct audio_config *config, size_t *size) {
     if (mDevice == 0) return NO_INIT;
     AudioConfig hidlConfig;
-    HidlUtils::audioConfigFromHal(*config, &hidlConfig);
+    HidlUtils::audioConfigFromHal(*config, true /*isInput*/, &hidlConfig);
     Result retval;
     Return<void> ret = mDevice->getInputBufferSize(
             hidlConfig,
@@ -240,7 +240,7 @@
     status_t status = deviceAddressFromHal(deviceType, address, &hidlDevice);
     if (status != OK) return status;
     AudioConfig hidlConfig;
-    HidlUtils::audioConfigFromHal(*config, &hidlConfig);
+    HidlUtils::audioConfigFromHal(*config, false /*isInput*/, &hidlConfig);
     Result retval = Result::NOT_INITIALIZED;
     Return<void> ret = mDevice->openOutputStream(
             handle,
@@ -275,7 +275,7 @@
     status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
     if (status != OK) return status;
     AudioConfig hidlConfig;
-    HidlUtils::audioConfigFromHal(*config, &hidlConfig);
+    HidlUtils::audioConfigFromHal(*config, true /*isInput*/, &hidlConfig);
     Result retval = Result::NOT_INITIALIZED;
 #if MAJOR_VERSION == 2
     auto sinkMetadata = AudioSource(source);
diff --git a/media/libaudiohal/impl/DeviceHalLocal.h b/media/libaudiohal/impl/DeviceHalLocal.h
index 195204b..46b510b 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.h
+++ b/media/libaudiohal/impl/DeviceHalLocal.h
@@ -117,6 +117,8 @@
     void closeOutputStream(struct audio_stream_out *stream_out);
     void closeInputStream(struct audio_stream_in *stream_in);
 
+    uint32_t version() const { return mDev->common.version; }
+
   private:
     audio_hw_device_t *mDev;
 
@@ -127,8 +129,6 @@
 
     // The destructor automatically closes the device.
     virtual ~DeviceHalLocal();
-
-    uint32_t version() const { return mDev->common.version; }
 };
 
 } // namespace CPP_VERSION
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 2726e36..09a7c1c 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -25,6 +25,7 @@
 
 #include "DeviceHalHidl.h"
 #include "EffectHalHidl.h"
+#include "HidlUtils.h"
 #include "StreamHalHidl.h"
 #include "VersionUtils.h"
 
@@ -610,12 +611,25 @@
         const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
     CPP_VERSION::SourceMetadata halMetadata = {
         .tracks = transformToHidlVec(sourceMetadata.tracks,
-              [](const playback_track_metadata& metadata) -> PlaybackTrackMetadata {
-                  return {
-                    .usage=static_cast<AudioUsage>(metadata.usage),
-                    .contentType=static_cast<AudioContentType>(metadata.content_type),
-                    .gain=metadata.gain,
+              [](const playback_track_metadata_v7& metadata) -> PlaybackTrackMetadata {
+                  PlaybackTrackMetadata halTrackMetadata = {
+                      .usage=static_cast<AudioUsage>(metadata.base.usage),
+                      .contentType=static_cast<AudioContentType>(metadata.base.content_type),
+                      .gain=metadata.base.gain,
                   };
+#if MAJOR_VERSION >= 7
+                  HidlUtils::audioChannelMaskFromHal(metadata.channel_mask, false /*isInput*/,
+                                                    &halTrackMetadata.channelMask);
+
+                  std::istringstream tags{metadata.tags};
+                  std::string tag;
+                  while (std::getline(tags, tag, HidlUtils::sAudioTagSeparator)) {
+                      if (!tag.empty()) {
+                          halTrackMetadata.tags.push_back(tag);
+                      }
+                  }
+#endif
+                  return halTrackMetadata;
               })};
     return processReturn("updateSourceMetadata", mStream->updateSourceMetadata(halMetadata));
 }
@@ -902,11 +916,23 @@
         StreamInHalInterface::SinkMetadata& sinkMetadata) {
     CPP_VERSION::SinkMetadata halMetadata = {
         .tracks = transformToHidlVec(sinkMetadata.tracks,
-              [](const record_track_metadata& metadata) -> RecordTrackMetadata {
-                  return {
-                    .source=static_cast<AudioSource>(metadata.source),
-                    .gain=metadata.gain,
+              [](const record_track_metadata_v7& metadata) -> RecordTrackMetadata {
+                  RecordTrackMetadata halTrackMetadata = {
+                      .source=static_cast<AudioSource>(metadata.base.source),
+                      .gain=metadata.base.gain,
                   };
+#if MAJOR_VERSION >= 7
+                  HidlUtils::audioChannelMaskFromHal(metadata.channel_mask, true /*isInput*/,
+                                                    &halTrackMetadata.channelMask);
+                  std::istringstream tags{metadata.tags};
+                  std::string tag;
+                  while (std::getline(tags, tag, HidlUtils::sAudioTagSeparator)) {
+                      if (!tag.empty()) {
+                          halTrackMetadata.tags.push_back(tag);
+                      }
+                  }
+#endif
+                  return halTrackMetadata;
               })};
     return processReturn("updateSinkMetadata", mStream->updateSinkMetadata(halMetadata));
 }
diff --git a/media/libaudiohal/impl/StreamHalLocal.cpp b/media/libaudiohal/impl/StreamHalLocal.cpp
index 69be303..f544e06 100644
--- a/media/libaudiohal/impl/StreamHalLocal.cpp
+++ b/media/libaudiohal/impl/StreamHalLocal.cpp
@@ -241,19 +241,55 @@
     return mStream->get_presentation_position(mStream, frames, timestamp);
 }
 
-status_t StreamOutHalLocal::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
-    if (mStream->update_source_metadata == nullptr) {
-        return INVALID_OPERATION;
+void StreamOutHalLocal::doUpdateSourceMetadata(const SourceMetadata& sourceMetadata) {
+    std::vector<playback_track_metadata> halTracks;
+    halTracks.reserve(sourceMetadata.tracks.size());
+    for (auto& metadata : sourceMetadata.tracks) {
+        playback_track_metadata halTrackMetadata;
+        playback_track_metadata_from_v7(&halTrackMetadata, &metadata);
+        halTracks.push_back(halTrackMetadata);
     }
+    const source_metadata_t halMetadata = {
+        .track_count = halTracks.size(),
+        .tracks = halTracks.data(),
+    };
+    mStream->update_source_metadata(mStream, &halMetadata);
+}
+
+#if MAJOR_VERSION >= 7
+void StreamOutHalLocal::doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata) {
     const source_metadata_t metadata {
         .track_count = sourceMetadata.tracks.size(),
         // const cast is fine as it is in a const structure
-        .tracks = const_cast<playback_track_metadata*>(sourceMetadata.tracks.data()),
+        .tracks = const_cast<playback_track_metadata_v7*>(sourceMetadata.tracks.data()),
     };
-    mStream->update_source_metadata(mStream, &metadata);
+    mStream->update_source_metadata_v7(mStream, &metadata);
+}
+#endif
+
+status_t StreamOutHalLocal::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
+#if MAJOR_VERSION < 7
+    if (mStream->update_source_metadata == nullptr) {
+        return INVALID_OPERATION;
+    }
+    doUpdateSourceMetadata(sourceMetadata);
+#else
+    if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2)
+        if (mStream->update_source_metadata == nullptr) {
+            return INVALID_OPERATION;
+        }
+        doUpdateSourceMetadata(sourceMetadata);
+    } else {
+        if (mStream->update_source_metadata_v7 == nullptr) {
+            return INVALID_OPERATION;
+        }
+        doUpdateSourceMetadataV7(sourceMetadata);
+    }
+#endif
     return OK;
 }
 
+
 status_t StreamOutHalLocal::start() {
     if (mStream->start == NULL) return INVALID_OPERATION;
     return mStream->start(mStream);
@@ -352,16 +388,52 @@
     return mStream->get_capture_position(mStream, frames, time);
 }
 
-status_t StreamInHalLocal::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
-    if (mStream->update_sink_metadata == nullptr) {
-        return INVALID_OPERATION;
+void StreamInHalLocal::doUpdateSinkMetadata(const SinkMetadata& sinkMetadata) {
+    std::vector<record_track_metadata> halTracks;
+    halTracks.reserve(sinkMetadata.tracks.size());
+    for (auto& metadata : sinkMetadata.tracks) {
+        record_track_metadata halTrackMetadata;
+        record_track_metadata_from_v7(&halTrackMetadata, &metadata);
+        halTracks.push_back(halTrackMetadata);
     }
-    const sink_metadata_t metadata {
+    const sink_metadata_t halMetadata = {
+        .track_count = halTracks.size(),
+        .tracks = halTracks.data(),
+    };
+    mStream->update_sink_metadata(mStream, &halMetadata);
+}
+
+#if MAJOR_VERSION >= 7
+void StreamInHalLocal::doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata) {
+    const sink_metadata_v7_t halMetadata {
         .track_count = sinkMetadata.tracks.size(),
         // const cast is fine as it is in a const structure
-        .tracks = const_cast<record_track_metadata*>(sinkMetadata.tracks.data()),
+        .tracks = const_cast<record_track_metadata_v7*>(sinkMetadata.tracks.data()),
     };
-    mStream->update_sink_metadata(mStream, &metadata);
+    mStream->update_sink_metadata_v7(mStream, &halMetadata);
+}
+#endif
+
+status_t StreamInHalLocal::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
+#if MAJOR_VERSION < 7
+
+    if (mStream->update_sink_metadata == nullptr) {
+        return INVALID_OPERATION;  // not supported by the HAL
+    }
+    doUpdateSinkMetadata(sinkMetadata);
+#else
+    if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2)
+        if (mStream->update_sink_metadata == nullptr) {
+            return INVALID_OPERATION;  // not supported by the HAL
+        }
+        doUpdateSinkMetadata(sinkMetadata);
+    } else {
+        if (mStream->update_sink_metadata_v7 == nullptr) {
+            return INVALID_OPERATION;  // not supported by the HAL
+        }
+        doUpdateSinkMetadataV7(sinkMetadata);
+    }
+#endif
     return OK;
 }
 
diff --git a/media/libaudiohal/impl/StreamHalLocal.h b/media/libaudiohal/impl/StreamHalLocal.h
index d17f9f3..8e5180f 100644
--- a/media/libaudiohal/impl/StreamHalLocal.h
+++ b/media/libaudiohal/impl/StreamHalLocal.h
@@ -173,6 +173,9 @@
     static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
 
     static int asyncEventCallback(stream_event_callback_type_t event, void *param, void *cookie);
+
+    void doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata);
+    void doUpdateSourceMetadata(const SourceMetadata& sourceMetadata);
 };
 
 class StreamInHalLocal : public StreamInHalInterface, public StreamHalLocal {
@@ -227,6 +230,9 @@
     StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device);
 
     virtual ~StreamInHalLocal();
+
+    void doUpdateSinkMetadata(const SinkMetadata& sinkMetadata);
+    void doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata);
 };
 
 } // namespace CPP_VERSION
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index e30cb72..523705e 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -158,7 +158,7 @@
     virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) = 0;
 
     struct SourceMetadata {
-        std::vector<playback_track_metadata_t> tracks;
+        std::vector<playback_track_metadata_v7_t> tracks;
     };
     /**
      * Called when the metadata of the stream's source has been changed.
@@ -197,7 +197,7 @@
     virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
 
     struct SinkMetadata {
-        std::vector<record_track_metadata_t> tracks;
+        std::vector<record_track_metadata_v7_t> tracks;
     };
     /**
      * Called when the metadata of the stream's sink has been changed.
diff --git a/media/libeffects/downmix/tests/build_and_run_all_unit_tests.sh b/media/libeffects/downmix/tests/build_and_run_all_unit_tests.sh
index d0faebe..8aadfbf 100755
--- a/media/libeffects/downmix/tests/build_and_run_all_unit_tests.sh
+++ b/media/libeffects/downmix/tests/build_and_run_all_unit_tests.sh
@@ -39,8 +39,7 @@
 echo "testing Downmix"
 adb shell mkdir $testdir
 
-adb push $ANDROID_BUILD_TOP/cts/tests/tests/media/res/raw/sinesweepraw.raw \
-$testdir
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/libeffects/res/raw/sinesweepraw.raw $testdir
 adb push $OUT/testcases/downmixtest/arm64/downmixtest $testdir
 
 #run the downmix test application for test.
diff --git a/media/libeffects/lvm/benchmarks/Android.bp b/media/libeffects/lvm/benchmarks/Android.bp
index 420e172..930292f 100644
--- a/media/libeffects/lvm/benchmarks/Android.bp
+++ b/media/libeffects/lvm/benchmarks/Android.bp
@@ -14,3 +14,24 @@
         "libhardware_headers",
     ],
 }
+
+cc_benchmark {
+    name: "reverb_benchmark",
+    vendor: true,
+    include_dirs: [
+        "frameworks/av/media/libeffects/lvm/wrapper/Reverb",
+    ],
+    srcs: ["reverb_benchmark.cpp"],
+    static_libs: [
+        "libreverb",
+        "libreverbwrapper",
+    ],
+    shared_libs: [
+        "libaudioutils",
+        "liblog",
+    ],
+    header_libs: [
+        "libaudioeffects",
+        "libhardware_headers",
+    ],
+}
diff --git a/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp b/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp
new file mode 100644
index 0000000..00a7ff2
--- /dev/null
+++ b/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+#include <array>
+#include <climits>
+#include <cstdlib>
+#include <random>
+#include <vector>
+#include <log/log.h>
+#include <benchmark/benchmark.h>
+#include <hardware/audio_effect.h>
+#include <system/audio.h>
+#include "EffectReverb.h"
+
+extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
+constexpr effect_uuid_t kEffectUuids[] = {
+        {0x172cdf00,
+         0xa3bc,
+         0x11df,
+         0xa72f,
+         {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},  // preset-insert mode
+        {0xf29a1400,
+         0xa3bb,
+         0x11df,
+         0x8ddc,
+         {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},  // preset-aux mode
+};
+
+constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
+
+constexpr size_t kFrameCount = 2048;
+
+constexpr int kPresets[] = {
+        REVERB_PRESET_NONE,      REVERB_PRESET_SMALLROOM,  REVERB_PRESET_MEDIUMROOM,
+        REVERB_PRESET_LARGEROOM, REVERB_PRESET_MEDIUMHALL, REVERB_PRESET_LARGEHALL,
+        REVERB_PRESET_PLATE,
+};
+
+constexpr size_t kNumPresets = std::size(kPresets);
+
+constexpr int kSampleRate = 44100;
+
+int reverbSetConfigParam(uint32_t paramType, uint32_t paramValue, effect_handle_t effectHandle) {
+    int reply = 0;
+    uint32_t replySize = sizeof(reply);
+    uint32_t paramData[2] = {paramType, paramValue};
+    auto effectParam = (effect_param_t*)malloc(sizeof(effect_param_t) + sizeof(paramData));
+    memcpy(&effectParam->data[0], &paramData[0], sizeof(paramData));
+    effectParam->psize = sizeof(paramData[0]);
+    effectParam->vsize = sizeof(paramData[1]);
+    int status = (*effectHandle)
+                         ->command(effectHandle, EFFECT_CMD_SET_PARAM,
+                                   sizeof(effect_param_t) + sizeof(paramData), effectParam,
+                                   &replySize, &reply);
+    free(effectParam);
+    if (status != 0) {
+        ALOGE("Reverb set config returned an error = %d\n", status);
+        return status;
+    }
+    return reply;
+}
+
+/*******************************************************************
+ * A test result running on Pixel 3 with for comparison.
+ * The first parameter indicates the preset level id.
+ * The second parameter indicates the effect.
+ * 0: preset-insert mode, 1: preset-aux mode
+ * --------------------------------------------------------
+ * Benchmark              Time             CPU   Iterations
+ * --------------------------------------------------------
+ * BM_REVERB/0/0      19312 ns        19249 ns        36282
+ * BM_REVERB/0/1       5613 ns         5596 ns       125032
+ * BM_REVERB/1/0     605453 ns       603714 ns         1131
+ * BM_REVERB/1/1     589421 ns       587758 ns         1161
+ * BM_REVERB/2/0     605760 ns       604006 ns         1131
+ * BM_REVERB/2/1     589434 ns       587777 ns         1161
+ * BM_REVERB/3/0     605574 ns       603828 ns         1131
+ * BM_REVERB/3/1     589566 ns       587862 ns         1162
+ * BM_REVERB/4/0     605634 ns       603894 ns         1131
+ * BM_REVERB/4/1     589506 ns       587856 ns         1161
+ * BM_REVERB/5/0     605644 ns       603929 ns         1131
+ * BM_REVERB/5/1     589592 ns       587863 ns         1161
+ * BM_REVERB/6/0     610544 ns       608561 ns         1131
+ * BM_REVERB/6/1     589686 ns       587871 ns         1161
+ *******************************************************************/
+
+static void BM_REVERB(benchmark::State& state) {
+    const size_t chMask = AUDIO_CHANNEL_OUT_STEREO;
+    const size_t preset = kPresets[state.range(0)];
+    const effect_uuid_t uuid = kEffectUuids[state.range(1)];
+    const size_t channelCount = audio_channel_count_from_out_mask(chMask);
+
+    // Initialize input buffer with deterministic pseudo-random values
+    std::minstd_rand gen(chMask);
+    std::uniform_real_distribution<> dis(-1.0f, 1.0f);
+    std::vector<float> input(kFrameCount * channelCount);
+    std::vector<float> output(kFrameCount * channelCount);
+    for (auto& in : input) {
+        in = dis(gen);
+    }
+
+    effect_handle_t effectHandle = nullptr;
+    if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&uuid, 1, 1, &effectHandle);
+        status != 0) {
+        ALOGE("create_effect returned an error = %d\n", status);
+        return;
+    }
+
+    effect_config_t config{};
+    config.inputCfg.samplingRate = config.outputCfg.samplingRate = kSampleRate;
+    config.inputCfg.channels = config.outputCfg.channels = chMask;
+    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, 0, nullptr, &replySize, &reply);
+        status != 0) {
+        ALOGE("Command enable call returned error %d\n", reply);
+        return;
+    }
+
+    if (int status = reverbSetConfigParam(REVERB_PARAM_PRESET, preset, effectHandle); status != 0) {
+        ALOGE("Invalid reverb preset. Error %d\n", status);
+        return;
+    }
+
+    // Run the test
+    for (auto _ : state) {
+        benchmark::DoNotOptimize(input.data());
+        benchmark::DoNotOptimize(output.data());
+
+        audio_buffer_t inBuffer = {.frameCount = kFrameCount, .f32 = input.data()};
+        audio_buffer_t outBuffer = {.frameCount = kFrameCount, .f32 = output.data()};
+        (*effectHandle)->process(effectHandle, &inBuffer, &outBuffer);
+
+        benchmark::ClobberMemory();
+    }
+
+    state.SetComplexityN(state.range(0));
+
+    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 REVERBArgs(benchmark::internal::Benchmark* b) {
+    for (int i = 0; i < kNumPresets; i++) {
+        for (int j = 0; j < kNumEffectUuids; ++j) {
+            b->Args({i, j});
+        }
+    }
+}
+
+BENCHMARK(BM_REVERB)->Apply(REVERBArgs);
+
+BENCHMARK_MAIN();
diff --git a/media/libeffects/lvm/lib/Android.bp b/media/libeffects/lvm/lib/Android.bp
index 8f2f016..8d248a3 100644
--- a/media/libeffects/lvm/lib/Android.bp
+++ b/media/libeffects/lvm/lib/Android.bp
@@ -69,28 +69,19 @@
         "Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp",
         "Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp",
         "Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.cpp",
-        "Common/src/Int16LShiftToInt32_16x32.cpp",
-        "Common/src/From2iToMono_16.cpp",
         "Common/src/Copy_16.cpp",
-        "Common/src/MonoTo2I_16.cpp",
         "Common/src/MonoTo2I_32.cpp",
-        "Common/src/LoadConst_16.cpp",
         "Common/src/LoadConst_32.cpp",
         "Common/src/dB_to_Lin32.cpp",
         "Common/src/Shift_Sat_v16xv16.cpp",
         "Common/src/Shift_Sat_v32xv32.cpp",
-        "Common/src/Abs_32.cpp",
-        "Common/src/Int32RShiftToInt16_Sat_32x16.cpp",
         "Common/src/From2iToMono_32.cpp",
-        "Common/src/mult3s_16x16.cpp",
         "Common/src/Mult3s_32x16.cpp",
         "Common/src/NonLinComp_D16.cpp",
         "Common/src/DelayMix_16x16.cpp",
         "Common/src/MSTo2i_Sat_16x16.cpp",
         "Common/src/From2iToMS_16x16.cpp",
-        "Common/src/Mac3s_Sat_16x16.cpp",
         "Common/src/Mac3s_Sat_32x16.cpp",
-        "Common/src/Add2_Sat_16x16.cpp",
         "Common/src/Add2_Sat_32x32.cpp",
         "Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp",
         "Common/src/LVC_MixSoft_1St_D16C31_SAT.cpp",
@@ -131,12 +122,15 @@
     shared_libs: [
         "liblog",
     ],
+    static_libs: [
+        "libaudioutils",
+    ],
     header_libs: [
         "libhardware_headers",
     ],
     cppflags: [
+        "-DBIQUAD_OPT",
         "-fvisibility=hidden",
-
         "-Wall",
         "-Werror",
     ],
@@ -163,18 +157,14 @@
         "Reverb/src/LVREV_Process.cpp",
         "Reverb/src/LVREV_SetControlParameters.cpp",
         "Reverb/src/LVREV_Tables.cpp",
-        "Common/src/Abs_32.cpp",
         "Common/src/InstAlloc.cpp",
-        "Common/src/LoadConst_16.cpp",
         "Common/src/LoadConst_32.cpp",
         "Common/src/From2iToMono_32.cpp",
         "Common/src/Mult3s_32x16.cpp",
         "Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp",
         "Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp",
-        "Common/src/DelayAllPass_Sat_32x16To32.cpp",
         "Common/src/Copy_16.cpp",
         "Common/src/Mac3s_Sat_32x16.cpp",
-        "Common/src/DelayWrite_32.cpp",
         "Common/src/Shift_Sat_v32xv32.cpp",
         "Common/src/Add2_Sat_32x32.cpp",
         "Common/src/JoinTo2i_32x32.cpp",
@@ -201,10 +191,12 @@
         "Reverb/lib",
         "Common/lib",
     ],
-
+    static_libs: [
+        "libaudioutils",
+    ],
     cppflags: [
+        "-DBIQUAD_OPT",
         "-fvisibility=hidden",
-
         "-Wall",
         "-Werror",
     ],
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
index 5b47aa6..814280f 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
@@ -21,6 +21,10 @@
 /*                                                                                      */
 /****************************************************************************************/
 
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#include <system/audio.h>
+#endif
 #include "LVDBE.h"
 #include "LVDBE_Private.h"
 #include "VectorArithmetic.h"
@@ -107,22 +111,37 @@
     /*
      * Setup the high pass filter
      */
+#ifdef BIQUAD_OPT
+    std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+            LVDBE_HPF_Table[Offset].A0, LVDBE_HPF_Table[Offset].A1, LVDBE_HPF_Table[Offset].A2,
+            -(LVDBE_HPF_Table[Offset].B1), -(LVDBE_HPF_Table[Offset].B2)};
+    pInstance->pHPFBiquad
+            ->setCoefficients<std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(coefs);
+#else
     LoadConst_Float(0,                                      /* Clear the history, value 0 */
                     (LVM_FLOAT*)&pInstance->pData->HPFTaps, /* Destination */
                     sizeof(pInstance->pData->HPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
     BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance, /* Initialise the filter */
                                     &pInstance->pData->HPFTaps,
                                     (BQ_FLOAT_Coefs_t*)&LVDBE_HPF_Table[Offset]);
+#endif
 
     /*
      * Setup the band pass filter
      */
+#ifdef BIQUAD_OPT
+    coefs = {LVDBE_BPF_Table[Offset].A0, 0.0, -(LVDBE_BPF_Table[Offset].A0),
+             -(LVDBE_BPF_Table[Offset].B1), -(LVDBE_BPF_Table[Offset].B2)};
+    pInstance->pBPFBiquad
+            ->setCoefficients<std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(coefs);
+#else
     LoadConst_Float(0,                                      /* Clear the history, value 0 */
                     (LVM_FLOAT*)&pInstance->pData->BPFTaps, /* Destination */
                     sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
     BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance, /* Initialise the filter */
                                     &pInstance->pData->BPFTaps,
                                     (BP_FLOAT_Coefs_t*)&LVDBE_BPF_Table[Offset]);
+#endif
 }
 
 /************************************************************************************/
@@ -275,6 +294,14 @@
     LVDBE_Instance_t* pInstance = (LVDBE_Instance_t*)hInstance;
     LVMixer3_2St_FLOAT_st* pBypassMixer_Instance = &pInstance->pData->BypassMixer;
 
+#ifdef BIQUAD_OPT
+    /*
+     * Create biquad instance
+     */
+    pInstance->pHPFBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(
+            (FCC_1 == pParams->NrChannels) ? FCC_2 : pParams->NrChannels));
+#endif
+
     /*
      * Update the filters
      */
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
index 12af162..6bdb7fe 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
@@ -20,8 +20,11 @@
 /*    Includes                                                                          */
 /*                                                                                      */
 /****************************************************************************************/
-#include <stdlib.h>
 
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
+#include <stdlib.h>
 #include "LVDBE.h"
 #include "LVDBE_Private.h"
 
@@ -89,10 +92,19 @@
     if (pInstance->pData == NULL) {
         return LVDBE_NULLADDRESS;
     }
+#ifdef BIQUAD_OPT
+    /*
+     * Create biquad instance
+     */
+    pInstance->pHPFBiquad.reset(
+            new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+    pInstance->pBPFBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1));
+#else
     pInstance->pCoef = (LVDBE_Coef_FLOAT_t*)calloc(1, sizeof(*(pInstance->pCoef)));
     if (pInstance->pCoef == NULL) {
         return LVDBE_NULLADDRESS;
     }
+#endif
 
     /*
      * Initialise the filters
@@ -182,10 +194,12 @@
         free(pInstance->pData);
         pInstance->pData = LVM_NULL;
     }
+#ifndef BIQUAD_OPT
     if (pInstance->pCoef != LVM_NULL) {
         free(pInstance->pCoef);
         pInstance->pCoef = LVM_NULL;
     }
+#endif
     free(pInstance);
     *phInstance = LVM_NULL;
 }
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
index 4fef1ef..23be2aa 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
@@ -33,6 +33,9 @@
 /*                                                                                      */
 /****************************************************************************************/
 
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
 #include "LVDBE.h" /* Calling or Application layer definitions */
 #include "BIQUAD.h"
 #include "LVC_Mixer.h"
@@ -63,19 +66,24 @@
     AGC_MIX_VOL_2St1Mon_FLOAT_t AGCInstance; /* AGC instance parameters */
 
     /* Process variables */
+#ifndef BIQUAD_OPT
     Biquad_2I_Order2_FLOAT_Taps_t HPFTaps; /* High pass filter taps */
     Biquad_1I_Order2_FLOAT_Taps_t BPFTaps; /* Band pass filter taps */
+#endif
     LVMixer3_1St_FLOAT_st BypassVolume;    /* Bypass volume scaler */
     LVMixer3_2St_FLOAT_st BypassMixer;     /* Bypass Mixer for Click Removal */
 
 } LVDBE_Data_FLOAT_t;
 
+#ifndef BIQUAD_OPT
 /* Coefs structure */
 typedef struct {
     /* Process variables */
     Biquad_FLOAT_Instance_t HPFInstance; /* High pass filter instance */
     Biquad_FLOAT_Instance_t BPFInstance; /* Band pass filter instance */
 } LVDBE_Coef_FLOAT_t;
+#endif
+
 /* Instance structure */
 typedef struct {
     /* Public parameters */
@@ -84,8 +92,16 @@
 
     /* Data and coefficient pointers */
     LVDBE_Data_FLOAT_t* pData; /* Instance data */
+#ifndef BIQUAD_OPT
     LVDBE_Coef_FLOAT_t* pCoef; /* Instance coefficients */
+#endif
     void* pScratch;            /* scratch pointer */
+#ifdef BIQUAD_OPT
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pHPFBiquad; /* Biquad filter instance for HPF */
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pBPFBiquad; /* Biquad filter instance for BPF */
+#endif
 } LVDBE_Instance_t;
 
 /****************************************************************************************/
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
index f4a4d6f..e8541fd 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
@@ -20,6 +20,9 @@
 /*    Includes                                                                          */
 /*                                                                                      */
 /****************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
 
 #include <string.h>  // memset
 #include "LVDBE.h"
@@ -125,10 +128,14 @@
          * Apply the high pass filter if selected
          */
         if (pInstance->Params.HPFSelect == LVDBE_HPF_ON) {
+#ifdef BIQUAD_OPT
+            pInstance->pHPFBiquad->process(pScratch, pScratch, NrFrames);
+#else
             BQ_MC_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance, /* Filter instance      */
                                        pScratch,                       /* Source               */
                                        pScratch,                       /* Destination          */
                                        (LVM_INT16)NrFrames, (LVM_INT16)NrChannels);
+#endif
         }
 
         /*
@@ -142,10 +149,14 @@
         /*
          * Apply the band pass filter
          */
+#ifdef BIQUAD_OPT
+        pInstance->pBPFBiquad->process(pMono, pMono, NrFrames);
+#else
         BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance       */
                                    pMono,                          /* Source                */
                                    pMono,                          /* Destination           */
                                    (LVM_INT16)NrFrames);
+#endif
 
         /*
          * Apply the AGC and mix
@@ -156,15 +167,6 @@
                                    pScratch,                       /* Destination    */
                                    NrFrames,                       /* Number of frames     */
                                    NrChannels);                    /* Number of channels     */
-
-        for (LVM_INT32 ii = 0; ii < NrSamples; ++ii) {
-            // TODO: replace with existing clamping function
-            if (pScratch[ii] < -1.0) {
-                pScratch[ii] = -1.0;
-            } else if (pScratch[ii] > 1.0) {
-                pScratch[ii] = 1.0;
-            }
-        }
     } else {
         // clear DBE processed path
         memset(pScratch, 0, sizeof(*pScratch) * NrSamples);
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
index 3118e77..7e8664a 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
@@ -276,6 +276,16 @@
              */
             Offset = (LVM_INT16)(EffectLevel - 1 +
                                  TrebleBoostSteps * (pParams->SampleRate - TrebleBoostMinRate));
+#ifdef BIQUAD_OPT
+            /*
+             * Create biquad instance
+             */
+            std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                    LVM_TrebleBoostCoefs[Offset].A0, LVM_TrebleBoostCoefs[Offset].A1, 0.0,
+                    -(LVM_TrebleBoostCoefs[Offset].B1), 0.0};
+            pInstance->pTEBiquad.reset(
+                    new android::audio_utils::BiquadFilter<LVM_FLOAT>(pParams->NrChannels, coefs));
+#else
             FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
                                                  &pInstance->pTE_Taps->TrebleBoost_Taps,
                                                  &LVM_TrebleBoostCoefs[Offset]);
@@ -288,6 +298,7 @@
                                                    Cast to void: no dereferencing in function */
                             (LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps) /
                                          sizeof(LVM_FLOAT))); /* Number of words */
+#endif
         }
     } else {
         /*
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
index bb962df..bbfa0dc 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
@@ -174,6 +174,7 @@
     /*
      * Treble Enhancement
      */
+#ifndef BIQUAD_OPT
     pInstance->pTE_Taps = (LVM_TE_Data_t*)calloc(1, sizeof(*(pInstance->pTE_Taps)));
     if (pInstance->pTE_Taps == LVM_NULL) {
         return LVM_NULLADDRESS;
@@ -182,6 +183,7 @@
     if (pInstance->pTE_State == LVM_NULL) {
         return LVM_NULLADDRESS;
     }
+#endif
     pInstance->Params.TE_OperatingMode = LVM_TE_OFF;
     pInstance->Params.TE_EffectLevel = 0;
     pInstance->TE_Active = LVM_FALSE;
@@ -494,6 +496,7 @@
     /*
      * Treble Enhancement
      */
+#ifndef BIQUAD_OPT
     if (pInstance->pTE_Taps != LVM_NULL) {
         free(pInstance->pTE_Taps);
         pInstance->pTE_Taps = LVM_NULL;
@@ -502,6 +505,7 @@
         free(pInstance->pTE_State);
         pInstance->pTE_State = LVM_NULL;
     }
+#endif
 
     /*
      * Free the default EQNB pre-gain and pointer to the band definitions
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
index 90a1f19..56bbfd1 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
@@ -33,6 +33,9 @@
 /*                                                                                  */
 /************************************************************************************/
 
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
 #include "LVM.h"            /* LifeVibes */
 #include "LVM_Common.h"     /* LifeVibes common */
 #include "BIQUAD.h"         /* Biquad library */
@@ -127,6 +130,7 @@
     LVM_INT16 SamplesToOutput; /* Samples to write to the output */
 } LVM_Buffer_t;
 
+#ifndef BIQUAD_OPT
 /* Filter taps */
 typedef struct {
     Biquad_2I_Order1_FLOAT_Taps_t TrebleBoost_Taps; /* Treble boost Taps */
@@ -136,6 +140,7 @@
 typedef struct {
     Biquad_FLOAT_Instance_t TrebleBoost_State; /* State for the treble boost filter */
 } LVM_TE_Coefs_t;
+#endif
 
 typedef struct {
     /* Public parameters */
@@ -185,8 +190,13 @@
     LVM_INT16 VC_AVLFixedVolume;         /* AVL fixed volume */
 
     /* Treble Enhancement */
+#ifdef BIQUAD_OPT
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pTEBiquad; /* Biquad filter instance */
+#else
     LVM_TE_Data_t* pTE_Taps;   /* Treble boost Taps */
     LVM_TE_Coefs_t* pTE_State; /* State for the treble boost filter */
+#endif
     LVM_INT16 TE_Active;       /* Control flag */
 
     /* Headroom */
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
index c94c469..acd594f 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
@@ -190,9 +190,13 @@
                 /*
                  * Apply the filter
                  */
+#ifdef BIQUAD_OPT
+                pInstance->pTEBiquad->process(pProcessed, pProcessed, NrFrames);
+#else
                 FO_Mc_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
                                                 pProcessed, pProcessed, (LVM_INT16)NrFrames,
                                                 (LVM_INT16)NrChannels);
+#endif
             }
             /*
              * Volume balance
diff --git a/media/libeffects/lvm/lib/Common/lib/AGC.h b/media/libeffects/lvm/lib/Common/lib/AGC.h
index c20b49a..31c8200 100644
--- a/media/libeffects/lvm/lib/Common/lib/AGC.h
+++ b/media/libeffects/lvm/lib/Common/lib/AGC.h
@@ -48,11 +48,6 @@
 /*    Function Prototypes                                                              */
 /*                                                                                */
 /**********************************************************************************/
-void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t* pInstance, /* Instance pointer */
-                                 const LVM_FLOAT* pStSrc,                /* Stereo source */
-                                 const LVM_FLOAT* pMonoSrc,              /* Mono source */
-                                 LVM_FLOAT* pDst,                        /* Stereo destination */
-                                 LVM_UINT16 n);                          /* Number of samples */
 void AGC_MIX_VOL_Mc1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t* pInstance,  /* Instance pointer */
                                 const LVM_FLOAT* pStSrc,                 /* Source */
                                 const LVM_FLOAT* pMonoSrc,               /* Mono source */
diff --git a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
index b38e9fb..08772e1 100644
--- a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
+++ b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
@@ -72,6 +72,7 @@
     LVM_FLOAT G;  /* Gain */
 } PK_FLOAT_Coefs_t;
 
+#ifndef BIQUAD_OPT
 /**********************************************************************************
    TAPS TYPE DEFINITIONS
 ***********************************************************************************/
@@ -100,6 +101,7 @@
 #define BQ_2I_D32F32Cll_TRC_WRA_01_Init Init_BQ_2I_D32F32Cll_TRC_WRA_01
 #define BP_1I_D32F32C30_TRC_WRA_02 TWO_BP_1I_D32F32C30_TRC_WRA_02
 
+
 /**********************************************************************************
    FUNCTION PROTOTYPES: BIQUAD FILTERS
 ***********************************************************************************/
@@ -161,8 +163,6 @@
                                           Biquad_2I_Order1_FLOAT_Taps_t* pTaps,
                                           FO_FLOAT_LShx_Coefs_t* pCoef);
 
-void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
-                                     LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
 /*** 32 bit data path *************************************************************/
 void FO_1I_D32F32Cll_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
                                      Biquad_1I_Order1_FLOAT_Taps_t* pTaps, FO_FLOAT_Coefs_t* pCoef);
@@ -170,6 +170,7 @@
                                 LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
 void FO_Mc_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
                                      LVM_FLOAT* pDataOut, LVM_INT16 NrFrames, LVM_INT16 NrChannels);
+
 /**********************************************************************************
    FUNCTION PROTOTYPES: BAND PASS FILTERS
 ***********************************************************************************/
@@ -183,6 +184,7 @@
                                      Biquad_1I_Order2_FLOAT_Taps_t* pTaps, BP_FLOAT_Coefs_t* pCoef);
 void BP_1I_D16F32C30_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
                                 LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
+
 /*** 32 bit data path *************************************************************/
 void BP_1I_D32F32Cll_TRC_WRA_02_Init(Biquad_FLOAT_Instance_t* pInstance,
                                      Biquad_1I_Order2_FLOAT_Taps_t* pTaps, BP_FLOAT_Coefs_t* pCoef);
@@ -193,10 +195,9 @@
 void PK_2I_D32F32CssGss_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
                                         Biquad_2I_Order2_FLOAT_Taps_t* pTaps,
                                         PK_FLOAT_Coefs_t* pCoef);
-void PK_2I_D32F32C14G11_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
-                                   LVM_FLOAT* pDataOut, LVM_INT16 NrSamples);
 void PK_Mc_D32F32C14G11_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
                                    LVM_FLOAT* pDataOut, LVM_INT16 NrFrames, LVM_INT16 NrChannels);
+#endif
 
 /**********************************************************************************
    FUNCTION PROTOTYPES: DC REMOVAL FILTERS
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
index fb797be..b95d076 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
@@ -26,7 +26,7 @@
 #define LVM_TYPES_H
 
 #include <stdint.h>
-
+#include <system/audio.h>
 /****************************************************************************************/
 /*                                                                                      */
 /*  definitions                                                                         */
@@ -82,7 +82,7 @@
 #define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_FLOAT
 typedef float effect_buffer_t;
 
-#define LVM_MAX_CHANNELS 8  // FCC_8
+#define LVM_MAX_CHANNELS FCC_24
 
 /****************************************************************************************/
 /*                                                                                      */
diff --git a/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
index 04b180c..36c4cd2 100644
--- a/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
+++ b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
@@ -21,7 +21,7 @@
 /*######################################################################################*/
 /*  Include files                                                                       */
 /*######################################################################################*/
-
+#include <math.h>
 #include "LVM_Types.h"
 
 /*######################################################################################*/
@@ -30,7 +30,13 @@
 
 /* Absolute value including the corner case for the extreme negative value */
 
-LVM_FLOAT Abs_Float(LVM_FLOAT input);
+static inline LVM_FLOAT Abs_Float(LVM_FLOAT input) {
+    return fabs(input);
+}
+
+static inline LVM_FLOAT LVM_Clamp(LVM_FLOAT val) {
+    return fmin(fmax(val, -1.0f), 1.0f);
+}
 
 /****************************************************************************************
  *  Name        : dB_to_Lin32()
diff --git a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
index 66e3e79..281d941 100644
--- a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
+++ b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
@@ -32,45 +32,16 @@
 void Copy_Float_Stereo_Mc(const LVM_FLOAT* src, LVM_FLOAT* StereoOut, LVM_FLOAT* dst,
                           LVM_INT16 NrFrames, LVM_INT32 NrChannels);
 
-/*********************************************************************************
- * note: In Mult3s_16x16() saturation of result is not taken care when           *
- *       overflow occurs.                                                        *
- *       For example when *src = 0x8000, val = *0x8000                           *
- *       The function gives the output as 0x8000 instead of 0x7fff               *
- *       This is the only case which will give wrong result.                     *
- *       For more information refer to Vector_Arithmetic.doc in /doc folder      *
- *********************************************************************************/
 void Mult3s_Float(const LVM_FLOAT* src, const LVM_FLOAT val, LVM_FLOAT* dst, LVM_INT16 n);
 
-/*********************************************************************************
- * note: In Mult3s_32x16() saturation of result is not taken care when           *
- *       overflow occurs.                                                        *
- *       For example when *src = 0x8000000, val = *0x8000                        *
- *       The function gives the output as 0x8000000 instead of 0x7fffffff        *
- *       This is the only extreme condition which is giving unexpected result    *
- *       For more information refer to Vector_Arithmetic.doc in /doc folder      *
- *********************************************************************************/
-void Mult3s_32x16(const LVM_INT32* src, const LVM_INT16 val, LVM_INT32* dst, LVM_INT16 n);
 void DelayMix_Float(const LVM_FLOAT* src, /* Source 1, to be delayed */
                     LVM_FLOAT* delay,     /* Delay buffer */
                     LVM_INT16 size,       /* Delay size */
                     LVM_FLOAT* dst,       /* Source/destination */
                     LVM_INT16* pOffset,   /* Delay offset */
                     LVM_INT16 n);         /* Number of stereo samples */
-void DelayWrite_32(const LVM_INT32* src,  /* Source 1, to be delayed */
-                   LVM_INT32* delay,      /* Delay buffer */
-                   LVM_UINT16 size,       /* Delay size */
-                   LVM_UINT16* pOffset,   /* Delay offset */
-                   LVM_INT16 n);
 void Add2_Sat_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n);
 void Mac3s_Sat_Float(const LVM_FLOAT* src, const LVM_FLOAT val, LVM_FLOAT* dst, LVM_INT16 n);
-void DelayAllPass_Sat_32x16To32(LVM_INT32* delay,           /* Delay buffer */
-                                LVM_UINT16 size,            /* Delay size */
-                                LVM_INT16 coeff,            /* All pass filter coefficient */
-                                LVM_UINT16 DelayOffset,     /* Simple delay offset */
-                                LVM_UINT16* pAllPassOffset, /* All pass filter delay offset */
-                                LVM_INT32* dst,             /* Source/destination */
-                                LVM_INT16 n);
 
 /**********************************************************************************
     SHIFT FUNCTIONS
@@ -87,15 +58,6 @@
 void From2iToMS_Float(const LVM_FLOAT* src, LVM_FLOAT* dstM, LVM_FLOAT* dstS, LVM_INT16 n);
 void JoinTo2i_Float(const LVM_FLOAT* srcL, const LVM_FLOAT* srcR, LVM_FLOAT* dst, LVM_INT16 n);
 
-/**********************************************************************************
-    DATA TYPE CONVERSION FUNCTIONS
-***********************************************************************************/
-
-void Int16LShiftToInt32_16x32(const LVM_INT16* src, LVM_INT32* dst, LVM_INT16 n, LVM_INT16 shift);
-
-void Int32RShiftToInt16_Sat_32x16(const LVM_INT32* src, LVM_INT16* dst, LVM_INT16 n,
-                                  LVM_INT16 shift);
-
 /**********************************************************************************/
 
 #endif /* _VECTOR_ARITHMETIC_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp
index ae8cdad..78f329e 100644
--- a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp
+++ b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp
@@ -20,7 +20,6 @@
 /*    Includes                                                                          */
 /*                                                                                      */
 /****************************************************************************************/
-
 #include "AGC.h"
 #include "ScalarArithmetic.h"
 
@@ -37,135 +36,6 @@
 
 /****************************************************************************************/
 /*                                                                                      */
-/* FUNCTION:                  AGC_MIX_VOL_2St1Mon_D32_WRA                               */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*    Apply AGC and mix signals                                                         */
-/*                                                                                      */
-/*                                                                                      */
-/*  StSrc   ------------------|                                                         */
-/*                            |                                                         */
-/*              ______       _|_        ________                                        */
-/*             |      |     |   |      |        |                                       */
-/*  MonoSrc -->| AGC  |---->| + |----->| Volume |------------------------------+--->    */
-/*             | Gain |     |___|      | Gain   |                              |        */
-/*             |______|                |________|                              |        */
-/*                /|\                               __________     ________    |        */
-/*                 |                               |          |   |        |   |        */
-/*                 |-------------------------------| AGC Gain |<--| Peak   |<--|        */
-/*                                                 | Update   |   | Detect |            */
-/*                                                 |__________|   |________|            */
-/*                                                                                      */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  pInstance               Instance pointer                                            */
-/*  pStereoIn               Stereo source                                               */
-/*  pMonoIn                 Mono band pass source                                       */
-/*  pStereoOut              Stereo destination                                          */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  Void                                                                                */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t* pInstance, /* Instance pointer */
-                                 const LVM_FLOAT* pStSrc,                /* Stereo source */
-                                 const LVM_FLOAT* pMonoSrc,              /* Mono source */
-                                 LVM_FLOAT* pDst,                        /* Stereo destination */
-                                 LVM_UINT16 NumSamples)                  /* Number of samples */
-{
-    /*
-     * General variables
-     */
-    LVM_UINT16 i;       /* Sample index */
-    LVM_FLOAT Left;     /* Left sample */
-    LVM_FLOAT Right;    /* Right sample */
-    LVM_FLOAT Mono;     /* Mono sample */
-    LVM_FLOAT AbsPeak;  /* Absolute peak signal */
-    LVM_FLOAT AGC_Mult; /* Short AGC gain */
-    LVM_FLOAT Vol_Mult; /* Short volume */
-
-    /*
-     * Instance control variables
-     */
-    LVM_FLOAT AGC_Gain = pInstance->AGC_Gain;       /* Get the current AGC gain */
-    LVM_FLOAT AGC_MaxGain = pInstance->AGC_MaxGain; /* Get maximum AGC gain */
-    LVM_FLOAT AGC_Attack = pInstance->AGC_Attack;   /* Attack scaler */
-    LVM_FLOAT AGC_Decay = (pInstance->AGC_Decay * (1 << (DECAY_SHIFT))); /* Decay scaler */
-    LVM_FLOAT AGC_Target = pInstance->AGC_Target;                        /* Get the target level */
-    LVM_FLOAT Vol_Current = pInstance->Volume;                           /* Actual volume setting */
-    LVM_FLOAT Vol_Target = pInstance->Target;                            /* Target volume setting */
-    LVM_FLOAT Vol_TC = pInstance->VolumeTC;                              /* Time constant */
-
-    /*
-     * Process on a sample by sample basis
-     */
-    for (i = 0; i < NumSamples; i++) /* For each sample */
-    {
-        /*
-         * Get the short scalers
-         */
-        AGC_Mult = (LVM_FLOAT)(AGC_Gain);    /* Get the short AGC gain */
-        Vol_Mult = (LVM_FLOAT)(Vol_Current); /* Get the short volume gain */
-
-        /*
-         * Get the input samples
-         */
-        Left = *pStSrc++;   /* Get the left sample */
-        Right = *pStSrc++;  /* Get the right sample */
-        Mono = *pMonoSrc++; /* Get the mono sample */
-
-        /*
-         * Apply the AGC gain to the mono input and mix with the stereo signal
-         */
-        Left += (Mono * AGC_Mult); /* Mix in the mono signal */
-        Right += (Mono * AGC_Mult);
-
-        /*
-         * Apply the volume and write to the output stream
-         */
-        Left = Left * Vol_Mult;
-        Right = Right * Vol_Mult;
-        *pDst++ = Left; /* Save the results */
-        *pDst++ = Right;
-
-        /*
-         * Update the AGC gain
-         */
-        AbsPeak = Abs_Float(Left) > Abs_Float(Right) ? Abs_Float(Left) : Abs_Float(Right);
-        if (AbsPeak > AGC_Target) {
-            /*
-             * The signal is too large so decrease the gain
-             */
-            AGC_Gain = AGC_Gain * AGC_Attack;
-        } else {
-            /*
-             * The signal is too small so increase the gain
-             */
-            if (AGC_Gain > AGC_MaxGain) {
-                AGC_Gain -= (AGC_Decay);
-            } else {
-                AGC_Gain += (AGC_Decay);
-            }
-        }
-
-        /*
-         * Update the gain
-         */
-        Vol_Current += (Vol_Target - Vol_Current) * ((LVM_FLOAT)Vol_TC / VOL_TC_FLOAT);
-    }
-
-    /*
-     * Update the parameters
-     */
-    pInstance->Volume = Vol_Current; /* Actual volume setting */
-    pInstance->AGC_Gain = AGC_Gain;
-
-    return;
-}
-/****************************************************************************************/
-/*                                                                                      */
 /* FUNCTION:                  AGC_MIX_VOL_Mc1Mon_D32_WRA                                */
 /*                                                                                      */
 /* DESCRIPTION:                                                                         */
@@ -255,7 +125,7 @@
              */
             SampleVal = SampleVal * Vol_Mult;
 
-            *pDst++ = SampleVal; /* Save the results */
+            *pDst++ = LVM_Clamp(SampleVal); /* Save the results */
 
             /*
              * Update the AGC gain
diff --git a/media/libeffects/lvm/lib/Common/src/Abs_32.cpp b/media/libeffects/lvm/lib/Common/src/Abs_32.cpp
deleted file mode 100644
index 3e37d89..0000000
--- a/media/libeffects/lvm/lib/Common/src/Abs_32.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 files                                                                       */
-/*######################################################################################*/
-
-#include "ScalarArithmetic.h"
-
-/****************************************************************************************
- *  Name        : Abs_32()
- *  Input       : Signed 32-bit integer
- *  Output      :
- *  Returns     : Absolute value
- *  Description : Absolute value with maximum negative value corner case
- *  Remarks     :
- ****************************************************************************************/
-
-LVM_INT32 Abs_32(LVM_INT32 input) {
-    if (input < 0) {
-        if (input == (LVM_INT32)(0x80000000U)) {
-            /* The corner case, so set to the maximum positive value */
-            input = (LVM_INT32)0x7fffffff;
-        } else {
-            /* Negative input, so invert */
-            input = (LVM_INT32)(-input);
-        }
-    }
-    return input;
-}
-LVM_FLOAT Abs_Float(LVM_FLOAT input) {
-    if (input < 0) {
-        /* Negative input, so invert */
-        input = (LVM_FLOAT)(-input);
-    }
-    return input;
-}
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.cpp b/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.cpp
deleted file mode 100644
index be20521..0000000
--- a/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION ADD2_SAT_16X16
-***********************************************************************************/
-
-void Add2_Sat_16x16(const LVM_INT16* src, LVM_INT16* dst, LVM_INT16 n) {
-    LVM_INT32 Temp;
-    LVM_INT16 ii;
-    for (ii = n; ii != 0; ii--) {
-        Temp = ((LVM_INT32)*src) + ((LVM_INT32)*dst);
-        src++;
-
-        if (Temp > 0x00007FFF) {
-            *dst = 0x7FFF;
-        } else if (Temp < -0x00008000) {
-            *dst = -0x8000;
-        } else {
-            *dst = (LVM_INT16)Temp;
-        }
-        dst++;
-    }
-    return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp
index 420f93e..1981edd 100644
--- a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp
@@ -18,53 +18,15 @@
 /**********************************************************************************
    INCLUDE FILES
 ***********************************************************************************/
-
+#include "ScalarArithmetic.h"
 #include "VectorArithmetic.h"
 
-/**********************************************************************************
-   FUNCTION ADD2_SAT_32X32
-***********************************************************************************/
-
-void Add2_Sat_32x32(const LVM_INT32* src, LVM_INT32* dst, LVM_INT16 n) {
-    LVM_INT32 a, b, c;
-    LVM_INT16 ii;
-    for (ii = n; ii != 0; ii--) {
-        a = *src;
-        src++;
-
-        b = *dst;
-        c = a + b;
-        if ((((c ^ a) & (c ^ b)) >> 31) != 0) /* overflow / underflow */
-        {
-            if (a < 0) {
-                c = 0x80000000L;
-            } else {
-                c = 0x7FFFFFFFL;
-            }
-        }
-
-        *dst = c;
-        dst++;
-    }
-    return;
-}
-
 void Add2_Sat_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n) {
     LVM_FLOAT Temp;
     LVM_INT16 ii;
     for (ii = n; ii != 0; ii--) {
-        Temp = ((LVM_FLOAT)*src) + ((LVM_FLOAT)*dst);
-        src++;
-
-        if (Temp > 1.000000f) {
-            *dst = 1.000000f;
-        } else if (Temp < -1.000000f) {
-            *dst = -1.000000f;
-        } else {
-            *dst = Temp;
-        }
-        dst++;
+        Temp = *src++ + *dst;
+        *dst++ = LVM_Clamp(Temp);
     }
     return;
 }
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp
index 198a6a1..bc9a2c5 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
@@ -67,3 +67,4 @@
         *pDataOut++ = ynL;  // Write Left output
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp
index 6d36302..571676b 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
  */
 
 /*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
 
@@ -47,5 +48,6 @@
     pBiquadState->coefs[1] = pCoef->B2;
     pBiquadState->coefs[2] = pCoef->B1;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BP_1I_D16F16Css_TRC_WRA_01_Init.c                              */
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
index a41c855..c19e2f4 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#ifndef BIQUAD_OPT
 #ifndef _BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
 #define _BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
 
@@ -32,3 +33,4 @@
 } Filter_State_FLOAT;
 typedef Filter_State_FLOAT* PFilter_State_FLOAT;
 #endif /*_BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_*/
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp
index d4d4eb1..ff3221a 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
@@ -68,3 +68,4 @@
         *pDataOut++ = (ynL);  // Write Left output
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp
index d322a8e..26a4793 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
  */
 
 /*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
 
@@ -57,5 +58,6 @@
     pBiquadState->coefs[1] = pCoef->B2;
     pBiquadState->coefs[2] = pCoef->B1;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BP_1I_D16F32Cll_TRC_WRA_01_Init.c                              */
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
index 0603256..ae52cf2 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#ifndef BIQUAD_OPT
 #ifndef _BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_
 #define _BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_
 
@@ -31,3 +32,4 @@
 } Filter_State_Float;
 typedef Filter_State_Float* PFilter_State_FLOAT;
 #endif /*_BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_*/
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp
index 0670334..6462092 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
 #include "LVM_Macros.h"
@@ -68,3 +69,4 @@
         *pDataOut++ = ynL;  // Write Left output in Q0
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp
index 146cc63..9b4cccc 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp
@@ -16,6 +16,7 @@
  */
 
 /*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
 
@@ -49,5 +50,6 @@
 
     pBiquadState->coefs[2] = pCoef->B1;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BP_1I_D32F32Cll_TRC_WRA_02_Init.c                              */
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
index ea83c0b..93a7bfd 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#ifndef BIQUAD_OPT
 #ifndef _BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_
 #define _BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_
 
@@ -32,3 +33,4 @@
 typedef Filter_State_Float* PFilter_State_FLOAT;
 
 #endif /*_BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_*/
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp
index a46b1ef..85a7453 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
@@ -71,3 +72,4 @@
         *pDataOut++ = (LVM_FLOAT)ynL;  // Write Left output in Q0
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp
index e8bfcd8..7ad0793 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
  */
 
 /*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
 
@@ -54,5 +55,6 @@
     temp = pCoef->B1;
     pBiquadState->coefs[4] = temp;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BQ_1I_D16F16Css_TRC_WRA_01_Init.c                              */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
index ac2819e..9d1a3b6 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#ifndef BIQUAD_OPT
 #ifndef _BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
 #define _BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
 
@@ -33,3 +34,4 @@
 } Filter_State_FLOAT;
 typedef Filter_State_FLOAT* PFilter_State_FLOAT;
 #endif /*_BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp
index c60dcf8..58320f7 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
@@ -71,3 +72,4 @@
         *pDataOut++ = (LVM_FLOAT)(ynL);  // Write Left output
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
index af0efc8..3293b2e 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#ifndef BIQUAD_OPT
 #ifndef _BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
 #define _BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
 
@@ -33,3 +34,4 @@
 } Filter_State_FLOAT;
 typedef Filter_State_FLOAT* PFilter_State_FLOAT;
 #endif /*_BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_*/
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp
index ecf44ca..0d36e67 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp
@@ -16,6 +16,7 @@
  */
 
 /*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
 
@@ -55,5 +56,6 @@
     temp = pCoef->B1;
     pBiquadState->coefs[4] = temp;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BQ_1I_D16F32Css_TRC_WRA_01_Init                              */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp
index d047e91..9ec9046 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
@@ -98,3 +99,4 @@
         *pDataOut++ = (LVM_FLOAT)ynR;  // Write Right output
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp
index 399b5ec..2478016 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
@@ -98,3 +99,4 @@
         *pDataOut++ = (LVM_FLOAT)ynR;  // Write Right output
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp
index e0cd934..8b2de31 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
  */
 
 /*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
 
@@ -57,3 +58,4 @@
 }
 /*-------------------------------------------------------------------------*/
 /* End Of File: BQ_2I_D16F16Css_TRC_WRA_01_Init.c                              */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
index 94cc794..f9a31a6 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #ifndef _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
 #define _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
 
@@ -35,3 +36,4 @@
 typedef Filter_State_FLOAT* PFilter_State_FLOAT;
 
 #endif /* _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp
index 3b7eb5e..7a66bf9 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
@@ -102,3 +103,4 @@
         pDataOut++;
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp
index 8c43430..db57150 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
@@ -102,3 +103,4 @@
         pDataOut++;
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp
index 84fbadf..bc9e2df 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
@@ -102,3 +103,4 @@
         pDataOut++;
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
index 1cc7618..de06cb1 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #ifndef _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
 #define _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
 
@@ -35,3 +36,4 @@
 typedef Filter_State_FLOAT* PFilter_State_FLOAT;
 
 #endif /* _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp
index 6817d9f..0b9fb5a 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
 
@@ -55,3 +56,4 @@
 }
 /*-------------------------------------------------------------------------*/
 /* End Of File: BQ_2I_D16F32Css_TRC_WRA_01_Init                              */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp
index 4eeaaa8..2097c4f 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
@@ -184,3 +185,4 @@
         }
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp
index 1e27391..2d2a61f 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
  */
 
 /*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
 
@@ -54,5 +55,6 @@
     temp = pCoef->B1;
     pBiquadState->coefs[4] = temp;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: BQ_2I_D32F32C32_TRC_WRA_01_Init.c                              */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
index 4a2149d..029c89d 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #ifndef _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
 #define _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
 
@@ -35,3 +36,4 @@
 typedef Filter_State_FLOAT* PFilter_State_FLOAT;
 
 #endif /* _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_*/
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/Copy_16.cpp b/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
index 8887890..7046a94 100644
--- a/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
@@ -18,53 +18,11 @@
 /**********************************************************************************
    INCLUDE FILES
 ***********************************************************************************/
-
+#include <string.h>
 #include "VectorArithmetic.h"
 
-/**********************************************************************************
-   FUNCTION COPY_16
-***********************************************************************************/
-
-void Copy_16(const LVM_INT16* src, LVM_INT16* dst, LVM_INT16 n) {
-    LVM_INT16 ii;
-
-    if (src > dst) {
-        for (ii = n; ii != 0; ii--) {
-            *dst = *src;
-            dst++;
-            src++;
-        }
-    } else {
-        src += n - 1;
-        dst += n - 1;
-        for (ii = n; ii != 0; ii--) {
-            *dst = *src;
-            dst--;
-            src--;
-        }
-    }
-
-    return;
-}
 void Copy_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n) {
-    LVM_INT16 ii;
-
-    if (src > dst) {
-        for (ii = n; ii != 0; ii--) {
-            *dst = *src;
-            dst++;
-            src++;
-        }
-    } else {
-        src += n - 1;
-        dst += n - 1;
-        for (ii = n; ii != 0; ii--) {
-            *dst = *src;
-            dst--;
-            src--;
-        }
-    }
-
+    memmove(dst, src, n * sizeof(LVM_FLOAT));
     return;
 }
 // Extract out the stereo channel pair from multichannel source.
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp
index be9e49b..b7f4b55 100644
--- a/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp
@@ -18,9 +18,9 @@
 /**********************************************************************************
    INCLUDE FILES
 ***********************************************************************************/
-
 #include "Mixer_private.h"
 #include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
 
 /**********************************************************************************
    FUNCTION CORE_MIXSOFT_1ST_D32C31_WRA
@@ -52,14 +52,7 @@
             Temp2 = *dst;
 
             Temp3 = Temp1 * (pInstance->Current);
-            Temp1 = Temp2 + Temp3;
-
-            if (Temp1 > 1.0f)
-                Temp1 = 1.0f;
-            else if (Temp1 < -1.0f)
-                Temp1 = -1.0f;
-
-            *dst++ = Temp1;
+            *dst++ = LVM_Clamp(Temp2 + Temp3);
         }
     }
 
@@ -72,13 +65,7 @@
             Temp2 = *dst;
 
             Temp3 = Temp1 * (pInstance->Current);
-            Temp1 = Temp2 + Temp3;
-
-            if (Temp1 > 1.0f)
-                Temp1 = 1.0f;
-            else if (Temp1 < -1.0f)
-                Temp1 = -1.0f;
-            *dst++ = Temp1;
+            *dst++ = LVM_Clamp(Temp2 + Temp3);
         }
     }
 }
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp
index 2861be6..6e859f4 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp
@@ -14,51 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #include "BIQUAD.h"
 #include "DC_2I_D16_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
-void DC_2I_D16_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
-                          LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
-    LVM_FLOAT LeftDC, RightDC;
-    LVM_FLOAT Diff;
-    LVM_INT32 j;
-    PFilter_FLOAT_State pBiquadState = (PFilter_FLOAT_State)pInstance;
-
-    LeftDC = pBiquadState->LeftDC;
-    RightDC = pBiquadState->RightDC;
-    for (j = NrSamples - 1; j >= 0; j--) {
-        /* Subtract DC and saturate */
-        Diff = *(pDataIn++) - (LeftDC);
-        if (Diff > 1.0f) {
-            Diff = 1.0f;
-        } else if (Diff < -1.0f) {
-            Diff = -1.0f;
-        }
-        *(pDataOut++) = (LVM_FLOAT)Diff;
-        if (Diff < 0) {
-            LeftDC -= DC_FLOAT_STEP;
-        } else {
-            LeftDC += DC_FLOAT_STEP;
-        }
-
-        /* Subtract DC an saturate */
-        Diff = *(pDataIn++) - (RightDC);
-        if (Diff > 1.0f) {
-            Diff = 1.0f;
-        } else if (Diff < -1.0f) {
-            Diff = -1.0f;
-        }
-        *(pDataOut++) = (LVM_FLOAT)Diff;
-        if (Diff < 0) {
-            RightDC -= DC_FLOAT_STEP;
-        } else {
-            RightDC += DC_FLOAT_STEP;
-        }
-    }
-    pBiquadState->LeftDC = LeftDC;
-    pBiquadState->RightDC = RightDC;
-}
+#include "ScalarArithmetic.h"
 /*
  * FUNCTION:       DC_Mc_D16_TRC_WRA_01
  *
@@ -89,12 +48,7 @@
         /* Subtract DC and saturate */
         for (i = NrChannels - 1; i >= 0; i--) {
             Diff = *(pDataIn++) - (ChDC[i]);
-            if (Diff > 1.0f) {
-                Diff = 1.0f;
-            } else if (Diff < -1.0f) {
-                Diff = -1.0f;
-            }
-            *(pDataOut++) = (LVM_FLOAT)Diff;
+            *(pDataOut++) = LVM_Clamp(Diff);
             if (Diff < 0) {
                 ChDC[i] -= DC_FLOAT_STEP;
             } else {
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp
index 2828cb3..c16718c 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp
@@ -17,11 +17,6 @@
 
 #include "BIQUAD.h"
 #include "DC_2I_D16_TRC_WRA_01_Private.h"
-void DC_2I_D16_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance) {
-    PFilter_FLOAT_State pBiquadState = (PFilter_FLOAT_State)pInstance;
-    pBiquadState->LeftDC = 0.0f;
-    pBiquadState->RightDC = 0.0f;
-}
 void DC_Mc_D16_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance) {
     PFilter_FLOAT_State_Mc pBiquadState = (PFilter_FLOAT_State_Mc)pInstance;
     LVM_INT32 i;
diff --git a/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.cpp b/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.cpp
deleted file mode 100644
index 5daef59..0000000
--- a/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION DelayAllPass_32x32
-***********************************************************************************/
-
-void DelayAllPass_Sat_32x16To32(LVM_INT32* delay,           /* Delay buffer */
-                                LVM_UINT16 size,            /* Delay size */
-                                LVM_INT16 coeff,            /* All pass filter coefficient */
-                                LVM_UINT16 DelayOffset,     /* Simple delay offset */
-                                LVM_UINT16* pAllPassOffset, /* All pass filter delay offset */
-                                LVM_INT32* dst,             /* Source/destination */
-                                LVM_INT16 n)                /* Number of  samples */
-{
-    LVM_INT16 i;
-    LVM_UINT16 AllPassOffset = *pAllPassOffset;
-    LVM_INT32 temp;
-    LVM_INT32 a, b, c;
-
-    for (i = 0; i < n; i++) {
-        MUL32x16INTO32(delay[AllPassOffset], coeff, temp, 15) a = temp;
-        b = delay[DelayOffset];
-        DelayOffset++;
-
-        c = a + b;
-        if ((((c ^ a) & (c ^ b)) >> 31) != 0) /* overflow / underflow */
-        {
-            if (a < 0) {
-                c = 0x80000000L;
-            } else {
-                c = 0x7FFFFFFFL;
-            }
-        }
-        *dst = c;
-        dst++;
-
-        MUL32x16INTO32(c, -coeff, temp, 15) a = temp;
-        b = delay[AllPassOffset];
-        c = a + b;
-        if ((((c ^ a) & (c ^ b)) >> 31) != 0) /* overflow / underflow */
-        {
-            if (a < 0) {
-                c = 0x80000000L;
-            } else {
-                c = 0x7FFFFFFFL;
-            }
-        }
-        delay[AllPassOffset] = c;
-        AllPassOffset++;
-
-        /* Make the delay buffer a circular buffer */
-        if (DelayOffset >= size) {
-            DelayOffset = 0;
-        }
-
-        if (AllPassOffset >= size) {
-            AllPassOffset = 0;
-        }
-    }
-
-    /* Update the offset */
-    *pAllPassOffset = AllPassOffset;
-
-    return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp
index da75982..d2537eb 100644
--- a/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp
@@ -21,51 +21,6 @@
 
 #include "VectorArithmetic.h"
 
-/**********************************************************************************
-   FUNCTION DelayMix_16x16
-***********************************************************************************/
-
-void DelayMix_16x16(const LVM_INT16* src, /* Source 1, to be delayed */
-                    LVM_INT16* delay,     /* Delay buffer */
-                    LVM_INT16 size,       /* Delay size */
-                    LVM_INT16* dst,       /* Source/destination */
-                    LVM_INT16* pOffset,   /* Delay offset */
-                    LVM_INT16 n)          /* Number of stereo samples */
-{
-    LVM_INT16 i;
-    LVM_INT16 Offset = *pOffset;
-    LVM_INT16 temp;
-
-    for (i = 0; i < n; i++) {
-        /* Left channel */
-        temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) + (LVM_INT32)delay[Offset]) >> 1);
-        *dst = temp;
-        dst++;
-
-        delay[Offset] = *src;
-        Offset++;
-        src++;
-
-        /* Right channel */
-        temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) - (LVM_INT32)delay[Offset]) >> 1);
-        *dst = temp;
-        dst++;
-
-        delay[Offset] = *src;
-        Offset++;
-        src++;
-
-        /* Make the reverb delay buffer a circular buffer */
-        if (Offset >= size) {
-            Offset = 0;
-        }
-    }
-
-    /* Update the offset */
-    *pOffset = Offset;
-
-    return;
-}
 void DelayMix_Float(const LVM_FLOAT* src, /* Source 1, to be delayed */
                     LVM_FLOAT* delay,     /* Delay buffer */
                     LVM_INT16 size,       /* Delay size */
@@ -107,4 +62,3 @@
 
     return;
 }
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DelayWrite_32.cpp b/media/libeffects/lvm/lib/Common/src/DelayWrite_32.cpp
deleted file mode 100644
index 47cffbf..0000000
--- a/media/libeffects/lvm/lib/Common/src/DelayWrite_32.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION DelayMix_16x16
-***********************************************************************************/
-
-void DelayWrite_32(const LVM_INT32* src, /* Source 1, to be delayed */
-                   LVM_INT32* delay,     /* Delay buffer */
-                   LVM_UINT16 size,      /* Delay size */
-                   LVM_UINT16* pOffset,  /* Delay offset */
-                   LVM_INT16 n)          /* Number of samples */
-{
-    LVM_INT16 i;
-    LVM_INT16 Offset = (LVM_INT16)*pOffset;
-
-    for (i = 0; i < n; i++) {
-        delay[Offset] = *src;
-        Offset++;
-        src++;
-
-        /* Make the delay buffer a circular buffer */
-        if (Offset >= size) {
-            Offset = 0;
-        }
-    }
-
-    /* Update the offset */
-    *pOffset = (LVM_UINT16)Offset;
-
-    return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp
index df8fadc..c85dfb6 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
@@ -62,3 +63,4 @@
         *pDataOut++ = (LVM_FLOAT)ynL;  // Write Left output
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp
index 10604bf..0cff849 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
  */
 
 /*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
 
@@ -52,3 +53,4 @@
 }
 /*------------------------------------------------*/
 /* End Of File: FO_1I_D16F16Css_TRC_WRA_01_Init.c */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
index d1819fc..50b09b6 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #ifndef _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
 #define _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
 
@@ -35,3 +36,4 @@
 
 typedef Filter_State_FLOAT* PFilter_State_FLOAT;
 #endif /* _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp
index 4c75e04..dac090f 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
@@ -63,3 +64,4 @@
         *pDataOut++ = (LVM_FLOAT)ynL;  // Write Left output in Q0
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp
index bf2e5e1..efd6bc0 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
 
@@ -50,5 +51,6 @@
     temp = pCoef->B1;
     pBiquadState->coefs[2] = temp;
 }
+#endif
 /*------------------------------------------------*/
 /* End Of File: FO_1I_D32F32Cll_TRC_WRA_01_Init.c */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
index 8645593..95705be 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #ifndef _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
 #define _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
 
@@ -34,3 +35,4 @@
 
 typedef Filter_State_FLOAT* PFilter_State_FLOAT;
 #endif /* _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp
index dad070b..1e3f1e8 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
@@ -24,86 +25,6 @@
 COEFS-
 pBiquadState->coefs[0] is A1,
 pBiquadState->coefs[1] is A0,
-pBiquadState->coefs[2] is -B1, these are in Q15 format
-pBiquadState->Shift    is Shift value
-DELAYS-
-pBiquadState->pDelays[0] is x(n-1)L in Q15 format
-pBiquadState->pDelays[1] is y(n-1)L in Q30 format
-pBiquadState->pDelays[2] is x(n-1)R in Q15 format
-pBiquadState->pDelays[3] is y(n-1)R in Q30 format
-***************************************************************************/
-void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
-                                     LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
-    LVM_FLOAT ynL, ynR;
-    LVM_FLOAT Temp;
-    LVM_FLOAT NegSatValue;
-    LVM_INT16 ii;
-
-    PFilter_Float_State pBiquadState = (PFilter_Float_State)pInstance;
-
-    NegSatValue = -1.0f;
-
-    for (ii = NrSamples; ii != 0; ii--) {
-        /**************************************************************************
-                        PROCESSING OF THE LEFT CHANNEL
-        ***************************************************************************/
-
-        // ynL =A1  * x(n-1)L
-        ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[0];
-        // ynR =A1  * x(n-1)R
-        ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
-        // ynL+=A0  * x(n)L
-        ynL += (LVM_FLOAT)pBiquadState->coefs[1] * (*pDataIn);
-        // ynR+=A0  * x(n)L
-        ynR += (LVM_FLOAT)pBiquadState->coefs[1] * (*(pDataIn + 1));
-
-        // ynL +=  (-B1  * y(n-1)L  )
-        Temp = pBiquadState->pDelays[1] * pBiquadState->coefs[2];
-        ynL += Temp;
-        // ynR +=  (-B1  * y(n-1)R ) )
-        Temp = pBiquadState->pDelays[3] * pBiquadState->coefs[2];
-        ynR += Temp;
-
-        /**************************************************************************
-                        UPDATING THE DELAYS
-        ***************************************************************************/
-        pBiquadState->pDelays[1] = ynL;           // Update y(n-1)L
-        pBiquadState->pDelays[0] = (*pDataIn++);  // Update x(n-1)L
-
-        pBiquadState->pDelays[3] = ynR;           // Update y(n-1)R
-        pBiquadState->pDelays[2] = (*pDataIn++);  // Update x(n-1)R
-
-        /**************************************************************************
-                        WRITING THE OUTPUT
-        ***************************************************************************/
-
-        /*Saturate results*/
-        if (ynL > 1.0f) {
-            ynL = 1.0f;
-        } else {
-            if (ynL < NegSatValue) {
-                ynL = NegSatValue;
-            }
-        }
-
-        if (ynR > 1.0f) {
-            ynR = 1.0f;
-        } else {
-            if (ynR < NegSatValue) {
-                ynR = NegSatValue;
-            }
-        }
-
-        *pDataOut++ = (LVM_FLOAT)ynL;
-        *pDataOut++ = (LVM_FLOAT)ynR;
-    }
-}
-/**************************************************************************
-ASSUMPTIONS:
-COEFS-
-pBiquadState->coefs[0] is A1,
-pBiquadState->coefs[1] is A0,
 pBiquadState->coefs[2] is -B1,
 DELAYS-
 pBiquadState->pDelays[2*ch + 0] is x(n-1) of the 'ch' - channel
@@ -173,3 +94,4 @@
         pDelays -= NrChannels * 2;
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp
index 552aeda..54fbe4a 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp
@@ -16,6 +16,7 @@
  */
 
 /*-------------------------------------------------------------------------*/
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
 
@@ -51,5 +52,6 @@
     temp = pCoef->B1;
     pBiquadState->coefs[2] = temp;
 }
+#endif
 /*-------------------------------------------------------------------------*/
 /* End Of File: FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c                     */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
index 0103328..a71fa32 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #ifndef _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_
 #define _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_
 
@@ -27,3 +28,4 @@
 
 typedef Filter_Float_State* PFilter_Float_State;
 #endif /* _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp
index b050267..e2f8c67 100644
--- a/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp
@@ -21,33 +21,6 @@
 
 #include "VectorArithmetic.h"
 
-/**********************************************************************************
-   FUNCTION  From2iToMS_16x16
-***********************************************************************************/
-
-void From2iToMS_16x16(const LVM_INT16* src, LVM_INT16* dstM, LVM_INT16* dstS, LVM_INT16 n) {
-    LVM_INT32 temp1, left, right;
-    LVM_INT16 ii;
-    for (ii = n; ii != 0; ii--) {
-        left = (LVM_INT32)*src;
-        src++;
-
-        right = (LVM_INT32)*src;
-        src++;
-
-        /* Compute M signal*/
-        temp1 = (left + right) >> 1;
-        *dstM = (LVM_INT16)temp1;
-        dstM++;
-
-        /* Compute S signal*/
-        temp1 = (left - right) >> 1;
-        *dstS = (LVM_INT16)temp1;
-        dstS++;
-    }
-
-    return;
-}
 void From2iToMS_Float(const LVM_FLOAT* src, LVM_FLOAT* dstM, LVM_FLOAT* dstS, LVM_INT16 n) {
     LVM_FLOAT temp1, left, right;
     LVM_INT16 ii;
@@ -71,4 +44,3 @@
 
     return;
 }
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_16.cpp b/media/libeffects/lvm/lib/Common/src/From2iToMono_16.cpp
deleted file mode 100644
index 9a54ee4..0000000
--- a/media/libeffects/lvm/lib/Common/src/From2iToMono_16.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION From2iToMono_16
-***********************************************************************************/
-
-void From2iToMono_16(const LVM_INT16* src, LVM_INT16* dst, LVM_INT16 n) {
-    LVM_INT16 ii;
-    LVM_INT32 Temp;
-    for (ii = n; ii != 0; ii--) {
-        Temp = (LVM_INT32)*src;
-        src++;
-
-        Temp += (LVM_INT32)*src;
-        src++;
-
-        *dst = (LVM_INT16)(Temp >> 1);
-        dst++;
-    }
-
-    return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp
index 6ede958..039ee14 100644
--- a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp
@@ -21,27 +21,6 @@
 
 #include "VectorArithmetic.h"
 
-/**********************************************************************************
-   FUNCTION From2iToMono_32
-***********************************************************************************/
-
-void From2iToMono_32(const LVM_INT32* src, LVM_INT32* dst, LVM_INT16 n) {
-    LVM_INT16 ii;
-    LVM_INT32 Temp;
-
-    for (ii = n; ii != 0; ii--) {
-        Temp = (*src >> 1);
-        src++;
-
-        Temp += (*src >> 1);
-        src++;
-
-        *dst = Temp;
-        dst++;
-    }
-
-    return;
-}
 void From2iToMono_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n) {
     LVM_INT16 ii;
     LVM_FLOAT Temp;
@@ -93,5 +72,3 @@
 
     return;
 }
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.cpp b/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.cpp
deleted file mode 100644
index 9ddcbe4..0000000
--- a/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION INT16LSHIFTTOINT32_16X32
-***********************************************************************************/
-
-void Int16LShiftToInt32_16x32(const LVM_INT16* src, LVM_INT32* dst, LVM_INT16 n, LVM_INT16 shift) {
-    LVM_INT16 ii;
-
-    src += n - 1;
-    dst += n - 1;
-
-    for (ii = n; ii != 0; ii--) {
-        *dst = (((LVM_INT32)*src) << shift);
-        src--;
-        dst--;
-    }
-
-    return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.cpp b/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.cpp
deleted file mode 100644
index 2584117..0000000
--- a/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION INT32RSHIFTTOINT16_SAT_32X16
-***********************************************************************************/
-
-void Int32RShiftToInt16_Sat_32x16(const LVM_INT32* src, LVM_INT16* dst, LVM_INT16 n,
-                                  LVM_INT16 shift) {
-    LVM_INT32 temp;
-    LVM_INT16 ii;
-
-    for (ii = n; ii != 0; ii--) {
-        temp = *src >> shift;
-        src++;
-
-        if (temp > 0x00007FFF) {
-            *dst = 0x7FFF;
-        } else if (temp < -0x00008000) {
-            *dst = -0x8000;
-        } else {
-            *dst = (LVM_INT16)temp;
-        }
-
-        dst++;
-    }
-
-    return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp
index 0721b76..6c7c8ae 100644
--- a/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp
+++ b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp
@@ -21,29 +21,6 @@
 
 #include "VectorArithmetic.h"
 
-/**********************************************************************************
-   FUNCTION JoinTo2i_32x32
-***********************************************************************************/
-
-void JoinTo2i_32x32(const LVM_INT32* srcL, const LVM_INT32* srcR, LVM_INT32* dst, LVM_INT16 n) {
-    LVM_INT16 ii;
-
-    srcL += n - 1;
-    srcR += n - 1;
-    dst += ((2 * n) - 1);
-
-    for (ii = n; ii != 0; ii--) {
-        *dst = *srcR;
-        dst--;
-        srcR--;
-
-        *dst = *srcL;
-        dst--;
-        srcL--;
-    }
-
-    return;
-}
 void JoinTo2i_Float(const LVM_FLOAT* srcL, const LVM_FLOAT* srcR, LVM_FLOAT* dst, LVM_INT16 n) {
     LVM_INT16 ii;
 
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp
index 8b00925..d670b3d 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp
@@ -18,39 +18,10 @@
 /**********************************************************************************
    INCLUDE FILES
 ***********************************************************************************/
-
 #include "LVC_Mixer_Private.h"
 #include "LVM_Macros.h"
 #include "ScalarArithmetic.h"
 
-/**********************************************************************************
-   FUNCTION LVC_Core_MixHard_1St_2i_D16C31_SAT
-***********************************************************************************/
-void LVC_Core_MixHard_1St_2i_D16C31_SAT(LVMixer3_FLOAT_st* ptrInstance1,
-                                        LVMixer3_FLOAT_st* ptrInstance2, const LVM_FLOAT* src,
-                                        LVM_FLOAT* dst, LVM_INT16 n) {
-    LVM_FLOAT Temp;
-    LVM_INT16 ii;
-    Mix_Private_FLOAT_st* pInstance1 = (Mix_Private_FLOAT_st*)(ptrInstance1->PrivateParams);
-    Mix_Private_FLOAT_st* pInstance2 = (Mix_Private_FLOAT_st*)(ptrInstance2->PrivateParams);
-    for (ii = n; ii != 0; ii--) {
-        Temp = ((LVM_FLOAT) * (src++) * (LVM_FLOAT)pInstance1->Current);
-        if (Temp > 1.0f)
-            *dst++ = 1.0f;
-        else if (Temp < -1.0f)
-            *dst++ = -1.0f;
-        else
-            *dst++ = (LVM_FLOAT)Temp;
-
-        Temp = ((LVM_FLOAT) * (src++) * (LVM_FLOAT)pInstance2->Current);
-        if (Temp > 1.0f)
-            *dst++ = 1.0f;
-        else if (Temp < -1.0f)
-            *dst++ = -1.0f;
-        else
-            *dst++ = (LVM_FLOAT)Temp;
-    }
-}
 void LVC_Core_MixHard_1St_MC_float_SAT(Mix_Private_FLOAT_st** ptrInstance, const LVM_FLOAT* src,
                                        LVM_FLOAT* dst, LVM_INT16 NrFrames, LVM_INT16 NrChannels) {
     LVM_FLOAT Temp;
@@ -58,14 +29,8 @@
     for (ii = NrFrames; ii != 0; ii--) {
         for (jj = 0; jj < NrChannels; jj++) {
             Mix_Private_FLOAT_st* pInstance1 = (Mix_Private_FLOAT_st*)(ptrInstance[jj]);
-            Temp = ((LVM_FLOAT) * (src++) * (LVM_FLOAT)pInstance1->Current);
-            if (Temp > 1.0f)
-                *dst++ = 1.0f;
-            else if (Temp < -1.0f)
-                *dst++ = -1.0f;
-            else
-                *dst++ = (LVM_FLOAT)Temp;
+            Temp =  *src++ * pInstance1->Current;
+            *dst++ = LVM_Clamp(Temp);
         }
     }
 }
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp
index 31cd805..417c1f0 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp
@@ -18,8 +18,8 @@
 /**********************************************************************************
    INCLUDE FILES
 ***********************************************************************************/
-
 #include "LVC_Mixer_Private.h"
+#include "ScalarArithmetic.h"
 
 /**********************************************************************************
    FUNCTION LVCore_MIXHARD_2ST_D16C31_SAT
@@ -34,18 +34,12 @@
     Mix_Private_FLOAT_st* pInstance1 = (Mix_Private_FLOAT_st*)(ptrInstance1->PrivateParams);
     Mix_Private_FLOAT_st* pInstance2 = (Mix_Private_FLOAT_st*)(ptrInstance2->PrivateParams);
 
-    Current1 = (pInstance1->Current);
-    Current2 = (pInstance2->Current);
+    Current1 = pInstance1->Current;
+    Current2 = pInstance2->Current;
 
     for (ii = n; ii != 0; ii--) {
-        Temp = (((LVM_FLOAT) * (src1++) * (LVM_FLOAT)Current1)) +
-               (((LVM_FLOAT) * (src2++) * (LVM_FLOAT)Current2));
-        if (Temp > 1.0f)
-            *dst++ = 1.0f;
-        else if (Temp < -1.0f)
-            *dst++ = -1.0f;
-        else
-            *dst++ = Temp;
+        Temp =  *src1++ * Current1 + *src2++ * Current2;
+        *dst++ = LVM_Clamp(Temp);
     }
 }
 /**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp
index b7865d9..d8c25c9 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp
@@ -18,9 +18,9 @@
 /**********************************************************************************
    INCLUDE FILES
 ***********************************************************************************/
-
 #include "LVC_Mixer_Private.h"
 #include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
 
 /**********************************************************************************
    FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
@@ -46,13 +46,8 @@
             if (Current > Target) Current = Target;
 
             for (ii = OutLoop; ii != 0; ii--) {
-                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT) * (src++) * Current));
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = (LVM_FLOAT)Temp;
+                Temp = *dst + *src++ * Current;
+                *dst++ = LVM_Clamp(Temp);
             }
         }
 
@@ -62,13 +57,8 @@
             if (Current > Target) Current = Target;
 
             for (jj = 4; jj != 0; jj--) {
-                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT) * (src++) * Current));
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = (LVM_FLOAT)Temp;
+                Temp = *dst + *src++ * Current;
+                *dst++ = LVM_Clamp(Temp);
             }
         }
     } else {
@@ -77,13 +67,8 @@
             if (Current < Target) Current = Target;
 
             for (ii = OutLoop; ii != 0; ii--) {
-                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT) * (src++) * Current));
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = (LVM_FLOAT)Temp;
+                Temp = *dst + *src++ * Current;
+                *dst++ = LVM_Clamp(Temp);
             }
         }
 
@@ -92,13 +77,8 @@
             if (Current < Target) Current = Target;
 
             for (jj = 4; jj != 0; jj--) {
-                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT) * (src++) * Current));
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = (LVM_FLOAT)Temp;
+                Temp = *dst + *src++ * Current;
+                *dst++ = LVM_Clamp(Temp);
             }
         }
     }
@@ -148,13 +128,8 @@
             if (Current > Target) Current = Target;
 
             for (ii = OutLoop * NrChannels; ii != 0; ii--) {
-                Temp = (*dst) + (*(src++) * Current);
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = Temp;
+                Temp = *dst + *src++ * Current;
+                *dst++ = LVM_Clamp(Temp);
             }
         }
 
@@ -164,21 +139,11 @@
             if (Current > Target) Current = Target;
 
             for (jj = NrChannels; jj != 0; jj--) {
-                Temp = (*dst) + (*(src++) * Current);
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = Temp;
+                Temp = *dst + *src++ * Current;
+                *dst++ = LVM_Clamp(Temp);
 
-                Temp = (*dst) + (*(src++) * Current);
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = Temp;
+                Temp = *dst + *src++ * Current;
+                *dst++ = LVM_Clamp(Temp);
             }
         }
     } else {
@@ -187,13 +152,8 @@
             if (Current < Target) Current = Target;
 
             for (ii = OutLoop * NrChannels; ii != 0; ii--) {
-                Temp = (*dst) + (*(src++) * Current);
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = Temp;
+                Temp = *dst + *src++ * Current;
+                *dst++ = LVM_Clamp(Temp);
             }
         }
 
@@ -202,21 +162,11 @@
             if (Current < Target) Current = Target;
 
             for (jj = NrChannels; jj != 0; jj--) {
-                Temp = (*dst) + (*(src++) * Current);
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = Temp;
+                Temp = *dst + *src++ * Current;
+                *dst++ = LVM_Clamp(Temp);
 
-                Temp = (*dst) + (*(src++) * Current);
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = Temp;
+                Temp = *dst + *src++ * Current;
+                *dst++ = LVM_Clamp(Temp);
             }
         }
     }
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp
index d45845a..0968cf8 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp
@@ -18,107 +18,16 @@
 /**********************************************************************************
    INCLUDE FILES
 ***********************************************************************************/
-
 #include "LVC_Mixer_Private.h"
-#include "ScalarArithmetic.h"
 #include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
 
-/**********************************************************************************
-   FUNCTION LVC_Core_MixSoft_1St_2i_D16C31_WRA
-***********************************************************************************/
-static LVM_FLOAT ADD2_SAT_FLOAT(LVM_FLOAT a, LVM_FLOAT b, LVM_FLOAT c) {
-    LVM_FLOAT temp;
-    temp = a + b;
-    if (temp < -1.0f)
-        c = -1.0f;
-    else if (temp > 1.0f)
-        c = 1.0f;
-    else
-        c = temp;
-    return c;
-}
-void LVC_Core_MixSoft_1St_2i_D16C31_WRA(LVMixer3_FLOAT_st* ptrInstance1,
-                                        LVMixer3_FLOAT_st* ptrInstance2, const LVM_FLOAT* src,
-                                        LVM_FLOAT* dst, LVM_INT16 n) {
-    LVM_INT16 OutLoop;
-    LVM_INT16 InLoop;
-    LVM_INT32 ii;
-    Mix_Private_FLOAT_st* pInstanceL = (Mix_Private_FLOAT_st*)(ptrInstance1->PrivateParams);
-    Mix_Private_FLOAT_st* pInstanceR = (Mix_Private_FLOAT_st*)(ptrInstance2->PrivateParams);
-
-    LVM_FLOAT DeltaL = pInstanceL->Delta;
-    LVM_FLOAT CurrentL = pInstanceL->Current;
-    LVM_FLOAT TargetL = pInstanceL->Target;
-
-    LVM_FLOAT DeltaR = pInstanceR->Delta;
-    LVM_FLOAT CurrentR = pInstanceR->Current;
-    LVM_FLOAT TargetR = pInstanceR->Target;
-
-    LVM_FLOAT Temp = 0;
-
-    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
-    OutLoop = (LVM_INT16)(n - (InLoop << 2));
-
-    if (OutLoop) {
-        if (CurrentL < TargetL) {
-            ADD2_SAT_FLOAT(CurrentL, DeltaL, Temp);
-            CurrentL = Temp;
-            if (CurrentL > TargetL) CurrentL = TargetL;
-        } else {
-            CurrentL -= DeltaL;
-            if (CurrentL < TargetL) CurrentL = TargetL;
-        }
-
-        if (CurrentR < TargetR) {
-            ADD2_SAT_FLOAT(CurrentR, DeltaR, Temp);
-            CurrentR = Temp;
-            if (CurrentR > TargetR) CurrentR = TargetR;
-        } else {
-            CurrentR -= DeltaR;
-            if (CurrentR < TargetR) CurrentR = TargetR;
-        }
-
-        for (ii = OutLoop * 2; ii != 0; ii -= 2) {
-            *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
-            *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
-        }
-    }
-
-    for (ii = InLoop * 2; ii != 0; ii -= 2) {
-        if (CurrentL < TargetL) {
-            ADD2_SAT_FLOAT(CurrentL, DeltaL, Temp);
-            CurrentL = Temp;
-            if (CurrentL > TargetL) CurrentL = TargetL;
-        } else {
-            CurrentL -= DeltaL;
-            if (CurrentL < TargetL) CurrentL = TargetL;
-        }
-
-        if (CurrentR < TargetR) {
-            ADD2_SAT_FLOAT(CurrentR, DeltaR, Temp);
-            CurrentR = Temp;
-            if (CurrentR > TargetR) CurrentR = TargetR;
-        } else {
-            CurrentR -= DeltaR;
-            if (CurrentR < TargetR) CurrentR = TargetR;
-        }
-
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentL));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT) * (src++) * (LVM_FLOAT)CurrentR));
-    }
-    pInstanceL->Current = CurrentL;
-    pInstanceR->Current = CurrentR;
+static inline LVM_FLOAT ADD2_SAT_FLOAT(LVM_FLOAT a, LVM_FLOAT b) {
+    return LVM_Clamp(a + b);
 }
 void LVC_Core_MixSoft_1St_MC_float_WRA(Mix_Private_FLOAT_st** ptrInstance, const LVM_FLOAT* src,
                                        LVM_FLOAT* dst, LVM_INT16 NrFrames, LVM_INT16 NrChannels) {
     LVM_INT32 ii, ch;
-    LVM_FLOAT Temp = 0.0f;
     LVM_FLOAT tempCurrent[NrChannels];
     for (ch = 0; ch < NrChannels; ch++) {
         tempCurrent[ch] = ptrInstance[ch]->Current;
@@ -130,8 +39,7 @@
             LVM_FLOAT Current = tempCurrent[ch];
             const LVM_FLOAT Target = pInstance->Target;
             if (Current < Target) {
-                ADD2_SAT_FLOAT(Current, Delta, Temp);
-                Current = Temp;
+                Current = ADD2_SAT_FLOAT(Current, Delta);
                 if (Current > Target) Current = Target;
             } else {
                 Current -= Delta;
@@ -145,4 +53,3 @@
         ptrInstance[ch]->Current = tempCurrent[ch];
     }
 }
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp
index f8c0a9d..fc464e6 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp
@@ -18,7 +18,6 @@
 /**********************************************************************************
    INCLUDE FILES
 ***********************************************************************************/
-
 #include "LVC_Mixer_Private.h"
 #include "LVM_Macros.h"
 #include "ScalarArithmetic.h"
@@ -35,20 +34,13 @@
     LVM_FLOAT Delta = (LVM_FLOAT)pInstance->Delta;
     LVM_FLOAT Current = (LVM_FLOAT)pInstance->Current;
     LVM_FLOAT Target = (LVM_FLOAT)pInstance->Target;
-    LVM_FLOAT Temp;
 
     InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
     OutLoop = (LVM_INT16)(n - (InLoop << 2));
 
     if (Current < Target) {
         if (OutLoop) {
-            Temp = Current + Delta;
-            if (Temp > 1.0f)
-                Temp = 1.0f;
-            else if (Temp < -1.0f)
-                Temp = -1.0f;
-
-            Current = Temp;
+            Current = LVM_Clamp(Current + Delta);
             if (Current > Target) Current = Target;
 
             for (ii = OutLoop; ii != 0; ii--) {
@@ -57,14 +49,8 @@
         }
 
         for (ii = InLoop; ii != 0; ii--) {
-            Temp = Current + Delta;
+            Current = LVM_Clamp(Current + Delta);
 
-            if (Temp > 1.0f)
-                Temp = 1.0f;
-            else if (Temp < -1.0f)
-                Temp = -1.0f;
-
-            Current = Temp;
             if (Current > Target) Current = Target;
 
             *(dst++) = (((LVM_FLOAT) * (src++) * Current));
@@ -121,7 +107,6 @@
     LVM_FLOAT Delta = (LVM_FLOAT)pInstance->Delta;
     LVM_FLOAT Current = (LVM_FLOAT)pInstance->Current;
     LVM_FLOAT Target = (LVM_FLOAT)pInstance->Target;
-    LVM_FLOAT Temp;
 
     /*
      * Same operation is performed on consecutive frames.
@@ -134,13 +119,7 @@
 
     if (Current < Target) {
         if (OutLoop) {
-            Temp = Current + Delta;
-            if (Temp > 1.0f)
-                Temp = 1.0f;
-            else if (Temp < -1.0f)
-                Temp = -1.0f;
-
-            Current = Temp;
+            Current = LVM_Clamp(Current + Delta);
             if (Current > Target) Current = Target;
 
             for (ii = OutLoop; ii != 0; ii--) {
@@ -151,14 +130,7 @@
         }
 
         for (ii = InLoop; ii != 0; ii--) {
-            Temp = Current + Delta;
-
-            if (Temp > 1.0f)
-                Temp = 1.0f;
-            else if (Temp < -1.0f)
-                Temp = -1.0f;
-
-            Current = Temp;
+            Current = LVM_Clamp(Current + Delta);
             if (Current > Target) Current = Target;
 
             for (jj = NrChannels; jj != 0; jj--) {
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp
index c74c8c6..58bc06e 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp
@@ -35,7 +35,7 @@
 #define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof(*(a))))
 
 /**********************************************************************************
-   FUNCTION LVC_MixSoft_1St_2i_D16C31_SAT
+   FUNCTION LVC_MixSoft_1St_MC_float_SAT
 ***********************************************************************************/
 /* This threshold is used to decide on the processing to be applied on
  * front center and back center channels
@@ -192,106 +192,3 @@
         }
     }
 }
-void LVC_MixSoft_1St_2i_D16C31_SAT(LVMixer3_2St_FLOAT_st* ptrInstance, const LVM_FLOAT* src,
-                                   LVM_FLOAT* dst, LVM_INT16 n) {
-    char HardMixing = TRUE;
-    LVM_FLOAT TargetGain;
-    Mix_Private_FLOAT_st* pInstance1 =
-            (Mix_Private_FLOAT_st*)(ptrInstance->MixerStream[0].PrivateParams);
-    Mix_Private_FLOAT_st* pInstance2 =
-            (Mix_Private_FLOAT_st*)(ptrInstance->MixerStream[1].PrivateParams);
-
-    if (n <= 0) return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if ((pInstance1->Current != pInstance1->Target) ||
-        (pInstance2->Current != pInstance2->Target)) {
-        if (pInstance1->Delta == 1.0f) {
-            pInstance1->Current = pInstance1->Target;
-            TargetGain = pInstance1->Target;
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
-        } else if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta) {
-            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
-                                                         Make them equal. */
-            TargetGain = pInstance1->Target;
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
-        } else {
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-        }
-
-        if (HardMixing == TRUE) {
-            if (pInstance2->Delta == 1.0f) {
-                pInstance2->Current = pInstance2->Target;
-                TargetGain = pInstance2->Target;
-                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
-            } else if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta) {
-                pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.
-                                                             \ Make them equal. */
-                TargetGain = pInstance2->Target;
-                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
-            } else {
-                /* Soft mixing has to be applied */
-                HardMixing = FALSE;
-            }
-        }
-
-        if (HardMixing == FALSE) {
-            LVC_Core_MixSoft_1St_2i_D16C31_WRA(&(ptrInstance->MixerStream[0]),
-                                               &(ptrInstance->MixerStream[1]), src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing) {
-        if ((pInstance1->Target == 1.0f) && (pInstance2->Target == 1.0f)) {
-            if (src != dst) {
-                Copy_Float(src, dst, n);
-            }
-        } else {
-            LVC_Core_MixHard_1St_2i_D16C31_SAT(&(ptrInstance->MixerStream[0]),
-                                               &(ptrInstance->MixerStream[1]), src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-
-    if (ptrInstance->MixerStream[0].CallbackSet) {
-        if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta) {
-            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
-                                                         Make them equal. */
-            TargetGain = pInstance1->Target;
-            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[0], TargetGain);
-            ptrInstance->MixerStream[0].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[0].pCallBack != 0) {
-                (*ptrInstance->MixerStream[0].pCallBack)(
-                        ptrInstance->MixerStream[0].pCallbackHandle,
-                        ptrInstance->MixerStream[0].pGeneralPurpose,
-                        ptrInstance->MixerStream[0].CallbackParam);
-            }
-        }
-    }
-    if (ptrInstance->MixerStream[1].CallbackSet) {
-        if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta) {
-            pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.
-                                                         Make them equal. */
-            TargetGain = pInstance2->Target;
-            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[1], TargetGain);
-            ptrInstance->MixerStream[1].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[1].pCallBack != 0) {
-                (*ptrInstance->MixerStream[1].pCallBack)(
-                        ptrInstance->MixerStream[1].pCallbackHandle,
-                        ptrInstance->MixerStream[1].pGeneralPurpose,
-                        ptrInstance->MixerStream[1].CallbackParam);
-            }
-        }
-    }
-}
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
index 55255a6..1eb2dea 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
@@ -101,9 +101,6 @@
 void LVC_MixSoft_1St_MC_float_SAT(LVMixer3_2St_FLOAT_st* pInstance, const LVM_FLOAT* src,
                                   LVM_FLOAT* dst, /* dst can be equal to src */
                                   LVM_INT16 NrFrames, LVM_INT32 NrChannels, LVM_INT32 ChMask);
-void LVC_MixSoft_1St_2i_D16C31_SAT(LVMixer3_2St_FLOAT_st* pInstance, const LVM_FLOAT* src,
-                                   LVM_FLOAT* dst, /* dst can be equal to src */
-                                   LVM_INT16 n);   /* Number of stereo samples */
 
 /**********************************************************************************/
 
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
index 5f22d77..9206fae 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
@@ -65,9 +65,6 @@
 /**********************************************************************************/
 void LVC_Core_MixSoft_1St_MC_float_WRA(Mix_Private_FLOAT_st** ptrInstance, const LVM_FLOAT* src,
                                        LVM_FLOAT* dst, LVM_INT16 NrFrames, LVM_INT16 NrChannels);
-void LVC_Core_MixSoft_1St_2i_D16C31_WRA(LVMixer3_FLOAT_st* ptrInstance1,
-                                        LVMixer3_FLOAT_st* ptrInstance2, const LVM_FLOAT* src,
-                                        LVM_FLOAT* dst, LVM_INT16 n);
 
 /**********************************************************************************/
 /* For applying different gains to Left and right chennals                        */
@@ -77,11 +74,5 @@
 /**********************************************************************************/
 void LVC_Core_MixHard_1St_MC_float_SAT(Mix_Private_FLOAT_st** ptrInstance, const LVM_FLOAT* src,
                                        LVM_FLOAT* dst, LVM_INT16 NrFrames, LVM_INT16 NrChannels);
-void LVC_Core_MixHard_1St_2i_D16C31_SAT(LVMixer3_FLOAT_st* ptrInstance1,
-                                        LVMixer3_FLOAT_st* ptrInstance2, const LVM_FLOAT* src,
-                                        LVM_FLOAT* dst, LVM_INT16 n);
-
-/*** 32 bit functions *************************************************************/
-/**********************************************************************************/
 
 #endif  //#ifndef __LVC_MIXER_PRIVATE_H__
diff --git a/media/libeffects/lvm/lib/Common/src/LoadConst_16.cpp b/media/libeffects/lvm/lib/Common/src/LoadConst_16.cpp
deleted file mode 100644
index a39fa2f..0000000
--- a/media/libeffects/lvm/lib/Common/src/LoadConst_16.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION LoadConst_16
-***********************************************************************************/
-
-void LoadConst_16(const LVM_INT16 val, LVM_INT16* dst, LVM_INT16 n) {
-    LVM_INT16 ii;
-
-    for (ii = n; ii != 0; ii--) {
-        *dst = val;
-        dst++;
-    }
-
-    return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp
index a19e66f..e5c6f15 100644
--- a/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp
@@ -18,49 +18,9 @@
 /**********************************************************************************
    INCLUDE FILES
 ***********************************************************************************/
-
+#include "ScalarArithmetic.h"
 #include "VectorArithmetic.h"
 
-/**********************************************************************************
-   FUNCTION  MSTO2I_SAT_16X16
-***********************************************************************************/
-
-void MSTo2i_Sat_16x16(const LVM_INT16* srcM, const LVM_INT16* srcS, LVM_INT16* dst, LVM_INT16 n) {
-    LVM_INT32 temp, mVal, sVal;
-    LVM_INT16 ii;
-
-    for (ii = n; ii != 0; ii--) {
-        mVal = (LVM_INT32)*srcM;
-        srcM++;
-
-        sVal = (LVM_INT32)*srcS;
-        srcS++;
-
-        temp = mVal + sVal;
-
-        if (temp > 0x00007FFF) {
-            *dst = 0x7FFF;
-        } else if (temp < -0x00008000) {
-            *dst = -0x8000;
-        } else {
-            *dst = (LVM_INT16)temp;
-        }
-        dst++;
-
-        temp = mVal - sVal;
-
-        if (temp > 0x00007FFF) {
-            *dst = 0x7FFF;
-        } else if (temp < -0x00008000) {
-            *dst = -0x8000;
-        } else {
-            *dst = (LVM_INT16)temp;
-        }
-        dst++;
-    }
-
-    return;
-}
 void MSTo2i_Sat_Float(const LVM_FLOAT* srcM, const LVM_FLOAT* srcS, LVM_FLOAT* dst, LVM_INT16 n) {
     LVM_FLOAT temp, mVal, sVal;
     LVM_INT16 ii;
@@ -73,28 +33,11 @@
         srcS++;
 
         temp = mVal + sVal;
-
-        if (temp > 1.0f) {
-            *dst = 1.0f;
-        } else if (temp < -1.0f) {
-            *dst = -1.0f;
-        } else {
-            *dst = (LVM_FLOAT)temp;
-        }
-        dst++;
+        *dst++ = LVM_Clamp(temp);
 
         temp = mVal - sVal;
-
-        if (temp > 1.0f) {
-            *dst = 1.0f;
-        } else if (temp < -1.0f) {
-            *dst = -1.0f;
-        } else {
-            *dst = (LVM_FLOAT)temp;
-        }
-        dst++;
+        *dst++ = LVM_Clamp(temp);
     }
 
     return;
 }
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.cpp b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.cpp
deleted file mode 100644
index 1d450b0..0000000
--- a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/**********************************************************************************
-
-     %created_by:    sra % (CM/S)
-     %name:          Mac3s_Sat_16x16.c % (CM/S)
-     %version:       1 % (CM/S)
-     %date_created:  Fri Nov 13 12:07:13 2009 % (CM/S)
-
-***********************************************************************************/
-
-/**********************************************************************************
-   INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-#include "LVM_Macros.h"
-
-/**********************************************************************************
-   FUNCTION Mac3S_16X16
-***********************************************************************************/
-
-void Mac3s_Sat_16x16(const LVM_INT16* src, const LVM_INT16 val, LVM_INT16* dst, LVM_INT16 n) {
-    LVM_INT16 ii;
-    LVM_INT16 srcval;
-    LVM_INT32 Temp, dInVal;
-
-    for (ii = n; ii != 0; ii--) {
-        srcval = *src;
-        src++;
-
-        Temp = (srcval * val) >> 15;
-
-        dInVal = (LVM_INT32)*dst;
-
-        Temp = Temp + dInVal;
-
-        if (Temp > 0x00007FFF) {
-            *dst = 0x7FFF;
-        } else if (Temp < -0x00008000) {
-            *dst = -0x8000;
-        } else {
-            *dst = (LVM_INT16)Temp;
-        }
-
-        dst++;
-    }
-
-    return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp
index 0fe9fef..24bdf3e 100644
--- a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp
@@ -18,66 +18,19 @@
 /**********************************************************************************
    INCLUDE FILES
 ***********************************************************************************/
-
+#include "ScalarArithmetic.h"
 #include "VectorArithmetic.h"
 #include "LVM_Macros.h"
 
-/**********************************************************************************
-   FUNCTION MAC3S_16X16
-***********************************************************************************/
-
-void Mac3s_Sat_32x16(const LVM_INT32* src, const LVM_INT16 val, LVM_INT32* dst, LVM_INT16 n) {
-    LVM_INT16 ii;
-    LVM_INT32 srcval, temp, dInVal, dOutVal;
-
-    for (ii = n; ii != 0; ii--) {
-        srcval = *src;
-        src++;
-
-        MUL32x16INTO32(srcval, val, temp, 15)
-
-                dInVal = *dst;
-        dOutVal = temp + dInVal;
-
-        if ((((dOutVal ^ temp) & (dOutVal ^ dInVal)) >> 31) != 0) /* overflow / underflow */
-        {
-            if (temp < 0) {
-                dOutVal = 0x80000000L;
-            } else {
-                dOutVal = 0x7FFFFFFFL;
-            }
-        }
-
-        *dst = dOutVal;
-        dst++;
-    }
-
-    return;
-}
 void Mac3s_Sat_Float(const LVM_FLOAT* src, const LVM_FLOAT val, LVM_FLOAT* dst, LVM_INT16 n) {
     LVM_INT16 ii;
-    LVM_FLOAT srcval;
-    LVM_FLOAT Temp, dInVal;
 
     for (ii = n; ii != 0; ii--) {
-        srcval = *src;
-        src++;
+        LVM_FLOAT Temp = *src++ * val;
+        Temp += *dst;
 
-        Temp = srcval * val;
-
-        dInVal = (LVM_FLOAT)*dst;
-        Temp = Temp + dInVal;
-
-        if (Temp > 1.000000f) {
-            *dst = 1.000000f;
-        } else if (Temp < -1.000000f) {
-            *dst = -1.000000f;
-        } else {
-            *dst = Temp;
-        }
-        dst++;
+        *dst++ = LVM_Clamp(Temp);
     }
 
     return;
 }
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.cpp b/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.cpp
deleted file mode 100644
index 7ab5d49..0000000
--- a/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION MonoTo2I_16
-***********************************************************************************/
-
-void MonoTo2I_16(const LVM_INT16* src, LVM_INT16* dst, LVM_INT16 n) {
-    LVM_INT16 ii;
-    src += (n - 1);
-    dst += ((n * 2) - 1);
-
-    for (ii = n; ii != 0; ii--) {
-        *dst = *src;
-        dst--;
-
-        *dst = *src;
-        dst--;
-        src--;
-    }
-
-    return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp
index 1ba669f..ef3e633 100644
--- a/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp
+++ b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp
@@ -21,26 +21,6 @@
 
 #include "VectorArithmetic.h"
 
-/**********************************************************************************
-   FUNCTION MonoTo2I_32
-***********************************************************************************/
-
-void MonoTo2I_32(const LVM_INT32* src, LVM_INT32* dst, LVM_INT16 n) {
-    LVM_INT16 ii;
-    src += (n - 1);
-    dst += ((n * 2) - 1);
-
-    for (ii = n; ii != 0; ii--) {
-        *dst = *src;
-        dst--;
-
-        *dst = *src;
-        dst--;
-        src--;
-    }
-
-    return;
-}
 void MonoTo2I_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n) {
     LVM_INT16 ii;
     src += (n - 1);
@@ -57,4 +37,3 @@
 
     return;
 }
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp
index 4589703..babfef3 100644
--- a/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp
@@ -22,26 +22,6 @@
 #include "VectorArithmetic.h"
 #include "LVM_Macros.h"
 
-/**********************************************************************************
-FUNCTION MULT3S_16X16
-***********************************************************************************/
-
-void Mult3s_32x16(const LVM_INT32* src, const LVM_INT16 val, LVM_INT32* dst, LVM_INT16 n) {
-    LVM_INT16 ii;
-    LVM_INT32 srcval, temp;
-
-    for (ii = n; ii != 0; ii--) {
-        srcval = *src;
-        src++;
-
-        MUL32x16INTO32(srcval, val, temp, 15)
-
-                * dst = temp;
-        dst++;
-    }
-
-    return;
-}
 void Mult3s_Float(const LVM_FLOAT* src, const LVM_FLOAT val, LVM_FLOAT* dst, LVM_INT16 n) {
     LVM_INT16 ii;
     LVM_FLOAT temp;
@@ -54,4 +34,3 @@
     }
     return;
 }
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp
index fba0666..f3a1a67 100644
--- a/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp
@@ -61,43 +61,6 @@
 /*                                                                                      */
 /****************************************************************************************/
 
-void NonLinComp_D16(LVM_INT16 Gain, LVM_INT16* pDataIn, LVM_INT16* pDataOut,
-                    LVM_INT32 BlockLength) {
-    LVM_INT16 Sample;   /* Input samples */
-    LVM_INT32 SampleNo; /* Sample index */
-    LVM_INT16 Temp;
-
-    /*
-     * Process a block of samples
-     */
-    for (SampleNo = 0; SampleNo < BlockLength; SampleNo++) {
-        /*
-         * Read the input
-         */
-        Sample = *pDataIn;
-        pDataIn++;
-
-        /*
-         * Apply the compander, this compresses the signal at the expense of
-         * harmonic distortion. The amount of compression is control by the
-         * gain factor
-         */
-        if ((LVM_INT32)Sample != -32768) {
-            Temp = (LVM_INT16)((Sample * Sample) >> 15);
-            if (Sample > 0) {
-                Sample = (LVM_INT16)(Sample + ((Gain * (Sample - Temp)) >> 15));
-            } else {
-                Sample = (LVM_INT16)(Sample + ((Gain * (Sample + Temp)) >> 15));
-            }
-        }
-
-        /*
-         * Save the output
-         */
-        *pDataOut = Sample;
-        pDataOut++;
-    }
-}
 void NonLinComp_Float(LVM_FLOAT Gain, LVM_FLOAT* pDataIn, LVM_FLOAT* pDataOut,
                       LVM_INT32 BlockLength) {
     LVM_FLOAT Sample;   /* Input samples */
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp
index 0afaad2..2a5540e 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp
@@ -15,102 +15,12 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
 #include "LVM_Macros.h"
 
 /**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A0,
- pBiquadState->coefs[1] is -B2,
- pBiquadState->coefs[2] is -B1, these are in Q14 format
- pBiquadState->coefs[3] is Gain, in Q11 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q0 format
- pBiquadState->pDelays[5] is y(n-1)R in Q0 format
- pBiquadState->pDelays[6] is y(n-2)L in Q0 format
- pBiquadState->pDelays[7] is y(n-2)R in Q0 format
-***************************************************************************/
-void PK_2I_D32F32C14G11_TRC_WRA_01(Biquad_FLOAT_Instance_t* pInstance, LVM_FLOAT* pDataIn,
-                                   LVM_FLOAT* pDataOut, LVM_INT16 NrSamples) {
-    LVM_FLOAT ynL, ynR, ynLO, ynRO, templ;
-    LVM_INT16 ii;
-    PFilter_State_Float pBiquadState = (PFilter_State_Float)pInstance;
-
-    for (ii = NrSamples; ii != 0; ii--) {
-        /**************************************************************************
-                        PROCESSING OF THE LEFT CHANNEL
-        ***************************************************************************/
-        /* ynL= (A0  * (x(n)L - x(n-2)L  ) )*/
-        templ = (*pDataIn) - pBiquadState->pDelays[2];
-        ynL = templ * pBiquadState->coefs[0];
-
-        /* ynL+= ((-B2  * y(n-2)L  )) */
-        templ = pBiquadState->pDelays[6] * pBiquadState->coefs[1];
-        ynL += templ;
-
-        /* ynL+= ((-B1 * y(n-1)L  ) ) */
-        templ = pBiquadState->pDelays[4] * pBiquadState->coefs[2];
-        ynL += templ;
-
-        /* ynLO= ((Gain * ynL )) */
-        ynLO = ynL * pBiquadState->coefs[3];
-
-        /* ynLO=( ynLO + x(n)L  )*/
-        ynLO += (*pDataIn);
-
-        /**************************************************************************
-                        PROCESSING OF THE RIGHT CHANNEL
-        ***************************************************************************/
-        /* ynR= (A0  * (x(n)R  - x(n-2)R  ) ) */
-        templ = (*(pDataIn + 1)) - pBiquadState->pDelays[3];
-        ynR = templ * pBiquadState->coefs[0];
-
-        /* ynR+= ((-B2  * y(n-2)R  ) )  */
-        templ = pBiquadState->pDelays[7] * pBiquadState->coefs[1];
-        ynR += templ;
-
-        /* ynR+= ((-B1  * y(n-1)R  ) )   */
-        templ = pBiquadState->pDelays[5] * pBiquadState->coefs[2];
-        ynR += templ;
-
-        /* ynRO= ((Gain  * ynR )) */
-        ynRO = ynR * pBiquadState->coefs[3];
-
-        /* ynRO=( ynRO + x(n)R  )*/
-        ynRO += (*(pDataIn + 1));
-
-        /**************************************************************************
-                        UPDATING THE DELAYS
-        ***************************************************************************/
-        pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
-        pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
-        pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
-        pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
-        pBiquadState->pDelays[5] = ynR;                      /* Update y(n-1)R */
-        pBiquadState->pDelays[4] = ynL;                      /* Update y(n-1)L */
-        pBiquadState->pDelays[0] = (*pDataIn);               /* Update x(n-1)L */
-        pDataIn++;
-        pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R */
-        pDataIn++;
-
-        /**************************************************************************
-                        WRITING THE OUTPUT
-        ***************************************************************************/
-        *pDataOut = ynLO; /* Write Left output*/
-        pDataOut++;
-        *pDataOut = ynRO; /* Write Right output*/
-        pDataOut++;
-    }
-}
-
-/**************************************************************************
 DELAYS-
 pBiquadState->pDelays[0] to
 pBiquadState->pDelays[NrChannels - 1] is x(n-1) for all NrChannels
@@ -173,3 +83,4 @@
         }
     }
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h
index 3f5d332..7fcd33c 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #ifndef _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_
 #define _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_
 
@@ -28,3 +29,4 @@
 typedef Filter_State* PFilter_State;
 
 #endif /* _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp
index 178d766..d782631 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #include "BIQUAD.h"
 #include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
 void PK_2I_D32F32CssGss_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t* pInstance,
@@ -31,3 +32,4 @@
 
     pBiquadState->coefs[3] = pCoef->G;
 }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
index 57a1c16..4c9f069 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#ifndef BIQUAD_OPT
 #ifndef _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_
 #define _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_
 
@@ -35,3 +36,4 @@
 typedef Filter_State* PFilter_State;
 
 #endif /* _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_ */
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/mult3s_16x16.cpp b/media/libeffects/lvm/lib/Common/src/mult3s_16x16.cpp
deleted file mode 100644
index 66f9132..0000000
--- a/media/libeffects/lvm/lib/Common/src/mult3s_16x16.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION MULT3S_16X16
-***********************************************************************************/
-
-void Mult3s_16x16(const LVM_INT16* src, const LVM_INT16 val, LVM_INT16* dst, LVM_INT16 n) {
-    LVM_INT16 ii;
-    LVM_INT32 temp;
-
-    for (ii = n; ii != 0; ii--) {
-        temp = (LVM_INT32)(*src) * (LVM_INT32)val;
-        src++;
-
-        *dst = (LVM_INT16)(temp >> 15);
-        dst++;
-    }
-
-    return;
-}
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
index bccbe86..f4e625f 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
@@ -21,6 +21,9 @@
 /*                                                                                      */
 /****************************************************************************************/
 
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
 #include "LVEQNB.h"
 #include "LVEQNB_Private.h"
 #include "VectorArithmetic.h"
@@ -179,6 +182,9 @@
     LVM_UINT16 i;                    /* Filter band index */
     LVEQNB_BiquadType_en BiquadType; /* Filter biquad type */
 
+#ifdef BIQUAD_OPT
+    pInstance->gain.resize(pInstance->Params.NBands);
+#endif
     /*
      * Set the coefficients for each band by the init function
      */
@@ -198,8 +204,19 @@
                 /*
                  * Set the coefficients
                  */
+#ifdef BIQUAD_OPT
+                pInstance->gain[i] = Coefficients.G;
+                std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                        Coefficients.A0, 0.0, -(Coefficients.A0), -(Coefficients.B1),
+                        -(Coefficients.B2)};
+                pInstance->eqBiquad[i]
+                        .setCoefficients<
+                                std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(
+                                coefs);
+#else
                 PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState_Float[i],
                                                    &pInstance->pEQNB_Taps_Float[i], &Coefficients);
+#endif
                 break;
             }
             default:
@@ -220,6 +237,11 @@
 /*                                                                                  */
 /************************************************************************************/
 void LVEQNB_ClearFilterHistory(LVEQNB_Instance_t* pInstance) {
+#ifdef BIQUAD_OPT
+    for (size_t i = 0; i < pInstance->eqBiquad.size(); i++) {
+        pInstance->eqBiquad[i].clear();
+    }
+#else
     LVM_FLOAT* pTapAddress;
     LVM_INT16 NumTaps;
 
@@ -233,6 +255,7 @@
                         pTapAddress, /* Destination */
                         NumTaps);    /* Number of words */
     }
+#endif
 }
 /****************************************************************************************/
 /*                                                                                      */
@@ -310,6 +333,16 @@
             (OperatingModeSave == LVEQNB_ON && pInstance->bInOperatingModeTransition &&
              LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0);
 
+#ifdef BIQUAD_OPT
+    /*
+     * Create biquad instance
+     */
+    pInstance->eqBiquad.resize(
+            pParams->NBands, android::audio_utils::BiquadFilter<LVM_FLOAT>(
+                                     (FCC_1 == pParams->NrChannels) ? FCC_2 : pParams->NrChannels));
+    LVEQNB_ClearFilterHistory(pInstance);
+#endif
+
     if (bChange || modeChange) {
         /*
          * If the sample rate has changed clear the history
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
index 1d2a5f5..57df4db 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
@@ -62,6 +62,9 @@
     pInstance->pScratch = pScratch;
 
     /* Equaliser Biquad Instance */
+#ifdef BIQUAD_OPT
+    LVM_UINT32 MemSize = pCapabilities->MaxBands * sizeof(*(pInstance->pBandDefinitions));
+#else
     LVM_UINT32 MemSize = pCapabilities->MaxBands * sizeof(*(pInstance->pEQNB_FilterState_Float));
     pInstance->pEQNB_FilterState_Float = (Biquad_FLOAT_Instance_t*)calloc(1, MemSize);
     if (pInstance->pEQNB_FilterState_Float == LVM_NULL) {
@@ -75,6 +78,7 @@
     }
 
     MemSize = (pCapabilities->MaxBands * sizeof(*(pInstance->pBandDefinitions)));
+#endif
     pInstance->pBandDefinitions = (LVEQNB_BandDef_t*)calloc(1, MemSize);
     if (pInstance->pBandDefinitions == LVM_NULL) {
         return LVEQNB_NULLADDRESS;
@@ -105,10 +109,11 @@
      */
     LVEQNB_SetFilters(pInstance, /* Set the filter types */
                       &pInstance->Params);
-
+#ifndef BIQUAD_OPT
     LVEQNB_SetCoefficients(pInstance); /* Set the filter coefficients */
 
     LVEQNB_ClearFilterHistory(pInstance); /* Clear the filter history */
+#endif
 
     /*
      * Initialise the bypass variables
@@ -154,6 +159,7 @@
     }
     pInstance = (LVEQNB_Instance_t*)*phInstance;
 
+#ifndef BIQUAD_OPT
     /* Equaliser Biquad Instance */
     if (pInstance->pEQNB_FilterState_Float != LVM_NULL) {
         free(pInstance->pEQNB_FilterState_Float);
@@ -163,6 +169,7 @@
         free(pInstance->pEQNB_Taps_Float);
         pInstance->pEQNB_Taps_Float = LVM_NULL;
     }
+#endif
     if (pInstance->pBandDefinitions != LVM_NULL) {
         free(pInstance->pBandDefinitions);
         pInstance->pBandDefinitions = LVM_NULL;
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
index 83a3449..32bad29 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
@@ -24,6 +24,9 @@
 /*                                                                                      */
 /****************************************************************************************/
 
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
 #include "LVEQNB.h" /* Calling or Application layer definitions */
 #include "BIQUAD.h"
 #include "LVC_Mixer.h"
@@ -69,8 +72,14 @@
     /* Aligned memory pointers */
     LVM_FLOAT* pFastTemporary; /* Fast temporary data base address */
 
+#ifdef BIQUAD_OPT
+    std::vector<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            eqBiquad;            /* Biquad filter instances */
+    std::vector<LVM_FLOAT> gain; /* Gain values for all bands*/
+#else
     Biquad_2I_Order2_FLOAT_Taps_t* pEQNB_Taps_Float;  /* Equaliser Taps */
     Biquad_FLOAT_Instance_t* pEQNB_FilterState_Float; /* State for each filter band */
+#endif
 
     /* Filter definitions and call back */
     LVM_UINT16 NBands;                  /* Number of bands */
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
index d2a26db..3f0be7c 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
@@ -104,19 +104,30 @@
                  * Check if band is non-zero dB gain
                  */
                 if (pInstance->pBandDefinitions[i].Gain != 0) {
+#ifndef BIQUAD_OPT
                     /*
                      * Get the address of the biquad instance
                      */
                     Biquad_FLOAT_Instance_t* pBiquad = &pInstance->pEQNB_FilterState_Float[i];
+#endif
 
                     /*
                      * Select single or double precision as required
                      */
                     switch (pInstance->pBiquadType[i]) {
                         case LVEQNB_SinglePrecision_Float: {
+#ifdef BIQUAD_OPT
+                            LVM_FLOAT* pTemp = pScratch + NrSamples;
+                            pInstance->eqBiquad[i].process(pTemp, pScratch, NrFrames);
+                            const auto gain = pInstance->gain[i];
+                            for (unsigned j = 0; j < NrSamples; ++j) {
+                                pScratch[j] += pTemp[j] * gain;
+                            }
+#else
                             PK_Mc_D32F32C14G11_TRC_WRA_01(pBiquad, pScratch, pScratch,
                                                           (LVM_INT16)NrFrames,
                                                           (LVM_INT16)NrChannels);
+#endif
                             break;
                         }
                         default:
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
index 737ef01..a744339 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
@@ -20,6 +20,10 @@
 /*  Includes                                                                            */
 /*                                                                                      */
 /****************************************************************************************/
+
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
 #include "LVREV_Private.h"
 #include "Filter.h"
 
@@ -71,10 +75,17 @@
 
         Omega = LVM_GetOmega(pPrivate->NewParams.HPF, pPrivate->NewParams.SampleRate);
         LVM_FO_HPF(Omega, &Coeffs);
+#ifdef BIQUAD_OPT
+        const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                Coeffs.A0, Coeffs.A1, 0.0, -(Coeffs.B1), 0.0};
+        pPrivate->pRevHPFBiquad.reset(
+                new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
         FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->HPCoefs, &pPrivate->pFastData->HPTaps,
                                         &Coeffs);
         LoadConst_Float(0, (LVM_FLOAT*)&pPrivate->pFastData->HPTaps,
                         sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
+#endif
     }
 
     /*
@@ -99,10 +110,17 @@
                 LVM_FO_LPF(Omega, &Coeffs);
             }
         }
+#ifdef BIQUAD_OPT
+        const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                Coeffs.A0, Coeffs.A1, 0.0, -(Coeffs.B1), 0.0};
+        pPrivate->pRevLPFBiquad.reset(
+                new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
         FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->LPCoefs, &pPrivate->pFastData->LPTaps,
                                         &Coeffs);
         LoadConst_Float(0, (LVM_FLOAT*)&pPrivate->pFastData->LPTaps,
                         sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
+#endif
     }
 
     /*
@@ -130,10 +148,6 @@
         LVM_INT16 i;
         LVM_FLOAT ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4,
                                   LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
-        LVM_INT16 MaxT_Delay[] = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, LVREV_MAX_T2_DELAY,
-                                  LVREV_MAX_T3_DELAY};
-        LVM_INT16 MaxAP_Delay[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY, LVREV_MAX_AP2_DELAY,
-                                   LVREV_MAX_AP3_DELAY};
 
         /*
          * For each delay line
@@ -153,7 +167,7 @@
              * Set the fixed delay
              */
 
-            Temp = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 192000;
+            Temp = (LVREV_MAX_T_DELAY[i] - LVREV_MAX_AP_DELAY[i]) * Fs / 192000;
             pPrivate->Delay_AP[i] = pPrivate->T[i] - Temp;
 
             /*
@@ -231,8 +245,15 @@
                 Coeffs.A1 = 0;
                 Coeffs.B1 = 0;
             }
+#ifdef BIQUAD_OPT
+            const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                    Coeffs.A0, Coeffs.A1, 0.0, -(Coeffs.B1), 0.0};
+            pPrivate->revLPFBiquad[i].reset(
+                    new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
             FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->RevLPCoefs[i],
                                             &pPrivate->pFastData->RevLPTaps[i], &Coeffs);
+#endif
         }
     }
 
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
index 5c83ce5..61b3732 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
@@ -56,31 +56,20 @@
      * Clear all filter tap data, delay-lines and other signal related data
      */
 
+#ifdef BIQUAD_OPT
+    pLVREV_Private->pRevHPFBiquad->clear();
+    pLVREV_Private->pRevLPFBiquad->clear();
+#else
     LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->HPTaps, 2);
     LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->LPTaps, 2);
-    if ((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays == LVREV_DELAYLINES_4) {
-        LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[3], 2);
-        LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[2], 2);
-        LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
-        LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[3], LVREV_MAX_T3_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[2], LVREV_MAX_T2_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
-    }
-
-    if ((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_2) {
-        LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
-        LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
-    }
-
-    if ((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_1) {
-        LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
+#endif
+    for (size_t i = 0; i < pLVREV_Private->InstanceParams.NumDelays; i++) {
+#ifdef BIQUAD_OPT
+        pLVREV_Private->revLPFBiquad[i]->clear();
+#else
+        LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[i], 2);
+#endif
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[i], LVREV_MAX_T_DELAY[i]);
     }
     return LVREV_SUCCESS;
 }
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
index b5db23b..fa96e52 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
@@ -120,11 +120,11 @@
     pLVREV_Private->MemoryTable = *pMemoryTable;
 
     if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
-        MaxBlockSize = LVREV_MAX_AP3_DELAY;
+        MaxBlockSize = LVREV_MAX_AP_DELAY[3];
     } else if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
-        MaxBlockSize = LVREV_MAX_AP1_DELAY;
+        MaxBlockSize = LVREV_MAX_AP_DELAY[1];
     } else {
-        MaxBlockSize = LVREV_MAX_AP0_DELAY;
+        MaxBlockSize = LVREV_MAX_AP_DELAY[0];
     }
 
     if (MaxBlockSize > pInstanceParams->MaxBlockSize) {
@@ -134,69 +134,30 @@
     /*
      * Set the data, coefficient and temporary memory pointers
      */
+#ifndef BIQUAD_OPT
     /* Fast data memory base address */
     pLVREV_Private->pFastData =
             (LVREV_FastData_st*)InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
-    if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
-        pLVREV_Private->pDelay_T[3] =
-                (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_FLOAT));
-        pLVREV_Private->pDelay_T[2] =
-                (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_FLOAT));
-        pLVREV_Private->pDelay_T[1] =
-                (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
-        pLVREV_Private->pDelay_T[0] =
-                (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-
-        for (i = 0; i < 4; i++) {
-            /* Scratch for each delay line output */
-            pLVREV_Private->pScratchDelayLine[i] =
-                    (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
-        }
-
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[3], LVREV_MAX_T3_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[2], LVREV_MAX_T2_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
-    }
-
-    if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
-        pLVREV_Private->pDelay_T[1] =
-                (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
-        pLVREV_Private->pDelay_T[0] =
-                (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-
-        for (i = 0; i < 2; i++) {
-            /* Scratch for each delay line output */
-            pLVREV_Private->pScratchDelayLine[i] =
-                    (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
-        }
-
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
-    }
-
-    if (pInstanceParams->NumDelays == LVREV_DELAYLINES_1) {
-        pLVREV_Private->pDelay_T[0] =
-                (LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-
-        for (i = 0; i < 1; i++) {
-            /* Scratch for each delay line output */
-            pLVREV_Private->pScratchDelayLine[i] =
-                    (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
-        }
-
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+#endif
+    for (size_t i = 0; i < pInstanceParams->NumDelays; i++) {
+        pLVREV_Private->pDelay_T[i] = (LVM_FLOAT*)InstAlloc_AddMember(
+                &FastData, LVREV_MAX_T_DELAY[i] * sizeof(LVM_FLOAT));
+        /* Scratch for each delay line output */
+        pLVREV_Private->pScratchDelayLine[i] =
+                (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[i], LVREV_MAX_T_DELAY[i]);
     }
     /* All-pass delay buffer addresses and sizes */
-    pLVREV_Private->T[0] = LVREV_MAX_T0_DELAY;
-    pLVREV_Private->T[1] = LVREV_MAX_T1_DELAY;
-    pLVREV_Private->T[2] = LVREV_MAX_T2_DELAY;
-    pLVREV_Private->T[3] = LVREV_MAX_T3_DELAY;
+    for (size_t i = 0; i < LVREV_DELAYLINES_4; i++) {
+        pLVREV_Private->T[i] = LVREV_MAX_T_DELAY[i];
+    }
     pLVREV_Private->AB_Selection = 1; /* Select smoothing A to B */
 
+#ifndef BIQUAD_OPT
     /* Fast coefficient memory base address */
     pLVREV_Private->pFastCoef =
             (LVREV_FastCoef_st*)InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));
+#endif
     /* General purpose scratch */
     pLVREV_Private->pScratch =
             (LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
@@ -299,14 +260,21 @@
         pLVREV_Private->FeedbackMixer[i].Target = 0;
     }
     /* Delay tap index */
-    pLVREV_Private->A_DelaySize[0] = LVREV_MAX_AP0_DELAY;
-    pLVREV_Private->B_DelaySize[0] = LVREV_MAX_AP0_DELAY;
-    pLVREV_Private->A_DelaySize[1] = LVREV_MAX_AP1_DELAY;
-    pLVREV_Private->B_DelaySize[1] = LVREV_MAX_AP1_DELAY;
-    pLVREV_Private->A_DelaySize[2] = LVREV_MAX_AP2_DELAY;
-    pLVREV_Private->B_DelaySize[2] = LVREV_MAX_AP2_DELAY;
-    pLVREV_Private->A_DelaySize[3] = LVREV_MAX_AP3_DELAY;
-    pLVREV_Private->B_DelaySize[3] = LVREV_MAX_AP3_DELAY;
+    for (size_t i = 0; i < LVREV_DELAYLINES_4; i++) {
+        pLVREV_Private->A_DelaySize[i] = LVREV_MAX_AP_DELAY[i];
+        pLVREV_Private->B_DelaySize[i] = LVREV_MAX_AP_DELAY[i];
+    }
+
+#ifdef BIQUAD_OPT
+    pLVREV_Private->pRevHPFBiquad.reset(
+            new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+    pLVREV_Private->pRevLPFBiquad.reset(
+            new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+    for (int i = 0; i < LVREV_DELAYLINES_4; i++) {
+        pLVREV_Private->revLPFBiquad[i].reset(
+                new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+    }
+#endif
 
     LVREV_ClearAudioBuffers(*phInstance);
 
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
index 2c1e04d..b344b20 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
@@ -63,7 +63,6 @@
     INST_ALLOC FastData;
     INST_ALLOC FastCoef;
     INST_ALLOC Temporary;
-    LVM_INT16 i;
     LVM_UINT16 MaxBlockSize;
 
     /*
@@ -117,11 +116,11 @@
          * Select the maximum internal block size
          */
         if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
-            MaxBlockSize = LVREV_MAX_AP3_DELAY;
+            MaxBlockSize = LVREV_MAX_AP_DELAY[3];
         } else if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
-            MaxBlockSize = LVREV_MAX_AP1_DELAY;
+            MaxBlockSize = LVREV_MAX_AP_DELAY[1];
         } else {
-            MaxBlockSize = LVREV_MAX_AP0_DELAY;
+            MaxBlockSize = LVREV_MAX_AP_DELAY[0];
         }
 
         if (MaxBlockSize > pInstanceParams->MaxBlockSize) {
@@ -139,21 +138,11 @@
         /*
          * Persistent fast data memory
          */
+#ifndef BIQUAD_OPT
         InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
-        if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_FLOAT));
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_FLOAT));
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-        }
-
-        if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-        }
-
-        if (pInstanceParams->NumDelays == LVREV_DELAYLINES_1) {
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
+#endif
+        for (size_t i = 0; i < pInstanceParams->NumDelays; i++) {
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T_DELAY[i] * sizeof(LVM_FLOAT));
         }
 
         pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size = InstAlloc_GetTotal(&FastData);
@@ -163,7 +152,9 @@
         /*
          * Persistent fast coefficient memory
          */
+#ifndef BIQUAD_OPT
         InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));
+#endif
         pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size = InstAlloc_GetTotal(&FastCoef);
         pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Type = LVM_PERSISTENT_FAST_COEF;
         pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
@@ -175,25 +166,9 @@
         InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
         /* Mono->stereo input saved for end mix */
         InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_FLOAT) * MaxBlockSize);
-        if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
-            for (i = 0; i < 4; i++) {
-                /* A Scratch buffer for each delay line */
-                InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
-            }
-        }
-
-        if (pInstanceParams->NumDelays == LVREV_DELAYLINES_2) {
-            for (i = 0; i < 2; i++) {
-                /* A Scratch buffer for each delay line */
-                InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
-            }
-        }
-
-        if (pInstanceParams->NumDelays == LVREV_DELAYLINES_1) {
-            for (i = 0; i < 1; i++) {
-                /* A Scratch buffer for each delay line */
-                InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
-            }
+        for (size_t i = 0; i < pInstanceParams->NumDelays; i++) {
+            /* A Scratch buffer for each delay line */
+            InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
         }
 
         pMemoryTable->Region[LVM_TEMPORARY_FAST].Size = InstAlloc_GetTotal(&Temporary);
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
index b6edb03..c62ad1e 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
@@ -23,6 +23,10 @@
 /*  Includes                                                                            */
 /*                                                                                      */
 /****************************************************************************************/
+
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
 #include "LVREV.h"
 #include "LVREV_Tables.h"
 #include "BIQUAD.h"
@@ -101,21 +105,23 @@
 /*                                                                                      */
 /****************************************************************************************/
 
+#ifndef BIQUAD_OPT
 /* Fast data structure */
 typedef struct {
     Biquad_1I_Order1_FLOAT_Taps_t HPTaps;       /* High pass filter taps */
     Biquad_1I_Order1_FLOAT_Taps_t LPTaps;       /* Low pass filter taps */
-    Biquad_1I_Order1_FLOAT_Taps_t RevLPTaps[4]; /* Reverb low pass filters taps */
-
+    Biquad_1I_Order1_FLOAT_Taps_t RevLPTaps[LVREV_DELAYLINES_4]; /* Reverb low pass filters taps */
 } LVREV_FastData_st;
 
 /* Fast coefficient structure */
 typedef struct {
     Biquad_FLOAT_Instance_t HPCoefs;       /* High pass filter coefficients */
     Biquad_FLOAT_Instance_t LPCoefs;       /* Low pass filter coefficients */
-    Biquad_FLOAT_Instance_t RevLPCoefs[4]; /* Reverb low pass filters coefficients */
-
+    Biquad_FLOAT_Instance_t
+            RevLPCoefs[LVREV_DELAYLINES_4]; /* Reverb low pass filters coefficients */
 } LVREV_FastCoef_st;
+#endif
+
 typedef struct {
     /* General */
     LVREV_InstanceParams_st InstanceParams; /* Initialisation time instance parameters */
@@ -134,30 +140,39 @@
                                                processing */
 
     /* Aligned memory pointers */
-    LVREV_FastData_st* pFastData;    /* Fast data memory base address */
-    LVREV_FastCoef_st* pFastCoef;    /* Fast coefficient memory base address */
-    LVM_FLOAT* pScratchDelayLine[4]; /* Delay line scratch memory */
+#ifdef BIQUAD_OPT
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pRevHPFBiquad; /* Biquad filter instance for HPF */
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pRevLPFBiquad; /* Biquad filter instance for LPF */
+    std::array<std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>, LVREV_DELAYLINES_4>
+            revLPFBiquad; /* Biquad filter instance for Reverb LPF */
+#else
+    LVREV_FastData_st* pFastData; /* Fast data memory base address */
+    LVREV_FastCoef_st* pFastCoef; /* Fast coefficient memory base address */
+#endif
+    LVM_FLOAT* pScratchDelayLine[LVREV_DELAYLINES_4]; /* Delay line scratch memory */
     LVM_FLOAT* pScratch;             /* Multi ussge scratch */
     LVM_FLOAT* pInputSave;           /* Reverb block input save for dry/wet
                                         mixing*/
 
     /* Feedback matrix */
-    Mix_1St_Cll_FLOAT_t FeedbackMixer[4]; /* Mixer for Pop and Click Suppression \
+    Mix_1St_Cll_FLOAT_t FeedbackMixer[LVREV_DELAYLINES_4]; /* Mixer for Pop and Click Suppression \
                                              caused by feedback Gain */
 
     /* All-Pass Filter */
-    LVM_INT32 T[4];                             /* Maximum delay size of buffer */
-    LVM_FLOAT* pDelay_T[4];                     /* Pointer to delay buffers */
-    LVM_INT32 Delay_AP[4];                      /* Offset to AP delay buffer start */
+    LVM_INT32 T[LVREV_DELAYLINES_4];                          /* Maximum delay size of buffer */
+    LVM_FLOAT* pDelay_T[LVREV_DELAYLINES_4];                  /* Pointer to delay buffers */
+    LVM_INT32 Delay_AP[LVREV_DELAYLINES_4];                   /* Offset to AP delay buffer start */
     LVM_INT16 AB_Selection;                     /* Smooth from tap A to B when 1 \
                                                    otherwise B to A */
-    LVM_INT32 A_DelaySize[4];                   /* A delay length in samples */
-    LVM_INT32 B_DelaySize[4];                   /* B delay length in samples */
-    LVM_FLOAT* pOffsetA[4];                     /* Offset for the A delay tap */
-    LVM_FLOAT* pOffsetB[4];                     /* Offset for the B delay tap */
-    Mix_2St_Cll_FLOAT_t Mixer_APTaps[4];        /* Smoothed AP delay mixer */
-    Mix_1St_Cll_FLOAT_t Mixer_SGFeedback[4];    /* Smoothed SAfeedback gain */
-    Mix_1St_Cll_FLOAT_t Mixer_SGFeedforward[4]; /* Smoothed AP feedforward gain */
+    LVM_INT32 A_DelaySize[LVREV_DELAYLINES_4];                /* A delay length in samples */
+    LVM_INT32 B_DelaySize[LVREV_DELAYLINES_4];                /* B delay length in samples */
+    LVM_FLOAT* pOffsetA[LVREV_DELAYLINES_4];                  /* Offset for the A delay tap */
+    LVM_FLOAT* pOffsetB[LVREV_DELAYLINES_4];                  /* Offset for the B delay tap */
+    Mix_2St_Cll_FLOAT_t Mixer_APTaps[LVREV_DELAYLINES_4];     /* Smoothed AP delay mixer */
+    Mix_1St_Cll_FLOAT_t Mixer_SGFeedback[LVREV_DELAYLINES_4]; /* Smoothed SAfeedback gain */
+    Mix_1St_Cll_FLOAT_t Mixer_SGFeedforward[LVREV_DELAYLINES_4]; /* Smoothed AP feedforward gain */
 
     /* Output gain */
     Mix_2St_Cll_FLOAT_t BypassMixer; /* Dry/wet mixer */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
index ed3b89c..e4f939f 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
@@ -204,11 +204,20 @@
     /*
      *  High pass filter
      */
+#ifdef BIQUAD_OPT
+    pPrivate->pRevHPFBiquad->process(pTemp, pTemp, NumSamples);
+#else
     FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->HPCoefs, pTemp, pTemp, (LVM_INT16)NumSamples);
+#endif
+
     /*
      *  Low pass filter
      */
+#ifdef BIQUAD_OPT
+    pPrivate->pRevLPFBiquad->process(pTemp, pTemp, NumSamples);
+#else
     FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->LPCoefs, pTemp, pTemp, (LVM_INT16)NumSamples);
+#endif
 
     /*
      *  Process all delay lines
@@ -253,8 +262,12 @@
         /*
          *  Low pass filter
          */
+#ifdef BIQUAD_OPT
+        pPrivate->revLPFBiquad[j]->process(pDelayLine, pDelayLine, NumSamples);
+#else
         FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->RevLPCoefs[j], pDelayLine, pDelayLine,
                                    (LVM_INT16)NumSamples);
+#endif
     }
 
     /*
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp
index 35a6522..bb6cf12 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp
@@ -29,6 +29,11 @@
 /*                                                                                      */
 /****************************************************************************************/
 
+const LVM_INT16 LVREV_MAX_T_DELAY[] = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, LVREV_MAX_T2_DELAY,
+                                       LVREV_MAX_T3_DELAY};
+const LVM_INT16 LVREV_MAX_AP_DELAY[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY,
+                                        LVREV_MAX_AP2_DELAY, LVREV_MAX_AP3_DELAY};
+
 /* Table with supported sampling rates.  The table can be indexed using LVM_Fs_en       */
 const LVM_UINT32 LVM_FsTable[] = {8000,  11025, 12000, 16000, 22050,  24000, 32000,
                                   44100, 48000, 88200, 96000, 176400, 192000};
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
index 4b0dcca..723d1ff 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
@@ -35,6 +35,8 @@
 extern LVM_UINT32 LVM_GetFsFromTable(LVM_Fs_en FsIndex);
 
 extern const LVM_FLOAT LVREV_GainPolyTable[24][5];
+extern const LVM_INT16 LVREV_MAX_T_DELAY[];
+extern const LVM_INT16 LVREV_MAX_AP_DELAY[];
 
 #endif /** _LVREV_TABLES_H_ **/
 
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp
index 4e90a42..436e7cb 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp
@@ -15,6 +15,9 @@
  * limitations under the License.
  */
 
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
 #include "LVPSA.h"
 #include "LVPSA_Private.h"
 #include "VectorArithmetic.h"
@@ -182,6 +185,13 @@
                 break;
             }
         }
+#ifdef BIQUAD_OPT
+        /*
+         * Create biquad instance
+         */
+        pInst->specBiquad.resize(pInst->nRelevantFilters,
+                                 android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1));
+#endif
         LVPSA_SetBPFiltersType(pInst, &Params);
         LVPSA_SetBPFCoefficients(pInst, &Params);
         LVPSA_SetQPFCoefficients(pInst, &Params);
@@ -302,8 +312,18 @@
                 /*
                  * Set the coefficients
                  */
+#ifdef BIQUAD_OPT
+                const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                        Coefficients.A0, 0.0, -(Coefficients.A0), -(Coefficients.B1),
+                        -(Coefficients.B2)};
+                pInst->specBiquad[ii]
+                        .setCoefficients<
+                                std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(
+                                coefs);
+#else
                 BP_1I_D16F32Cll_TRC_WRA_01_Init(&pInst->pBP_Instances[ii], &pInst->pBP_Taps[ii],
                                                 &Coefficients);
+#endif
                 break;
             }
 
@@ -319,8 +339,18 @@
                 /*
                  * Set the coefficients
                  */
+#ifdef BIQUAD_OPT
+                const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                        Coefficients.A0, 0.0, -(Coefficients.A0), -(Coefficients.B1),
+                        -(Coefficients.B2)};
+                pInst->specBiquad[ii]
+                        .setCoefficients<
+                                std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(
+                                coefs);
+#else
                 BP_1I_D16F16Css_TRC_WRA_01_Init(&pInst->pBP_Instances[ii], &pInst->pBP_Taps[ii],
                                                 &Coefficients);
+#endif
                 break;
             }
         }
@@ -604,6 +634,11 @@
 /*                                                                                  */
 /************************************************************************************/
 LVPSA_RETURN LVPSA_ClearFilterHistory(LVPSA_InstancePr_t* pInst) {
+#ifdef BIQUAD_OPT
+    for (size_t i = 0; i < pInst->specBiquad.size(); i++) {
+        pInst->specBiquad[i].clear();
+    }
+#else
     LVM_INT8* pTapAddress;
     LVM_UINT32 i;
 
@@ -617,6 +652,7 @@
     for (i = 0; i < pInst->nBands * sizeof(QPD_Taps_t); i++) {
         pTapAddress[i] = 0;
     }
+#endif
 
     return (LVPSA_OK);
 }
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp
index 9a2b29f..f77460b 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp
@@ -108,21 +108,25 @@
     if (pLVPSA_Inst->pBPFiltersPrecision == LVM_NULL) {
         return LVPSA_ERROR_NULLADDRESS;
     }
+#ifndef BIQUAD_OPT
     pLVPSA_Inst->pBP_Instances = (Biquad_FLOAT_Instance_t*)calloc(
             pInitParams->nBands, sizeof(*(pLVPSA_Inst->pBP_Instances)));
     if (pLVPSA_Inst->pBP_Instances == LVM_NULL) {
         return LVPSA_ERROR_NULLADDRESS;
     }
+#endif
     pLVPSA_Inst->pQPD_States =
             (QPD_FLOAT_State_t*)calloc(pInitParams->nBands, sizeof(*(pLVPSA_Inst->pQPD_States)));
     if (pLVPSA_Inst->pQPD_States == LVM_NULL) {
         return LVPSA_ERROR_NULLADDRESS;
     }
+#ifndef BIQUAD_OPT
     pLVPSA_Inst->pBP_Taps = (Biquad_1I_Order2_FLOAT_Taps_t*)calloc(
             pInitParams->nBands, sizeof(*(pLVPSA_Inst->pBP_Taps)));
     if (pLVPSA_Inst->pBP_Taps == LVM_NULL) {
         return LVPSA_ERROR_NULLADDRESS;
     }
+#endif
     pLVPSA_Inst->pQPD_Taps =
             (QPD_FLOAT_Taps_t*)calloc(pInitParams->nBands, sizeof(*(pLVPSA_Inst->pQPD_Taps)));
     if (pLVPSA_Inst->pQPD_Taps == LVM_NULL) {
@@ -193,18 +197,22 @@
         free(pLVPSA_Inst->pBPFiltersPrecision);
         pLVPSA_Inst->pBPFiltersPrecision = LVM_NULL;
     }
+#ifndef BIQUAD_OPT
     if (pLVPSA_Inst->pBP_Instances != LVM_NULL) {
         free(pLVPSA_Inst->pBP_Instances);
         pLVPSA_Inst->pBP_Instances = LVM_NULL;
     }
+#endif
     if (pLVPSA_Inst->pQPD_States != LVM_NULL) {
         free(pLVPSA_Inst->pQPD_States);
         pLVPSA_Inst->pQPD_States = LVM_NULL;
     }
+#ifndef BIQUAD_OPT
     if (pLVPSA_Inst->pBP_Taps != LVM_NULL) {
         free(pLVPSA_Inst->pBP_Taps);
         pLVPSA_Inst->pBP_Taps = LVM_NULL;
     }
+#endif
     if (pLVPSA_Inst->pQPD_Taps != LVM_NULL) {
         free(pLVPSA_Inst->pQPD_Taps);
         pLVPSA_Inst->pQPD_Taps = LVM_NULL;
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
index e00c11c..553156f 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
@@ -18,6 +18,9 @@
 #ifndef _LVPSA_PRIVATE_H_
 #define _LVPSA_PRIVATE_H_
 
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
 #include "LVPSA.h"
 #include "BIQUAD.h"
 #include "LVPSA_QPD.h"
@@ -82,9 +85,14 @@
 
     LVPSA_BPFilterPrecision_en* pBPFiltersPrecision; /* Points a nBands elements array that contains
                                                         the filter precision for each band */
+#ifdef BIQUAD_OPT
+    std::vector<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            specBiquad; /* Biquad filter instances */
+#else
     Biquad_FLOAT_Instance_t* pBP_Instances;
     /* Points a nBands elements array that contains the band pass filter taps for each band */
     Biquad_1I_Order2_FLOAT_Taps_t* pBP_Taps;
+#endif
     /* Points a nBands elements array that contains the QPD filter instance for each band */
     QPD_FLOAT_State_t* pQPD_States;
     /* Points a nBands elements array that contains the QPD filter taps for each band */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp
index 299dfd2..148b21f 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp
@@ -96,13 +96,23 @@
     for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++) {
         switch (pLVPSA_Inst->pBPFiltersPrecision[ii]) {
             case LVPSA_SimplePrecisionFilter:
+#ifdef BIQUAD_OPT
+                pLVPSA_Inst->specBiquad[ii].process(pScratch + InputBlockSize, pScratch,
+                                                    (LVM_INT16)InputBlockSize);
+#else
                 BP_1I_D16F16C14_TRC_WRA_01(&pLVPSA_Inst->pBP_Instances[ii], pScratch,
                                            pScratch + InputBlockSize, (LVM_INT16)InputBlockSize);
+#endif
                 break;
 
             case LVPSA_DoublePrecisionFilter:
+#ifdef BIQUAD_OPT
+                pLVPSA_Inst->specBiquad[ii].process(pScratch + InputBlockSize, pScratch,
+                                                    (LVM_INT16)InputBlockSize);
+#else
                 BP_1I_D16F32C30_TRC_WRA_01(&pLVPSA_Inst->pBP_Instances[ii], pScratch,
                                            pScratch + InputBlockSize, (LVM_INT16)InputBlockSize);
+#endif
                 break;
             default:
                 break;
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
index bad9aef..a5952fb 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
@@ -21,6 +21,9 @@
 /*                                                                                  */
 /************************************************************************************/
 
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
 #include "LVCS.h"
 #include "LVCS_Private.h"
 #include "LVCS_Equaliser.h"
@@ -56,14 +59,18 @@
 LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t hInstance, LVCS_Params_t* pParams) {
     LVM_UINT16 Offset;
     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
+#ifndef BIQUAD_OPT
     LVCS_Equaliser_t* pConfig = (LVCS_Equaliser_t*)&pInstance->Equaliser;
     LVCS_Data_t* pData;
     LVCS_Coefficient_t* pCoefficients;
     BQ_FLOAT_Coefs_t Coeffs;
+#endif
     const BiquadA012B12CoefsSP_t* pEqualiserCoefTable;
 
+#ifndef BIQUAD_OPT
     pData = (LVCS_Data_t*)pInstance->pData;
     pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
     /*
      * If the sample rate changes re-initialise the filters
      */
@@ -75,6 +82,13 @@
         Offset = (LVM_UINT16)(pParams->SampleRate + (pParams->SpeakerType * (1 + LVM_FS_48000)));
         pEqualiserCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_EqualiserCoefTable[0];
 
+#ifdef BIQUAD_OPT
+        std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                pEqualiserCoefTable[Offset].A0, pEqualiserCoefTable[Offset].A1,
+                pEqualiserCoefTable[Offset].A2, -(pEqualiserCoefTable[Offset].B1),
+                -(pEqualiserCoefTable[Offset].B2)};
+        pInstance->pEqBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_2, coefs));
+#else
         /* Left and right filters */
         /* Convert incoming coefficients to the required format/ordering */
         Coeffs.A0 = (LVM_FLOAT)pEqualiserCoefTable[Offset].A0;
@@ -103,6 +117,7 @@
                 pConfig->pBiquadCallBack = BQ_2I_D16F32C15_TRC_WRA_01;
                 break;
         }
+#endif
     }
 
     return (LVCS_SUCCESS);
@@ -129,19 +144,25 @@
 LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t hInstance, LVM_FLOAT* pInputOutput,
                                     LVM_UINT16 NumSamples) {
     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
+#ifndef BIQUAD_OPT
     LVCS_Equaliser_t* pConfig = (LVCS_Equaliser_t*)&pInstance->Equaliser;
     LVCS_Coefficient_t* pCoefficients;
 
     pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
 
     /*
      * Check if the equaliser is required
      */
     if ((pInstance->Params.OperatingMode & LVCS_EQUALISERSWITCH) != 0) {
         /* Apply filter to the left and right channels */
+#ifdef BIQUAD_OPT
+        pInstance->pEqBiquad->process(pInputOutput, pInputOutput, NumSamples);
+#else
         (pConfig->pBiquadCallBack)(
                 (Biquad_FLOAT_Instance_t*)&pCoefficients->EqualiserBiquadInstance,
                 (LVM_FLOAT*)pInputOutput, (LVM_FLOAT*)pInputOutput, (LVM_INT16)NumSamples);
+#endif
     }
 
     return (LVCS_SUCCESS);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
index c0d0950..18b350d 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
@@ -23,12 +23,12 @@
 /*    Structures                                                                    */
 /*                                                                                  */
 /************************************************************************************/
-
+#ifndef BIQUAD_OPT
 /* Equaliser structure */
 typedef struct {
     void (*pBiquadCallBack)(Biquad_FLOAT_Instance_t*, LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
 } LVCS_Equaliser_t;
-
+#endif
 /************************************************************************************/
 /*                                                                                  */
 /*    Function prototypes                                                           */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
index 5c8f1ae..f23261f 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
@@ -123,6 +123,7 @@
     if (pInstance == LVM_NULL) {
         return;
     }
+#ifndef BIQUAD_OPT
     if (pInstance->pCoeff != LVM_NULL) {
         free(pInstance->pCoeff);
         pInstance->pCoeff = LVM_NULL;
@@ -131,6 +132,7 @@
         free(pInstance->pData);
         pInstance->pData = LVM_NULL;
     }
+#endif
     free(pInstance);
     *phInstance = LVM_NULL;
     return;
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
index f9c23b3..605a204 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
@@ -33,6 +33,9 @@
 /*                                                                                  */
 /************************************************************************************/
 
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
 #include "LVCS.h"                 /* Calling or Application layer definitions */
 #include "LVCS_StereoEnhancer.h"  /* Stereo enhancer module definitions */
 #include "LVCS_ReverbGenerator.h" /* Reverberation module definitions */
@@ -110,7 +113,9 @@
     /* Sub-block configurations */
     LVCS_StereoEnhancer_t StereoEnhancer; /* Stereo enhancer configuration */
     LVCS_ReverbGenerator_t Reverberation; /* Reverberation configuration */
+#ifndef BIQUAD_OPT
     LVCS_Equaliser_t Equaliser;           /* Equaliser configuration */
+#endif
     LVCS_BypassMix_t BypassMix;           /* Bypass mixer configuration */
 
     /* Bypass variable */
@@ -120,12 +125,24 @@
     LVM_INT16 bTimerDone;                 /* Timer completion flag */
     LVM_Timer_Params_t TimerParams;       /* Timer parameters */
     LVM_Timer_Instance_t TimerInstance;   /* Timer instance */
+#ifdef BIQUAD_OPT
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pEqBiquad; /* Biquad filter instance for Equaliser */
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pRevBiquad; /* Biquad filter instance for Reverberation */
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pSEMidBiquad; /* Biquad filter instance for Stereo enhancement mid */
+    std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+            pSESideBiquad; /* Biquad filter instance for Stereo enhancement side */
+#else
     void* pCoeff;                         /* pointer to buffer for equaliser filter coeffs */
     void* pData;                          /* pointer to buffer for equaliser filter states */
+#endif
     void* pScratch;                       /* Pointer to bundle scratch buffer */
 
 } LVCS_Instance_t;
 
+#ifndef BIQUAD_OPT
 /* Coefficient Structure */
 typedef struct {
     Biquad_FLOAT_Instance_t EqualiserBiquadInstance;
@@ -141,6 +158,7 @@
     Biquad_1I_Order1_FLOAT_Taps_t SEBiquadTapsMid;
     Biquad_1I_Order2_FLOAT_Taps_t SEBiquadTapsSide;
 } LVCS_Data_t;
+#endif
 
 void LVCS_TimerCallBack(void* hInstance, void* pCallBackParams, LVM_INT32 CallbackParam);
 
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
index f6d2453..82a3a43 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
@@ -20,6 +20,9 @@
 /*  Includes                                                                        */
 /*                                                                                  */
 /************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
 #include <stdlib.h>
 #include "LVCS.h"
 #include "LVCS_Private.h"
@@ -62,11 +65,14 @@
     LVM_UINT16 Offset;
     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
     LVCS_ReverbGenerator_t* pConfig = (LVCS_ReverbGenerator_t*)&pInstance->Reverberation;
+#ifndef BIQUAD_OPT
     LVCS_Data_t* pData;
     LVCS_Coefficient_t* pCoefficients;
     BQ_FLOAT_Coefs_t Coeffs;
+#endif
     const BiquadA012B12CoefsSP_t* pReverbCoefTable;
 
+#ifndef BIQUAD_OPT
     if (pInstance->pData == LVM_NULL) {
         pInstance->pData = pData = (LVCS_Data_t*)calloc(1, sizeof(*pData));
         if (pData == LVM_NULL) {
@@ -83,6 +89,7 @@
     } else {
         pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
     }
+#endif
 
     /*
      * Initialise the delay and filters if:
@@ -109,6 +116,14 @@
         Offset = (LVM_UINT16)pParams->SampleRate;
         pReverbCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_ReverbCoefTable[0];
 
+#ifdef BIQUAD_OPT
+        std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                pReverbCoefTable[Offset].A0, pReverbCoefTable[Offset].A1,
+                pReverbCoefTable[Offset].A2, -(pReverbCoefTable[Offset].B1),
+                -(pReverbCoefTable[Offset].B2)};
+        pInstance->pRevBiquad.reset(
+                new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_2, coefs));
+#else
         /* Convert incoming coefficients to the required format/ordering */
         Coeffs.A0 = (LVM_FLOAT)pReverbCoefTable[Offset].A0;
         Coeffs.A1 = (LVM_FLOAT)pReverbCoefTable[Offset].A1;
@@ -133,6 +148,7 @@
                 pConfig->pBiquadCallBack = BQ_2I_D16F16C15_TRC_WRA_01;
                 break;
         }
+#endif
 
         /*
          * Setup the mixer
@@ -190,10 +206,14 @@
                                           LVM_FLOAT* pOutData, LVM_UINT16 NumSamples) {
     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
     LVCS_ReverbGenerator_t* pConfig = (LVCS_ReverbGenerator_t*)&pInstance->Reverberation;
+#ifndef BIQUAD_OPT
     LVCS_Coefficient_t* pCoefficients;
+#endif
     LVM_FLOAT* pScratch;
 
+#ifndef BIQUAD_OPT
     pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
     pScratch = (LVM_FLOAT*)pInstance->pScratch;
 
     /*
@@ -233,9 +253,13 @@
         /*
          * Filter the data
          */
+#ifdef BIQUAD_OPT
+        pInstance->pRevBiquad->process(pScratch, pScratch, NumSamples);
+#else
         (pConfig->pBiquadCallBack)((Biquad_FLOAT_Instance_t*)&pCoefficients->ReverbBiquadInstance,
                                    (LVM_FLOAT*)pScratch, (LVM_FLOAT*)pScratch,
                                    (LVM_INT16)NumSamples);
+#endif
 
         Mult3s_Float((LVM_FLOAT*)pScratch, pConfig->ReverbLevel, (LVM_FLOAT*)pScratch,
                      (LVM_INT16)(2 * NumSamples));
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
index b666da3..a200267 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
@@ -51,8 +51,10 @@
     LVM_FLOAT StereoSamples[2 * LVCS_STEREODELAY_CS_MAX_VAL];
     /* Reverb Level */
     LVM_FLOAT ReverbLevel;
+#ifndef BIQUAD_OPT
     /* Filter */
     void (*pBiquadCallBack)(Biquad_FLOAT_Instance_t*, LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
+#endif
 } LVCS_ReverbGenerator_t;
 
 /************************************************************************************/
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
index ffa9c9b..0e488f5 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
@@ -21,6 +21,9 @@
 /*                                                                                  */
 /************************************************************************************/
 
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
 #include "LVCS.h"
 #include "LVCS_Private.h"
 #include "LVCS_StereoEnhancer.h"
@@ -52,15 +55,19 @@
 LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t hInstance, LVCS_Params_t* pParams) {
     LVM_UINT16 Offset;
     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
+#ifndef BIQUAD_OPT
     LVCS_StereoEnhancer_t* pConfig = (LVCS_StereoEnhancer_t*)&pInstance->StereoEnhancer;
     LVCS_Data_t* pData;
     LVCS_Coefficient_t* pCoefficient;
     FO_FLOAT_Coefs_t CoeffsMid;
     BQ_FLOAT_Coefs_t CoeffsSide;
+#endif
     const BiquadA012B12CoefsSP_t* pSESideCoefs;
 
+#ifndef BIQUAD_OPT
     pData = (LVCS_Data_t*)pInstance->pData;
     pCoefficient = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
 
     /*
      * If the sample rate or speaker type has changed update the filters
@@ -73,6 +80,13 @@
         /* Mid filter */
         Offset = (LVM_UINT16)pParams->SampleRate;
 
+#ifdef BIQUAD_OPT
+        std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+                LVCS_SEMidCoefTable[Offset].A0, LVCS_SEMidCoefTable[Offset].A1, 0.0,
+                -(LVCS_SEMidCoefTable[Offset].B1), 0.0};
+        pInstance->pSEMidBiquad.reset(
+                new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
         /* Convert incoming coefficients to the required format/ordering */
         CoeffsMid.A0 = (LVM_FLOAT)LVCS_SEMidCoefTable[Offset].A0;
         CoeffsMid.A1 = (LVM_FLOAT)LVCS_SEMidCoefTable[Offset].A1;
@@ -91,11 +105,18 @@
         if (LVCS_SEMidCoefTable[Offset].Scale == 15) {
             pConfig->pBiquadCallBack_Mid = FO_1I_D16F16C15_TRC_WRA_01;
         }
+#endif
 
         Offset = (LVM_UINT16)(pParams->SampleRate);
         pSESideCoefs = (BiquadA012B12CoefsSP_t*)&LVCS_SESideCoefTable[0];
 
         /* Side filter */
+#ifdef BIQUAD_OPT
+        coefs = {pSESideCoefs[Offset].A0, pSESideCoefs[Offset].A1, pSESideCoefs[Offset].A2,
+                 -(pSESideCoefs[Offset].B1), -(pSESideCoefs[Offset].B2)};
+        pInstance->pSESideBiquad.reset(
+                new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
         /* Convert incoming coefficients to the required format/ordering */
         CoeffsSide.A0 = (LVM_FLOAT)pSESideCoefs[Offset].A0;
         CoeffsSide.A1 = (LVM_FLOAT)pSESideCoefs[Offset].A1;
@@ -123,6 +144,7 @@
                 pConfig->pBiquadCallBack_Side = BQ_1I_D16F16C15_TRC_WRA_01;
                 break;
         }
+#endif
     }
 
     return (LVCS_SUCCESS);
@@ -169,9 +191,13 @@
                                          LVM_FLOAT* pOutData, LVM_UINT16 NumSamples) {
     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
     LVCS_StereoEnhancer_t* pConfig = (LVCS_StereoEnhancer_t*)&pInstance->StereoEnhancer;
+#ifndef BIQUAD_OPT
     LVCS_Coefficient_t* pCoefficient;
+#endif
     LVM_FLOAT* pScratch;
+#ifndef BIQUAD_OPT
     pCoefficient = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
     pScratch = (LVM_FLOAT*)pInstance->pScratch;
     /*
      * Check if the Stereo Enhancer is enabled
@@ -186,9 +212,13 @@
          * Apply filter to the middle signal
          */
         if (pInstance->OutputDevice == LVCS_HEADPHONE) {
+#ifdef BIQUAD_OPT
+            pInstance->pSEMidBiquad->process(pScratch, pScratch, NumSamples);
+#else
             (pConfig->pBiquadCallBack_Mid)(
                     (Biquad_FLOAT_Instance_t*)&pCoefficient->SEBiquadInstanceMid,
                     (LVM_FLOAT*)pScratch, (LVM_FLOAT*)pScratch, (LVM_INT16)NumSamples);
+#endif
         } else {
             Mult3s_Float(pScratch,                    /* Source */
                          (LVM_FLOAT)pConfig->MidGain, /* Gain */
@@ -201,10 +231,15 @@
          * and in all modes for mobile speakers
          */
         if (pInstance->Params.SourceFormat == LVCS_STEREO) {
+#ifdef BIQUAD_OPT
+            pInstance->pSESideBiquad->process(pScratch + NumSamples, pScratch + NumSamples,
+                                              NumSamples);
+#else
             (pConfig->pBiquadCallBack_Side)(
                     (Biquad_FLOAT_Instance_t*)&pCoefficient->SEBiquadInstanceSide,
                     (LVM_FLOAT*)(pScratch + NumSamples), (LVM_FLOAT*)(pScratch + NumSamples),
                     (LVM_INT16)NumSamples);
+#endif
         }
 
         /*
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
index c92f8a5..a083c47 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
@@ -36,6 +36,7 @@
 
 /* Stereo enhancer structure */
 typedef struct {
+#ifndef BIQUAD_OPT
     /*
      * Middle filter
      */
@@ -45,6 +46,7 @@
      * Side filter
      */
     void (*pBiquadCallBack_Side)(Biquad_FLOAT_Instance_t*, LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
+#endif
     LVM_FLOAT MidGain; /* Middle gain in mobile speaker mode */
 } LVCS_StereoEnhancer_t;
 
diff --git a/media/libeffects/lvm/tests/Android.bp b/media/libeffects/lvm/tests/Android.bp
index d026ab6..abacc94 100644
--- a/media/libeffects/lvm/tests/Android.bp
+++ b/media/libeffects/lvm/tests/Android.bp
@@ -59,9 +59,12 @@
     shared_libs: [
         "libaudioutils",
         "liblog",
-        "libreverbwrapper",
     ],
 
+    static_libs: [
+        "libreverb",
+        "libreverbwrapper",
+    ],
     srcs: [
         "reverb_test.cpp",
     ],
diff --git a/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh b/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
index a97acc9..7b0ff5e 100755
--- a/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
+++ b/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
@@ -23,7 +23,7 @@
 echo "========================================"
 echo "testing lvm"
 adb shell mkdir -p $testdir
-adb push $ANDROID_BUILD_TOP/cts/tests/tests/media/res/raw/sinesweepraw.raw $testdir
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/libeffects/res/raw/sinesweepraw.raw $testdir
 adb push $OUT/testcases/snr/arm64/snr $testdir
 
 E_VAL=1
@@ -91,7 +91,7 @@
     do
         for fs in ${fs_arr[*]}
         do
-            for chMask in {0..22}
+            for chMask in {0..38}
             do
                 adb shell $testdir/lvmtest -i:$testdir/sinesweepraw.raw \
                     -o:$testdir/sinesweep_$((chMask))_$((fs)).raw -chMask:$chMask -fs:$fs $flags
diff --git a/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh b/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh
index 0c3b0b5..72b370e 100755
--- a/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh
+++ b/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh
@@ -23,7 +23,7 @@
 echo "========================================"
 echo "testing reverb"
 adb shell mkdir -p $testdir
-adb push $ANDROID_BUILD_TOP/cts/tests/tests/media/res/raw/sinesweepraw.raw $testdir
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/libeffects/res/raw/sinesweepraw.raw $testdir
 
 E_VAL=1
 cmds="adb push $OUT/testcases/reverb_test/arm/reverb_test $testdir"
@@ -59,9 +59,9 @@
         do
             for fs in ${fs_arr[*]}
             do
-                for chMask in {0..22}
+                for chMask in {0..38}
                 do
-                    adb shell LD_LIBRARY_PATH=/system/vendor/lib/soundfx $testdir/reverb_test \
+                    adb shell $testdir/reverb_test \
                         --input $testdir/sinesweepraw.raw \
                         --output $testdir/sinesweep_$((chMask))_$((fs)).raw \
                         --chMask $chMask $flags --fs $fs --preset $preset_val
diff --git a/media/libeffects/lvm/tests/lvmtest.cpp b/media/libeffects/lvm/tests/lvmtest.cpp
index 5c5f646..f107b18 100644
--- a/media/libeffects/lvm/tests/lvmtest.cpp
+++ b/media/libeffects/lvm/tests/lvmtest.cpp
@@ -109,6 +109,22 @@
         AUDIO_CHANNEL_OUT_5POINT1POINT2,
         AUDIO_CHANNEL_OUT_7POINT1,
         AUDIO_CHANNEL_INDEX_MASK_8,
+        AUDIO_CHANNEL_INDEX_MASK_9,
+        AUDIO_CHANNEL_INDEX_MASK_10,
+        AUDIO_CHANNEL_INDEX_MASK_11,
+        AUDIO_CHANNEL_INDEX_MASK_12,
+        AUDIO_CHANNEL_INDEX_MASK_13,
+        AUDIO_CHANNEL_INDEX_MASK_14,
+        AUDIO_CHANNEL_INDEX_MASK_15,
+        AUDIO_CHANNEL_INDEX_MASK_16,
+        AUDIO_CHANNEL_INDEX_MASK_17,
+        AUDIO_CHANNEL_INDEX_MASK_18,
+        AUDIO_CHANNEL_INDEX_MASK_19,
+        AUDIO_CHANNEL_INDEX_MASK_20,
+        AUDIO_CHANNEL_INDEX_MASK_21,
+        AUDIO_CHANNEL_INDEX_MASK_22,
+        AUDIO_CHANNEL_INDEX_MASK_23,
+        AUDIO_CHANNEL_INDEX_MASK_24,
 };
 
 void printUsage() {
@@ -394,7 +410,7 @@
         params->SourceFormat = LVM_MONO;
     } else if (params->NrChannels == 2) {
         params->SourceFormat = LVM_STEREO;
-    } else if (params->NrChannels > 2 && params->NrChannels <= 8) {  // FCC_2 FCC_8
+    } else if (params->NrChannels > FCC_2 && params->NrChannels <= FCC_24) {
         params->SourceFormat = LVM_MULTICHANNEL;
     } else {
         return -EINVAL;
diff --git a/media/libeffects/lvm/tests/reverb_test.cpp b/media/libeffects/lvm/tests/reverb_test.cpp
index 7cbca9b..cecc975 100644
--- a/media/libeffects/lvm/tests/reverb_test.cpp
+++ b/media/libeffects/lvm/tests/reverb_test.cpp
@@ -94,6 +94,22 @@
         AUDIO_CHANNEL_OUT_5POINT1POINT2,
         AUDIO_CHANNEL_OUT_7POINT1,
         AUDIO_CHANNEL_INDEX_MASK_8,
+        AUDIO_CHANNEL_INDEX_MASK_9,
+        AUDIO_CHANNEL_INDEX_MASK_10,
+        AUDIO_CHANNEL_INDEX_MASK_11,
+        AUDIO_CHANNEL_INDEX_MASK_12,
+        AUDIO_CHANNEL_INDEX_MASK_13,
+        AUDIO_CHANNEL_INDEX_MASK_14,
+        AUDIO_CHANNEL_INDEX_MASK_15,
+        AUDIO_CHANNEL_INDEX_MASK_16,
+        AUDIO_CHANNEL_INDEX_MASK_17,
+        AUDIO_CHANNEL_INDEX_MASK_18,
+        AUDIO_CHANNEL_INDEX_MASK_19,
+        AUDIO_CHANNEL_INDEX_MASK_20,
+        AUDIO_CHANNEL_INDEX_MASK_21,
+        AUDIO_CHANNEL_INDEX_MASK_22,
+        AUDIO_CHANNEL_INDEX_MASK_23,
+        AUDIO_CHANNEL_INDEX_MASK_24,
 };
 
 constexpr int kReverbConfigChMaskCount = std::size(kReverbConfigChMask);
@@ -340,7 +356,7 @@
     const int outChannelCount = (channelCount == 1 ? 2 : channelCount);
 
     std::vector<short> in(frameLength * maxChannelCount);
-    std::vector<short> out(frameLength * maxChannelCount);
+    std::vector<short> out(frameLength * outChannelCount);
     std::vector<float> floatIn(frameLength * channelCount);
     std::vector<float> floatOut(frameLength * outChannelCount);
 
diff --git a/media/libeffects/lvm/wrapper/Android.bp b/media/libeffects/lvm/wrapper/Android.bp
index be60aae..f96928b 100644
--- a/media/libeffects/lvm/wrapper/Android.bp
+++ b/media/libeffects/lvm/wrapper/Android.bp
@@ -38,7 +38,7 @@
 }
 
 // reverb wrapper
-cc_library_shared {
+cc_library {
     name: "libreverbwrapper",
 
     arch: {
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 670b415..865baad 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -1021,6 +1021,16 @@
         ActiveParams.NrChannels = NrChannels;
         ActiveParams.ChMask = pConfig->inputCfg.channels;
 
+        if (NrChannels == 1) {
+            ActiveParams.SourceFormat = LVM_MONO;
+        } else if (NrChannels == 2) {
+            ActiveParams.SourceFormat = LVM_STEREO;
+        } else if (NrChannels > 2 && NrChannels <= LVM_MAX_CHANNELS) {
+            ActiveParams.SourceFormat = LVM_MULTICHANNEL;
+        } else {
+            return -EINVAL;
+        }
+
         LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
 
         LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "Effect_setConfig")
diff --git a/media/libeffects/preprocessing/Android.bp b/media/libeffects/preprocessing/Android.bp
index 5217cf9..681e247 100644
--- a/media/libeffects/preprocessing/Android.bp
+++ b/media/libeffects/preprocessing/Android.bp
@@ -1,35 +1,5 @@
 // audio preprocessing wrapper
 cc_library_shared {
-    name: "libaudiopreprocessing_legacy",
-
-    vendor: true,
-
-    relative_install_path: "soundfx",
-
-    srcs: ["PreProcessing.cpp"],
-
-    shared_libs: [
-        "libwebrtc_audio_preprocessing",
-        "libspeexresampler",
-        "libutils",
-        "liblog",
-    ],
-
-    cflags: [
-        "-DWEBRTC_POSIX",
-        "-DWEBRTC_LEGACY",
-        "-fvisibility=hidden",
-        "-Wall",
-        "-Werror",
-    ],
-
-    header_libs: [
-        "libaudioeffects",
-        "libhardware_headers",
-    ],
-}
-
-cc_library_shared {
     name: "libaudiopreprocessing",
     vendor: true,
     relative_install_path: "soundfx",
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 1a5547b..03ccc34 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -23,15 +23,10 @@
 #include <hardware/audio_effect.h>
 #include <utils/Log.h>
 #include <utils/Timers.h>
-#ifndef WEBRTC_LEGACY
 #include <audio_effects/effect_agc2.h>
-#endif
 #include <audio_effects/effect_ns.h>
 #include <audio_processing.h>
 #include <module_common_types.h>
-#ifdef WEBRTC_LEGACY
-#include "speex/speex_resampler.h"
-#endif
 
 // undefine to perform multi channels API functional tests
 //#define DUAL_MIC_TEST
@@ -46,9 +41,7 @@
 // types of pre processing modules
 enum preproc_id {
     PREPROC_AGC,  // Automatic Gain Control
-#ifndef WEBRTC_LEGACY
     PREPROC_AGC2,  // Automatic Gain Control 2
-#endif
     PREPROC_AEC,  // Acoustic Echo Canceler
     PREPROC_NS,   // Noise Suppressor
     PREPROC_NUM_EFFECTS
@@ -110,10 +103,8 @@
     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)
-#ifndef WEBRTC_LEGACY
     // Audio Processing module builder
     webrtc::AudioProcessingBuilder ap_builder;
-#endif
     size_t apmFrameCount;      // buffer size for webRTC process (10 ms)
     uint32_t apmSamplingRate;  // webRTC APM sampling rate (8/16 or 32 kHz)
     size_t frameCount;         // buffer size before input resampler ( <=> apmFrameCount)
@@ -124,42 +115,25 @@
     uint32_t enabledMsk;       // bit field containing IDs of enabled pre processors
     uint32_t processedMsk;     // bit field containing IDs of pre processors already
                                // processed in current round
-#ifdef WEBRTC_LEGACY
-    webrtc::AudioFrame* procFrame;  // audio frame passed to webRTC AMP ProcessStream()
-#else
     // audio config strucutre
     webrtc::AudioProcessing::Config config;
     webrtc::StreamConfig inputConfig;   // input stream configuration
     webrtc::StreamConfig outputConfig;  // output stream configuration
-#endif
     int16_t* inBuf;    // input buffer used when resampling
     size_t inBufSize;  // input buffer size in frames
     size_t framesIn;   // number of frames in input buffer
-#ifdef WEBRTC_LEGACY
-    SpeexResamplerState* inResampler;  // handle on input speex resampler
-#endif
     int16_t* outBuf;    // output buffer used when resampling
     size_t outBufSize;  // output buffer size in frames
     size_t framesOut;   // number of frames in output buffer
-#ifdef WEBRTC_LEGACY
-    SpeexResamplerState* outResampler;  // handle on output speex resampler
-#endif
     uint32_t revChannelCount;  // number of channels on reverse stream
     uint32_t revEnabledMsk;    // bit field containing IDs of enabled pre processors
                                // with reverse channel
     uint32_t revProcessedMsk;  // bit field containing IDs of pre processors with reverse
                                // channel already processed in current round
-#ifdef WEBRTC_LEGACY
-    webrtc::AudioFrame* revFrame;  // audio frame passed to webRTC AMP AnalyzeReverseStream()
-#else
     webrtc::StreamConfig revConfig;     // reverse stream configuration.
-#endif
     int16_t* revBuf;    // reverse channel input buffer
     size_t revBufSize;  // reverse channel input buffer size
     size_t framesRev;   // number of frames in reverse channel input buffer
-#ifdef WEBRTC_LEGACY
-    SpeexResamplerState* revResampler;  // handle on reverse channel input speex resampler
-#endif
 };
 
 #ifdef DUAL_MIC_TEST
@@ -213,7 +187,6 @@
         "Automatic Gain Control",
         "The Android Open Source Project"};
 
-#ifndef WEBRTC_LEGACY
 // Automatic Gain Control 2
 static const effect_descriptor_t sAgc2Descriptor = {
         {0xae3c653b, 0xbe18, 0x4ab8, 0x8938, {0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac}},  // type
@@ -224,7 +197,6 @@
         0,  // FIXME indicate memory usage
         "Automatic Gain Control 2",
         "The Android Open Source Project"};
-#endif
 
 // Acoustic Echo Cancellation
 static const effect_descriptor_t sAecDescriptor = {
@@ -249,9 +221,7 @@
         "The Android Open Source Project"};
 
 static const effect_descriptor_t* sDescriptors[PREPROC_NUM_EFFECTS] = {&sAgcDescriptor,
-#ifndef WEBRTC_LEGACY
                                                                        &sAgc2Descriptor,
-#endif
                                                                        &sAecDescriptor,
                                                                        &sNsDescriptor};
 
@@ -260,9 +230,7 @@
 //------------------------------------------------------------------------------
 
 const effect_uuid_t* const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {FX_IID_AGC,
-#ifndef WEBRTC_LEGACY
                                                                        FX_IID_AGC2,
-#endif
                                                                        FX_IID_AEC, FX_IID_NS};
 
 const effect_uuid_t* ProcIdToUuid(int procId) {
@@ -297,7 +265,6 @@
 static const int kAgcDefaultCompGain = 9;
 static const bool kAgcDefaultLimiter = true;
 
-#ifndef WEBRTC_LEGACY
 int Agc2Init(preproc_effect_t* effect) {
     ALOGV("Agc2Init");
     effect->session->config = effect->session->apm->GetConfig();
@@ -308,48 +275,27 @@
     effect->session->apm->ApplyConfig(effect->session->config);
     return 0;
 }
-#endif
 
 int AgcInit(preproc_effect_t* effect) {
     ALOGV("AgcInit");
-#ifdef WEBRTC_LEGACY
-    webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
-    agc->set_mode(webrtc::GainControl::kFixedDigital);
-    agc->set_target_level_dbfs(kAgcDefaultTargetLevel);
-    agc->set_compression_gain_db(kAgcDefaultCompGain);
-    agc->enable_limiter(kAgcDefaultLimiter);
-#else
     effect->session->config = effect->session->apm->GetConfig();
     effect->session->config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
     effect->session->config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
     effect->session->config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
     effect->session->apm->ApplyConfig(effect->session->config);
-#endif
     return 0;
 }
 
-#ifndef WEBRTC_LEGACY
 int Agc2Create(preproc_effect_t* effect) {
     Agc2Init(effect);
     return 0;
 }
-#endif
 
 int AgcCreate(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
-    webrtc::GainControl* agc = effect->session->apm->gain_control();
-    ALOGV("AgcCreate got agc %p", agc);
-    if (agc == NULL) {
-        ALOGW("AgcCreate Error");
-        return -ENOMEM;
-    }
-    effect->engine = static_cast<preproc_fx_handle_t>(agc);
-#endif
     AgcInit(effect);
     return 0;
 }
 
-#ifndef WEBRTC_LEGACY
 int Agc2GetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
     int status = 0;
     uint32_t param = *(uint32_t*)pParam;
@@ -422,15 +368,11 @@
 
     return status;
 }
-#endif
 
 int AgcGetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
     int status = 0;
     uint32_t param = *(uint32_t*)pParam;
     t_agc_settings* pProperties = (t_agc_settings*)pValue;
-#ifdef WEBRTC_LEGACY
-    webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
-#endif
 
     switch (param) {
         case AGC_PARAM_TARGET_LEVEL:
@@ -459,32 +401,6 @@
             break;
     }
 
-#ifdef WEBRTC_LEGACY
-    switch (param) {
-        case AGC_PARAM_TARGET_LEVEL:
-            *(int16_t*)pValue = (int16_t)(agc->target_level_dbfs() * -100);
-            ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t*)pValue);
-            break;
-        case AGC_PARAM_COMP_GAIN:
-            *(int16_t*)pValue = (int16_t)(agc->compression_gain_db() * 100);
-            ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t*)pValue);
-            break;
-        case AGC_PARAM_LIMITER_ENA:
-            *(bool*)pValue = (bool)agc->is_limiter_enabled();
-            ALOGV("AgcGetParameter() limiter enabled %s",
-                  (*(int16_t*)pValue != 0) ? "true" : "false");
-            break;
-        case AGC_PARAM_PROPERTIES:
-            pProperties->targetLevel = (int16_t)(agc->target_level_dbfs() * -100);
-            pProperties->compGain = (int16_t)(agc->compression_gain_db() * 100);
-            pProperties->limiterEnabled = (bool)agc->is_limiter_enabled();
-            break;
-        default:
-            ALOGW("AgcGetParameter() unknown param %d", param);
-            status = -EINVAL;
-            break;
-    }
-#else
     effect->session->config = effect->session->apm->GetConfig();
     switch (param) {
         case AGC_PARAM_TARGET_LEVEL:
@@ -515,11 +431,9 @@
             status = -EINVAL;
             break;
     }
-#endif
     return status;
 }
 
-#ifndef WEBRTC_LEGACY
 int Agc2SetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
     int status = 0;
     uint32_t param = *(uint32_t*)pParam;
@@ -567,43 +481,9 @@
 
     return status;
 }
-#endif
 
 int AgcSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
     int status = 0;
-#ifdef WEBRTC_LEGACY
-    uint32_t param = *(uint32_t*)pParam;
-    t_agc_settings* pProperties = (t_agc_settings*)pValue;
-    webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
-
-    switch (param) {
-        case AGC_PARAM_TARGET_LEVEL:
-            ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t*)pValue);
-            status = agc->set_target_level_dbfs(-(*(int16_t*)pValue / 100));
-            break;
-        case AGC_PARAM_COMP_GAIN:
-            ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t*)pValue);
-            status = agc->set_compression_gain_db(*(int16_t*)pValue / 100);
-            break;
-        case AGC_PARAM_LIMITER_ENA:
-            ALOGV("AgcSetParameter() limiter enabled %s", *(bool*)pValue ? "true" : "false");
-            status = agc->enable_limiter(*(bool*)pValue);
-            break;
-        case AGC_PARAM_PROPERTIES:
-            ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
-                  pProperties->targetLevel, pProperties->compGain, pProperties->limiterEnabled);
-            status = agc->set_target_level_dbfs(-(pProperties->targetLevel / 100));
-            if (status != 0) break;
-            status = agc->set_compression_gain_db(pProperties->compGain / 100);
-            if (status != 0) break;
-            status = agc->enable_limiter(pProperties->limiterEnabled);
-            break;
-        default:
-            ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
-            status = -EINVAL;
-            break;
-    }
-#else
     uint32_t param = *(uint32_t*)pParam;
     t_agc_settings* pProperties = (t_agc_settings*)pValue;
     effect->session->config = effect->session->apm->GetConfig();
@@ -637,96 +517,57 @@
             break;
     }
     effect->session->apm->ApplyConfig(effect->session->config);
-#endif
 
     ALOGV("AgcSetParameter() done status %d", status);
 
     return status;
 }
 
-#ifndef WEBRTC_LEGACY
 void Agc2Enable(preproc_effect_t* effect) {
     effect->session->config = effect->session->apm->GetConfig();
     effect->session->config.gain_controller2.enabled = true;
     effect->session->apm->ApplyConfig(effect->session->config);
 }
-#endif
 
 void AgcEnable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
-    webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
-    ALOGV("AgcEnable agc %p", agc);
-    agc->Enable(true);
-#else
     effect->session->config = effect->session->apm->GetConfig();
     effect->session->config.gain_controller1.enabled = true;
     effect->session->apm->ApplyConfig(effect->session->config);
-#endif
 }
 
-#ifndef WEBRTC_LEGACY
 void Agc2Disable(preproc_effect_t* effect) {
     effect->session->config = effect->session->apm->GetConfig();
     effect->session->config.gain_controller2.enabled = false;
     effect->session->apm->ApplyConfig(effect->session->config);
 }
-#endif
 
 void AgcDisable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
-    ALOGV("AgcDisable");
-    webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
-    agc->Enable(false);
-#else
     effect->session->config = effect->session->apm->GetConfig();
     effect->session->config.gain_controller1.enabled = false;
     effect->session->apm->ApplyConfig(effect->session->config);
-#endif
 }
 
 static const preproc_ops_t sAgcOps = {AgcCreate,       AgcInit,         NULL, AgcEnable, AgcDisable,
                                       AgcSetParameter, AgcGetParameter, NULL};
 
-#ifndef WEBRTC_LEGACY
 static const preproc_ops_t sAgc2Ops = {Agc2Create,       Agc2Init,    NULL,
                                        Agc2Enable,       Agc2Disable, Agc2SetParameter,
                                        Agc2GetParameter, NULL};
-#endif
 
 //------------------------------------------------------------------------------
 // Acoustic Echo Canceler (AEC)
 //------------------------------------------------------------------------------
 
-#ifdef WEBRTC_LEGACY
-static const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode =
-        webrtc::EchoControlMobile::kEarpiece;
-static const bool kAecDefaultComfortNoise = true;
-#endif
 
 int AecInit(preproc_effect_t* effect) {
     ALOGV("AecInit");
-#ifdef WEBRTC_LEGACY
-    webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
-    aec->set_routing_mode(kAecDefaultMode);
-    aec->enable_comfort_noise(kAecDefaultComfortNoise);
-#else
     effect->session->config = effect->session->apm->GetConfig();
     effect->session->config.echo_canceller.mobile_mode = true;
     effect->session->apm->ApplyConfig(effect->session->config);
-#endif
     return 0;
 }
 
 int AecCreate(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
-    webrtc::EchoControlMobile* aec = effect->session->apm->echo_control_mobile();
-    ALOGV("AecCreate got aec %p", aec);
-    if (aec == NULL) {
-        ALOGW("AgcCreate Error");
-        return -ENOMEM;
-    }
-    effect->engine = static_cast<preproc_fx_handle_t>(aec);
-#endif
     AecInit(effect);
     return 0;
 }
@@ -744,13 +585,11 @@
             *(uint32_t*)pValue = 1000 * effect->session->apm->stream_delay_ms();
             ALOGV("AecGetParameter() echo delay %d us", *(uint32_t*)pValue);
             break;
-#ifndef WEBRTC_LEGACY
         case AEC_PARAM_MOBILE_MODE:
             effect->session->config = effect->session->apm->GetConfig();
             *(uint32_t*)pValue = effect->session->config.echo_canceller.mobile_mode;
             ALOGV("AecGetParameter() mobile mode %d us", *(uint32_t*)pValue);
             break;
-#endif
         default:
             ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
             status = -EINVAL;
@@ -770,14 +609,12 @@
             status = effect->session->apm->set_stream_delay_ms(value / 1000);
             ALOGV("AecSetParameter() echo delay %d us, status %d", value, status);
             break;
-#ifndef WEBRTC_LEGACY
         case AEC_PARAM_MOBILE_MODE:
             effect->session->config = effect->session->apm->GetConfig();
             effect->session->config.echo_canceller.mobile_mode = value;
             ALOGV("AecSetParameter() mobile mode %d us", value);
             effect->session->apm->ApplyConfig(effect->session->config);
             break;
-#endif
         default:
             ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
             status = -EINVAL;
@@ -787,57 +624,24 @@
 }
 
 void AecEnable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
-    webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
-    ALOGV("AecEnable aec %p", aec);
-    aec->Enable(true);
-#else
     effect->session->config = effect->session->apm->GetConfig();
     effect->session->config.echo_canceller.enabled = true;
     effect->session->apm->ApplyConfig(effect->session->config);
-#endif
 }
 
 void AecDisable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
-    ALOGV("AecDisable");
-    webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
-    aec->Enable(false);
-#else
     effect->session->config = effect->session->apm->GetConfig();
     effect->session->config.echo_canceller.enabled = false;
     effect->session->apm->ApplyConfig(effect->session->config);
-#endif
 }
 
 int AecSetDevice(preproc_effect_t* effect, uint32_t device) {
     ALOGV("AecSetDevice %08x", device);
-#ifdef WEBRTC_LEGACY
-    webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
-    webrtc::EchoControlMobile::RoutingMode mode =
-            webrtc::EchoControlMobile::kQuietEarpieceOrHeadset;
-#endif
 
     if (audio_is_input_device(device)) {
         return 0;
     }
 
-#ifdef WEBRTC_LEGACY
-    switch (device) {
-        case AUDIO_DEVICE_OUT_EARPIECE:
-            mode = webrtc::EchoControlMobile::kEarpiece;
-            break;
-        case AUDIO_DEVICE_OUT_SPEAKER:
-            mode = webrtc::EchoControlMobile::kSpeakerphone;
-            break;
-        case AUDIO_DEVICE_OUT_WIRED_HEADSET:
-        case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
-        case AUDIO_DEVICE_OUT_USB_HEADSET:
-        default:
-            break;
-    }
-    aec->set_routing_mode(mode);
-#endif
     return 0;
 }
 
@@ -849,49 +653,19 @@
 // Noise Suppression (NS)
 //------------------------------------------------------------------------------
 
-#ifdef WEBRTC_LEGACY
-static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate;
-#else
 static const webrtc::AudioProcessing::Config::NoiseSuppression::Level kNsDefaultLevel =
         webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
-#endif
 
 int NsInit(preproc_effect_t* effect) {
     ALOGV("NsInit");
-#ifdef WEBRTC_LEGACY
-    webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
-    ns->set_level(kNsDefaultLevel);
-    webrtc::Config config;
-    std::vector<webrtc::Point> geometry;
-    // TODO(aluebs): Make the geometry settable.
-    geometry.push_back(webrtc::Point(-0.03f, 0.f, 0.f));
-    geometry.push_back(webrtc::Point(-0.01f, 0.f, 0.f));
-    geometry.push_back(webrtc::Point(0.01f, 0.f, 0.f));
-    geometry.push_back(webrtc::Point(0.03f, 0.f, 0.f));
-    // The geometry needs to be set with Beamforming enabled.
-    config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
-    effect->session->apm->SetExtraOptions(config);
-    config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry));
-    effect->session->apm->SetExtraOptions(config);
-#else
     effect->session->config = effect->session->apm->GetConfig();
     effect->session->config.noise_suppression.level = kNsDefaultLevel;
     effect->session->apm->ApplyConfig(effect->session->config);
-#endif
     effect->type = NS_TYPE_SINGLE_CHANNEL;
     return 0;
 }
 
 int NsCreate(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
-    webrtc::NoiseSuppression* ns = effect->session->apm->noise_suppression();
-    ALOGV("NsCreate got ns %p", ns);
-    if (ns == NULL) {
-        ALOGW("AgcCreate Error");
-        return -ENOMEM;
-    }
-    effect->engine = static_cast<preproc_fx_handle_t>(ns);
-#endif
     NsInit(effect);
     return 0;
 }
@@ -904,31 +678,6 @@
 
 int NsSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
     int status = 0;
-#ifdef WEBRTC_LEGACY
-    webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
-    uint32_t param = *(uint32_t*)pParam;
-    uint32_t value = *(uint32_t*)pValue;
-    switch (param) {
-        case NS_PARAM_LEVEL:
-            ns->set_level((webrtc::NoiseSuppression::Level)value);
-            ALOGV("NsSetParameter() level %d", value);
-            break;
-        case NS_PARAM_TYPE: {
-            webrtc::Config config;
-            std::vector<webrtc::Point> geometry;
-            bool is_beamforming_enabled = value == NS_TYPE_MULTI_CHANNEL && ns->is_enabled();
-            config.Set<webrtc::Beamforming>(
-                    new webrtc::Beamforming(is_beamforming_enabled, geometry));
-            effect->session->apm->SetExtraOptions(config);
-            effect->type = value;
-            ALOGV("NsSetParameter() type %d", value);
-            break;
-        }
-        default:
-            ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
-            status = -EINVAL;
-    }
-#else
     uint32_t param = *(uint32_t*)pParam;
     uint32_t value = *(uint32_t*)pValue;
     effect->session->config = effect->session->apm->GetConfig();
@@ -943,52 +692,28 @@
             status = -EINVAL;
     }
     effect->session->apm->ApplyConfig(effect->session->config);
-#endif
 
     return status;
 }
 
 void NsEnable(preproc_effect_t* effect) {
-#ifdef WEBRTC_LEGACY
-    webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
-    ALOGV("NsEnable ns %p", ns);
-    ns->Enable(true);
-    if (effect->type == NS_TYPE_MULTI_CHANNEL) {
-        webrtc::Config config;
-        std::vector<webrtc::Point> geometry;
-        config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
-        effect->session->apm->SetExtraOptions(config);
-    }
-#else
     effect->session->config = effect->session->apm->GetConfig();
     effect->session->config.noise_suppression.enabled = true;
     effect->session->apm->ApplyConfig(effect->session->config);
-#endif
 }
 
 void NsDisable(preproc_effect_t* effect) {
     ALOGV("NsDisable");
-#ifdef WEBRTC_LEGACY
-    webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
-    ns->Enable(false);
-    webrtc::Config config;
-    std::vector<webrtc::Point> geometry;
-    config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry));
-    effect->session->apm->SetExtraOptions(config);
-#else
     effect->session->config = effect->session->apm->GetConfig();
     effect->session->config.noise_suppression.enabled = false;
     effect->session->apm->ApplyConfig(effect->session->config);
-#endif
 }
 
 static const preproc_ops_t sNsOps = {NsCreate,  NsInit,         NULL,           NsEnable,
                                      NsDisable, NsSetParameter, NsGetParameter, NULL};
 
 static const preproc_ops_t* sPreProcOps[PREPROC_NUM_EFFECTS] = {&sAgcOps,
-#ifndef WEBRTC_LEGACY
                                                                 &sAgc2Ops,
-#endif
                                                                 &sAecOps, &sNsOps};
 
 //------------------------------------------------------------------------------
@@ -1119,9 +844,6 @@
     session->id = 0;
     session->io = 0;
     session->createdMsk = 0;
-#ifdef WEBRTC_LEGACY
-    session->apm = NULL;
-#endif
     for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
         status = Effect_Init(&session->effects[i], i);
     }
@@ -1135,75 +857,32 @@
     ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
 
     if (session->createdMsk == 0) {
-#ifdef WEBRTC_LEGACY
-        session->apm = webrtc::AudioProcessing::Create();
-        if (session->apm == NULL) {
-            ALOGW("Session_CreateEffect could not get apm engine");
-            goto error;
-        }
-        const webrtc::ProcessingConfig processing_config = {
-                {{kPreprocDefaultSr, kPreProcDefaultCnl},
-                 {kPreprocDefaultSr, kPreProcDefaultCnl},
-                 {kPreprocDefaultSr, kPreProcDefaultCnl},
-                 {kPreprocDefaultSr, kPreProcDefaultCnl}}};
-        session->apm->Initialize(processing_config);
-        session->procFrame = new webrtc::AudioFrame();
-        if (session->procFrame == NULL) {
-            ALOGW("Session_CreateEffect could not allocate audio frame");
-            goto error;
-        }
-        session->revFrame = new webrtc::AudioFrame();
-        if (session->revFrame == NULL) {
-            ALOGW("Session_CreateEffect could not allocate reverse audio frame");
-            goto error;
-        }
-#else
         session->apm = session->ap_builder.Create();
         if (session->apm == NULL) {
             ALOGW("Session_CreateEffect could not get apm engine");
             goto error;
         }
-#endif
         session->apmSamplingRate = kPreprocDefaultSr;
         session->apmFrameCount = (kPreprocDefaultSr) / 100;
         session->frameCount = session->apmFrameCount;
         session->samplingRate = kPreprocDefaultSr;
         session->inChannelCount = kPreProcDefaultCnl;
         session->outChannelCount = kPreProcDefaultCnl;
-#ifdef WEBRTC_LEGACY
-        session->procFrame->sample_rate_hz_ = kPreprocDefaultSr;
-        session->procFrame->num_channels_ = kPreProcDefaultCnl;
-#else
         session->inputConfig.set_sample_rate_hz(kPreprocDefaultSr);
         session->inputConfig.set_num_channels(kPreProcDefaultCnl);
         session->outputConfig.set_sample_rate_hz(kPreprocDefaultSr);
         session->outputConfig.set_num_channels(kPreProcDefaultCnl);
-#endif
         session->revChannelCount = kPreProcDefaultCnl;
-#ifdef WEBRTC_LEGACY
-        session->revFrame->sample_rate_hz_ = kPreprocDefaultSr;
-        session->revFrame->num_channels_ = kPreProcDefaultCnl;
-#else
         session->revConfig.set_sample_rate_hz(kPreprocDefaultSr);
         session->revConfig.set_num_channels(kPreProcDefaultCnl);
-#endif
         session->enabledMsk = 0;
         session->processedMsk = 0;
         session->revEnabledMsk = 0;
         session->revProcessedMsk = 0;
-#ifdef WEBRTC_LEGACY
-        session->inResampler = NULL;
-#endif
         session->inBuf = NULL;
         session->inBufSize = 0;
-#ifdef WEBRTC_LEGACY
-        session->outResampler = NULL;
-#endif
         session->outBuf = NULL;
         session->outBufSize = 0;
-#ifdef WEBRTC_LEGACY
-        session->revResampler = NULL;
-#endif
         session->revBuf = NULL;
         session->revBufSize = 0;
     }
@@ -1217,17 +896,8 @@
 
 error:
     if (session->createdMsk == 0) {
-#ifdef WEBRTC_LEGACY
-        delete session->revFrame;
-        session->revFrame = NULL;
-        delete session->procFrame;
-        session->procFrame = NULL;
-        delete session->apm;
-        session->apm = NULL;  // NOLINT(clang-analyzer-cplusplus.NewDelete)
-#else
         delete session->apm;
         session->apm = NULL;
-#endif
     }
     return status;
 }
@@ -1236,29 +906,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) {
-#ifdef WEBRTC_LEGACY
         delete session->apm;
         session->apm = NULL;
-        delete session->procFrame;
-        session->procFrame = NULL;
-        delete session->revFrame;
-        session->revFrame = NULL;
-        if (session->inResampler != NULL) {
-            speex_resampler_destroy(session->inResampler);
-            session->inResampler = NULL;
-        }
-        if (session->outResampler != NULL) {
-            speex_resampler_destroy(session->outResampler);
-            session->outResampler = NULL;
-        }
-        if (session->revResampler != NULL) {
-            speex_resampler_destroy(session->revResampler);
-            session->revResampler = NULL;
-        }
-#else
-        delete session->apm;
-        session->apm = NULL;
-#endif
         delete session->inBuf;
         session->inBuf = NULL;
         delete session->outBuf;
@@ -1284,9 +933,6 @@
 
     ALOGV("Session_SetConfig sr %d cnl %08x", config->inputCfg.samplingRate,
           config->inputCfg.channels);
-#ifdef WEBRTC_LEGACY
-    int status;
-#endif
 
     // AEC implementation is limited to 16kHz
     if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
@@ -1297,51 +943,25 @@
         session->apmSamplingRate = 8000;
     }
 
-#ifdef WEBRTC_LEGACY
-    const webrtc::ProcessingConfig processing_config = {
-            {{static_cast<int>(session->apmSamplingRate), inCnl},
-             {static_cast<int>(session->apmSamplingRate), outCnl},
-             {static_cast<int>(session->apmSamplingRate), inCnl},
-             {static_cast<int>(session->apmSamplingRate), inCnl}}};
-    status = session->apm->Initialize(processing_config);
-    if (status < 0) {
-        return -EINVAL;
-    }
-#endif
 
     session->samplingRate = config->inputCfg.samplingRate;
     session->apmFrameCount = session->apmSamplingRate / 100;
     if (session->samplingRate == session->apmSamplingRate) {
         session->frameCount = session->apmFrameCount;
     } else {
-#ifdef WEBRTC_LEGACY
-        session->frameCount =
-                (session->apmFrameCount * session->samplingRate) / session->apmSamplingRate + 1;
-#else
         session->frameCount =
                 (session->apmFrameCount * session->samplingRate) / session->apmSamplingRate;
-#endif
     }
     session->inChannelCount = inCnl;
     session->outChannelCount = outCnl;
-#ifdef WEBRTC_LEGACY
-    session->procFrame->num_channels_ = inCnl;
-    session->procFrame->sample_rate_hz_ = session->apmSamplingRate;
-#else
     session->inputConfig.set_sample_rate_hz(session->samplingRate);
     session->inputConfig.set_num_channels(inCnl);
     session->outputConfig.set_sample_rate_hz(session->samplingRate);
     session->outputConfig.set_num_channels(inCnl);
-#endif
 
     session->revChannelCount = inCnl;
-#ifdef WEBRTC_LEGACY
-    session->revFrame->num_channels_ = inCnl;
-    session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
-#else
     session->revConfig.set_sample_rate_hz(session->samplingRate);
     session->revConfig.set_num_channels(inCnl);
-#endif
 
     // force process buffer reallocation
     session->inBufSize = 0;
@@ -1349,53 +969,6 @@
     session->framesIn = 0;
     session->framesOut = 0;
 
-#ifdef WEBRTC_LEGACY
-    if (session->inResampler != NULL) {
-        speex_resampler_destroy(session->inResampler);
-        session->inResampler = NULL;
-    }
-    if (session->outResampler != NULL) {
-        speex_resampler_destroy(session->outResampler);
-        session->outResampler = NULL;
-    }
-    if (session->revResampler != NULL) {
-        speex_resampler_destroy(session->revResampler);
-        session->revResampler = NULL;
-    }
-    if (session->samplingRate != session->apmSamplingRate) {
-        int error;
-        session->inResampler =
-                speex_resampler_init(session->inChannelCount, session->samplingRate,
-                                     session->apmSamplingRate, RESAMPLER_QUALITY, &error);
-        if (session->inResampler == NULL) {
-            ALOGW("Session_SetConfig Cannot create speex resampler: %s",
-                  speex_resampler_strerror(error));
-            return -EINVAL;
-        }
-        session->outResampler =
-                speex_resampler_init(session->outChannelCount, session->apmSamplingRate,
-                                     session->samplingRate, RESAMPLER_QUALITY, &error);
-        if (session->outResampler == NULL) {
-            ALOGW("Session_SetConfig Cannot create speex resampler: %s",
-                  speex_resampler_strerror(error));
-            speex_resampler_destroy(session->inResampler);
-            session->inResampler = NULL;
-            return -EINVAL;
-        }
-        session->revResampler =
-                speex_resampler_init(session->inChannelCount, session->samplingRate,
-                                     session->apmSamplingRate, RESAMPLER_QUALITY, &error);
-        if (session->revResampler == NULL) {
-            ALOGW("Session_SetConfig Cannot create speex resampler: %s",
-                  speex_resampler_strerror(error));
-            speex_resampler_destroy(session->inResampler);
-            session->inResampler = NULL;
-            speex_resampler_destroy(session->outResampler);
-            session->outResampler = NULL;
-            return -EINVAL;
-        }
-    }
-#endif
 
     session->state = PREPROC_SESSION_STATE_CONFIG;
     return 0;
@@ -1430,22 +1003,7 @@
         return -EINVAL;
     }
     uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels);
-#ifdef WEBRTC_LEGACY
-    const webrtc::ProcessingConfig processing_config = {
-            {{static_cast<int>(session->apmSamplingRate), session->inChannelCount},
-             {static_cast<int>(session->apmSamplingRate), session->outChannelCount},
-             {static_cast<int>(session->apmSamplingRate), inCnl},
-             {static_cast<int>(session->apmSamplingRate), inCnl}}};
-    int status = session->apm->Initialize(processing_config);
-    if (status < 0) {
-        return -EINVAL;
-    }
-#endif
     session->revChannelCount = inCnl;
-#ifdef WEBRTC_LEGACY
-    session->revFrame->num_channels_ = inCnl;
-    session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
-#endif
     // force process buffer reallocation
     session->revBufSize = 0;
     session->framesRev = 0;
@@ -1467,24 +1025,10 @@
     if (enabled) {
         if (session->enabledMsk == 0) {
             session->framesIn = 0;
-#ifdef WEBRTC_LEGACY
-            if (session->inResampler != NULL) {
-                speex_resampler_reset_mem(session->inResampler);
-            }
-            session->framesOut = 0;
-            if (session->outResampler != NULL) {
-                speex_resampler_reset_mem(session->outResampler);
-            }
-#endif
         }
         session->enabledMsk |= (1 << procId);
         if (HasReverseStream(procId)) {
             session->framesRev = 0;
-#ifdef WEBRTC_LEGACY
-            if (session->revResampler != NULL) {
-                speex_resampler_reset_mem(session->revResampler);
-            }
-#endif
             session->revEnabledMsk |= (1 << procId);
         }
     } else {
@@ -1600,82 +1144,6 @@
             return 0;
         }
 
-#ifdef WEBRTC_LEGACY
-        if (session->inResampler != NULL) {
-            size_t fr = session->frameCount - session->framesIn;
-            if (inBuffer->frameCount < fr) {
-                fr = inBuffer->frameCount;
-            }
-            if (session->inBufSize < session->framesIn + fr) {
-                int16_t* buf;
-                session->inBufSize = session->framesIn + fr;
-                buf = (int16_t*)realloc(
-                        session->inBuf,
-                        session->inBufSize * session->inChannelCount * sizeof(int16_t));
-                if (buf == NULL) {
-                    session->framesIn = 0;
-                    free(session->inBuf);
-                    session->inBuf = NULL;
-                    return -ENOMEM;
-                }
-                session->inBuf = buf;
-            }
-            memcpy(session->inBuf + session->framesIn * session->inChannelCount, inBuffer->s16,
-                   fr * session->inChannelCount * sizeof(int16_t));
-#ifdef DUAL_MIC_TEST
-            pthread_mutex_lock(&gPcmDumpLock);
-            if (gPcmDumpFh != NULL) {
-                fwrite(inBuffer->raw, fr * session->inChannelCount * sizeof(int16_t), 1,
-                       gPcmDumpFh);
-            }
-            pthread_mutex_unlock(&gPcmDumpLock);
-#endif
-
-            session->framesIn += fr;
-            inBuffer->frameCount = fr;
-            if (session->framesIn < session->frameCount) {
-                return 0;
-            }
-            spx_uint32_t frIn = session->framesIn;
-            spx_uint32_t frOut = session->apmFrameCount;
-            if (session->inChannelCount == 1) {
-                speex_resampler_process_int(session->inResampler, 0, session->inBuf, &frIn,
-                                            session->procFrame->data_, &frOut);
-            } else {
-                speex_resampler_process_interleaved_int(session->inResampler, session->inBuf, &frIn,
-                                                        session->procFrame->data_, &frOut);
-            }
-            memmove(session->inBuf, session->inBuf + frIn * session->inChannelCount,
-                    (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t));
-            session->framesIn -= frIn;
-        } else {
-            size_t fr = session->frameCount - session->framesIn;
-            if (inBuffer->frameCount < fr) {
-                fr = inBuffer->frameCount;
-            }
-            memcpy(session->procFrame->data_ + session->framesIn * session->inChannelCount,
-                   inBuffer->s16, fr * session->inChannelCount * sizeof(int16_t));
-
-#ifdef DUAL_MIC_TEST
-            pthread_mutex_lock(&gPcmDumpLock);
-            if (gPcmDumpFh != NULL) {
-                fwrite(inBuffer->raw, fr * session->inChannelCount * sizeof(int16_t), 1,
-                       gPcmDumpFh);
-            }
-            pthread_mutex_unlock(&gPcmDumpLock);
-#endif
-
-            session->framesIn += fr;
-            inBuffer->frameCount = fr;
-            if (session->framesIn < session->frameCount) {
-                return 0;
-            }
-            session->framesIn = 0;
-        }
-        session->procFrame->samples_per_channel_ = session->apmFrameCount;
-
-        effect->session->apm->ProcessStream(session->procFrame);
-#else
         size_t fr = session->frameCount - session->framesIn;
         if (inBuffer->frameCount < fr) {
             fr = inBuffer->frameCount;
@@ -1696,7 +1164,6 @@
             return status;
         }
         outBuffer->frameCount = inBuffer->frameCount;
-#endif
 
         if (session->outBufSize < session->framesOut + session->frameCount) {
             int16_t* buf;
@@ -1713,30 +1180,7 @@
             session->outBuf = buf;
         }
 
-#ifdef WEBRTC_LEGACY
-        if (session->outResampler != NULL) {
-            spx_uint32_t frIn = session->apmFrameCount;
-            spx_uint32_t frOut = session->frameCount;
-            if (session->inChannelCount == 1) {
-                speex_resampler_process_int(
-                        session->outResampler, 0, session->procFrame->data_, &frIn,
-                        session->outBuf + session->framesOut * session->outChannelCount, &frOut);
-            } else {
-                speex_resampler_process_interleaved_int(
-                        session->outResampler, session->procFrame->data_, &frIn,
-                        session->outBuf + session->framesOut * session->outChannelCount, &frOut);
-            }
-            session->framesOut += frOut;
-        } else {
-            memcpy(session->outBuf + session->framesOut * session->outChannelCount,
-                   session->procFrame->data_,
-                   session->frameCount * session->outChannelCount * sizeof(int16_t));
-            session->framesOut += session->frameCount;
-        }
-        size_t fr = session->framesOut;
-#else
         fr = session->framesOut;
-#endif
         if (framesRq - framesWr < fr) {
             fr = framesRq - framesWr;
         }
@@ -2129,63 +1573,6 @@
 
     if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
         effect->session->revProcessedMsk = 0;
-#ifdef WEBRTC_LEGACY
-        if (session->revResampler != NULL) {
-            size_t fr = session->frameCount - session->framesRev;
-            if (inBuffer->frameCount < fr) {
-                fr = inBuffer->frameCount;
-            }
-            if (session->revBufSize < session->framesRev + fr) {
-                int16_t* buf;
-                session->revBufSize = session->framesRev + fr;
-                buf = (int16_t*)realloc(
-                        session->revBuf,
-                        session->revBufSize * session->inChannelCount * sizeof(int16_t));
-                if (buf == NULL) {
-                    session->framesRev = 0;
-                    free(session->revBuf);
-                    session->revBuf = NULL;
-                    return -ENOMEM;
-                }
-                session->revBuf = buf;
-            }
-            memcpy(session->revBuf + session->framesRev * session->inChannelCount, inBuffer->s16,
-                   fr * session->inChannelCount * sizeof(int16_t));
-
-            session->framesRev += fr;
-            inBuffer->frameCount = fr;
-            if (session->framesRev < session->frameCount) {
-                return 0;
-            }
-            spx_uint32_t frIn = session->framesRev;
-            spx_uint32_t frOut = session->apmFrameCount;
-            if (session->inChannelCount == 1) {
-                speex_resampler_process_int(session->revResampler, 0, session->revBuf, &frIn,
-                                            session->revFrame->data_, &frOut);
-            } else {
-                speex_resampler_process_interleaved_int(session->revResampler, session->revBuf,
-                                                        &frIn, session->revFrame->data_, &frOut);
-            }
-            memmove(session->revBuf, session->revBuf + frIn * session->inChannelCount,
-                    (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t));
-            session->framesRev -= frIn;
-        } else {
-            size_t fr = session->frameCount - session->framesRev;
-            if (inBuffer->frameCount < fr) {
-                fr = inBuffer->frameCount;
-            }
-            memcpy(session->revFrame->data_ + session->framesRev * session->inChannelCount,
-                   inBuffer->s16, fr * session->inChannelCount * sizeof(int16_t));
-            session->framesRev += fr;
-            inBuffer->frameCount = fr;
-            if (session->framesRev < session->frameCount) {
-                return 0;
-            }
-            session->framesRev = 0;
-        }
-        session->revFrame->samples_per_channel_ = session->apmFrameCount;
-        effect->session->apm->AnalyzeReverseStream(session->revFrame);
-#else
         size_t fr = session->frameCount - session->framesRev;
         if (inBuffer->frameCount < fr) {
             fr = inBuffer->frameCount;
@@ -2205,7 +1592,6 @@
             ALOGE("Process Reverse Stream failed with error %d\n", status);
             return status;
         }
-#endif
         return 0;
     } else {
         return -ENODATA;
diff --git a/media/libeffects/preprocessing/benchmarks/Android.bp b/media/libeffects/preprocessing/benchmarks/Android.bp
index 2808293..262fd19 100644
--- a/media/libeffects/preprocessing/benchmarks/Android.bp
+++ b/media/libeffects/preprocessing/benchmarks/Android.bp
@@ -1,31 +1,4 @@
 cc_benchmark {
-    name: "preprocessing_legacy_benchmark",
-    vendor: true,
-    relative_install_path: "soundfx",
-    srcs: ["preprocessing_benchmark.cpp"],
-    shared_libs: [
-        "libaudiopreprocessing_legacy",
-        "libaudioutils",
-        "liblog",
-        "libutils",
-        "libwebrtc_audio_preprocessing",
-    ],
-    cflags: [
-        "-DWEBRTC_POSIX",
-        "-DWEBRTC_LEGACY",
-        "-fvisibility=default",
-        "-Wall",
-        "-Werror",
-        "-Wextra",
-    ],
-    header_libs: [
-        "libaudioeffects",
-        "libhardware_headers",
-        "libwebrtc_absl_headers",
-    ],
-}
-
-cc_benchmark {
     name: "preprocessing_benchmark",
     vendor: true,
     relative_install_path: "soundfx",
diff --git a/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp b/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp
index 3a0ad6d..694a6c4 100644
--- a/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp
+++ b/media/libeffects/preprocessing/benchmarks/preprocessing_benchmark.cpp
@@ -54,9 +54,7 @@
 #include <cstdlib>
 #include <random>
 #include <vector>
-#ifndef WEBRTC_LEGACY
 #include <audio_effects/effect_agc2.h>
-#endif
 #include <audio_effects/effect_ns.h>
 #include <benchmark/benchmark.h>
 #include <hardware/audio_effect.h>
@@ -76,10 +74,8 @@
         {0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
         // ns  uuid
         {0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
-#ifndef WEBRTC_LEGACY
         // agc2 uuid
         {0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}},
-#endif
 };
 constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
 constexpr audio_channel_mask_t kChMasks[] = {
@@ -93,9 +89,7 @@
     PREPROC_AGC,  // Automatic Gain Control
     PREPROC_AEC,  // Acoustic Echo Canceler
     PREPROC_NS,   // Noise Suppressor
-#ifndef WEBRTC_LEGACY
     PREPROC_AGC2,  // Automatic Gain Control 2
-#endif
     PREPROC_NUM_EFFECTS
 };
 
diff --git a/media/libeffects/preprocessing/tests/Android.bp b/media/libeffects/preprocessing/tests/Android.bp
index 045b0d3..b439880 100644
--- a/media/libeffects/preprocessing/tests/Android.bp
+++ b/media/libeffects/preprocessing/tests/Android.bp
@@ -1,37 +1,5 @@
 // audio preprocessing unit test
 cc_test {
-    name: "AudioPreProcessingLegacyTest",
-
-    vendor: true,
-
-    relative_install_path: "soundfx",
-
-    srcs: ["PreProcessingTest.cpp"],
-
-    shared_libs: [
-        "libaudiopreprocessing_legacy",
-        "libaudioutils",
-        "liblog",
-        "libutils",
-        "libwebrtc_audio_preprocessing",
-    ],
-
-    cflags: [
-        "-DWEBRTC_POSIX",
-        "-DWEBRTC_LEGACY",
-        "-fvisibility=default",
-        "-Wall",
-        "-Werror",
-        "-Wextra",
-    ],
-
-    header_libs: [
-        "libaudioeffects",
-        "libhardware_headers",
-    ],
-}
-
-cc_test {
     name: "AudioPreProcessingTest",
 
     vendor: true,
diff --git a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
index 65b9469..5f223c9 100644
--- a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
+++ b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
@@ -22,9 +22,7 @@
 
 #include <audio_effects/effect_aec.h>
 #include <audio_effects/effect_agc.h>
-#ifndef WEBRTC_LEGACY
 #include <audio_effects/effect_agc2.h>
-#endif
 #include <audio_effects/effect_ns.h>
 #include <log/log.h>
 
@@ -38,9 +36,7 @@
 // types of pre processing modules
 enum PreProcId {
     PREPROC_AGC,  // Automatic Gain Control
-#ifndef WEBRTC_LEGACY
     PREPROC_AGC2,  // Automatic Gain Control 2
-#endif
     PREPROC_AEC,  // Acoustic Echo Canceler
     PREPROC_NS,   // Noise Suppressor
     PREPROC_NUM_EFFECTS
@@ -57,11 +53,9 @@
     ARG_AGC_COMP_LVL,
     ARG_AEC_DELAY,
     ARG_NS_LVL,
-#ifndef WEBRTC_LEGACY
     ARG_AGC2_GAIN,
     ARG_AGC2_LVL,
     ARG_AGC2_SAT_MGN
-#endif
 };
 
 struct preProcConfigParams_t {
@@ -70,19 +64,15 @@
     int nsLevel = 0;         // a value between 0-3
     int agcTargetLevel = 3;  // in dB
     int agcCompLevel = 9;    // in dB
-#ifndef WEBRTC_LEGACY
     float agc2Gain = 0.f;              // in dB
     float agc2SaturationMargin = 2.f;  // in dB
     int agc2Level = 0;                 // either kRms(0) or kPeak(1)
-#endif
     int aecDelay = 0;  // in ms
 };
 
 const effect_uuid_t kPreProcUuids[PREPROC_NUM_EFFECTS] = {
         {0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},  // agc uuid
-#ifndef WEBRTC_LEGACY
         {0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}},  // agc2 uuid
-#endif
         {0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},  // aec uuid
         {0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},  // ns  uuid
 };
@@ -138,24 +128,20 @@
     printf("\n           Enable Noise Suppression, default disabled");
     printf("\n     --agc");
     printf("\n           Enable Gain Control, default disabled");
-#ifndef WEBRTC_LEGACY
     printf("\n     --agc2");
     printf("\n           Enable Gain Controller 2, default disabled");
-#endif
     printf("\n     --ns_lvl <ns_level>");
     printf("\n           Noise Suppression level in dB, default value 0dB");
     printf("\n     --agc_tgt_lvl <target_level>");
     printf("\n           AGC Target Level in dB, default value 3dB");
     printf("\n     --agc_comp_lvl <comp_level>");
     printf("\n           AGC Comp Level in dB, default value 9dB");
-#ifndef WEBRTC_LEGACY
     printf("\n     --agc2_gain <fixed_digital_gain>");
     printf("\n           AGC Fixed Digital Gain in dB, default value 0dB");
     printf("\n     --agc2_lvl <level_estimator>");
     printf("\n           AGC Adaptive Digital Level Estimator, default value kRms");
     printf("\n     --agc2_sat_mgn <saturation_margin>");
     printf("\n           AGC Adaptive Digital Saturation Margin in dB, default value 2dB");
-#endif
     printf("\n     --aec_delay <delay>");
     printf("\n           AEC delay value in ms, default value 0ms");
     printf("\n");
@@ -217,18 +203,14 @@
             {"ch_mask", required_argument, nullptr, ARG_CH_MASK},
             {"agc_tgt_lvl", required_argument, nullptr, ARG_AGC_TGT_LVL},
             {"agc_comp_lvl", required_argument, nullptr, ARG_AGC_COMP_LVL},
-#ifndef WEBRTC_LEGACY
             {"agc2_gain", required_argument, nullptr, ARG_AGC2_GAIN},
             {"agc2_lvl", required_argument, nullptr, ARG_AGC2_LVL},
             {"agc2_sat_mgn", required_argument, nullptr, ARG_AGC2_SAT_MGN},
-#endif
             {"aec_delay", required_argument, nullptr, ARG_AEC_DELAY},
             {"ns_lvl", required_argument, nullptr, ARG_NS_LVL},
             {"aec", no_argument, &effectEn[PREPROC_AEC], 1},
             {"agc", no_argument, &effectEn[PREPROC_AGC], 1},
-#ifndef WEBRTC_LEGACY
             {"agc2", no_argument, &effectEn[PREPROC_AGC2], 1},
-#endif
             {"ns", no_argument, &effectEn[PREPROC_NS], 1},
             {nullptr, 0, nullptr, 0},
     };
@@ -277,7 +259,6 @@
                 preProcCfgParams.agcCompLevel = atoi(optarg);
                 break;
             }
-#ifndef WEBRTC_LEGACY
             case ARG_AGC2_GAIN: {
                 preProcCfgParams.agc2Gain = atof(optarg);
                 break;
@@ -290,7 +271,6 @@
                 preProcCfgParams.agc2SaturationMargin = atof(optarg);
                 break;
             }
-#endif
             case ARG_AEC_DELAY: {
                 preProcCfgParams.aecDelay = atoi(optarg);
                 break;
@@ -387,7 +367,6 @@
             return EXIT_FAILURE;
         }
     }
-#ifndef WEBRTC_LEGACY
     if (effectEn[PREPROC_AGC2]) {
         if (int status = preProcSetConfigParam(AGC2_PARAM_FIXED_DIGITAL_GAIN,
                                                (float)preProcCfgParams.agc2Gain,
@@ -411,7 +390,6 @@
             return EXIT_FAILURE;
         }
     }
-#endif
     if (effectEn[PREPROC_NS]) {
         if (int status = preProcSetConfigParam(NS_PARAM_LEVEL, (uint32_t)preProcCfgParams.nsLevel,
                                                effectHandle[PREPROC_NS]);
diff --git a/media/libeffects/res/raw/sinesweepraw.raw b/media/libeffects/res/raw/sinesweepraw.raw
new file mode 100644
index 0000000..c0d48ce
--- /dev/null
+++ b/media/libeffects/res/raw/sinesweepraw.raw
Binary files differ
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index 39caf53..7ed76d8 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -38,7 +38,8 @@
     FLAGS,
     SETMEDIACAS,
     NAME,
-    GETMETRICS
+    GETMETRICS,
+    SETENTRYPOINT
 };
 
 class BpMediaExtractor : public BpInterface<IMediaExtractor> {
@@ -142,6 +143,13 @@
         }
         return nm;
     }
+
+    virtual status_t setEntryPoint(EntryPoint entryPoint) {
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+        data.writeInt32(static_cast<int32_t>(entryPoint));
+        return remote()->transact(SETENTRYPOINT, data, &reply);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(MediaExtractor, "android.media.IMediaExtractor");
@@ -232,6 +240,16 @@
             reply->writeString8(nm);
             return NO_ERROR;
         }
+        case SETENTRYPOINT: {
+            ALOGV("setEntryPoint");
+            CHECK_INTERFACE(IMediaExtractor, data, reply);
+            int32_t entryPoint;
+            status_t err = data.readInt32(&entryPoint);
+            if (err == OK) {
+                setEntryPoint(EntryPoint(entryPoint));
+            }
+            return err;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index da272e3..f682b6e 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -21,6 +21,7 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <algorithm>
 
 #include <media/MidiIoWrapper.h>
 #include <media/MediaExtractorPluginApi.h>
@@ -33,6 +34,8 @@
 }
 
 namespace android {
+int MidiIoWrapper::sCacheBufferSize = 0;
+Mutex MidiIoWrapper::mCacheLock;
 
 MidiIoWrapper::MidiIoWrapper(const char *path) {
     ALOGV("MidiIoWrapper(%s)", path);
@@ -40,6 +43,8 @@
     mBase = 0;
     mLength = lseek(mFd, 0, SEEK_END);
     mDataSource = nullptr;
+    mCacheBuffer = NULL;
+    mCacheBufRangeLength = 0;
 }
 
 MidiIoWrapper::MidiIoWrapper(int fd, off64_t offset, int64_t size) {
@@ -48,6 +53,8 @@
     mBase = offset;
     mLength = size;
     mDataSource = nullptr;
+    mCacheBuffer = NULL;
+    mCacheBufRangeLength = 0;
 }
 
 class MidiIoWrapper::DataSourceUnwrapper {
@@ -97,6 +104,8 @@
     } else {
         mLength = 0;
     }
+    mCacheBuffer = NULL;
+    mCacheBufRangeLength = 0;
 }
 
 MidiIoWrapper::~MidiIoWrapper() {
@@ -105,11 +114,80 @@
         close(mFd);
     }
     delete mDataSource;
+
+    if (NULL != mCacheBuffer) {
+        delete [] mCacheBuffer;
+        mCacheBuffer = NULL;
+        {
+            Mutex::Autolock _l(mCacheLock);
+            sCacheBufferSize -= mLength;
+        }
+    }
 }
 
 int MidiIoWrapper::readAt(void *buffer, int offset, int size) {
     ALOGV("readAt(%p, %d, %d)", buffer, offset, size);
 
+    if (offset < 0) {
+        return UNKNOWN_ERROR;
+    }
+
+    if (offset + size > mLength) {
+        size = mLength - offset;
+    }
+
+    if (mCacheBuffer == NULL) {
+        Mutex::Autolock _l(mCacheLock);
+        if (sCacheBufferSize + mLength <= kTotalCacheSize) {
+            mCacheBuffer = new (std::nothrow) unsigned char[mLength];
+            if (NULL != mCacheBuffer) {
+                sCacheBufferSize += mLength;
+                ALOGV("sCacheBufferSize : %d", sCacheBufferSize);
+            } else {
+                ALOGE("failed to allocate memory for mCacheBuffer");
+            }
+        } else {
+            ALOGV("not allocate memory for mCacheBuffer");
+        }
+    }
+
+    if (mCacheBuffer != NULL) {
+        if (mCacheBufRangeLength > 0 && mCacheBufRangeLength >= (offset + size)) {
+            /* Use buffered data */
+            memcpy(buffer, (void*)(mCacheBuffer + offset), size);
+            return size;
+        } else {
+            /* Buffer new data */
+            int64_t beyondCacheBufRangeLength = (offset + size) - mCacheBufRangeLength;
+            int64_t numRequiredBytesToCache =
+                  std::max((int64_t)kSingleCacheSize, beyondCacheBufRangeLength);
+            int64_t availableReadLength = mLength - mCacheBufRangeLength;
+            int64_t readSize = std::min(availableReadLength, numRequiredBytesToCache);
+            int actualNumBytesRead =
+                unbufferedReadAt(mCacheBuffer + mCacheBufRangeLength,
+                        mCacheBufRangeLength, readSize);
+            if(actualNumBytesRead > 0) {
+                mCacheBufRangeLength += actualNumBytesRead;
+                if (offset >= mCacheBufRangeLength) {
+                    return 0;
+                } else if (offset + size >= mCacheBufRangeLength) {
+                    memcpy(buffer, (void*)(mCacheBuffer + offset), mCacheBufRangeLength - offset);
+                    return mCacheBufRangeLength - offset;
+                } else {
+                    memcpy(buffer, (void*)(mCacheBuffer + offset), size);
+                    return size;
+                }
+            } else {
+                return actualNumBytesRead;
+            }
+        }
+    } else {
+        return unbufferedReadAt(buffer, offset, size);
+    }
+}
+
+int MidiIoWrapper::unbufferedReadAt(void *buffer, int offset, int size) {
+    ALOGV("unbufferedReadAt(%p, %d, %d)", buffer, offset, size);
     if (mDataSource != NULL) {
         return mDataSource->readAt(offset, buffer, size);
     }
diff --git a/media/libmedia/include/android/IMediaExtractor.h b/media/libmedia/include/android/IMediaExtractor.h
index 3e035ad..f9cafde 100644
--- a/media/libmedia/include/android/IMediaExtractor.h
+++ b/media/libmedia/include/android/IMediaExtractor.h
@@ -63,6 +63,15 @@
     virtual status_t setMediaCas(const HInterfaceToken &casToken) = 0;
 
     virtual String8 name() = 0;
+
+    enum class EntryPoint {
+        SDK = 1,
+        NDK_WITH_JVM = 2,
+        NDK_NO_JVM = 3,
+        OTHER = 4,
+    };
+
+    virtual status_t setEntryPoint(EntryPoint entryPoint) = 0;
 };
 
 
diff --git a/media/libmedia/include/media/MidiIoWrapper.h b/media/libmedia/include/media/MidiIoWrapper.h
index 0cdd4ad..5fa745c 100644
--- a/media/libmedia/include/media/MidiIoWrapper.h
+++ b/media/libmedia/include/media/MidiIoWrapper.h
@@ -18,6 +18,7 @@
 #define MIDI_IO_WRAPPER_H_
 
 #include <libsonivox/eas_types.h>
+#include <utils/Mutex.h>
 
 namespace android {
 
@@ -32,17 +33,27 @@
     ~MidiIoWrapper();
 
     int readAt(void *buffer, int offset, int size);
+    int unbufferedReadAt(void *buffer, int offset, int size);
     int size();
 
     EAS_FILE_LOCATOR getLocator();
 
 private:
+    enum {
+        kTotalCacheSize      = 1024 * 1024 + 512 * 1024,
+        kSingleCacheSize     = 65536,
+    };
+
     int mFd;
     off64_t mBase;
     int64_t  mLength;
     class DataSourceUnwrapper;
     DataSourceUnwrapper *mDataSource;
     EAS_FILE mEasFile;
+    unsigned char *mCacheBuffer;
+    int64_t mCacheBufRangeLength;
+    static int sCacheBufferSize;
+    static Mutex mCacheLock;
 };
 
 
diff --git a/media/libmedia/include/media/mediametadataretriever.h b/media/libmedia/include/media/mediametadataretriever.h
index 1fe6ffc..fba1a30 100644
--- a/media/libmedia/include/media/mediametadataretriever.h
+++ b/media/libmedia/include/media/mediametadataretriever.h
@@ -74,6 +74,8 @@
     METADATA_KEY_SAMPLERATE      = 38,
     METADATA_KEY_BITS_PER_SAMPLE = 39,
     METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40,
+    METADATA_KEY_XMP_OFFSET      = 41,
+    METADATA_KEY_XMP_LENGTH      = 42,
 
     // Add more here...
 };
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 1cc255d..89c7032 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -127,7 +127,8 @@
     pid_t pid = IPCThreadState::self()->getCallingPid();
     uid_t uid = IPCThreadState::self()->getCallingUid();
 
-    if ((as == AUDIO_SOURCE_FM_TUNER && !captureAudioOutputAllowed(pid, uid))
+    if ((as == AUDIO_SOURCE_FM_TUNER
+            && !(captureAudioOutputAllowed(pid, uid) || captureTunerAudioInputAllowed(pid, uid)))
             || !recordingAllowed(String16(""), pid, uid)) {
         return PERMISSION_DENIED;
     }
diff --git a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
index 02fb6bb..6dc3e3f 100644
--- a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -529,6 +529,15 @@
         mMetaData.add(METADATA_KEY_EXIF_LENGTH, String8(tmp));
     }
 
+    int64_t xmpOffset, xmpSize;
+    if (meta->findInt64(kKeyXmpOffset, &xmpOffset)
+     && meta->findInt64(kKeyXmpSize, &xmpSize)) {
+        sprintf(tmp, "%lld", (long long)xmpOffset);
+        mMetaData.add(METADATA_KEY_XMP_OFFSET, String8(tmp));
+        sprintf(tmp, "%lld", (long long)xmpSize);
+        mMetaData.add(METADATA_KEY_XMP_LENGTH, String8(tmp));
+    }
+
     bool hasAudio = false;
     bool hasVideo = false;
     int32_t videoWidth = -1;
@@ -629,7 +638,8 @@
     }
 
     // The duration value is a string representing the duration in ms.
-    sprintf(tmp, "%" PRId64, (maxDurationUs + 500) / 1000);
+    sprintf(tmp, "%" PRId64,
+           (maxDurationUs > (INT64_MAX - 500) ? INT64_MAX : (maxDurationUs + 500)) / 1000);
     mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
 
     if (hasAudio) {
diff --git a/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp b/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
index 5a52ea5..d08c66d 100644
--- a/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
+++ b/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
@@ -41,7 +41,7 @@
         "libmediandk",
     ],
 
-    compile_multilib: "32",
+    compile_multilib: "prefer32",
 
     cflags: [
         "-Werror",
diff --git a/media/libmediatranscoding/Android.bp b/media/libmediatranscoding/Android.bp
index ec806d1..094d7c3 100644
--- a/media/libmediatranscoding/Android.bp
+++ b/media/libmediatranscoding/Android.bp
@@ -44,13 +44,32 @@
     {
         java: {
             enabled: true,
+            apex_available: [
+                "com.android.media",
+                "test_com.android.media",
+            ],
+            min_sdk_version: "29",
+        },
+        ndk: {
+            enabled: true,
+            apex_available: [
+                "com.android.media",
+                "test_com.android.media",
+            ],
+            min_sdk_version: "29",
         },
     },
 }
 
-cc_library_shared {
+cc_library {
     name: "libmediatranscoding",
 
+    min_sdk_version: "29",
+    apex_available: [
+        "com.android.media",
+        "test_com.android.media",
+    ],
+
     srcs: [
         "TranscodingClientManager.cpp",
         "TranscodingSessionController.cpp",
@@ -60,13 +79,12 @@
     ],
 
     shared_libs: [
-        "libandroid",
+        "libandroid#31",
         "libbinder_ndk",
         "libcutils",
         "liblog",
         "libutils",
         "libmediatranscoder",
-        "libbinder",
         "libmediandk",
     ],
     export_shared_lib_headers: [
diff --git a/media/libmediatranscoding/TranscodingResourcePolicy.cpp b/media/libmediatranscoding/TranscodingResourcePolicy.cpp
index f2e973a..af53f64 100644
--- a/media/libmediatranscoding/TranscodingResourcePolicy.cpp
+++ b/media/libmediatranscoding/TranscodingResourcePolicy.cpp
@@ -21,7 +21,6 @@
 #include <aidl/android/media/IResourceObserverService.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
-#include <binder/IServiceManager.h>
 #include <media/TranscodingResourcePolicy.h>
 #include <utils/Log.h>
 
diff --git a/media/libmediatranscoding/TranscodingSessionController.cpp b/media/libmediatranscoding/TranscodingSessionController.cpp
index 49a7083..b77a3a4 100644
--- a/media/libmediatranscoding/TranscodingSessionController.cpp
+++ b/media/libmediatranscoding/TranscodingSessionController.cpp
@@ -31,6 +31,7 @@
 static_assert((SessionIdType)-1 < 0, "SessionIdType should be signed");
 
 constexpr static uid_t OFFLINE_UID = -1;
+constexpr static size_t kSessionHistoryMax = 100;
 
 //static
 String8 TranscodingSessionController::sessionToString(const SessionKeyType& sessionKey) {
@@ -47,6 +48,12 @@
         return "RUNNING";
     case Session::State::PAUSED:
         return "PAUSED";
+    case Session::State::FINISHED:
+        return "FINISHED";
+    case Session::State::CANCELED:
+        return "CANCELED";
+    case Session::State::ERROR:
+        return "ERROR";
     default:
         break;
     }
@@ -71,6 +78,30 @@
 
 TranscodingSessionController::~TranscodingSessionController() {}
 
+void TranscodingSessionController::dumpSession_l(const Session& session, String8& result,
+                                                 bool closedSession) {
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    const TranscodingRequestParcel& request = session.request;
+    snprintf(buffer, SIZE, "      Session: %s, %s, %d%%\n", sessionToString(session.key).c_str(),
+             sessionStateToString(session.getState()), session.lastProgress);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "        pkg: %s\n", request.clientPackageName.c_str());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "        src: %s\n", request.sourceFilePath.c_str());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "        dst: %s\n", request.destinationFilePath.c_str());
+    result.append(buffer);
+
+    if (closedSession) {
+        snprintf(buffer, SIZE,
+                 "        waiting: %.1fs, running: %.1fs, paused: %.1fs, paused count: %d\n",
+                 session.waitingTime.count() / 1000000.0f, session.runningTime.count() / 1000000.0f,
+                 session.pausedTime.count() / 1000000.0f, session.pauseCount);
+        result.append(buffer);
+    }
+}
+
 void TranscodingSessionController::dumpAllSessions(int fd, const Vector<String16>& args __unused) {
     String8 result;
 
@@ -78,7 +109,7 @@
     char buffer[SIZE];
     std::scoped_lock lock{mLock};
 
-    snprintf(buffer, SIZE, "\n========== Dumping all sessions queues =========\n");
+    snprintf(buffer, SIZE, "\n========== Dumping live sessions queues =========\n");
     result.append(buffer);
     snprintf(buffer, SIZE, "  Total num of Sessions: %zu\n", mSessionMap.size());
     result.append(buffer);
@@ -91,7 +122,7 @@
         if (mSessionQueues[uid].empty()) {
             continue;
         }
-        snprintf(buffer, SIZE, "    Uid: %d, pkg: %s\n", uid,
+        snprintf(buffer, SIZE, "    uid: %d, pkg: %s\n", uid,
                  mUidPackageNames.count(uid) > 0 ? mUidPackageNames[uid].c_str() : "(unknown)");
         result.append(buffer);
         snprintf(buffer, SIZE, "      Num of sessions: %zu\n", mSessionQueues[uid].size());
@@ -104,25 +135,16 @@
                 result.append(buffer);
                 continue;
             }
-            Session& session = sessionIt->second;
-            TranscodingRequestParcel& request = session.request;
-            snprintf(buffer, SIZE, "      Session: %s, %s, %d%%\n",
-                     sessionToString(sessionKey).c_str(), sessionStateToString(session.state),
-                     session.lastProgress);
-            result.append(buffer);
-            snprintf(buffer, SIZE, "        Src: %s\n", request.sourceFilePath.c_str());
-            result.append(buffer);
-            snprintf(buffer, SIZE, "        Dst: %s\n", request.destinationFilePath.c_str());
-            result.append(buffer);
-            // For the offline queue, print out the original client.
-            if (uid == OFFLINE_UID) {
-                snprintf(buffer, SIZE, "        Original Client: %s\n",
-                         request.clientPackageName.c_str());
-                result.append(buffer);
-            }
+            dumpSession_l(sessionIt->second, result);
         }
     }
 
+    snprintf(buffer, SIZE, "\n========== Dumping past sessions =========\n");
+    result.append(buffer);
+    for (auto &session : mSessionHistory) {
+        dumpSession_l(session, result, true /*closedSession*/);
+    }
+
     write(fd, result.string(), result.size());
 }
 
@@ -135,6 +157,34 @@
     return &mSessionMap[topSessionKey];
 }
 
+void TranscodingSessionController::Session::setState(Session::State newState) {
+    if (state == newState) {
+        return;
+    }
+    auto nowTime = std::chrono::system_clock::now();
+    if (state != INVALID) {
+        std::chrono::microseconds elapsedTime = (nowTime - stateEnterTime);
+        switch (state) {
+        case PAUSED:
+            pausedTime = pausedTime + elapsedTime;
+            break;
+        case RUNNING:
+            runningTime = runningTime + elapsedTime;
+            break;
+        case NOT_STARTED:
+            waitingTime = waitingTime + elapsedTime;
+            break;
+        default:
+            break;
+        }
+    }
+    if (newState == PAUSED) {
+        pauseCount++;
+    }
+    stateEnterTime = nowTime;
+    state = newState;
+}
+
 void TranscodingSessionController::updateCurrentSession_l() {
     Session* topSession = getTopSession_l();
     Session* curSession = mCurrentSession;
@@ -145,29 +195,30 @@
     // If we found a topSession that should be run, and it's not already running,
     // take some actions to ensure it's running.
     if (topSession != nullptr &&
-        (topSession != curSession || topSession->state != Session::RUNNING)) {
+        (topSession != curSession || topSession->getState() != Session::RUNNING)) {
         // If another session is currently running, pause it first.
-        if (curSession != nullptr && curSession->state == Session::RUNNING) {
+        if (curSession != nullptr && curSession->getState() == Session::RUNNING) {
             mTranscoder->pause(curSession->key.first, curSession->key.second);
-            curSession->state = Session::PAUSED;
+            curSession->setState(Session::PAUSED);
         }
         // If we are not experiencing resource loss, we can start or resume
         // the topSession now.
         if (!mResourceLost) {
-            if (topSession->state == Session::NOT_STARTED) {
+            if (topSession->getState() == Session::NOT_STARTED) {
                 mTranscoder->start(topSession->key.first, topSession->key.second,
                                    topSession->request, topSession->callback.lock());
-            } else if (topSession->state == Session::PAUSED) {
+            } else if (topSession->getState() == Session::PAUSED) {
                 mTranscoder->resume(topSession->key.first, topSession->key.second,
                                     topSession->request, topSession->callback.lock());
             }
-            topSession->state = Session::RUNNING;
+            topSession->setState(Session::RUNNING);
         }
     }
     mCurrentSession = topSession;
 }
 
-void TranscodingSessionController::removeSession_l(const SessionKeyType& sessionKey) {
+void TranscodingSessionController::removeSession_l(const SessionKeyType& sessionKey,
+                                                   Session::State finalState) {
     ALOGV("%s: session %s", __FUNCTION__, sessionToString(sessionKey).c_str());
 
     if (mSessionMap.count(sessionKey) == 0) {
@@ -201,6 +252,12 @@
         mCurrentSession = nullptr;
     }
 
+    mSessionMap[sessionKey].setState(finalState);
+    mSessionHistory.push_back(mSessionMap[sessionKey]);
+    if (mSessionHistory.size() > kSessionHistoryMax) {
+        mSessionHistory.erase(mSessionHistory.begin());
+    }
+
     // Remove session from session map.
     mSessionMap.erase(sessionKey);
 }
@@ -288,10 +345,11 @@
     // Add session to session map.
     mSessionMap[sessionKey].key = sessionKey;
     mSessionMap[sessionKey].uid = uid;
-    mSessionMap[sessionKey].state = Session::NOT_STARTED;
     mSessionMap[sessionKey].lastProgress = 0;
+    mSessionMap[sessionKey].pauseCount = 0;
     mSessionMap[sessionKey].request = request;
     mSessionMap[sessionKey].callback = callback;
+    mSessionMap[sessionKey].setState(Session::NOT_STARTED);
 
     // If it's an offline session, the queue was already added in constructor.
     // If it's a real-time sessions, check if a queue is already present for the uid,
@@ -350,12 +408,12 @@
         // Note that stop() is needed even if the session is currently paused. This instructs
         // the transcoder to discard any states for the session, otherwise the states may
         // never be discarded.
-        if (mSessionMap[*it].state != Session::NOT_STARTED) {
+        if (mSessionMap[*it].getState() != Session::NOT_STARTED) {
             mTranscoder->stop(it->first, it->second);
         }
 
         // Remove the session.
-        removeSession_l(*it);
+        removeSession_l(*it, Session::CANCELED);
     }
 
     // Start next session.
@@ -396,7 +454,7 @@
     // Only ignore if session was never started. In particular, propagate the status
     // to client if the session is paused. Transcoder could have posted finish when
     // we're pausing it, and the finish arrived after we changed current session.
-    if (mSessionMap[sessionKey].state == Session::NOT_STARTED) {
+    if (mSessionMap[sessionKey].getState() == Session::NOT_STARTED) {
         ALOGW("%s: ignoring %s for session %s that was never started", __FUNCTION__, reason,
               sessionToString(sessionKey).c_str());
         return;
@@ -445,7 +503,7 @@
         }
 
         // Remove the session.
-        removeSession_l(sessionKey);
+        removeSession_l(sessionKey, Session::FINISHED);
 
         // Start next session.
         updateCurrentSession_l();
@@ -465,7 +523,7 @@
         }
 
         // Remove the session.
-        removeSession_l(sessionKey);
+        removeSession_l(sessionKey, Session::ERROR);
 
         // Start next session.
         updateCurrentSession_l();
@@ -494,15 +552,15 @@
         }
 
         Session* resourceLostSession = &mSessionMap[sessionKey];
-        if (resourceLostSession->state != Session::RUNNING) {
+        if (resourceLostSession->getState() != Session::RUNNING) {
             ALOGW("session %s lost resource but is no longer running",
-                    sessionToString(sessionKey).c_str());
+                  sessionToString(sessionKey).c_str());
             return;
         }
         // If we receive a resource loss event, the transcoder already paused the transcoding,
         // so we don't need to call onPaused() to pause it. However, we still need to notify
         // the client and update the session state here.
-        resourceLostSession->state = Session::PAUSED;
+        resourceLostSession->setState(Session::PAUSED);
         // Notify the client as a paused event.
         auto clientCallback = resourceLostSession->callback.lock();
         if (clientCallback != nullptr) {
diff --git a/media/libmediatranscoding/TranscodingUidPolicy.cpp b/media/libmediatranscoding/TranscodingUidPolicy.cpp
index 8a74d5d..a725387 100644
--- a/media/libmediatranscoding/TranscodingUidPolicy.cpp
+++ b/media/libmediatranscoding/TranscodingUidPolicy.cpp
@@ -17,11 +17,9 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "TranscodingUidPolicy"
 
+#include <android/activity_manager.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
-#include <binder/ActivityManager.h>
-#include <cutils/misc.h>  // FIRST_APPLICATION_UID
-#include <cutils/multiuser.h>
 #include <inttypes.h>
 #include <media/TranscodingUidPolicy.h>
 #include <utils/Log.h>
@@ -31,51 +29,12 @@
 namespace android {
 
 constexpr static uid_t OFFLINE_UID = -1;
-constexpr static const char* kTranscodingTag = "transcoding";
-
-struct TranscodingUidPolicy::UidObserver : public BnUidObserver,
-                                           public virtual IBinder::DeathRecipient {
-    explicit UidObserver(TranscodingUidPolicy* owner) : mOwner(owner) {}
-
-    // IUidObserver
-    void onUidGone(uid_t uid, bool disabled) override;
-    void onUidActive(uid_t uid) override;
-    void onUidIdle(uid_t uid, bool disabled) override;
-    void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
-                           int32_t capability) override;
-
-    // IBinder::DeathRecipient implementation
-    void binderDied(const wp<IBinder>& who) override;
-
-    TranscodingUidPolicy* mOwner;
-};
-
-void TranscodingUidPolicy::UidObserver::onUidGone(uid_t uid __unused, bool disabled __unused) {}
-
-void TranscodingUidPolicy::UidObserver::onUidActive(uid_t uid __unused) {}
-
-void TranscodingUidPolicy::UidObserver::onUidIdle(uid_t uid __unused, bool disabled __unused) {}
-
-void TranscodingUidPolicy::UidObserver::onUidStateChanged(uid_t uid, int32_t procState,
-                                                          int64_t procStateSeq __unused,
-                                                          int32_t capability __unused) {
-    mOwner->onUidStateChanged(uid, procState);
-}
-
-void TranscodingUidPolicy::UidObserver::binderDied(const wp<IBinder>& /*who*/) {
-    ALOGW("TranscodingUidPolicy: ActivityManager has died");
-    // TODO(chz): this is a rare event (since if the AMS is dead, the system is
-    // probably dead as well). But we should try to reconnect.
-    mOwner->setUidObserverRegistered(false);
-}
-
-////////////////////////////////////////////////////////////////////////////
+constexpr static int32_t IMPORTANCE_UNKNOWN = INT32_MAX;
 
 TranscodingUidPolicy::TranscodingUidPolicy()
-      : mAm(std::make_shared<ActivityManager>()),
-        mUidObserver(new UidObserver(this)),
+      : mUidObserver(nullptr),
         mRegistered(false),
-        mTopUidState(ActivityManager::PROCESS_STATE_UNKNOWN) {
+        mTopUidState(IMPORTANCE_UNKNOWN) {
     registerSelf();
 }
 
@@ -83,39 +42,32 @@
     unregisterSelf();
 }
 
+void TranscodingUidPolicy::OnUidImportance(uid_t uid, int32_t uidImportance, void* cookie) {
+    TranscodingUidPolicy* owner = reinterpret_cast<TranscodingUidPolicy*>(cookie);
+    owner->onUidStateChanged(uid, uidImportance);
+}
+
 void TranscodingUidPolicy::registerSelf() {
-    status_t res = mAm->linkToDeath(mUidObserver.get());
-    mAm->registerUidObserver(
-            mUidObserver.get(),
-            ActivityManager::UID_OBSERVER_GONE | ActivityManager::UID_OBSERVER_IDLE |
-                    ActivityManager::UID_OBSERVER_ACTIVE | ActivityManager::UID_OBSERVER_PROCSTATE,
-            ActivityManager::PROCESS_STATE_UNKNOWN, String16(kTranscodingTag));
+    mUidObserver = AActivityManager_addUidImportanceListener(
+            &OnUidImportance, -1, (void*)this);
 
-    if (res == OK) {
-        Mutex::Autolock _l(mUidLock);
-
-        mRegistered = true;
-        ALOGI("TranscodingUidPolicy: Registered with ActivityManager");
-    } else {
-        mAm->unregisterUidObserver(mUidObserver.get());
+    if (mUidObserver == nullptr) {
+        ALOGE("Failed to register uid observer");
+        return;
     }
+
+    Mutex::Autolock _l(mUidLock);
+    mRegistered = true;
+    ALOGI("Registered uid observer");
 }
 
 void TranscodingUidPolicy::unregisterSelf() {
-    mAm->unregisterUidObserver(mUidObserver.get());
-    mAm->unlinkToDeath(mUidObserver.get());
+    AActivityManager_removeUidImportanceListener(mUidObserver);
+    mUidObserver = nullptr;
 
     Mutex::Autolock _l(mUidLock);
-
     mRegistered = false;
-
-    ALOGI("TranscodingUidPolicy: Unregistered with ActivityManager");
-}
-
-void TranscodingUidPolicy::setUidObserverRegistered(bool registered) {
-    Mutex::Autolock _l(mUidLock);
-
-    mRegistered = registered;
+    ALOGI("Unregistered uid observer");
 }
 
 void TranscodingUidPolicy::setCallback(const std::shared_ptr<UidPolicyCallbackInterface>& cb) {
@@ -133,9 +85,9 @@
         return;
     }
 
-    int32_t state = ActivityManager::PROCESS_STATE_UNKNOWN;
-    if (mRegistered && mAm->isUidActive(uid, String16(kTranscodingTag))) {
-        state = mAm->getUidProcessState(uid, String16(kTranscodingTag));
+    int32_t state = IMPORTANCE_UNKNOWN;
+    if (mRegistered && AActivityManager_isUidActive(uid)) {
+        state = AActivityManager_getUidImportance(uid);
     }
 
     ALOGV("%s: inserting new uid: %u, procState %d", __FUNCTION__, uid, state);
@@ -170,14 +122,14 @@
 bool TranscodingUidPolicy::isUidOnTop(uid_t uid) {
     Mutex::Autolock _l(mUidLock);
 
-    return mTopUidState != ActivityManager::PROCESS_STATE_UNKNOWN &&
+    return mTopUidState != IMPORTANCE_UNKNOWN &&
            mTopUidState == getProcState_l(uid);
 }
 
 std::unordered_set<uid_t> TranscodingUidPolicy::getTopUids() const {
     Mutex::Autolock _l(mUidLock);
 
-    if (mTopUidState == ActivityManager::PROCESS_STATE_UNKNOWN) {
+    if (mTopUidState == IMPORTANCE_UNKNOWN) {
         return std::unordered_set<uid_t>();
     }
 
@@ -195,11 +147,13 @@
         if (it != mUidStateMap.end() && it->second != procState) {
             // Top set changed if 1) the uid is in the current top uid set, or 2) the
             // new procState is at least the same priority as the current top uid state.
-            bool isUidCurrentTop = mTopUidState != ActivityManager::PROCESS_STATE_UNKNOWN &&
-                                   mStateUidMap[mTopUidState].count(uid) > 0;
-            bool isNewStateHigherThanTop = procState != ActivityManager::PROCESS_STATE_UNKNOWN &&
-                                           (procState <= mTopUidState ||
-                                            mTopUidState == ActivityManager::PROCESS_STATE_UNKNOWN);
+            bool isUidCurrentTop =
+                    mTopUidState != IMPORTANCE_UNKNOWN &&
+                    mStateUidMap[mTopUidState].count(uid) > 0;
+            bool isNewStateHigherThanTop =
+                    procState != IMPORTANCE_UNKNOWN &&
+                    (procState <= mTopUidState ||
+                     mTopUidState == IMPORTANCE_UNKNOWN);
             topUidSetChanged = (isUidCurrentTop || isNewStateHigherThanTop);
 
             // Move uid to the new procState.
@@ -227,11 +181,12 @@
 }
 
 void TranscodingUidPolicy::updateTopUid_l() {
-    mTopUidState = ActivityManager::PROCESS_STATE_UNKNOWN;
+    mTopUidState = IMPORTANCE_UNKNOWN;
 
     // Find the lowest uid state (ignoring PROCESS_STATE_UNKNOWN) with some monitored uids.
     for (auto stateIt = mStateUidMap.begin(); stateIt != mStateUidMap.end(); stateIt++) {
-        if (stateIt->first != ActivityManager::PROCESS_STATE_UNKNOWN && !stateIt->second.empty()) {
+        if (stateIt->first != IMPORTANCE_UNKNOWN &&
+            !stateIt->second.empty()) {
             mTopUidState = stateIt->first;
             break;
         }
@@ -245,7 +200,7 @@
     if (it != mUidStateMap.end()) {
         return it->second;
     }
-    return ActivityManager::PROCESS_STATE_UNKNOWN;
+    return IMPORTANCE_UNKNOWN;
 }
 
 }  // namespace android
diff --git a/media/libmediatranscoding/include/media/TranscoderWrapper.h b/media/libmediatranscoding/include/media/TranscoderWrapper.h
index 9ec32d7..02beede 100644
--- a/media/libmediatranscoding/include/media/TranscoderWrapper.h
+++ b/media/libmediatranscoding/include/media/TranscoderWrapper.h
@@ -17,7 +17,6 @@
 #ifndef ANDROID_TRANSCODER_WRAPPER_H
 #define ANDROID_TRANSCODER_WRAPPER_H
 
-#include <android-base/thread_annotations.h>
 #include <media/NdkMediaError.h>
 #include <media/TranscoderInterface.h>
 
diff --git a/media/libmediatranscoding/include/media/TranscodingSessionController.h b/media/libmediatranscoding/include/media/TranscodingSessionController.h
index 4215e06..a443265 100644
--- a/media/libmediatranscoding/include/media/TranscodingSessionController.h
+++ b/media/libmediatranscoding/include/media/TranscodingSessionController.h
@@ -26,6 +26,7 @@
 #include <utils/String8.h>
 #include <utils/Vector.h>
 
+#include <chrono>
 #include <list>
 #include <map>
 #include <mutex>
@@ -82,16 +83,33 @@
     using SessionQueueType = std::list<SessionKeyType>;
 
     struct Session {
-        SessionKeyType key;
-        uid_t uid;
         enum State {
-            NOT_STARTED,
+            INVALID = -1,
+            NOT_STARTED = 0,
             RUNNING,
             PAUSED,
-        } state;
+            FINISHED,
+            CANCELED,
+            ERROR,
+        };
+        SessionKeyType key;
+        uid_t uid;
         int32_t lastProgress;
+        int32_t pauseCount;
+        std::chrono::time_point<std::chrono::system_clock> stateEnterTime;
+        std::chrono::microseconds waitingTime;
+        std::chrono::microseconds runningTime;
+        std::chrono::microseconds pausedTime;
+
         TranscodingRequest request;
         std::weak_ptr<ITranscodingClientCallback> callback;
+
+        // Must use setState to change state.
+        void setState(Session::State state);
+        State getState() const { return state; }
+
+    private:
+        State state = INVALID;
     };
 
     // TODO(chz): call transcoder without global lock.
@@ -115,15 +133,17 @@
 
     Session* mCurrentSession;
     bool mResourceLost;
+    std::list<Session> mSessionHistory;
 
     // Only allow MediaTranscodingService and unit tests to instantiate.
     TranscodingSessionController(const std::shared_ptr<TranscoderInterface>& transcoder,
                                  const std::shared_ptr<UidPolicyInterface>& uidPolicy,
                                  const std::shared_ptr<ResourcePolicyInterface>& resourcePolicy);
 
+    void dumpSession_l(const Session& session, String8& result, bool closedSession = false);
     Session* getTopSession_l();
     void updateCurrentSession_l();
-    void removeSession_l(const SessionKeyType& sessionKey);
+    void removeSession_l(const SessionKeyType& sessionKey, Session::State finalState);
     void moveUidsToTop_l(const std::unordered_set<uid_t>& uids, bool preserveTopUid);
     void notifyClient(ClientIdType clientId, SessionIdType sessionId, const char* reason,
                       std::function<void(const SessionKeyType&)> func);
diff --git a/media/libmediatranscoding/include/media/TranscodingUidPolicy.h b/media/libmediatranscoding/include/media/TranscodingUidPolicy.h
index acd3cff..4dde5a6 100644
--- a/media/libmediatranscoding/include/media/TranscodingUidPolicy.h
+++ b/media/libmediatranscoding/include/media/TranscodingUidPolicy.h
@@ -22,18 +22,16 @@
 #include <media/UidPolicyInterface.h>
 #include <sys/types.h>
 #include <utils/Condition.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
 
 #include <map>
 #include <mutex>
 #include <unordered_map>
 #include <unordered_set>
 
+struct AActivityManager_UidImportanceListener;
+
 namespace android {
 
-class ActivityManager;
 // Observer for UID lifecycle and provide information about the uid's app
 // priority used by the session controller.
 class TranscodingUidPolicy : public UidPolicyInterface {
@@ -51,17 +49,17 @@
 
 private:
     void onUidStateChanged(uid_t uid, int32_t procState);
-    void setUidObserverRegistered(bool registerd);
     void registerSelf();
     void unregisterSelf();
     int32_t getProcState_l(uid_t uid) NO_THREAD_SAFETY_ANALYSIS;
     void updateTopUid_l() NO_THREAD_SAFETY_ANALYSIS;
 
-    struct UidObserver;
+    static void OnUidImportance(uid_t uid, int32_t uidImportance, void* cookie);
+
     struct ResourceManagerClient;
     mutable Mutex mUidLock;
-    std::shared_ptr<ActivityManager> mAm;
-    sp<UidObserver> mUidObserver;
+    AActivityManager_UidImportanceListener* mUidObserver;
+
     bool mRegistered GUARDED_BY(mUidLock);
     int32_t mTopUidState GUARDED_BY(mUidLock);
     std::unordered_map<uid_t, int32_t> mUidStateMap GUARDED_BY(mUidLock);
diff --git a/media/libmediatranscoding/tests/Android.bp b/media/libmediatranscoding/tests/Android.bp
index e49df35..8bff10a 100644
--- a/media/libmediatranscoding/tests/Android.bp
+++ b/media/libmediatranscoding/tests/Android.bp
@@ -14,15 +14,16 @@
     ],
 
     shared_libs: [
+        "libandroid",
         "libbinder_ndk",
         "libcutils",
         "liblog",
         "libutils",
-        "libmediatranscoding"
     ],
 
     static_libs: [
         "mediatranscoding_aidl_interface-ndk_platform",
+        "libmediatranscoding",
     ],
 
     cflags: [
diff --git a/media/libmediatranscoding/transcoder/Android.bp b/media/libmediatranscoding/transcoder/Android.bp
index aa7cdde..bebe6b1 100644
--- a/media/libmediatranscoding/transcoder/Android.bp
+++ b/media/libmediatranscoding/transcoder/Android.bp
@@ -28,6 +28,14 @@
         "VideoTrackTranscoder.cpp",
     ],
 
+    min_sdk_version: "29",
+    apex_available: [
+        "com.android.media",
+        "test_com.android.media",
+    ],
+
+    //header_libs: [ "libarect_headers", "libarect_headers_for_ndk" ],
+    static_libs: [ "libarect" ],
     shared_libs: [
         "libbase",
         "libcutils",
diff --git a/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp b/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
index 92ba818..1a6e7ed 100644
--- a/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
+++ b/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
@@ -235,6 +235,33 @@
     return AMEDIA_OK;
 }
 
+media_status_t MediaSampleReaderNDK::unselectTrack(int trackIndex) {
+    std::scoped_lock lock(mExtractorMutex);
+
+    if (trackIndex < 0 || trackIndex >= mTrackCount) {
+        LOG(ERROR) << "Invalid trackIndex " << trackIndex << " for trackCount " << mTrackCount;
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    } else if (mExtractorTrackIndex >= 0) {
+        LOG(ERROR) << "unselectTrack must be called before sample reading begins.";
+        return AMEDIA_ERROR_UNSUPPORTED;
+    }
+
+    auto it = mTrackSignals.find(trackIndex);
+    if (it == mTrackSignals.end()) {
+        LOG(ERROR) << "TrackIndex " << trackIndex << " is not selected";
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    }
+    mTrackSignals.erase(it);
+
+    media_status_t status = AMediaExtractor_unselectTrack(mExtractor, trackIndex);
+    if (status != AMEDIA_OK) {
+        LOG(ERROR) << "AMediaExtractor_selectTrack returned error: " << status;
+        return status;
+    }
+
+    return AMEDIA_OK;
+}
+
 media_status_t MediaSampleReaderNDK::setEnforceSequentialAccess(bool enforce) {
     LOG(DEBUG) << "setEnforceSequentialAccess( " << enforce << " )";
 
diff --git a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
index 94a9a33..3d4ff15 100644
--- a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
@@ -275,12 +275,6 @@
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
 
-    media_status_t status = mSampleReader->selectTrack(trackIndex);
-    if (status != AMEDIA_OK) {
-        LOG(ERROR) << "Unable to select track " << trackIndex;
-        return status;
-    }
-
     std::shared_ptr<MediaTrackTranscoder> transcoder;
     std::shared_ptr<AMediaFormat> format;
 
@@ -322,10 +316,17 @@
         format = std::shared_ptr<AMediaFormat>(mergedFormat, &AMediaFormat_delete);
     }
 
+    media_status_t status = mSampleReader->selectTrack(trackIndex);
+    if (status != AMEDIA_OK) {
+        LOG(ERROR) << "Unable to select track " << trackIndex;
+        return status;
+    }
+
     status = transcoder->configure(mSampleReader, trackIndex, format);
     if (status != AMEDIA_OK) {
         LOG(ERROR) << "Configure track transcoder for track #" << trackIndex << " returned error "
                    << status;
+        mSampleReader->unselectTrack(trackIndex);
         return status;
     }
 
diff --git a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
index 5ec5e08..21d60ea 100644
--- a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "VideoTrackTranscoder"
 
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <media/NdkCommon.h>
 #include <media/VideoTrackTranscoder.h>
 #include <utils/AndroidThreads.h>
@@ -39,11 +40,16 @@
 // Default key frame interval in seconds.
 static constexpr float kDefaultKeyFrameIntervalSeconds = 1.0f;
 // Default codec operating rate.
-static constexpr int32_t kDefaultCodecOperatingRate = 240;
+static int32_t kDefaultCodecOperatingRate720P = base::GetIntProperty(
+        "debug.media.transcoding.codec_max_operating_rate_720P", /*default*/ 480);
+static int32_t kDefaultCodecOperatingRate1080P = base::GetIntProperty(
+        "debug.media.transcoding.codec_max_operating_rate_1080P", /*default*/ 240);
 // Default codec priority.
 static constexpr int32_t kDefaultCodecPriority = 1;
 // Default bitrate, in case source estimation fails.
 static constexpr int32_t kDefaultBitrateMbps = 10 * 1000 * 1000;
+// Default frame rate.
+static constexpr int32_t kDefaultFrameRate = 30;
 
 template <typename T>
 void VideoTrackTranscoder::BlockingQueue<T>::push(T const& value, bool front) {
@@ -179,6 +185,25 @@
     }
 }
 
+// Search the default operating rate based on resolution.
+static int32_t getDefaultOperatingRate(AMediaFormat* encoderFormat) {
+    int32_t width, height;
+    if (AMediaFormat_getInt32(encoderFormat, AMEDIAFORMAT_KEY_WIDTH, &width) && (width > 0) &&
+        AMediaFormat_getInt32(encoderFormat, AMEDIAFORMAT_KEY_HEIGHT, &height) && (height > 0)) {
+        if ((width == 1280 && height == 720) || (width == 720 && height == 1280)) {
+            return kDefaultCodecOperatingRate720P;
+        } else if ((width == 1920 && height == 1080) || (width == 1080 && height == 1920)) {
+            return kDefaultCodecOperatingRate1080P;
+        } else {
+            LOG(WARNING) << "Could not find default operating rate: " << width << " " << height;
+            // Don't set operating rate if the correct dimensions are not found.
+        }
+    } else {
+        LOG(ERROR) << "Failed to get default operating rate due to missing resolution";
+    }
+    return -1;
+}
+
 // Creates and configures the codecs.
 media_status_t VideoTrackTranscoder::configureDestinationFormat(
         const std::shared_ptr<AMediaFormat>& destinationFormat) {
@@ -209,10 +234,15 @@
 
     SetDefaultFormatValueFloat(AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, encoderFormat,
                                kDefaultKeyFrameIntervalSeconds);
-    SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_OPERATING_RATE, encoderFormat,
-                               kDefaultCodecOperatingRate);
-    SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_PRIORITY, encoderFormat, kDefaultCodecPriority);
 
+    int32_t operatingRate = getDefaultOperatingRate(encoderFormat);
+
+    if (operatingRate != -1) {
+        SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_OPERATING_RATE, encoderFormat, operatingRate);
+    }
+
+    SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_PRIORITY, encoderFormat, kDefaultCodecPriority);
+    SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_FRAME_RATE, encoderFormat, kDefaultFrameRate);
     AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT, kColorFormatSurface);
 
     // Always encode without rotation. The rotation degree will be transferred directly to
@@ -230,13 +260,19 @@
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
 
+#if !defined(__ANDROID_APEX__)
+    // TODO(jiyong): replace this #ifdef with a __builtin_available check.
     AMediaCodec* encoder = AMediaCodec_createEncoderByTypeForClient(destinationMime, mPid, mUid);
+#else
+    AMediaCodec* encoder = AMediaCodec_createEncoderByType(destinationMime);
+#endif
     if (encoder == nullptr) {
         LOG(ERROR) << "Unable to create encoder for type " << destinationMime;
         return AMEDIA_ERROR_UNSUPPORTED;
     }
     mEncoder = std::make_shared<CodecWrapper>(encoder, shared_from_this());
 
+    LOG(DEBUG) << "Configuring encoder with: " << AMediaFormat_toString(mDestinationFormat.get());
     status = AMediaCodec_configure(mEncoder->getCodec(), mDestinationFormat.get(),
                                    NULL /* surface */, NULL /* crypto */,
                                    AMEDIACODEC_CONFIGURE_FLAG_ENCODE);
@@ -259,7 +295,12 @@
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
 
+#if !defined(__ANDROID_APEX__)
+    // TODO(jiyong): replace this #ifdef with a __builtin_available check.
     mDecoder = AMediaCodec_createDecoderByTypeForClient(sourceMime, mPid, mUid);
+#else
+    mDecoder = AMediaCodec_createDecoderByType(sourceMime);
+#endif
     if (mDecoder == nullptr) {
         LOG(ERROR) << "Unable to create decoder for type " << sourceMime;
         return AMEDIA_ERROR_UNSUPPORTED;
@@ -284,6 +325,7 @@
     CopyFormatEntries(mDestinationFormat.get(), decoderFormat.get(), kEncoderEntriesToCopy,
                       entryCount);
 
+    LOG(DEBUG) << "Configuring decoder with: " << AMediaFormat_toString(decoderFormat.get());
     status = AMediaCodec_configure(mDecoder, decoderFormat.get(), mSurface, NULL /* crypto */,
                                    0 /* flags */);
     if (status != AMEDIA_OK) {
diff --git a/media/libmediatranscoding/transcoder/benchmark/Android.bp b/media/libmediatranscoding/transcoder/benchmark/Android.bp
index ce34702..74f65b9 100644
--- a/media/libmediatranscoding/transcoder/benchmark/Android.bp
+++ b/media/libmediatranscoding/transcoder/benchmark/Android.bp
@@ -1,7 +1,16 @@
 cc_defaults {
     name: "benchmarkdefaults",
-    shared_libs: ["libmediatranscoder", "libmediandk", "libbase", "libbinder_ndk"],
-    static_libs: ["libgoogle-benchmark"],
+    shared_libs: [
+        "libmediandk",
+        "libbase",
+        "libbinder_ndk",
+        "libbinder",
+        "libutils",
+        "libnativewindow",
+    ],
+    static_libs: ["libmediatranscoder", "libgoogle-benchmark"],
+    test_config_template: "AndroidTestTemplate.xml",
+    test_suites: ["device-tests", "TranscoderBenchmarks"],
 }
 
 cc_test {
diff --git a/media/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml b/media/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml
new file mode 100644
index 0000000..64085d8
--- /dev/null
+++ b/media/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Unit test configuration for {MODULE}">
+    <option name="test-suite-tag" value="TranscoderBenchmarks" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="false" />
+        <option name="push-file" key="{MODULE}" value="/data/local/tmp/{MODULE}" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.1.zip?unzip=true"
+            value="/data/local/tmp/TranscodingBenchmark/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GoogleBenchmarkTest" >
+        <option name="native-benchmark-device-path" value="/data/local/tmp" />
+        <option name="benchmark-module-name" value="{MODULE}" />
+    </test>
+</configuration>
+
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp b/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
index 351d80b..d6ed2c6 100644
--- a/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
+++ b/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
@@ -167,6 +167,10 @@
         return AMEDIA_OK;
     }
 
+    media_status_t unselectTrack(int trackIndex __unused) override {
+        return AMEDIA_ERROR_UNSUPPORTED;
+    }
+
     media_status_t setEnforceSequentialAccess(bool enforce __unused) override { return AMEDIA_OK; }
 
     media_status_t getEstimatedBitrateForTrack(int trackIndex __unused,
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp b/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
index 93a08d1..d47a30c 100644
--- a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
+++ b/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
@@ -30,11 +30,15 @@
  */
 
 #include <benchmark/benchmark.h>
+#include <binder/ProcessState.h>
 #include <fcntl.h>
 #include <media/MediaTranscoder.h>
+#include <iostream>
 
 using namespace android;
 
+const std::string PARAM_VIDEO_FRAME_RATE = "VideoFrameRate";
+
 class TranscoderCallbacks : public MediaTranscoder::CallbackInterface {
 public:
     virtual void onFinished(const MediaTranscoder* transcoder __unused) override {
@@ -110,7 +114,6 @@
     std::string srcPath = kAssetDirectory + srcFileName;
     std::string dstPath = kAssetDirectory + dstFileName;
 
-    auto callbacks = std::make_shared<TranscoderCallbacks>();
     media_status_t status = AMEDIA_OK;
 
     if ((srcFd = open(srcPath.c_str(), O_RDONLY)) < 0) {
@@ -123,6 +126,7 @@
     }
 
     for (auto _ : state) {
+        auto callbacks = std::make_shared<TranscoderCallbacks>();
         auto transcoder = MediaTranscoder::create(callbacks);
 
         status = transcoder->configureSource(srcFd);
@@ -151,8 +155,8 @@
             if (strncmp(mime, "video/", 6) == 0) {
                 int32_t frameCount;
                 if (AMediaFormat_getInt32(srcFormat, AMEDIAFORMAT_KEY_FRAME_COUNT, &frameCount)) {
-                    state.counters["VideoFrameRate"] =
-                            benchmark::Counter(frameCount, benchmark::Counter::kIsRate);
+                    state.counters[PARAM_VIDEO_FRAME_RATE] = benchmark::Counter(
+                            frameCount, benchmark::Counter::kIsIterationInvariantRate);
                 }
             }
 
@@ -332,4 +336,70 @@
 TRANSCODER_BENCHMARK(BM_TranscodeAudioVideoPassthrough);
 TRANSCODER_BENCHMARK(BM_TranscodeVideoPassthrough);
 
-BENCHMARK_MAIN();
+class CustomCsvReporter : public benchmark::BenchmarkReporter {
+public:
+    CustomCsvReporter() : mPrintedHeader(false) {}
+    virtual bool ReportContext(const Context& context);
+    virtual void ReportRuns(const std::vector<Run>& reports);
+
+private:
+    void PrintRunData(const Run& report);
+
+    bool mPrintedHeader;
+    std::vector<std::string> mHeaders = {"name", "real_time", "cpu_time", PARAM_VIDEO_FRAME_RATE};
+};
+
+bool CustomCsvReporter::ReportContext(const Context& context __unused) {
+    return true;
+}
+
+void CustomCsvReporter::ReportRuns(const std::vector<Run>& reports) {
+    std::ostream& Out = GetOutputStream();
+
+    if (!mPrintedHeader) {
+        // print the header
+        for (auto header = mHeaders.begin(); header != mHeaders.end();) {
+            Out << *header++;
+            if (header != mHeaders.end()) Out << ",";
+        }
+        Out << "\n";
+        mPrintedHeader = true;
+    }
+
+    // print results for each run
+    for (const auto& run : reports) {
+        PrintRunData(run);
+    }
+}
+
+void CustomCsvReporter::PrintRunData(const Run& run) {
+    if (run.error_occurred) {
+        return;
+    }
+    std::ostream& Out = GetOutputStream();
+    Out << run.benchmark_name() << ",";
+    Out << run.GetAdjustedRealTime() << ",";
+    Out << run.GetAdjustedCPUTime() << ",";
+    auto frameRate = run.counters.find(PARAM_VIDEO_FRAME_RATE);
+    if (frameRate == run.counters.end()) {
+        Out << "NA"
+            << ",";
+    } else {
+        Out << frameRate->second << ",";
+    }
+    Out << '\n';
+}
+
+int main(int argc, char** argv) {
+    android::ProcessState::self()->startThreadPool();
+    std::unique_ptr<benchmark::BenchmarkReporter> fileReporter;
+    for (int i = 1; i < argc; ++i) {
+        if (std::string(argv[i]).find("--benchmark_out") != std::string::npos) {
+            fileReporter.reset(new CustomCsvReporter);
+            break;
+        }
+    }
+    ::benchmark::Initialize(&argc, argv);
+    if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
+    ::benchmark::RunSpecifiedBenchmarks(nullptr, fileReporter.get());
+}
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h b/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
index 7b6fbef..5c7eeac 100644
--- a/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
+++ b/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
@@ -69,6 +69,13 @@
     virtual media_status_t selectTrack(int trackIndex) = 0;
 
     /**
+     * Undo a track selection.
+     * @param trackIndex The track to un-select.
+     * @return AMEDIA_OK on success.
+     */
+    virtual media_status_t unselectTrack(int trackIndex) = 0;
+
+    /**
      * Toggles sequential access enforcement on or off. When the reader enforces sequential access
      * calls to read sample information will block unless the underlying extractor points to the
      * specified track.
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h b/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
index 2032def..30cc37f 100644
--- a/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
+++ b/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
@@ -48,6 +48,7 @@
     size_t getTrackCount() const override;
     AMediaFormat* getTrackFormat(int trackIndex) override;
     media_status_t selectTrack(int trackIndex) override;
+    media_status_t unselectTrack(int trackIndex) override;
     media_status_t setEnforceSequentialAccess(bool enforce) override;
     media_status_t getEstimatedBitrateForTrack(int trackIndex, int32_t* bitrate) override;
     media_status_t getSampleInfoForTrack(int trackIndex, MediaSampleInfo* info) override;
diff --git a/media/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h b/media/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h
index d2ffb01..e3f3f4f 100644
--- a/media/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h
+++ b/media/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h
@@ -97,8 +97,12 @@
     BlockingQueue<std::function<void()>> mCodecMessageQueue;
     std::shared_ptr<AMediaFormat> mDestinationFormat;
     std::shared_ptr<AMediaFormat> mActualOutputFormat;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-private-field"
+    // These could be unused on older platforms
     pid_t mPid;
     uid_t mUid;
+#pragma clang diagnostic pop
 };
 
 }  // namespace android
diff --git a/media/libmediatranscoding/transcoder/setloglevel.sh b/media/libmediatranscoding/transcoder/setloglevel.sh
new file mode 100755
index 0000000..5eb7b67
--- /dev/null
+++ b/media/libmediatranscoding/transcoder/setloglevel.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+if [ $# -ne 1 ]
+then
+    echo Usage: $0 loglevel
+    exit 1
+fi
+
+level=$1
+echo Setting transcoder log level to $level
+
+# List all log tags
+declare -a tags=(
+  MediaTranscoder MediaTrackTranscoder VideoTrackTranscoder PassthroughTrackTranscoder
+  MediaSampleWriter MediaSampleReader MediaSampleQueue MediaTranscoderTests
+  MediaTrackTranscoderTests VideoTrackTranscoderTests PassthroughTrackTranscoderTests
+  MediaSampleWriterTests MediaSampleReaderNDKTests MediaSampleQueueTests)
+
+# Set log level for all tags
+for tag in "${tags[@]}"
+do
+    adb shell setprop log.tag.${tag} $level
+done
+
+# Pick up new settings
+adb shell stop && adb shell start
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
index 5c59992..bfc1f3b 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
@@ -283,20 +283,22 @@
         }
 
         EXPECT_NE(videoFormat, nullptr);
+        if (videoFormat != nullptr) {
+            LOG(INFO) << "source video format: " << AMediaFormat_toString(mSourceVideoFormat.get());
+            LOG(INFO) << "transcoded video format: " << AMediaFormat_toString(videoFormat.get());
 
-        LOG(INFO) << "source video format: " << AMediaFormat_toString(mSourceVideoFormat.get());
-        LOG(INFO) << "transcoded video format: " << AMediaFormat_toString(videoFormat.get());
+            for (int i = 0; i < (sizeof(kFieldsToPreserve) / sizeof(kFieldsToPreserve[0])); ++i) {
+                EXPECT_TRUE(kFieldsToPreserve[i].equal(kFieldsToPreserve[i].key,
+                                                       mSourceVideoFormat.get(), videoFormat.get()))
+                        << "Failed at key " << kFieldsToPreserve[i].key;
+            }
 
-        for (int i = 0; i < (sizeof(kFieldsToPreserve) / sizeof(kFieldsToPreserve[0])); ++i) {
-            EXPECT_TRUE(kFieldsToPreserve[i].equal(kFieldsToPreserve[i].key,
-                                                   mSourceVideoFormat.get(), videoFormat.get()))
-                    << "Failed at key " << kFieldsToPreserve[i].key;
-        }
-
-        if (extraVerifiers != nullptr) {
-            for (int i = 0; i < extraVerifiers->size(); ++i) {
-                const FormatVerifierEntry& entry = (*extraVerifiers)[i];
-                EXPECT_TRUE(entry.equal(entry.key, mSourceVideoFormat.get(), videoFormat.get()));
+            if (extraVerifiers != nullptr) {
+                for (int i = 0; i < extraVerifiers->size(); ++i) {
+                    const FormatVerifierEntry& entry = (*extraVerifiers)[i];
+                    EXPECT_TRUE(
+                            entry.equal(entry.key, mSourceVideoFormat.get(), videoFormat.get()));
+                }
             }
         }
 
diff --git a/media/libmediatranscoding/transcoder/tests/fuzzer/Android.bp b/media/libmediatranscoding/transcoder/tests/fuzzer/Android.bp
new file mode 100644
index 0000000..3ae349b
--- /dev/null
+++ b/media/libmediatranscoding/transcoder/tests/fuzzer/Android.bp
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_fuzz {
+    name: "media_transcoder_fuzzer",
+    srcs: [
+        "media_transcoder_fuzzer.cpp",
+    ],
+    static_libs: [
+        "liblog",
+        "libmediatranscoder",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libmediandk",
+        "libnativewindow",
+        "libutils",
+    ],
+    header_libs: [
+        "libcodec2_headers",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 155276,
+    },
+}
diff --git a/media/libmediatranscoding/transcoder/tests/fuzzer/README.md b/media/libmediatranscoding/transcoder/tests/fuzzer/README.md
new file mode 100644
index 0000000..d376a20
--- /dev/null
+++ b/media/libmediatranscoding/transcoder/tests/fuzzer/README.md
@@ -0,0 +1,59 @@
+# Fuzzer for libmediatranscoder
+
+## Plugin Design Considerations
+The fuzzer plugin for libmediatranscoder is designed based on the understanding of the
+transcoder and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+Transcoder supports the following parameters:
+1. Destination Mime Type (parameter name: `dstMime`)
+2. AVC Profile (parameter name: `profile`)
+3. HEVC Profile (parameter name: `profile`)
+4. AVC Level (parameter name: `level`)
+5. HEVC Level (parameter name: `level`)
+6. Bitrate (parameter name: `bitrate`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `dstMime` | 0. `AMEDIA_MIMETYPE_VIDEO_AVC` 1. `AMEDIA_MIMETYPE_VIDEO_HEVC` | Bit 0 (LSB) of 1st byte of data |
+| `profile` for AVC | 0. `PROFILE_AVC_BASELINE` 1. `PROFILE_AVC_CONSTRAINED_BASELINE` 2. `PROFILE_AVC_MAIN`| All bits of 2nd byte of data modulus 3 |
+| `profile` for HEVC | 0. `PROFILE_HEVC_MAIN` 1. `PROFILE_HEVC_MAIN_STILL` | All bits of 2nd byte of data modulus 2 |
+| `level` for AVC | 0. `LEVEL_AVC_1` 1. `LEVEL_AVC_1B` 2. `LEVEL_AVC_1_1` 3. `LEVEL_AVC_1_2` 4. `LEVEL_AVC_1_3` 5. `LEVEL_AVC_2` 6. `LEVEL_AVC_2_1` 7. `LEVEL_AVC_2_2` 8. `LEVEL_AVC_3` 9. `LEVEL_AVC_3_1` 10. `LEVEL_AVC_3_2` 11. `LEVEL_AVC_4` 12. `LEVEL_AVC_4_1` 13. `LEVEL_AVC_4_2` 14. `LEVEL_AVC_5`| All bits of 3rd byte of data modulus 15 |
+| `level` for HEVC | 0. `LEVEL_HEVC_MAIN_1` 1. `LEVEL_HEVC_MAIN_2` 2. `LEVEL_HEVC_MAIN_2_1` 3. `LEVEL_HEVC_MAIN_3` 4. `LEVEL_HEVC_MAIN_3_1` 5. `LEVEL_HEVC_MAIN_4` 6. `LEVEL_HEVC_MAIN_4_1` 7. `LEVEL_HEVC_MAIN_5` 8. `LEVEL_HEVC_MAIN_5_1` 9. `LEVEL_HEVC_MAIN_5_2` | All bits of 3rd byte of data modulus 10 |
+| `bitrate` | In the range `0` to `500000000` | All bits of 4th and 5th byte of data |
+
+This also ensures that the plugin is always deterministic for any given input.
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the transcoder.
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build media_transcoder_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) media_transcoder_fuzzer
+```
+#### Steps to run
+Create a directory CORPUS_DIR
+```
+  $ adb shell mkdir CORPUS_DIR
+```
+To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/${TARGET_ARCH}/media_transcoder_fuzzer/media_transcoder_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/media/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp b/media/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp
new file mode 100644
index 0000000..48d3406
--- /dev/null
+++ b/media/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp
@@ -0,0 +1,209 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <C2Config.h>
+#include <android/binder_process.h>
+#include <fcntl.h>
+#include <media/MediaTranscoder.h>
+#include <media/NdkCommon.h>
+#include <stdio.h>
+
+#define UNUSED_PARAM __attribute__((unused))
+#define SRC_FILE "sourceTranscodingFile"
+#define DEST_FILE "destTranscodingFile"
+
+using namespace std;
+using namespace android;
+
+const char* kMimeType[] = {AMEDIA_MIMETYPE_VIDEO_AVC, AMEDIA_MIMETYPE_VIDEO_HEVC};
+const C2Config::profile_t kAvcProfile[] = {C2Config::PROFILE_AVC_BASELINE,
+                                           C2Config::PROFILE_AVC_CONSTRAINED_BASELINE,
+                                           C2Config::PROFILE_AVC_MAIN};
+const C2Config::level_t kAvcLevel[] = {
+        C2Config::LEVEL_AVC_1,   C2Config::LEVEL_AVC_1B,  C2Config::LEVEL_AVC_1_1,
+        C2Config::LEVEL_AVC_1_2, C2Config::LEVEL_AVC_1_3, C2Config::LEVEL_AVC_2,
+        C2Config::LEVEL_AVC_2_1, C2Config::LEVEL_AVC_2_2, C2Config::LEVEL_AVC_3,
+        C2Config::LEVEL_AVC_3_1, C2Config::LEVEL_AVC_3_2, C2Config::LEVEL_AVC_4,
+        C2Config::LEVEL_AVC_4_1, C2Config::LEVEL_AVC_4_2, C2Config::LEVEL_AVC_5,
+};
+const C2Config::profile_t kHevcProfile[] = {C2Config::PROFILE_HEVC_MAIN,
+                                            C2Config::PROFILE_HEVC_MAIN_STILL};
+const C2Config::level_t kHevcLevel[] = {
+        C2Config::LEVEL_HEVC_MAIN_1,   C2Config::LEVEL_HEVC_MAIN_2,   C2Config::LEVEL_HEVC_MAIN_2_1,
+        C2Config::LEVEL_HEVC_MAIN_3,   C2Config::LEVEL_HEVC_MAIN_3_1, C2Config::LEVEL_HEVC_MAIN_4,
+        C2Config::LEVEL_HEVC_MAIN_4_1, C2Config::LEVEL_HEVC_MAIN_5,   C2Config::LEVEL_HEVC_MAIN_5_1,
+        C2Config::LEVEL_HEVC_MAIN_5_2};
+const size_t kNumAvcProfile = size(kAvcProfile);
+const size_t kNumAvcLevel = size(kAvcLevel);
+const size_t kNumHevcProfile = size(kHevcProfile);
+const size_t kNumHevcLevel = size(kHevcLevel);
+const size_t kMaxBitrate = 500000000;
+
+enum {
+    IDX_MIME_TYPE = 0,
+    IDX_PROFILE,
+    IDX_LEVEL,
+    IDX_BITRATE_BYTE_1,
+    IDX_BITRATE_BYTE_2,
+    IDX_LAST
+};
+
+class TestCallbacks : public MediaTranscoder::CallbackInterface {
+public:
+    virtual void onFinished(const MediaTranscoder* transcoder UNUSED_PARAM) override {
+        unique_lock<mutex> lock(mMutex);
+        mFinished = true;
+        mCondition.notify_all();
+    }
+
+    virtual void onError(const MediaTranscoder* transcoder UNUSED_PARAM,
+                         media_status_t error UNUSED_PARAM) override {
+        unique_lock<mutex> lock(mMutex);
+        mFinished = true;
+        mCondition.notify_all();
+    }
+
+    virtual void onProgressUpdate(const MediaTranscoder* transcoder UNUSED_PARAM,
+                                  int32_t progress) override {
+        unique_lock<mutex> lock(mMutex);
+        if (progress > 0 && !mProgressMade) {
+            mProgressMade = true;
+            mCondition.notify_all();
+        }
+    }
+
+    virtual void onCodecResourceLost(const MediaTranscoder* transcoder UNUSED_PARAM,
+                                     const shared_ptr<ndk::ScopedAParcel>& pausedState
+                                             UNUSED_PARAM) override {}
+
+    void waitForTranscodingFinished() {
+        unique_lock<mutex> lock(mMutex);
+        while (!mFinished) {
+            mCondition.wait(lock);
+        }
+    }
+
+private:
+    mutex mMutex;
+    condition_variable mCondition;
+    bool mFinished = false;
+    bool mProgressMade = false;
+};
+
+class MediaTranscoderFuzzer {
+public:
+    void init();
+    void invokeTranscoder(const uint8_t* data, size_t size);
+    void deInit();
+
+private:
+    AMediaFormat* getFormat(AMediaFormat* sourceFormat) {
+        AMediaFormat* format = nullptr;
+        const char* mime = nullptr;
+        AMediaFormat_getString(sourceFormat, AMEDIAFORMAT_KEY_MIME, &mime);
+        if (mime != nullptr) {
+            if (strncmp(mime, "video/", 6) == 0 && (mDestMime != nullptr)) {
+                format = AMediaFormat_new();
+                AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, mDestMime);
+                AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_PROFILE, mProfile);
+                AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_LEVEL, mLevel);
+                AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, mBitrate);
+                AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_OPERATING_RATE, INT32_MAX);
+                AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_PRIORITY, 1);
+            }
+        }
+        return format;
+    }
+
+    shared_ptr<TestCallbacks> mCallbacks;
+    int mSrcFd = 0;
+    int mDestFd = 0;
+    const char* mDestMime;
+    C2Config::profile_t mProfile;
+    C2Config::level_t mLevel;
+    uint64_t mBitrate = 0;
+};
+
+void MediaTranscoderFuzzer::init() {
+    mCallbacks = make_shared<TestCallbacks>();
+    ABinderProcess_startThreadPool();
+}
+
+void MediaTranscoderFuzzer::deInit() {
+    mCallbacks.reset();
+    if (mSrcFd) {
+        close(mSrcFd);
+    }
+    if (mDestFd) {
+        close(mDestFd);
+    }
+}
+
+void MediaTranscoderFuzzer::invokeTranscoder(const uint8_t* data, size_t size) {
+    auto transcoder = MediaTranscoder::create(mCallbacks);
+    if (transcoder == nullptr) {
+        return;
+    }
+
+    mDestMime = kMimeType[data[IDX_MIME_TYPE] & 0x01];
+    mBitrate = (((data[IDX_BITRATE_BYTE_1] << 8) | data[IDX_BITRATE_BYTE_2]) * 1000) % kMaxBitrate;
+    if (mDestMime == AMEDIA_MIMETYPE_VIDEO_AVC) {
+        mProfile = kAvcProfile[data[IDX_PROFILE] % kNumAvcProfile];
+        mLevel = kAvcLevel[data[IDX_LEVEL] % kNumAvcLevel];
+    } else {
+        mProfile = kHevcProfile[data[IDX_PROFILE] % kNumHevcProfile];
+        mLevel = kHevcLevel[data[IDX_LEVEL] % kNumHevcLevel];
+    }
+
+    data += IDX_LAST;
+    size -= IDX_LAST;
+
+    mSrcFd = memfd_create(SRC_FILE, MFD_ALLOW_SEALING);
+    write(mSrcFd, data, size);
+
+    transcoder->configureSource(mSrcFd);
+    vector<shared_ptr<AMediaFormat>> trackFormats = transcoder->getTrackFormats();
+    for (int i = 0; i < trackFormats.size(); ++i) {
+        AMediaFormat* format = getFormat(trackFormats[i].get());
+        transcoder->configureTrackFormat(i, format);
+
+        if (format != nullptr) {
+            AMediaFormat_delete(format);
+        }
+    }
+    mDestFd = memfd_create(DEST_FILE, MFD_ALLOW_SEALING);
+    transcoder->configureDestination(mDestFd);
+    if (transcoder->start() == AMEDIA_OK) {
+        mCallbacks->waitForTranscodingFinished();
+        transcoder->cancel();
+    }
+    close(mSrcFd);
+    close(mDestFd);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    if (size < IDX_LAST + 1) {
+        return 0;
+    }
+    MediaTranscoderFuzzer transcoderFuzzer;
+    transcoderFuzzer.init();
+    transcoderFuzzer.invokeTranscoder(data, size);
+    transcoderFuzzer.deInit();
+    return 0;
+}
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 71c1b0b..8f1da0d 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -7078,10 +7078,9 @@
         return err;
     }
 
-    using hardware::media::omx::V1_0::utils::TWOmxNode;
     err = statusFromBinderStatus(
             mCodec->mGraphicBufferSource->configure(
-                    new TWOmxNode(mCodec->mOMXNode),
+                    mCodec->mOMXNode->getHalInterface<IOmxNode>(),
                     static_cast<hardware::graphics::common::V1_0::Dataspace>(dataSpace)));
     if (err != OK) {
         ALOGE("[%s] Unable to configure for node (err %d)",
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index e783578..d11408d 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -44,7 +44,7 @@
 namespace android {
 
 static const int64_t kBufferTimeOutUs = 10000LL; // 10 msec
-static const size_t kRetryCount = 50; // must be >0
+static const size_t kRetryCount = 100; // must be >0
 static const int64_t kDefaultSampleDurationUs = 33333LL; // 33ms
 
 sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta,
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 0af97df..447d599 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -1137,11 +1137,24 @@
     if (!truncatePreAllocation()) {
         if (err == OK) { err = ERROR_IO; }
     }
+
+    // TODO(b/174770856) remove this measurement (and perhaps the fsync)
+    nsecs_t sync_started = systemTime(SYSTEM_TIME_REALTIME);
     if (fsync(mFd) != 0) {
         ALOGW("(ignored)fsync err:%s(%d)", std::strerror(errno), errno);
         // Don't bubble up fsync error, b/157291505.
         // if (err == OK) { err = ERROR_IO; }
     }
+    nsecs_t sync_finished = systemTime(SYSTEM_TIME_REALTIME);
+    nsecs_t sync_elapsed_ns = sync_finished - sync_started;
+    int64_t filesize = -1;
+    struct stat statbuf;
+    if (fstat(mFd, &statbuf) == 0) {
+        filesize = statbuf.st_size;
+    }
+    ALOGD("final fsync() takes %" PRId64 " ms, file size %" PRId64,
+          sync_elapsed_ns / 1000000, (int64_t) filesize);
+
     if (close(mFd) != 0) {
         ALOGE("close err:%s(%d)", std::strerror(errno), errno);
         if (err == OK) { err = ERROR_IO; }
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index da8f024..358c5e3 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -19,6 +19,8 @@
 #define LOG_TAG "MediaCodec"
 #include <utils/Log.h>
 
+#include <set>
+
 #include <inttypes.h>
 #include <stdlib.h>
 
@@ -202,6 +204,10 @@
     // implements DeathRecipient
     static void BinderDiedCallback(void* cookie);
     void binderDied();
+    static Mutex sLockCookies;
+    static std::set<void*> sCookies;
+    static void addCookie(void* cookie);
+    static void removeCookie(void* cookie);
 
     void addResource(const MediaResourceParcel &resource);
     void removeResource(const MediaResourceParcel &resource);
@@ -228,8 +234,15 @@
 }
 
 MediaCodec::ResourceManagerServiceProxy::~ResourceManagerServiceProxy() {
+
+    // remove the cookie, so any in-flight death notification will get dropped
+    // by our handler.
+    removeCookie(this);
+
+    Mutex::Autolock _l(mLock);
     if (mService != nullptr) {
         AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
+        mService = nullptr;
     }
 }
 
@@ -241,16 +254,39 @@
         return;
     }
 
-    AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
-
     // Kill clients pending removal.
     mService->reclaimResourcesFromClientsPendingRemoval(mPid);
+
+    // so our handler will process the death notifications
+    addCookie(this);
+
+    // after this, require mLock whenever using mService
+    AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
+}
+
+//static
+Mutex MediaCodec::ResourceManagerServiceProxy::sLockCookies;
+std::set<void*> MediaCodec::ResourceManagerServiceProxy::sCookies;
+
+//static
+void MediaCodec::ResourceManagerServiceProxy::addCookie(void* cookie) {
+    Mutex::Autolock _l(sLockCookies);
+    sCookies.insert(cookie);
+}
+
+//static
+void MediaCodec::ResourceManagerServiceProxy::removeCookie(void* cookie) {
+    Mutex::Autolock _l(sLockCookies);
+    sCookies.erase(cookie);
 }
 
 //static
 void MediaCodec::ResourceManagerServiceProxy::BinderDiedCallback(void* cookie) {
-    auto thiz = static_cast<ResourceManagerServiceProxy*>(cookie);
-    thiz->binderDied();
+    Mutex::Autolock _l(sLockCookies);
+    if (sCookies.find(cookie) != sCookies.end()) {
+        auto thiz = static_cast<ResourceManagerServiceProxy*>(cookie);
+        thiz->binderDied();
+    }
 }
 
 void MediaCodec::ResourceManagerServiceProxy::binderDied() {
@@ -4094,7 +4130,15 @@
                 }
             }
         }
-        mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
+        status_t err = mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
+
+        if (err == NO_INIT) {
+            ALOGE("rendering to non-initilized(obsolete) surface");
+            return err;
+        }
+        if (err != OK) {
+            ALOGI("rendring output error %d", err);
+        }
     } else {
         mBufferChannel->discardBuffer(buffer);
     }
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index ac54fa1..799ca0d 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -209,9 +209,12 @@
             ALOGD("ignored a null builder");
             continue;
         }
-        mInitCheck = builder->buildMediaCodecList(&writer);
-        if (mInitCheck != OK) {
-            break;
+        auto currentCheck = builder->buildMediaCodecList(&writer);
+        if (currentCheck != OK) {
+            ALOGD("ignored failed builder");
+            continue;
+        } else {
+            mInitCheck = currentCheck;
         }
     }
     writer.writeGlobalSettings(mGlobalSettings);
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 6245014..f2c7dd6 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -50,8 +50,9 @@
       mSampleTimeUs(timeUs) {
 }
 
-NuMediaExtractor::NuMediaExtractor()
-    : mTotalBitrate(-1LL),
+NuMediaExtractor::NuMediaExtractor(EntryPoint entryPoint)
+    : mEntryPoint(entryPoint),
+      mTotalBitrate(-1LL),
       mDurationUs(-1LL) {
 }
 
@@ -93,6 +94,7 @@
     if (mImpl == NULL) {
         return ERROR_UNSUPPORTED;
     }
+    setEntryPointToRemoteMediaExtractor();
 
     status_t err = OK;
     if (!mCasToken.empty()) {
@@ -134,6 +136,7 @@
     if (mImpl == NULL) {
         return ERROR_UNSUPPORTED;
     }
+    setEntryPointToRemoteMediaExtractor();
 
     if (!mCasToken.empty()) {
         err = mImpl->setMediaCas(mCasToken);
@@ -168,6 +171,7 @@
     if (mImpl == NULL) {
         return ERROR_UNSUPPORTED;
     }
+    setEntryPointToRemoteMediaExtractor();
 
     if (!mCasToken.empty()) {
         err = mImpl->setMediaCas(mCasToken);
@@ -489,6 +493,16 @@
     }
 }
 
+void NuMediaExtractor::setEntryPointToRemoteMediaExtractor() {
+    if (mImpl == NULL) {
+        return;
+    }
+    status_t err = mImpl->setEntryPoint(mEntryPoint);
+    if (err != OK) {
+        ALOGW("Failed to set entry point with error %d.", err);
+    }
+}
+
 ssize_t NuMediaExtractor::fetchAllTrackSamples(
         int64_t seekTimeUs, MediaSource::ReadOptions::SeekMode mode) {
     TrackInfo *minInfo = NULL;
diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp
index 25e43c2..381eb1a 100644
--- a/media/libstagefright/RemoteMediaExtractor.cpp
+++ b/media/libstagefright/RemoteMediaExtractor.cpp
@@ -39,6 +39,12 @@
 static const char *kExtractorFormat = "android.media.mediaextractor.fmt";
 static const char *kExtractorMime = "android.media.mediaextractor.mime";
 static const char *kExtractorTracks = "android.media.mediaextractor.ntrk";
+static const char *kExtractorEntryPoint = "android.media.mediaextractor.entry";
+
+static const char *kEntryPointSdk = "sdk";
+static const char *kEntryPointWithJvm = "ndk-with-jvm";
+static const char *kEntryPointNoJvm = "ndk-no-jvm";
+static const char *kEntryPointOther = "other";
 
 RemoteMediaExtractor::RemoteMediaExtractor(
         MediaExtractor *extractor,
@@ -74,6 +80,9 @@
             }
             // what else is interesting and not already available?
         }
+        // By default, we set the entry point to be "other". Clients of this
+        // class will override this value by calling setEntryPoint.
+        mMetricsItem->setCString(kExtractorEntryPoint, kEntryPointOther);
     }
 }
 
@@ -143,6 +152,28 @@
     return String8(mExtractor->name());
 }
 
+status_t RemoteMediaExtractor::setEntryPoint(EntryPoint entryPoint) {
+    const char* entryPointString;
+    switch (entryPoint) {
+      case EntryPoint::SDK:
+            entryPointString = kEntryPointSdk;
+            break;
+        case EntryPoint::NDK_WITH_JVM:
+            entryPointString = kEntryPointWithJvm;
+            break;
+        case EntryPoint::NDK_NO_JVM:
+            entryPointString = kEntryPointNoJvm;
+            break;
+        case EntryPoint::OTHER:
+            entryPointString = kEntryPointOther;
+            break;
+        default:
+            return BAD_VALUE;
+    }
+    mMetricsItem->setCString(kExtractorEntryPoint, entryPointString);
+    return OK;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 // static
diff --git a/media/libstagefright/TEST_MAPPING b/media/libstagefright/TEST_MAPPING
index 76fc74f..dff7b22 100644
--- a/media/libstagefright/TEST_MAPPING
+++ b/media/libstagefright/TEST_MAPPING
@@ -11,7 +11,7 @@
 
   ],
 
-  "presubmit": [
+  "presubmit-large": [
     {
       "name": "CtsMediaTestCases",
       "options": [
@@ -29,7 +29,9 @@
           "exclude-filter": "android.media.cts.AudioRecordTest"
         }
       ]
-    },
+    }
+  ],
+  "presubmit": [
     {
       "name": "mediacodecTest"
     }
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 48b3255..f63740e 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -729,6 +729,8 @@
     {
         { "exif-offset", kKeyExifOffset },
         { "exif-size", kKeyExifSize },
+        { "xmp-offset", kKeyXmpOffset },
+        { "xmp-size", kKeyXmpSize },
         { "target-time", kKeyTargetTime },
         { "thumbnail-time", kKeyThumbnailTime },
         { "timeUs", kKeyTime },
@@ -2192,7 +2194,7 @@
 #ifdef DISABLE_AUDIO_SYSTEM_OFFLOAD
     return false;
 #else
-    return AudioSystem::isOffloadSupported(info);
+    return AudioSystem::getOffloadSupport(info) != AUDIO_OFFLOAD_NOT_SUPPORTED;
 #endif
 }
 
diff --git a/media/libstagefright/bqhelper/Android.bp b/media/libstagefright/bqhelper/Android.bp
index 8698d33..2b0494c 100644
--- a/media/libstagefright/bqhelper/Android.bp
+++ b/media/libstagefright/bqhelper/Android.bp
@@ -101,6 +101,7 @@
         "//apex_available:platform",
     ],
     vendor_available: false,
+    min_sdk_version: "29",
     static_libs: [
         "libgui_bufferqueue_static",
     ],
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 28a7a1e..92ec94f 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -1247,6 +1247,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
index 6e437cf..90421b9 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
@@ -732,6 +732,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index cdfc03a..01da3f8 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -576,6 +576,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
index 85ab64e..a1f6686 100644
--- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
@@ -421,6 +421,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
index 7fb8a4c..657a5ce 100644
--- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
@@ -476,6 +476,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/avcdec/Android.bp b/media/libstagefright/codecs/avcdec/Android.bp
index 0bb6bb0..61379d2 100644
--- a/media/libstagefright/codecs/avcdec/Android.bp
+++ b/media/libstagefright/codecs/avcdec/Android.bp
@@ -16,6 +16,12 @@
             "signed-integer-overflow",
         ],
         cfi: true,
+        diag: {
+            cfi: true,
+        },
+        config: {
+            cfi_assembly_support: true,
+        },
     },
 
     ldflags: ["-Wl,-Bsymbolic"],
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index 5a4b2f8..3891f23 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -724,6 +724,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
         OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/avcenc/Android.bp b/media/libstagefright/codecs/avcenc/Android.bp
index 980261c..aceaebf 100644
--- a/media/libstagefright/codecs/avcenc/Android.bp
+++ b/media/libstagefright/codecs/avcenc/Android.bp
@@ -10,6 +10,12 @@
             "signed-integer-overflow",
         ],
         cfi: true,
+        diag: {
+            cfi: true,
+        },
+        config: {
+            cfi_assembly_support: true,
+        },
     },
 
     cflags: [
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
index 9db6465..01174c9 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
@@ -1507,6 +1507,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
index 842a7ce..d6448d3 100644
--- a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
+++ b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
@@ -491,6 +491,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
index 078c8e3..24216a2 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
@@ -592,6 +592,7 @@
 }  // namespace android
 
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
index 877cb5a..fe91510 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -382,6 +382,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
index d777229..330cb8a 100644
--- a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
+++ b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
@@ -354,6 +354,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
index f6ae1f4..176da47 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
@@ -713,6 +713,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(const char *name,
         const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
         OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index 60750d9..a4b3e2f 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -412,6 +412,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index fa7db81..fb6c4e2 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -528,6 +528,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index 15cde20..07bb45a 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -498,6 +498,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
index 9d5f342..9f8001f 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
@@ -864,6 +864,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
         OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
index 0f2ff17..bffc23a 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -355,6 +355,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index d0cb071..e9b4341 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -775,6 +775,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
index 5bb1879..dcd8dda 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -666,6 +666,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/raw/SoftRaw.cpp b/media/libstagefright/codecs/raw/SoftRaw.cpp
index 0e31804..82dd171 100644
--- a/media/libstagefright/codecs/raw/SoftRaw.cpp
+++ b/media/libstagefright/codecs/raw/SoftRaw.cpp
@@ -273,6 +273,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 08e20cc..3daed10 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -636,6 +636,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
diff --git a/media/libstagefright/codecs/xaacdec/Android.bp b/media/libstagefright/codecs/xaacdec/Android.bp
index 5385dbc..2d90910 100644
--- a/media/libstagefright/codecs/xaacdec/Android.bp
+++ b/media/libstagefright/codecs/xaacdec/Android.bp
@@ -14,6 +14,12 @@
         // integer_overflow: true,
         misc_undefined: [ "signed-integer-overflow", "unsigned-integer-overflow", ],
         cfi: true,
+	diag: {
+            cfi: true,
+        },
+        config: {
+            cfi_assembly_support: true,
+        },
     },
 
     static_libs: ["libxaacdec"],
diff --git a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
index 87e8fd4..a478642 100644
--- a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
+++ b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
@@ -1693,6 +1693,7 @@
 
 }  // namespace android
 
+__attribute__((cfi_canonical_jump_table))
 android::SoftOMXComponent* createSoftOMXComponent(const char* name,
                                                   const OMX_CALLBACKTYPE* callbacks,
                                                   OMX_PTR appData, OMX_COMPONENTTYPE** component) {
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 7752bda..f242b19 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -33,7 +33,7 @@
 
 #include <media/stagefright/foundation/hexdump.h>
 
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 #include <binder/Parcel.h>
 #endif
 
@@ -646,7 +646,7 @@
     return s;
 }
 
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 // static
 sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) {
     int32_t what = parcel.readInt32();
@@ -813,7 +813,7 @@
         }
     }
 }
-#endif  // __ANDROID_VNDK__
+#endif  // !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 
 sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) const {
     if (other == NULL) {
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
index 8722e14..b1ed077 100644
--- a/media/libstagefright/foundation/AString.cpp
+++ b/media/libstagefright/foundation/AString.cpp
@@ -27,7 +27,7 @@
 #include "ADebug.h"
 #include "AString.h"
 
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 #include <binder/Parcel.h>
 #endif
 
@@ -365,7 +365,7 @@
     return !strcasecmp(mData + mSize - suffixLen, suffix);
 }
 
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 // static
 AString AString::FromParcel(const Parcel &parcel) {
     size_t size = static_cast<size_t>(parcel.readInt32());
@@ -380,7 +380,7 @@
     }
     return err;
 }
-#endif
+#endif // !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 
 AString AStringPrintf(const char *format, ...) {
     va_list ap;
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index ebf1035..39670a2 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -86,6 +86,11 @@
                 "-DNO_IMEMORY",
             ],
         },
+        apex: {
+            exclude_shared_libs: [
+                "libbinder",
+            ],
+        },
         darwin: {
             enabled: false,
         },
diff --git a/media/libstagefright/foundation/MediaBuffer.cpp b/media/libstagefright/foundation/MediaBuffer.cpp
index 8e245dc..68df21f 100644
--- a/media/libstagefright/foundation/MediaBuffer.cpp
+++ b/media/libstagefright/foundation/MediaBuffer.cpp
@@ -51,12 +51,12 @@
       mRangeLength(size),
       mOwnsData(true),
       mMetaData(new MetaDataBase) {
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
     if (size < kSharedMemThreshold
             || std::atomic_load_explicit(&mUseSharedMemory, std::memory_order_seq_cst) == 0) {
 #endif
         mData = malloc(size);
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
     } else {
         ALOGV("creating memoryDealer");
         size_t newSize = 0;
diff --git a/media/libstagefright/foundation/MediaBufferGroup.cpp b/media/libstagefright/foundation/MediaBufferGroup.cpp
index 3c25047..fc98f28 100644
--- a/media/libstagefright/foundation/MediaBufferGroup.cpp
+++ b/media/libstagefright/foundation/MediaBufferGroup.cpp
@@ -62,7 +62,7 @@
         mInternal->mGrowthLimit = buffers;
     }
 
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
     if (buffer_size >= kSharedMemoryThreshold) {
         ALOGD("creating MemoryDealer");
         // Using a single MemoryDealer is efficient for a group of shared memory objects.
diff --git a/media/libstagefright/foundation/MetaData.cpp b/media/libstagefright/foundation/MetaData.cpp
index 8174597..7f48cfd 100644
--- a/media/libstagefright/foundation/MetaData.cpp
+++ b/media/libstagefright/foundation/MetaData.cpp
@@ -28,7 +28,7 @@
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/MetaData.h>
 
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 #include <binder/Parcel.h>
 #endif
 
@@ -48,7 +48,7 @@
 MetaData::~MetaData() {
 }
 
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 /* static */
 sp<MetaData> MetaData::createFromParcel(const Parcel &parcel) {
 
diff --git a/media/libstagefright/foundation/MetaDataBase.cpp b/media/libstagefright/foundation/MetaDataBase.cpp
index 4b439c6..3f050ea 100644
--- a/media/libstagefright/foundation/MetaDataBase.cpp
+++ b/media/libstagefright/foundation/MetaDataBase.cpp
@@ -28,7 +28,7 @@
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/MetaDataBase.h>
 
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 #include <binder/Parcel.h>
 #endif
 
@@ -452,7 +452,7 @@
     }
 }
 
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 status_t MetaDataBase::writeToParcel(Parcel &parcel) {
     status_t ret;
     size_t numItems = mInternalData->mItems.size();
@@ -532,7 +532,7 @@
     ALOGW("no metadata in parcel");
     return UNKNOWN_ERROR;
 }
-#endif
+#endif // !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 
 }  // namespace android
 
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
index b5d6666..31e58ba 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
@@ -63,7 +63,7 @@
     AMessage();
     AMessage(uint32_t what, const sp<const AHandler> &handler);
 
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
     // Construct an AMessage from a parcel.
     // nestingAllowed determines how many levels AMessage can be nested inside
     // AMessage. The default value here is arbitrarily set to 255.
@@ -88,7 +88,7 @@
     // All items in the AMessage must have types that are recognized by
     // FromParcel(); otherwise, TRESPASS error will occur.
     void writeToParcel(Parcel *parcel) const;
-#endif
+#endif // !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 
     void setWhat(uint32_t what);
     uint32_t what() const;
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h
index deef0d4..517774b 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h
@@ -89,7 +89,7 @@
 
     void tolower();
 
-#ifndef __ANDROID_VNDK__
+#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
     static AString FromParcel(const Parcel &parcel);
     status_t writeToParcel(Parcel *parcel) const;
 #endif
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 5509512..e97f6eb 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -813,6 +813,10 @@
                 baseSize = U32_AT(&mParent.mData[mOffset + 4]);
             }
 
+            if (baseSize == 0) {
+                return;
+            }
+
             // Prevent integer overflow when adding
             if (SIZE_MAX - 10 <= baseSize) {
                 return;
diff --git a/media/libstagefright/id3/TEST_MAPPING b/media/libstagefright/id3/TEST_MAPPING
index d070d25..d82d26e 100644
--- a/media/libstagefright/id3/TEST_MAPPING
+++ b/media/libstagefright/id3/TEST_MAPPING
@@ -7,7 +7,7 @@
     { "name": "ID3Test" }
   ],
 
-  "presubmit": [
+  "presubmit-large": [
     // this doesn't seem to run any tests.
     // but: cts-tradefed run -m CtsMediaTestCases -t android.media.cts.MediaMetadataRetrieverTest
     // does run he 32 and 64 bit tests, but not the instant tests
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 4c97b4d..30bc44e 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -31,6 +31,7 @@
 #include <OMX_Audio.h>
 #include <hardware/gralloc.h>
 #include <nativebase/nativebase.h>
+#include <android/hardware/graphics/common/1.2/types.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 
@@ -54,6 +55,7 @@
 struct DescribeColorFormat2Params;
 struct DataConverter;
 
+using android::hardware::graphics::common::V1_2::BufferUsage;
 typedef hidl::allocator::V1_0::IAllocator TAllocator;
 typedef hidl::memory::V1_0::IMemory TMemory;
 
@@ -165,7 +167,8 @@
     enum {
         kVideoGrallocUsage = (GRALLOC_USAGE_HW_TEXTURE
                             | GRALLOC_USAGE_HW_COMPOSER
-                            | GRALLOC_USAGE_EXTERNAL_DISP),
+                            | GRALLOC_USAGE_EXTERNAL_DISP)
+                            | static_cast<uint64_t>(BufferUsage::VIDEO_DECODER),
     };
 
     struct BufferInfo {
diff --git a/media/libstagefright/include/media/stagefright/MediaBuffer.h b/media/libstagefright/include/media/stagefright/MediaBuffer.h
index 9145b63..2c03f27 100644
--- a/media/libstagefright/include/media/stagefright/MediaBuffer.h
+++ b/media/libstagefright/include/media/stagefright/MediaBuffer.h
@@ -46,7 +46,7 @@
     explicit MediaBuffer(size_t size);
 
     explicit MediaBuffer(const sp<ABuffer> &buffer);
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
     MediaBuffer(const sp<IMemory> &mem) :
          // TODO: Using unsecurePointer() has some associated security pitfalls
          //       (see declaration for details).
@@ -97,7 +97,7 @@
     }
 
     virtual int remoteRefcount() const {
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
          // TODO: Using unsecurePointer() has some associated security pitfalls
          //       (see declaration for details).
          //       Either document why it is safe in this case or address the
@@ -114,7 +114,7 @@
 
     // returns old value
     int addRemoteRefcount(int32_t value) {
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
           // TODO: Using unsecurePointer() has some associated security pitfalls
          //       (see declaration for details).
          //       Either document why it is safe in this case or address the
@@ -132,7 +132,7 @@
     }
 
     static bool isDeadObject(const sp<IMemory> &memory) {
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
          // TODO: Using unsecurePointer() has some associated security pitfalls
          //       (see declaration for details).
          //       Either document why it is safe in this case or address the
@@ -235,7 +235,7 @@
     };
 
     inline SharedControl *getSharedControl() const {
-#ifndef NO_IMEMORY
+#if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
          // TODO: Using unsecurePointer() has some associated security pitfalls
          //       (see declaration for details).
          //       Either document why it is safe in this case or address the
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecList.h b/media/libstagefright/include/media/stagefright/MediaCodecList.h
index e681d25..78d1005 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecList.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecList.h
@@ -88,7 +88,7 @@
     static sp<IMediaCodecList> sCodecList;
     static sp<IMediaCodecList> sRemoteList;
 
-    status_t mInitCheck;
+    status_t mInitCheck{NO_INIT};
 
     sp<AMessage> mGlobalSettings;
     std::vector<sp<MediaCodecInfo> > mCodecInfos;
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index f260510..940bd86 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -225,6 +225,8 @@
     kKeyExifSize         = 'exsz', // int64_t, Exif data size
     kKeyExifTiffOffset   = 'thdr', // int32_t, if > 0, buffer contains exif data block with
                                    // tiff hdr at specified offset
+    kKeyXmpOffset        = 'xmof', // int64_t, XMP data offset
+    kKeyXmpSize          = 'xmsz', // int64_t, XMP data size
     kKeyPcmBigEndian     = 'pcmb', // bool (int32_t)
 
     // Key for ALAC Magic Cookie
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index 227cead..d8f2b00 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -47,12 +47,14 @@
         SAMPLE_FLAG_ENCRYPTED   = 2,
     };
 
+    typedef IMediaExtractor::EntryPoint EntryPoint;
+
     // identical to IMediaExtractor::GetTrackMetaDataFlags
     enum GetTrackFormatFlags {
         kIncludeExtensiveMetaData = 1, // reads sample table and possibly stream headers
     };
 
-    NuMediaExtractor();
+    explicit NuMediaExtractor(EntryPoint entryPoint);
 
     status_t setDataSource(
             const sp<MediaHTTPService> &httpService,
@@ -128,6 +130,8 @@
         uint32_t mTrackFlags;  // bitmask of "TrackFlags"
     };
 
+    const EntryPoint mEntryPoint;
+
     mutable Mutex mLock;
 
     sp<DataSource> mDataSource;
@@ -139,6 +143,8 @@
     int64_t mTotalBitrate;  // in bits/sec
     int64_t mDurationUs;
 
+    void setEntryPointToRemoteMediaExtractor();
+
     ssize_t fetchAllTrackSamples(
             int64_t seekTimeUs = -1ll,
             MediaSource::ReadOptions::SeekMode mode =
diff --git a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
index 2ce7bc7..25125f2 100644
--- a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
@@ -42,6 +42,7 @@
     virtual uint32_t flags() const;
     virtual status_t setMediaCas(const HInterfaceToken &casToken);
     virtual String8 name();
+    virtual status_t setEntryPoint(EntryPoint entryPoint);
 
 private:
     MediaExtractor *mExtractor;
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index 62e3a4b..27a94fd 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -60,21 +60,23 @@
 
     mIsAudio = false;
     mIsVideo = false;
+    const char *mime;
 
-    if (meta == NULL) {
+    // Do not use meta if no mime.
+    if (meta == NULL || !meta->findCString(kKeyMIMEType, &mime)) {
         return;
     }
 
     mFormat = meta;
-    const char *mime;
-    CHECK(meta->findCString(kKeyMIMEType, &mime));
 
     if (!strncasecmp("audio/", mime, 6)) {
         mIsAudio = true;
-    } else  if (!strncasecmp("video/", mime, 6)) {
+    } else if (!strncasecmp("video/", mime, 6)) {
         mIsVideo = true;
+    } else if (!strncasecmp("text/", mime, 5) || !strncasecmp("application/", mime, 12)) {
+        return;
     } else {
-        CHECK(!strncasecmp("text/", mime, 5) || !strncasecmp("application/", mime, 12));
+        ALOGW("Unsupported mime type: %s", mime);
     }
 }
 
diff --git a/media/libstagefright/renderfright/include/renderengine/RenderEngine.h b/media/libstagefright/renderfright/include/renderengine/RenderEngine.h
index 09a0f65..40fdff4 100644
--- a/media/libstagefright/renderfright/include/renderengine/RenderEngine.h
+++ b/media/libstagefright/renderfright/include/renderengine/RenderEngine.h
@@ -33,7 +33,7 @@
 /**
  * Allows to set RenderEngine backend to GLES (default) or Vulkan (NOT yet supported).
  */
-#define PROPERTY_DEBUG_RENDERENGINE_BACKEND "debug.renderengine.backend"
+#define PROPERTY_DEBUG_RENDERENGINE_BACKEND "debug.stagefright.renderengine.backend"
 
 struct ANativeWindowBuffer;
 
diff --git a/media/libstagefright/renderfright/tests/RenderEngineTest.cpp b/media/libstagefright/renderfright/tests/RenderEngineTest.cpp
index 730f606..2697ff4 100644
--- a/media/libstagefright/renderfright/tests/RenderEngineTest.cpp
+++ b/media/libstagefright/renderfright/tests/RenderEngineTest.cpp
@@ -111,9 +111,9 @@
         std::vector<uint8_t> outBuffer(mBuffer->getWidth() * mBuffer->getHeight() * 3);
         auto outPtr = reinterpret_cast<uint8_t*>(outBuffer.data());
 
-        for (int32_t j = 0; j < mBuffer->getHeight(); j++) {
+        for (uint32_t j = 0; j < mBuffer->getHeight(); j++) {
             const uint8_t* src = pixels + (mBuffer->getStride() * j) * 4;
-            for (int32_t i = 0; i < mBuffer->getWidth(); i++) {
+            for (uint32_t i = 0; i < mBuffer->getWidth(); i++) {
                 // Only copy R, G and B components
                 outPtr[0] = src[0];
                 outPtr[1] = src[1];
@@ -419,9 +419,9 @@
         buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
                   reinterpret_cast<void**>(&pixels));
 
-        for (int32_t j = 0; j < buf->getHeight(); j++) {
+        for (uint32_t j = 0; j < buf->getHeight(); j++) {
             uint8_t* iter = pixels + (buf->getStride() * j) * 4;
-            for (int32_t i = 0; i < buf->getWidth(); i++) {
+            for (uint32_t i = 0; i < buf->getWidth(); i++) {
                 iter[0] = uint8_t(r * 255);
                 iter[1] = uint8_t(g * 255);
                 iter[2] = uint8_t(b * 255);
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index f57077c..07f9dd3 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -131,7 +131,7 @@
     unsigned start = (unsigned)((rand()* 1000LL)/RAND_MAX) + 15550;
     start &= ~1;
 
-    for (unsigned port = start; port < 65536; port += 2) {
+    for (unsigned port = start; port < 65535; port += 2) {
         struct sockaddr_in addr;
         memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
         addr.sin_family = AF_INET;
@@ -149,6 +149,13 @@
                  (const struct sockaddr *)&addr, sizeof(addr)) == 0) {
             *rtpPort = port;
             return;
+        } else {
+            // we should recreate a RTP socket to avoid bind other port in same RTP socket
+            close(*rtpSocket);
+
+            *rtpSocket = socket(AF_INET, SOCK_DGRAM, 0);
+            CHECK_GE(*rtpSocket, 0);
+            bumpSocketBufferSize(*rtpSocket);
         }
     }
 
diff --git a/media/libstagefright/tests/Android.bp b/media/libstagefright/tests/Android.bp
index a7f94c1..5f3f72c 100644
--- a/media/libstagefright/tests/Android.bp
+++ b/media/libstagefright/tests/Android.bp
@@ -20,7 +20,7 @@
         "frameworks/native/include/media/openmax",
     ],
 
-    compile_multilib: "32",
+    compile_multilib: "prefer32",
 
     cflags: [
         "-Werror",
@@ -44,4 +44,4 @@
         "-Werror",
         "-Wall",
     ],
-}
\ No newline at end of file
+}
diff --git a/media/libstagefright/writer_fuzzers/Android.bp b/media/libstagefright/writer_fuzzers/Android.bp
new file mode 100644
index 0000000..224aeb3
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/Android.bp
@@ -0,0 +1,60 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+cc_defaults {
+    name: "writer-fuzzerbase-defaults",
+    local_include_dirs: [
+        "include",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+    static_libs: [
+        "liblog",
+        "libstagefright_foundation",
+        "libstagefright",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libcutils",
+        "libutils",
+    ],
+}
+
+cc_defaults {
+    name: "writer-fuzzer-defaults",
+    defaults: ["writer-fuzzerbase-defaults"],
+    static_libs: [
+        "libwriterfuzzerbase",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 155276,
+    },
+}
+
+cc_library_static {
+    name: "libwriterfuzzerbase",
+    defaults: ["writer-fuzzerbase-defaults"],
+    srcs: [
+        "WriterFuzzerBase.cpp",
+    ],
+}
diff --git a/media/libstagefright/writer_fuzzers/README.md b/media/libstagefright/writer_fuzzers/README.md
new file mode 100644
index 0000000..037236a
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/README.md
@@ -0,0 +1,46 @@
+# Fuzzer for writers
+
+## Table of contents
+   [libwriterfuzzerbase](#WriterFuzzerBase)
+
+# <a name="WriterFuzzerBase"></a> Fuzzer for libwriterfuzzerbase
+All the writers have a common API - creating a writer, adding a source for
+all the tracks, etc. These common APIs have been abstracted in a base class
+called `WriterFuzzerBase` to ensure code is reused between fuzzer plugins.
+
+## Plugin Design Considerations
+The fuzzer plugin for writers is designed based on the understanding of the
+writer and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+Fuzzer for writers supports the following parameters:
+1. Track Mime (parameter name: `mime`)
+2. Channel Count (parameter name: `channel-count`)
+3. Sample Rate (parameter name: `sample-rate`)
+4. Frame Height (parameter name: `height`)
+5. Frame Width (parameter name: `width`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `mime` | 0. `audio/3gpp` 1. `audio/amr-wb` 2. `audio/vorbis` 3. `audio/opus` 4. `audio/mp4a-latm` 5. `video/avc` 6. `video/hevc` 7. `video/mp4v-es` 8. `video/3gpp` 9. `video/x-vnd.on2.vp8` 10. `video/x-vnd.on2.vp9` | All the bits of 2nd byte of data for first track and 11th byte of data for second track (if present) modulus 10 |
+| `channel-count` | In the range `0 to INT32_MAX` | All the bits of 3rd byte to 6th bytes of data if first track is audio and 12th to 15th bytes of data if second track is audio |
+| `sample-rate` | In the range `1 to INT32_MAX` | All the bits of 7th byte to 10th bytes of data if first track is audio and 16th to 19th bytes of data if second track is audio |
+| `height` | In the range `0 to INT32_MAX` | All the bits of 3rd byte to 6th bytes of data if first track is video and 12th to 15th bytes of data if second track is video |
+| `width` | In the range `0 to INT32_MAX` | All the bits of 7th byte to 10th bytes of data if first track is video and 16th to 19th bytes of data if second track is video |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin divides the entire input data into frames based on frame markers.
+If no frame marker is found then the entire input data is treated as single frame.
+
+This ensures that the plugin tolerates any kind of input (huge,
+malformed, etc) and thereby increasing the chance of identifying vulnerabilities.
+
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
new file mode 100644
index 0000000..65593e7
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
@@ -0,0 +1,260 @@
+/*
+ * 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.
+ */
+#include <utils/Log.h>
+
+#include "WriterFuzzerBase.h"
+
+using namespace android;
+
+/**
+ * Buffer source implementations to parse input file
+ */
+
+uint32_t WriterFuzzerBase::BufferSource::getNumTracks() {
+    uint32_t numTracks = 0;
+    if (mSize > sizeof(uint8_t)) {
+        numTracks = min(mData[0], kMaxTrackCount);
+        mReadIndex += sizeof(uint8_t);
+    }
+    return numTracks;
+}
+
+bool WriterFuzzerBase::BufferSource::searchForMarker(size_t startIndex) {
+    while (true) {
+        if (isMarker()) {
+            return true;
+        }
+        --mReadIndex;
+        if (mReadIndex < startIndex) {
+            break;
+        }
+    }
+    return false;
+}
+
+ConfigFormat WriterFuzzerBase::BufferSource::getConfigFormat(int32_t trackIndex) {
+    return mParams[trackIndex];
+}
+
+int32_t WriterFuzzerBase::BufferSource::getNumCsds(int32_t trackIndex) {
+    return mNumCsds[trackIndex];
+}
+
+vector<FrameData> WriterFuzzerBase::BufferSource::getFrameList(int32_t trackIndex) {
+    return mFrameList[trackIndex];
+}
+
+void WriterFuzzerBase::BufferSource::getFrameInfo() {
+    size_t readIndexStart = mReadIndex;
+    if (mSize - mReadIndex > kMarkerSize + kMarkerSuffixSize) {
+        bool isFrameAvailable = true;
+        size_t bytesRemaining = mSize;
+        mReadIndex = mSize - kMarkerSize;
+        while (isFrameAvailable) {
+            isFrameAvailable = searchForMarker(readIndexStart);
+            if (isFrameAvailable) {
+                size_t location = mReadIndex + kMarkerSize;
+                if (location + kMarkerSuffixSize >= bytesRemaining) {
+                    break;
+                }
+                bool isCSD = isCSDMarker(location);
+                location += kMarkerSuffixSize;
+                uint8_t *framePtr = const_cast<uint8_t *>(&mData[location]);
+                size_t frameSize = bytesRemaining - location, bufferSize = 0;
+                uint8_t trackIndex = framePtr[0] % kMaxTrackCount;
+                ++framePtr;
+                uint8_t flags = 0;
+                int64_t pts = 0;
+                if (isCSD && frameSize > 1) {
+                    flags |= kCodecConfigFlag;
+                    pts = 0;
+                    ++mNumCsds[trackIndex];
+                    bufferSize = frameSize - 1;
+                } else if (frameSize > sizeof(uint8_t) + sizeof(int64_t) + 1) {
+                    flags = flagTypes[framePtr[0] % size(flagTypes)];
+                    ++framePtr;
+                    copy(framePtr, framePtr + sizeof(int64_t), reinterpret_cast<uint8_t *>(&pts));
+                    framePtr += sizeof(int64_t);
+                    bufferSize = frameSize - (sizeof(uint8_t) + sizeof(int64_t)) - 1;
+                } else {
+                    break;
+                }
+                mFrameList[trackIndex].insert(
+                    mFrameList[trackIndex].begin(),
+                    FrameData{static_cast<int32_t>(bufferSize), flags, pts, framePtr});
+                bytesRemaining -= (frameSize + kMarkerSize + kMarkerSuffixSize);
+                --mReadIndex;
+            }
+        }
+    }
+    if (mFrameList[0].empty() && mFrameList[1].empty()) {
+        /**
+         * Scenario where input data does not contain the custom frame markers.
+         * Hence feed the entire data as single frame.
+         */
+        mFrameList[0].emplace_back(
+            FrameData{static_cast<int32_t>(mSize - readIndexStart), 0, 0, mData + readIndexStart});
+    }
+}
+bool WriterFuzzerBase::BufferSource::getTrackInfo(int32_t trackIndex) {
+    if (mSize <= mReadIndex + 2 * sizeof(int) + sizeof(uint8_t)) {
+        return false;
+    }
+    size_t mimeTypeIdx = mData[mReadIndex] % kSupportedMimeTypes;
+    char *mime = (char *)supportedMimeTypes[mimeTypeIdx].c_str();
+    mParams[trackIndex].mime = mime;
+    ++mReadIndex;
+
+    if (!strncmp(mime, "audio/", 6)) {
+        copy(mData + mReadIndex, mData + mReadIndex + sizeof(int),
+             reinterpret_cast<char *>(&mParams[trackIndex].channelCount));
+        copy(mData + mReadIndex + sizeof(int), mData + mReadIndex + 2 * sizeof(int),
+             reinterpret_cast<char *>(&mParams[trackIndex].sampleRate));
+    } else {
+        copy(mData + mReadIndex, mData + mReadIndex + sizeof(int),
+             reinterpret_cast<char *>(&mParams[trackIndex].height));
+        copy(mData + mReadIndex + sizeof(int), mData + mReadIndex + 2 * sizeof(int),
+             reinterpret_cast<char *>(&mParams[trackIndex].width));
+    }
+    mReadIndex += 2 * sizeof(int);
+    return true;
+}
+
+void writeHeaderBuffers(vector<FrameData> &bufferInfo, sp<AMessage> &format, int32_t numCsds) {
+    char csdName[kMaxCSDStrlen];
+    for (int csdId = 0; csdId < numCsds; ++csdId) {
+        int32_t flags = bufferInfo[csdId].flags;
+        if (flags == kCodecConfigFlag) {
+            sp<ABuffer> csdBuffer =
+                ABuffer::CreateAsCopy((void *)bufferInfo[csdId].buf, bufferInfo[csdId].size);
+            if (csdBuffer.get() == nullptr || csdBuffer->base() == nullptr) {
+                return;
+            }
+            snprintf(csdName, sizeof(csdName), "csd-%d", csdId);
+            format->setBuffer(csdName, csdBuffer);
+        }
+    }
+}
+
+bool WriterFuzzerBase::createOutputFile() {
+    mFd = memfd_create(mOutputFileName.c_str(), MFD_ALLOW_SEALING);
+    if (mFd == -1) {
+        return false;
+    }
+    return true;
+}
+
+void WriterFuzzerBase::addWriterSource(int32_t trackIndex) {
+    ConfigFormat params = mBufferSource->getConfigFormat(trackIndex);
+    sp<AMessage> format = new AMessage;
+    format->setString("mime", params.mime);
+    if (!strncmp(params.mime, "audio/", 6)) {
+        if (!strncmp(params.mime, "audio/3gpp", 10)) {
+            params.channelCount = 1;
+            params.sampleRate = 8000;
+        } else if (!strncmp(params.mime, "audio/amr-wb", 12)) {
+            params.channelCount = 1;
+            params.sampleRate = 16000;
+        } else {
+            params.sampleRate = max(1, params.sampleRate);
+        }
+        format->setInt32("channel-count", params.channelCount);
+        format->setInt32("sample-rate", params.sampleRate);
+    } else {
+        format->setInt32("width", params.width);
+        format->setInt32("height", params.height);
+    }
+    int32_t numCsds = mBufferSource->getNumCsds(trackIndex);
+    if (numCsds) {
+        vector<FrameData> mFrames = mBufferSource->getFrameList(trackIndex);
+        writeHeaderBuffers(mFrames, format, numCsds);
+    }
+    sp<MetaData> trackMeta = new MetaData;
+    convertMessageToMetaData(format, trackMeta);
+    mCurrentTrack[trackIndex] = new MediaAdapter(trackMeta);
+    mWriter->addSource(mCurrentTrack[trackIndex]);
+}
+
+void WriterFuzzerBase::start() {
+    mFileMeta->setInt32(kKeyRealTimeRecording, false);
+    mWriter->start(mFileMeta.get());
+}
+
+void WriterFuzzerBase::sendBuffersToWriter(sp<MediaAdapter> &currentTrack, int32_t trackIndex) {
+    int32_t numCsds = mBufferSource->getNumCsds(trackIndex);
+    vector<FrameData> bufferInfo = mBufferSource->getFrameList(trackIndex);
+    int32_t range = bufferInfo.size();
+    for (int idx = numCsds; idx < range; ++idx) {
+        sp<ABuffer> buffer = new ABuffer((void *)bufferInfo[idx].buf, bufferInfo[idx].size);
+        MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
+
+        // Released in MediaAdapter::signalBufferReturned().
+        mediaBuffer->add_ref();
+        mediaBuffer->set_range(buffer->offset(), buffer->size());
+        MetaDataBase &sampleMetaData = mediaBuffer->meta_data();
+        sampleMetaData.setInt64(kKeyTime, bufferInfo[idx].timeUs);
+
+        // Just set the kKeyDecodingTime as the presentation time for now.
+        sampleMetaData.setInt64(kKeyDecodingTime, bufferInfo[idx].timeUs);
+        if (bufferInfo[idx].flags == 1) {
+            sampleMetaData.setInt32(kKeyIsSyncFrame, true);
+        }
+
+        // This pushBuffer will wait until the mediaBuffer is consumed.
+        currentTrack->pushBuffer(mediaBuffer);
+    }
+}
+
+void WriterFuzzerBase::processData(const uint8_t *data, size_t size) {
+    if (!createOutputFile()) {
+        return;
+    }
+    if (!createWriter()) {
+        return;
+    }
+    mBufferSource = new BufferSource(data, size);
+    if (!mBufferSource) {
+        return;
+    }
+    mNumTracks = mBufferSource->getNumTracks();
+    if (mNumTracks > 0) {
+        for (int32_t idx = 0; idx < mNumTracks; ++idx) {
+            if (!mBufferSource->getTrackInfo(idx)) {
+                if (idx == 0) {
+                    delete mBufferSource;
+                    return;
+                }
+                mNumTracks = idx;
+                break;
+            }
+        }
+        mBufferSource->getFrameInfo();
+        for (int32_t idx = 0; idx < mNumTracks; ++idx) {
+            addWriterSource(idx);
+        }
+        start();
+        for (int32_t idx = 0; idx < mNumTracks; ++idx) {
+            sendBuffersToWriter(mCurrentTrack[idx], idx);
+        }
+        for (int32_t idx = 0; idx < mNumTracks; ++idx) {
+            if (mCurrentTrack[idx]) {
+                mCurrentTrack[idx]->stop();
+            }
+        }
+    }
+    delete mBufferSource;
+    mWriter->stop();
+}
diff --git a/media/libstagefright/writer_fuzzers/include/WriterFuzzerBase.h b/media/libstagefright/writer_fuzzers/include/WriterFuzzerBase.h
new file mode 100644
index 0000000..d819d43
--- /dev/null
+++ b/media/libstagefright/writer_fuzzers/include/WriterFuzzerBase.h
@@ -0,0 +1,168 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#ifndef __WRITER_FUZZER_BASE_H__
+#define __WRITER_FUZZER_BASE_H__
+
+#include <media/stagefright/MediaAdapter.h>
+#include <media/stagefright/MediaWriter.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <algorithm>
+#include <cstring>
+#include <vector>
+
+using namespace std;
+
+constexpr uint32_t kMimeSize = 128;
+constexpr uint8_t kMaxTrackCount = 2;
+constexpr uint32_t kMaxCSDStrlen = 16;
+constexpr uint32_t kCodecConfigFlag = 32;
+
+namespace android {
+
+struct ConfigFormat {
+    char* mime;
+    int32_t width;
+    int32_t height;
+    int32_t sampleRate;
+    int32_t channelCount;
+};
+
+struct FrameData {
+    int32_t size;
+    uint8_t flags;
+    int64_t timeUs;
+    const uint8_t* buf;
+};
+
+static string supportedMimeTypes[] = {
+    "audio/3gpp",      "audio/amr-wb",        "audio/vorbis",        "audio/opus",
+    "audio/mp4a-latm", "video/avc",           "video/hevc",          "video/mp4v-es",
+    "video/3gpp",      "video/x-vnd.on2.vp8", "video/x-vnd.on2.vp9",
+};
+
+enum {
+    DEFAULT_FLAG = 0,
+    SYNC_FLAG = 1,
+    ENCRYPTED_FLAG = 2,
+};
+
+static uint8_t flagTypes[] = {DEFAULT_FLAG, SYNC_FLAG, ENCRYPTED_FLAG};
+
+class WriterFuzzerBase {
+   public:
+    WriterFuzzerBase() = default;
+    virtual ~WriterFuzzerBase() {
+        if (mFileMeta) {
+            mFileMeta.clear();
+            mFileMeta = nullptr;
+        }
+        if (mWriter) {
+            mWriter.clear();
+            mWriter = nullptr;
+        }
+        for (int32_t idx = 0; idx < kMaxTrackCount; ++idx) {
+            if (mCurrentTrack[idx]) {
+                mCurrentTrack[idx]->stop();
+                mCurrentTrack[idx].clear();
+                mCurrentTrack[idx] = nullptr;
+            }
+        }
+        close(mFd);
+    };
+
+    /** Function to create the media writer component.
+     * To be implemented by the derived class.
+     */
+    virtual bool createWriter() = 0;
+
+    /** Parent class functions to be reused by derived class.
+     * These are common for all media writer components.
+     */
+    bool createOutputFile();
+
+    void addWriterSource(int32_t trackIndex);
+
+    void start();
+
+    void sendBuffersToWriter(sp<MediaAdapter>& currentTrack, int32_t trackIndex);
+
+    void processData(const uint8_t* data, size_t size);
+
+   protected:
+    class BufferSource {
+       public:
+        BufferSource(const uint8_t* data, size_t size) : mData(data), mSize(size), mReadIndex(0) {}
+        ~BufferSource() {
+            mData = nullptr;
+            mSize = 0;
+            mReadIndex = 0;
+            for (int32_t idx = 0; idx < kMaxTrackCount; ++idx) {
+                mFrameList[idx].clear();
+            }
+        }
+        uint32_t getNumTracks();
+        bool getTrackInfo(int32_t trackIndex);
+        void getFrameInfo();
+        ConfigFormat getConfigFormat(int32_t trackIndex);
+        int32_t getNumCsds(int32_t trackIndex);
+        vector<FrameData> getFrameList(int32_t trackIndex);
+
+       private:
+        bool isMarker() { return (memcmp(&mData[mReadIndex], kMarker, kMarkerSize) == 0); }
+
+        bool isCSDMarker(size_t position) {
+            return (memcmp(&mData[position], kCsdMarkerSuffix, kMarkerSuffixSize) == 0);
+        }
+
+        bool searchForMarker(size_t startIndex);
+
+        const uint8_t* mData = nullptr;
+        size_t mSize = 0;
+        size_t mReadIndex = 0;
+        ConfigFormat mParams[kMaxTrackCount] = {};
+        int32_t mNumCsds[kMaxTrackCount] = {0};
+        vector<FrameData> mFrameList[kMaxTrackCount];
+
+        static constexpr int kSupportedMimeTypes = size(supportedMimeTypes);
+        static constexpr uint8_t kMarker[] = "_MARK";
+        static constexpr uint8_t kCsdMarkerSuffix[] = "_H_";
+        static constexpr uint8_t kFrameMarkerSuffix[] = "_F_";
+        // All markers should be 5 bytes long ( sizeof '_MARK' which is 5)
+        static constexpr size_t kMarkerSize = (sizeof(kMarker) - 1);
+        // All marker types should be 3 bytes long ('_H_', '_F_')
+        static constexpr size_t kMarkerSuffixSize = 3;
+    };
+
+    BufferSource* mBufferSource = nullptr;
+    int32_t mFd = -1;
+    uint32_t mNumTracks = 0;
+    string mOutputFileName = "writer.out";
+    sp<MediaWriter> mWriter = nullptr;
+    sp<MetaData> mFileMeta = nullptr;
+    sp<MediaAdapter> mCurrentTrack[kMaxTrackCount] = {};
+};
+
+}  // namespace android
+
+#endif  // __WRITER_FUZZER_BASE_H__
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index 8d5c77f..ee7285d 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -17,6 +17,7 @@
     shared_libs: [
         "android.hardware.media.omx@1.0",
         "libandroidicu",
+        "libfmq",
         "libbinder",
         "libhidlbase",
         "liblog",
diff --git a/media/mediaserver/mediaserver.rc b/media/mediaserver/mediaserver.rc
index 05373c9..c82e532 100644
--- a/media/mediaserver/mediaserver.rc
+++ b/media/mediaserver/mediaserver.rc
@@ -7,3 +7,9 @@
     group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
     ioprio rt 4
     task_profiles ProcessCapacityHigh HighPerformance
+
+# media.transcoding service is defined on com.android.media apex which goes back
+# to API29, but we only want it started on API31+ devices. So we declare it as
+# "disabled" and start it explicitly on boot.
+on boot
+    start media.transcoding
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index 1145b7b..5fdd45a 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -58,7 +58,7 @@
     if (mIsClosed) {
         return;
     }
-    if (!mReader->mIsClosed) {
+    if (mReader->mIsOpen) {
         mReader->releaseImageLocked(this, releaseFenceFd);
     }
     // Should have been set to nullptr in releaseImageLocked
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index 5d8f0b8..b75901a 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -273,7 +273,7 @@
 
 AImageReader::~AImageReader() {
     Mutex::Autolock _l(mLock);
-    LOG_FATAL_IF("AImageReader not closed before destruction", mIsClosed != true);
+    LOG_FATAL_IF(mIsOpen, "AImageReader not closed before destruction");
 }
 
 media_status_t
@@ -347,16 +347,16 @@
     }
     mHandler = new CallbackHandler(this);
     mCbLooper->registerHandler(mHandler);
-
+    mIsOpen = true;
     return AMEDIA_OK;
 }
 
 void AImageReader::close() {
     Mutex::Autolock _l(mLock);
-    if (mIsClosed) {
+    if (!mIsOpen) {
         return;
     }
-    mIsClosed = true;
+    mIsOpen = false;
     AImageReader_ImageListener nullListener = {nullptr, nullptr};
     setImageListenerLocked(&nullListener);
 
diff --git a/media/ndk/NdkImageReaderPriv.h b/media/ndk/NdkImageReaderPriv.h
index 0779a71..37c606e 100644
--- a/media/ndk/NdkImageReaderPriv.h
+++ b/media/ndk/NdkImageReaderPriv.h
@@ -166,7 +166,7 @@
     native_handle_t*           mWindowHandle = nullptr;
 
     List<AImage*>              mAcquiredImages;
-    bool                       mIsClosed = false;
+    bool                       mIsOpen = false;
 
     Mutex                      mLock;
 };
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index 0da0740..0c65e9e 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -22,6 +22,7 @@
 #include <media/NdkMediaExtractor.h>
 #include <media/NdkMediaErrorPriv.h>
 #include <media/NdkMediaFormatPriv.h>
+#include "NdkJavaVMHelperPriv.h"
 #include "NdkMediaDataSourcePriv.h"
 
 
@@ -63,7 +64,10 @@
 AMediaExtractor* AMediaExtractor_new() {
     ALOGV("ctor");
     AMediaExtractor *mData = new AMediaExtractor();
-    mData->mImpl = new NuMediaExtractor();
+    mData->mImpl = new NuMediaExtractor(
+        NdkJavaVMHelper::getJNIEnv() != nullptr
+                ? NuMediaExtractor::EntryPoint::NDK_WITH_JVM
+                : NuMediaExtractor::EntryPoint::NDK_NO_JVM );
     return mData;
 }
 
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 47214c5..8e673ca 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -384,6 +384,8 @@
 EXPORT const char* AMEDIAFORMAT_KEY_TRACK_INDEX = "track-index";
 EXPORT const char* AMEDIAFORMAT_KEY_VALID_SAMPLES = "valid-samples";
 EXPORT const char* AMEDIAFORMAT_KEY_WIDTH = "width";
+EXPORT const char* AMEDIAFORMAT_KEY_XMP_OFFSET = "xmp-offset";
+EXPORT const char* AMEDIAFORMAT_KEY_XMP_SIZE = "xmp-size";
 EXPORT const char* AMEDIAFORMAT_KEY_YEAR = "year";
 
 } // extern "C"
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 8f39929..0b9024f 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -325,6 +325,8 @@
 #if __ANDROID_API__ >= 31
 extern const char* AMEDIAFORMAT_KEY_SLOW_MOTION_MARKERS __INTRODUCED_IN(31);
 extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_CSD_AV1C __INTRODUCED_IN(31);
+extern const char* AMEDIAFORMAT_KEY_XMP_OFFSET __INTRODUCED_IN(31);
+extern const char* AMEDIAFORMAT_KEY_XMP_SIZE __INTRODUCED_IN(31);
 #endif /* __ANDROID_API__ >= 31 */
 
 __END_DECLS
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 96f1710..2b389fe 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -151,6 +151,8 @@
     AMEDIAFORMAT_KEY_TRACK_ID; # var introduced=28
     AMEDIAFORMAT_KEY_VALID_SAMPLES; # var introduced=29
     AMEDIAFORMAT_KEY_WIDTH; # var introduced=21
+    AMEDIAFORMAT_KEY_XMP_OFFSET; # var introduced=31
+    AMEDIAFORMAT_KEY_XMP_SIZE; # var introduced=31
     AMEDIAFORMAT_KEY_YEAR; # var introduced=29
     AMediaCodecActionCode_isRecoverable; # introduced=28
     AMediaCodecActionCode_isTransient; # introduced=28
@@ -165,11 +167,11 @@
     AMediaCodecCryptoInfo_setPattern; # introduced=24
     AMediaCodec_configure;
     AMediaCodec_createCodecByName;
-    AMediaCodec_createCodecByNameForClient; # apex #introduced = 31
+    AMediaCodec_createCodecByNameForClient; # apex # introduced=31
     AMediaCodec_createDecoderByType;
-    AMediaCodec_createDecoderByTypeForClient; # apex #introduced = 31
+    AMediaCodec_createDecoderByTypeForClient; # apex # introduced=31
     AMediaCodec_createEncoderByType;
-    AMediaCodec_createEncoderByTypeForClient; # apex #introduced = 31
+    AMediaCodec_createEncoderByTypeForClient; # apex # introduced=31
     AMediaCodec_delete;
     AMediaCodec_dequeueInputBuffer;
     AMediaCodec_dequeueOutputBuffer;
diff --git a/media/tests/benchmark/src/native/decoder/C2Decoder.cpp b/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
index 46c4a7c..6539f24 100644
--- a/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
+++ b/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
@@ -53,8 +53,8 @@
     }
 
     int64_t sTime = mStats->getCurTime();
-    mComponent = mClient->CreateComponentByName(compName.c_str(), mListener, &mClient);
-    if (mComponent == nullptr) {
+    if (mClient->CreateComponentByName(compName.c_str(), mListener, &mComponent, &mClient) !=
+        C2_OK) {
         ALOGE("Create component failed for %s", compName.c_str());
         return -1;
     }
diff --git a/media/tests/benchmark/src/native/encoder/C2Encoder.cpp b/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
index 6a50d40..ca79881 100644
--- a/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
+++ b/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
@@ -68,8 +68,8 @@
     }
 
     int64_t sTime = mStats->getCurTime();
-    mComponent = mClient->CreateComponentByName(compName.c_str(), mListener, &mClient);
-    if (mComponent == nullptr) {
+    if (mClient->CreateComponentByName(compName.c_str(), mListener, &mComponent, &mClient) !=
+        C2_OK) {
         ALOGE("Create component failed for %s", compName.c_str());
         return -1;
     }
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 87ea084..2c8a452 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -22,6 +22,7 @@
 #include <binder/IServiceManager.h>
 #include <binder/PermissionCache.h>
 #include "mediautils/ServiceUtilities.h"
+#include <system/audio-hal-enums.h>
 
 #include <iterator>
 #include <algorithm>
@@ -61,8 +62,20 @@
     return packages[0];
 }
 
+static int32_t getOpForSource(audio_source_t source) {
+  switch (source) {
+    case AUDIO_SOURCE_HOTWORD:
+      return AppOpsManager::OP_RECORD_AUDIO_HOTWORD;
+    case AUDIO_SOURCE_REMOTE_SUBMIX:
+      return AppOpsManager::OP_RECORD_AUDIO_OUTPUT;
+    case AUDIO_SOURCE_DEFAULT:
+    default:
+      return AppOpsManager::OP_RECORD_AUDIO;
+  }
+}
+
 static bool checkRecordingInternal(const String16& opPackageName, pid_t pid,
-        uid_t uid, bool start) {
+        uid_t uid, bool start, audio_source_t source) {
     // Okay to not track in app ops as audio server or media server is us and if
     // device is rooted security model is considered compromised.
     // system_server loses its RECORD_AUDIO permission when a secondary
@@ -87,16 +100,21 @@
     }
 
     AppOpsManager appOps;
-    const int32_t op = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+    const int32_t op = getOpForSource(source);
     if (start) {
-        if (appOps.startOpNoThrow(op, uid, resolvedOpPackageName, /*startIfModeDefault*/ false)
-                != AppOpsManager::MODE_ALLOWED) {
-            ALOGE("Request denied by app op: %d", op);
+        if (int32_t mode = appOps.startOpNoThrow(
+                        op, uid, resolvedOpPackageName, /*startIfModeDefault*/ false);
+                mode != AppOpsManager::MODE_ALLOWED) {
+            ALOGE("Request start for \"%s\" (uid %d) denied by app op: %d, mode: %d",
+                    String8(resolvedOpPackageName).c_str(), uid, op, mode);
             return false;
         }
     } else {
-        if (appOps.checkOp(op, uid, resolvedOpPackageName) != AppOpsManager::MODE_ALLOWED) {
-            ALOGE("Request denied by app op: %d", op);
+        // Always use OP_RECORD_AUDIO for checks at creation time.
+        if (int32_t mode = appOps.checkOp(op, uid, resolvedOpPackageName);
+                mode != AppOpsManager::MODE_ALLOWED) {
+            ALOGE("Request check for \"%s\" (uid %d) denied by app op: %d, mode: %d",
+                    String8(resolvedOpPackageName).c_str(), uid, op, mode);
             return false;
         }
     }
@@ -105,14 +123,14 @@
 }
 
 bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid) {
-    return checkRecordingInternal(opPackageName, pid, uid, /*start*/ false);
+    return checkRecordingInternal(opPackageName, pid, uid, /*start*/ false, AUDIO_SOURCE_DEFAULT);
 }
 
-bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid) {
-     return checkRecordingInternal(opPackageName, pid, uid, /*start*/ true);
+bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, audio_source_t source) {
+     return checkRecordingInternal(opPackageName, pid, uid, /*start*/ true, source);
 }
 
-void finishRecording(const String16& opPackageName, uid_t uid) {
+void finishRecording(const String16& opPackageName, uid_t uid, audio_source_t source) {
     // Okay to not track in app ops as audio server is us and if
     // device is rooted security model is considered compromised.
     if (isAudioServerOrRootUid(uid)) return;
@@ -125,7 +143,8 @@
     }
 
     AppOpsManager appOps;
-    const int32_t op = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+
+    const int32_t op = getOpForSource(source);
     appOps.finishOp(op, uid, resolvedOpPackageName);
 }
 
@@ -145,6 +164,14 @@
     return ok;
 }
 
+bool captureTunerAudioInputAllowed(pid_t pid, uid_t uid) {
+    if (isAudioServerOrRootUid(uid)) return true;
+    static const String16 sCaptureTunerAudioInput("android.permission.CAPTURE_TUNER_AUDIO_INPUT");
+    bool ok = PermissionCache::checkPermission(sCaptureTunerAudioInput, pid, uid);
+    if (!ok) ALOGV("Request requires android.permission.CAPTURE_TUNER_AUDIO_INPUT");
+    return ok;
+}
+
 bool captureVoiceCommunicationOutputAllowed(pid_t pid, uid_t uid) {
     if (isAudioServerOrRootUid(uid)) return true;
     static const String16 sCaptureVoiceCommOutput(
@@ -259,7 +286,7 @@
     return NO_ERROR;
 }
 
-sp<content::pm::IPackageManagerNative> MediaPackageManager::retreivePackageManager() {
+sp<content::pm::IPackageManagerNative> MediaPackageManager::retrievePackageManager() {
     const sp<IServiceManager> sm = defaultServiceManager();
     if (sm == nullptr) {
         ALOGW("%s: failed to retrieve defaultServiceManager", __func__);
@@ -276,27 +303,27 @@
 std::optional<bool> MediaPackageManager::doIsAllowed(uid_t uid) {
     if (mPackageManager == nullptr) {
         /** Can not fetch package manager at construction it may not yet be registered. */
-        mPackageManager = retreivePackageManager();
+        mPackageManager = retrievePackageManager();
         if (mPackageManager == nullptr) {
             ALOGW("%s: Playback capture is denied as package manager is not reachable", __func__);
             return std::nullopt;
         }
     }
 
+    // Retrieve package names for the UID and transform to a std::vector<std::string>.
+    Vector<String16> str16PackageNames;
+    PermissionController{}.getPackagesForUid(uid, str16PackageNames);
     std::vector<std::string> packageNames;
-    auto status = mPackageManager->getNamesForUids({(int32_t)uid}, &packageNames);
-    if (!status.isOk()) {
-        ALOGW("%s: Playback capture is denied for uid %u as the package names could not be "
-              "retrieved from the package manager: %s", __func__, uid, status.toString8().c_str());
-        return std::nullopt;
+    for (const auto& str16PackageName : str16PackageNames) {
+        packageNames.emplace_back(String8(str16PackageName).string());
     }
     if (packageNames.empty()) {
         ALOGW("%s: Playback capture for uid %u is denied as no package name could be retrieved "
-              "from the package manager: %s", __func__, uid, status.toString8().c_str());
+              "from the package manager.", __func__, uid);
         return std::nullopt;
     }
     std::vector<bool> isAllowed;
-    status = mPackageManager->isAudioPlaybackCaptureAllowed(packageNames, &isAllowed);
+    auto status = mPackageManager->isAudioPlaybackCaptureAllowed(packageNames, &isAllowed);
     if (!status.isOk()) {
         ALOGW("%s: Playback capture is denied for uid %u as the manifest property could not be "
               "retrieved from the package manager: %s", __func__, uid, status.toString8().c_str());
diff --git a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
index 3d141b5..f4c815c 100644
--- a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
+++ b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
@@ -17,6 +17,7 @@
 #include <fcntl.h>
 
 #include <functional>
+#include  <type_traits>
 
 #include "fuzzer/FuzzedDataProvider.h"
 #include "mediautils/ServiceUtilities.h"
@@ -44,6 +45,8 @@
     FuzzedDataProvider data_provider(data, size);
     uid_t uid = data_provider.ConsumeIntegral<uid_t>();
     pid_t pid = data_provider.ConsumeIntegral<pid_t>();
+    audio_source_t source = static_cast<audio_source_t>(data_provider
+        .ConsumeIntegral<std::underlying_type_t<audio_source_t>>());
 
     // There is not state here, and order is not significant,
     // so we can simply call all of the target functions
@@ -54,8 +57,8 @@
     std::string packageNameStr = data_provider.ConsumeRandomLengthString(kMaxStringLen);
     android::String16 opPackageName(packageNameStr.c_str());
     android::recordingAllowed(opPackageName, pid, uid);
-    android::startRecording(opPackageName, pid, uid);
-    android::finishRecording(opPackageName, uid);
+    android::startRecording(opPackageName, pid, uid, source);
+    android::finishRecording(opPackageName, uid, source);
     android::captureAudioOutputAllowed(pid, uid);
     android::captureMediaOutputAllowed(pid, uid);
     android::captureHotwordAllowed(opPackageName, pid, uid);
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 212599a..03965db 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -24,6 +24,7 @@
 #include <binder/PermissionController.h>
 #include <cutils/multiuser.h>
 #include <private/android_filesystem_config.h>
+#include <system/audio-hal-enums.h>
 
 #include <map>
 #include <optional>
@@ -79,10 +80,11 @@
 }
 
 bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
-bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid);
-void finishRecording(const String16& opPackageName, uid_t uid);
+bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, audio_source_t source);
+void finishRecording(const String16& opPackageName, uid_t uid, audio_source_t source);
 bool captureAudioOutputAllowed(pid_t pid, uid_t uid);
 bool captureMediaOutputAllowed(pid_t pid, uid_t uid);
+bool captureTunerAudioInputAllowed(pid_t pid, uid_t uid);
 bool captureVoiceCommunicationOutputAllowed(pid_t pid, uid_t uid);
 bool captureHotwordAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
 bool settingsAllowed();
@@ -110,7 +112,7 @@
 private:
     static constexpr const char* nativePackageManagerName = "package_native";
     std::optional<bool> doIsAllowed(uid_t uid);
-    sp<content::pm::IPackageManagerNative> retreivePackageManager();
+    sp<content::pm::IPackageManagerNative> retrievePackageManager();
     sp<content::pm::IPackageManagerNative> mPackageManager; // To check apps manifest
     uint_t mPackageManagerErrors = 0;
     struct Package {
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 87b5ff4..a005250 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -69,6 +69,7 @@
     ],
 
     header_libs: [
+        "libaudioclient_headers",
         "libaudiohal_headers",
         "libmedia_headers",
     ],
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e7a12df..a6f0953 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -185,9 +185,15 @@
 
 // ----------------------------------------------------------------------------
 
+void AudioFlinger::instantiate() {
+    sp<IServiceManager> sm(defaultServiceManager());
+    sm->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME),
+                   new AudioFlingerServerAdapter(new AudioFlinger()), false,
+                   IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
+}
+
 AudioFlinger::AudioFlinger()
-    : BnAudioFlinger(),
-      mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
+    : mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
       mPrimaryHardwareDev(NULL),
       mAudioHwDevs(NULL),
       mHardwareStatus(AUDIO_HW_IDLE),
@@ -1486,6 +1492,20 @@
     }
 }
 
+// Update downstream patches for all playback threads attached to an MSD module
+void AudioFlinger::updateDownStreamPatches_l(const struct audio_patch *patch,
+                                             const std::set<audio_io_handle_t> streams)
+{
+    for (const audio_io_handle_t stream : streams) {
+        PlaybackThread *playbackThread = checkPlaybackThread_l(stream);
+        if (playbackThread == nullptr || !playbackThread->isMsdDevice()) {
+            continue;
+        }
+        playbackThread->setDownStreamPatch(patch);
+        playbackThread->sendIoConfigEvent(AUDIO_OUTPUT_CONFIG_CHANGED);
+    }
+}
+
 // Filter reserved keys from setParameters() before forwarding to audio HAL or acting upon.
 // Some keys are used for audio routing and audio path configuration and should be reserved for use
 // by audio policy and audio flinger for functional, privacy and security reasons.
@@ -2569,7 +2589,11 @@
                       *output, thread.get());
             }
             mPlaybackThreads.add(*output, thread);
-            mPatchPanel.notifyStreamOpened(outHwDev, *output);
+            struct audio_patch patch;
+            mPatchPanel.notifyStreamOpened(outHwDev, *output, &patch);
+            if (thread->isMsdDevice()) {
+                thread->setDownStreamPatch(&patch);
+            }
             return thread;
         }
     }
@@ -2587,7 +2611,7 @@
     sp<DeviceDescriptorBase> device = VALUE_OR_RETURN_STATUS(
             aidl2legacy_DeviceDescriptorBase(request.device));
     audio_output_flags_t flags = VALUE_OR_RETURN_STATUS(
-            aidl2legacy_audio_output_flags_mask(request.flags));
+            aidl2legacy_int32_t_audio_output_flags_t_mask(request.flags));
 
     audio_io_handle_t output;
     uint32_t latencyMs;
@@ -2637,7 +2661,8 @@
         response->output = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
         response->config = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_config_t_AudioConfig(config));
         response->latencyMs = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(latencyMs));
-        response->flags = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_output_flags_mask(flags));
+        response->flags = VALUE_OR_RETURN_STATUS(
+                legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
         return NO_ERROR;
     }
 
@@ -2813,7 +2838,7 @@
             device.mType,
             device.address().c_str(),
             VALUE_OR_RETURN_STATUS(aidl2legacy_AudioSourceType_audio_source_t(request.source)),
-            VALUE_OR_RETURN_STATUS(aidl2legacy_audio_input_flags_mask(request.flags)),
+            VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_input_flags_t_mask(request.flags)),
             AUDIO_DEVICE_NONE,
             String8{});
 
@@ -4042,42 +4067,40 @@
 
 // ----------------------------------------------------------------------------
 
-status_t AudioFlinger::onTransact(
-        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+status_t AudioFlinger::onPreTransact(
+        TransactionCode code, const Parcel& /* data */, uint32_t /* flags */)
 {
     // make sure transactions reserved to AudioPolicyManager do not come from other processes
     switch (code) {
-        case SET_STREAM_VOLUME:
-        case SET_STREAM_MUTE:
-        case OPEN_OUTPUT:
-        case OPEN_DUPLICATE_OUTPUT:
-        case CLOSE_OUTPUT:
-        case SUSPEND_OUTPUT:
-        case RESTORE_OUTPUT:
-        case OPEN_INPUT:
-        case CLOSE_INPUT:
-        case INVALIDATE_STREAM:
-        case SET_VOICE_VOLUME:
-        case MOVE_EFFECTS:
-        case SET_EFFECT_SUSPENDED:
-        case LOAD_HW_MODULE:
-        case LIST_AUDIO_PORTS:
-        case GET_AUDIO_PORT:
-        case CREATE_AUDIO_PATCH:
-        case RELEASE_AUDIO_PATCH:
-        case LIST_AUDIO_PATCHES:
-        case SET_AUDIO_PORT_CONFIG:
-        case SET_RECORD_SILENCED:
+        case TransactionCode::SET_STREAM_VOLUME:
+        case TransactionCode::SET_STREAM_MUTE:
+        case TransactionCode::OPEN_OUTPUT:
+        case TransactionCode::OPEN_DUPLICATE_OUTPUT:
+        case TransactionCode::CLOSE_OUTPUT:
+        case TransactionCode::SUSPEND_OUTPUT:
+        case TransactionCode::RESTORE_OUTPUT:
+        case TransactionCode::OPEN_INPUT:
+        case TransactionCode::CLOSE_INPUT:
+        case TransactionCode::INVALIDATE_STREAM:
+        case TransactionCode::SET_VOICE_VOLUME:
+        case TransactionCode::MOVE_EFFECTS:
+        case TransactionCode::SET_EFFECT_SUSPENDED:
+        case TransactionCode::LOAD_HW_MODULE:
+        case TransactionCode::GET_AUDIO_PORT:
+        case TransactionCode::CREATE_AUDIO_PATCH:
+        case TransactionCode::RELEASE_AUDIO_PATCH:
+        case TransactionCode::LIST_AUDIO_PATCHES:
+        case TransactionCode::SET_AUDIO_PORT_CONFIG:
+        case TransactionCode::SET_RECORD_SILENCED:
             ALOGW("%s: transaction %d received from PID %d",
                   __func__, code, IPCThreadState::self()->getCallingPid());
             // return status only for non void methods
             switch (code) {
-                case SET_RECORD_SILENCED:
-                case SET_EFFECT_SUSPENDED:
+                case TransactionCode::SET_RECORD_SILENCED:
+                case TransactionCode::SET_EFFECT_SUSPENDED:
                     break;
                 default:
-                    reply->writeInt32(static_cast<int32_t> (INVALID_OPERATION));
-                    break;
+                    return INVALID_OPERATION;
             }
             return OK;
         default:
@@ -4086,24 +4109,24 @@
 
     // make sure the following transactions come from system components
     switch (code) {
-        case SET_MASTER_VOLUME:
-        case SET_MASTER_MUTE:
-        case SET_MODE:
-        case SET_MIC_MUTE:
-        case SET_LOW_RAM_DEVICE:
-        case SYSTEM_READY:
-        case SET_AUDIO_HAL_PIDS: {
+        case TransactionCode::SET_MASTER_VOLUME:
+        case TransactionCode::SET_MASTER_MUTE:
+        case TransactionCode::MASTER_MUTE:
+        case TransactionCode::SET_MODE:
+        case TransactionCode::SET_MIC_MUTE:
+        case TransactionCode::SET_LOW_RAM_DEVICE:
+        case TransactionCode::SYSTEM_READY:
+        case TransactionCode::SET_AUDIO_HAL_PIDS: {
             if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
                 ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
                       __func__, code, IPCThreadState::self()->getCallingPid(),
                       IPCThreadState::self()->getCallingUid());
                 // return status only for non void methods
                 switch (code) {
-                    case SYSTEM_READY:
+                    case TransactionCode::SYSTEM_READY:
                         break;
                     default:
-                        reply->writeInt32(static_cast<int32_t> (INVALID_OPERATION));
-                        break;
+                        return INVALID_OPERATION;
                 }
                 return OK;
             }
@@ -4117,14 +4140,14 @@
     // most relevant events.
     // TODO should select more wisely the items from the list
     switch (code) {
-        case CREATE_TRACK:
-        case CREATE_RECORD:
-        case SET_MASTER_VOLUME:
-        case SET_MASTER_MUTE:
-        case SET_MIC_MUTE:
-        case SET_PARAMETERS:
-        case CREATE_EFFECT:
-        case SYSTEM_READY: {
+        case TransactionCode::CREATE_TRACK:
+        case TransactionCode::CREATE_RECORD:
+        case TransactionCode::SET_MASTER_VOLUME:
+        case TransactionCode::SET_MASTER_MUTE:
+        case TransactionCode::SET_MIC_MUTE:
+        case TransactionCode::SET_PARAMETERS:
+        case TransactionCode::CREATE_EFFECT:
+        case TransactionCode::SYSTEM_READY: {
             requestLogMerge();
             break;
         }
@@ -4132,7 +4155,8 @@
             break;
     }
 
-    std::string tag("IAudioFlinger command " + std::to_string(code));
+    std::string tag("IAudioFlinger command " +
+                    std::to_string(static_cast<std::underlying_type_t<TransactionCode>>(code)));
     TimeCheck check(tag.c_str());
 
     // Make sure we connect to Audio Policy Service before calling into AudioFlinger:
@@ -4145,7 +4169,7 @@
         AudioSystem::get_audio_policy_service();
     }
 
-    return BnAudioFlinger::onTransact(code, data, reply, flags);
+    return OK;
 }
 
 } // namespace android
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index a2e50f8..1c6f57c 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -123,16 +123,12 @@
 
 #define INCLUDING_FROM_AUDIOFLINGER_H
 
-class AudioFlinger :
-    public BinderService<AudioFlinger>,
-    public BnAudioFlinger
+class AudioFlinger : public AudioFlingerServerAdapter::Delegate
 {
-    friend class BinderService<AudioFlinger>;   // for AudioFlinger()
-
 public:
-    static const char* getServiceName() ANDROID_API { return "media.audio_flinger"; }
+    static void instantiate() ANDROID_API;
 
-    virtual     status_t    dump(int fd, const Vector<String16>& args);
+    status_t dump(int fd, const Vector<String16>& args) override;
 
     // IAudioFlinger interface, in binder opcode order
     status_t createTrack(const media::CreateTrackRequest& input,
@@ -270,11 +266,7 @@
 
     virtual status_t setAudioHalPids(const std::vector<pid_t>& pids);
 
-    virtual     status_t    onTransact(
-                                uint32_t code,
-                                const Parcel& data,
-                                Parcel* reply,
-                                uint32_t flags);
+    status_t onPreTransact(TransactionCode code, const Parcel& data, uint32_t flags) override;
 
     // end of IAudioFlinger interface
 
@@ -300,6 +292,9 @@
     status_t removeEffectFromHal(audio_port_handle_t deviceId,
             audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect);
 
+    void updateDownStreamPatches_l(const struct audio_patch *patch,
+                                   const std::set<audio_io_handle_t> streams);
+
 private:
     // FIXME The 400 is temporarily too high until a leak of writers in media.log is fixed.
     static const size_t kLogMemorySize = 400 * 1024;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index eaad6ef..3ab7737 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -60,6 +60,7 @@
 
 namespace android {
 
+using aidl_utils::statusTFromBinderStatus;
 using binder::Status;
 
 namespace {
@@ -3027,7 +3028,7 @@
                 bs = handle.second->disable(&status);
             }
             if (!bs.isOk()) {
-              status = bs.transactionError();
+              status = statusTFromBinderStatus(bs);
             }
         }
     }
@@ -3142,7 +3143,7 @@
             bs = (*handle)->disable(&status);
         }
         if (!bs.isOk()) {
-            status = bs.transactionError();
+            status = statusTFromBinderStatus(bs);
         }
     }
     return status;
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 03bdc60..89321f9 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -373,8 +373,8 @@
     DISALLOW_COPY_AND_ASSIGN(EffectHandle);
 
     Mutex mLock;                             // protects IEffect method calls
-    wp<EffectBase> mEffect;                  // pointer to controlled EffectModule
-    sp<media::IEffectClient> mEffectClient;  // callback interface for client notifications
+    const wp<EffectBase> mEffect;            // pointer to controlled EffectModule
+    const sp<media::IEffectClient> mEffectClient;  // callback interface for client notifications
     /*const*/ sp<Client> mClient;            // client for shared memory allocation, see
                                              //   disconnect()
     sp<IMemory> mCblkMemory;                 // shared memory for control block
@@ -558,6 +558,8 @@
 
         wp<ThreadBase> thread() { return mThread; }
 
+        // TODO(b/161341295) secure this against concurrent access to mThread
+        // by other callers.
         void setThread(const wp<ThreadBase>& thread) {
             mThread = thread;
             sp<ThreadBase> p = thread.promote();
@@ -565,9 +567,9 @@
         }
 
     private:
-        wp<EffectChain> mChain;
-        wp<ThreadBase> mThread;
-        wp<AudioFlinger> mAudioFlinger;
+        const wp<EffectChain> mChain;
+        wp<ThreadBase> mThread;         // TODO(b/161341295) protect against concurrent access
+        wp<AudioFlinger> mAudioFlinger; // this could be const with some rearrangement.
     };
 
     friend class AudioFlinger;  // for mThread, mEffects
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 1e11660..806cd86 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -435,10 +435,10 @@
         *handle = (audio_patch_handle_t) mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH);
         newPatch.mHalHandle = halHandle;
         mAudioFlinger.mDeviceEffectManager.createAudioPatch(*handle, newPatch);
-        mPatches.insert(std::make_pair(*handle, std::move(newPatch)));
         if (insertedModule != AUDIO_MODULE_HANDLE_NONE) {
-            addSoftwarePatchToInsertedModules(insertedModule, *handle);
+            addSoftwarePatchToInsertedModules(insertedModule, *handle, &newPatch.mAudioPatch);
         }
+        mPatches.insert(std::make_pair(*handle, std::move(newPatch)));
     } else {
         newPatch.clearConnections(this);
     }
@@ -803,10 +803,20 @@
 }
 
 void AudioFlinger::PatchPanel::notifyStreamOpened(
-        AudioHwDevice *audioHwDevice, audio_io_handle_t stream)
+        AudioHwDevice *audioHwDevice, audio_io_handle_t stream, struct audio_patch *patch)
 {
     if (audioHwDevice->isInsert()) {
         mInsertedModules[audioHwDevice->handle()].streams.insert(stream);
+        if (patch != nullptr) {
+            std::vector <SoftwarePatch> swPatches;
+            getDownstreamSoftwarePatches(stream, &swPatches);
+            if (swPatches.size() > 0) {
+                auto iter = mPatches.find(swPatches[0].getPatchHandle());
+                if (iter != mPatches.end()) {
+                    *patch = iter->second.mAudioPatch;
+                }
+            }
+        }
     }
 }
 
@@ -835,9 +845,13 @@
 }
 
 void AudioFlinger::PatchPanel::addSoftwarePatchToInsertedModules(
-        audio_module_handle_t module, audio_patch_handle_t handle)
+        audio_module_handle_t module, audio_patch_handle_t handle,
+        const struct audio_patch *patch)
 {
     mInsertedModules[module].sw_patches.insert(handle);
+    if (!mInsertedModules[module].streams.empty()) {
+        mAudioFlinger.updateDownStreamPatches_l(patch, mInsertedModules[module].streams);
+    }
 }
 
 void AudioFlinger::PatchPanel::removeSoftwarePatchFromInsertedModules(
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 2568dd3..c4c28fa 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -71,7 +71,8 @@
             std::vector<SoftwarePatch> *patches) const;
 
     // Notifies patch panel about all opened and closed streams.
-    void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream);
+    void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream,
+                            struct audio_patch *patch);
     void notifyStreamClosed(audio_io_handle_t stream);
 
     void dump(int fd) const;
@@ -226,7 +227,8 @@
     AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module);
     sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module);
     void addSoftwarePatchToInsertedModules(
-            audio_module_handle_t module, audio_patch_handle_t handle);
+            audio_module_handle_t module, audio_patch_handle_t handle,
+            const struct audio_patch *patch);
     void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
     void erasePatch(audio_patch_handle_t handle);
 
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index a4b8650..dbc190c 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -148,7 +148,7 @@
      */
     bool            readAndClearHasChanged() { return !mChangeNotified.test_and_set(); }
 
-    using SourceMetadatas = std::vector<playback_track_metadata_t>;
+    using SourceMetadatas = std::vector<playback_track_metadata_v7_t>;
     using MetadataInserter = std::back_insert_iterator<SourceMetadatas>;
     /** Copy the track metadata in the provided iterator. Thread safe. */
     virtual void    copyMetadataTo(MetadataInserter& backInserter) const;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index b13b7be..7e1c67e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1876,7 +1876,8 @@
         // index 0 is reserved for normal mixer's submix
         mFastTrackAvailMask(((1 << FastMixerState::sMaxFastTracks) - 1) & ~1),
         mHwSupportsPause(false), mHwPaused(false), mFlushPending(false),
-        mLeftVolFloat(-1.0), mRightVolFloat(-1.0)
+        mLeftVolFloat(-1.0), mRightVolFloat(-1.0),
+        mDownStreamPatch{}
 {
     snprintf(mThreadName, kThreadNameLength, "AudioOut_%X", id);
     mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
@@ -2660,12 +2661,16 @@
     ALOGV("PlaybackThread::ioConfigChanged, thread %p, event %d", this, event);
 
     desc->mIoHandle = mId;
+    struct audio_patch patch = mPatch;
+    if (isMsdDevice()) {
+        patch = mDownStreamPatch;
+    }
 
     switch (event) {
     case AUDIO_OUTPUT_OPENED:
     case AUDIO_OUTPUT_REGISTERED:
     case AUDIO_OUTPUT_CONFIG_CHANGED:
-        desc->mPatch = mPatch;
+        desc->mPatch = patch;
         desc->mChannelMask = mChannelMask;
         desc->mSamplingRate = mSampleRate;
         desc->mFormat = mFormat;
@@ -2675,7 +2680,7 @@
         desc->mLatency = latency_l();
         break;
     case AUDIO_CLIENT_STARTED:
-        desc->mPatch = mPatch;
+        desc->mPatch = patch;
         desc->mPortId = portId;
         break;
     case AUDIO_OUTPUT_CLOSED:
@@ -8097,10 +8102,15 @@
     StreamInHalInterface::SinkMetadata metadata;
     for (const sp<RecordTrack> &track : mActiveTracks) {
         // No track is invalid as this is called after prepareTrack_l in the same critical section
-        metadata.tracks.push_back({
+        record_track_metadata_v7_t trackMetadata;
+        trackMetadata.base = {
                 .source = track->attributes().source,
                 .gain = 1, // capture tracks do not have volumes
-        });
+        };
+        trackMetadata.channel_mask = track->channelMask(),
+        strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+
+        metadata.tracks.push_back(trackMetadata);
     }
     mInput->stream->updateSinkMetadata(metadata);
 }
@@ -8684,6 +8694,7 @@
 
 void AudioFlinger::RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
 {
+    Mutex::Autolock _l(mLock);
     mOutDevices = outDevices;
     mOutDeviceTypeAddrs = deviceTypeAddrsFromDescriptors(mOutDevices);
     for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -9674,11 +9685,15 @@
     StreamOutHalInterface::SourceMetadata metadata;
     for (const sp<MmapTrack> &track : mActiveTracks) {
         // No track is invalid as this is called after prepareTrack_l in the same critical section
-        metadata.tracks.push_back({
+        playback_track_metadata_v7_t trackMetadata;
+        trackMetadata.base = {
                 .usage = track->attributes().usage,
                 .content_type = track->attributes().content_type,
                 .gain = mHalVolFloat, // TODO: propagate from aaudio pre-mix volume
-        });
+        };
+        trackMetadata.channel_mask = track->channelMask(),
+        strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+        metadata.tracks.push_back(trackMetadata);
     }
     mOutput->stream->updateSourceMetadata(metadata);
 }
@@ -9799,10 +9814,14 @@
     StreamInHalInterface::SinkMetadata metadata;
     for (const sp<MmapTrack> &track : mActiveTracks) {
         // No track is invalid as this is called after prepareTrack_l in the same critical section
-        metadata.tracks.push_back({
+        record_track_metadata_v7_t trackMetadata;
+        trackMetadata.base = {
                 .source = track->attributes().source,
                 .gain = 1, // capture tracks do not have volumes
-        });
+        };
+        trackMetadata.channel_mask = track->channelMask(),
+        strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+        metadata.tracks.push_back(trackMetadata);
     }
     mInput->stream->updateSinkMetadata(metadata);
 }
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 014f2d7..cf4bb8a 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -967,6 +967,11 @@
                     return (mHapticChannelMask & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE;
                 }
 
+                void setDownStreamPatch(const struct audio_patch *patch) {
+                    Mutex::Autolock _l(mLock);
+                    mDownStreamPatch = *patch;
+                }
+
 protected:
     // updated by readOutputParameters_l()
     size_t                          mNormalFrameCount;  // normal mixer and effects
@@ -1250,6 +1255,10 @@
                 // volumes last sent to audio HAL with stream->setVolume()
                 float mLeftVolFloat;
                 float mRightVolFloat;
+
+                // audio patch used by the downstream software patch.
+                // Only used if ThreadBase::mIsMsdDevice is true.
+                struct audio_patch mDownStreamPatch;
 };
 
 class MixerThread : public PlaybackThread {
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 01d5345..38dab5b 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -253,6 +253,8 @@
     // Called to tally underrun frames in playback.
     virtual void tallyUnderrunFrames(size_t /* frames */) {}
 
+    audio_channel_mask_t channelMask() const { return mChannelMask; }
+
 protected:
     DISALLOW_COPY_AND_ASSIGN(TrackBase);
 
@@ -278,8 +280,6 @@
 
     size_t frameSize() const { return mFrameSize; }
 
-    audio_channel_mask_t channelMask() const { return mChannelMask; }
-
     virtual uint32_t sampleRate() const { return mSampleRate; }
 
     bool isStopped() const {
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 68b709f..06cbe87 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -54,6 +54,7 @@
 
 namespace android {
 
+using aidl_utils::binderStatusFromStatusT;
 using binder::Status;
 using media::VolumeShaper;
 // ----------------------------------------------------------------------------
@@ -371,7 +372,7 @@
     if (*_aidl_return != OK) {
         return Status::ok();
     }
-    *timestamp = legacy2aidl_AudioTimestamp(legacy).value();
+    *timestamp = legacy2aidl_AudioTimestamp_AudioTimestampInternal(legacy).value();
     return Status::ok();
 }
 
@@ -1309,11 +1310,15 @@
 
 void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backInserter) const
 {
-    *backInserter++ = {
+    playback_track_metadata_v7_t metadata;
+    metadata.base = {
             .usage = mAttr.usage,
             .content_type = mAttr.content_type,
             .gain = mFinalVolume,
     };
+    metadata.channel_mask = mChannelMask,
+    strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+    *backInserter++ = metadata;
 }
 
 void AudioFlinger::PlaybackThread::Track::setTeePatches(TeePatches teePatches) {
@@ -2132,7 +2137,7 @@
 binder::Status AudioFlinger::RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
         int /*audio_session_t*/ triggerSession) {
     ALOGV("%s()", __func__);
-    return binder::Status::fromStatusT(
+    return binderStatusFromStatusT(
         mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
 }
 
@@ -2155,19 +2160,19 @@
     for (size_t i = 0; status == OK && i < mics.size(); ++i) {
        status = mics[i].writeToParcelable(&activeMicrophones->at(i));
     }
-    return binder::Status::fromStatusT(status);
+    return binderStatusFromStatusT(status);
 }
 
 binder::Status AudioFlinger::RecordHandle::setPreferredMicrophoneDirection(
         int /*audio_microphone_direction_t*/ direction) {
     ALOGV("%s()", __func__);
-    return binder::Status::fromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
+    return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
             static_cast<audio_microphone_direction_t>(direction)));
 }
 
 binder::Status AudioFlinger::RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
     ALOGV("%s()", __func__);
-    return binder::Status::fromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
+    return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
 }
 
 // ----------------------------------------------------------------------------
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index b00426f..e52ad5e 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -133,8 +133,8 @@
     virtual status_t startOutput(audio_port_handle_t portId) = 0;
     // indicates to the audio policy manager that the output stops being used by corresponding stream.
     virtual status_t stopOutput(audio_port_handle_t portId) = 0;
-    // releases the output.
-    virtual void releaseOutput(audio_port_handle_t portId) = 0;
+    // releases the output, return true if the output descriptor is reopened.
+    virtual bool releaseOutput(audio_port_handle_t portId) = 0;
 
     // request an input appropriate for record from the supplied device with supplied parameters.
     virtual status_t getInputForAttr(const audio_attributes_t *attr,
@@ -220,16 +220,16 @@
     virtual status_t    dump(int fd) = 0;
 
     virtual status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags) = 0;
-    virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo) = 0;
+    virtual audio_offload_mode_t getOffloadSupport(const audio_offload_info_t& offloadInfo) = 0;
     virtual bool isDirectOutputSupported(const audio_config_base_t& config,
                                          const audio_attributes_t& attributes) = 0;
 
     virtual status_t listAudioPorts(audio_port_role_t role,
                                     audio_port_type_t type,
                                     unsigned int *num_ports,
-                                    struct audio_port *ports,
+                                    struct audio_port_v7 *ports,
                                     unsigned int *generation) = 0;
-    virtual status_t getAudioPort(struct audio_port *port) = 0;
+    virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
     virtual status_t createAudioPatch(const struct audio_patch *patch,
                                        audio_patch_handle_t *handle,
                                        uid_t uid) = 0;
@@ -439,6 +439,8 @@
                                                 audio_patch_handle_t patchHandle,
                                                 audio_source_t source) = 0;
 
+    virtual void onRoutingUpdated() = 0;
+
     // Used to notify the sound trigger module that an audio capture is about to
     // take place. This should typically result in any active recognition
     // sessions to be preempted on modules that do not support sound trigger
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 6f47abc..a40f6aa 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -72,7 +72,7 @@
             const struct audio_port_config *srcConfig = NULL) const;
     virtual sp<AudioPort> getAudioPort() const { return mProfile; }
 
-    void toAudioPort(struct audio_port *port) const;
+    void toAudioPort(struct audio_port_v7 *port) const;
     void setPreemptedSessions(const SortedVector<audio_session_t>& sessions);
     SortedVector<audio_session_t> getPreemptedSessions() const;
     bool hasPreemptedSession(audio_session_t session) const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 1302486..1f9b535 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -261,7 +261,7 @@
                            const struct audio_port_config *srcConfig = NULL) const;
     virtual sp<AudioPort> getAudioPort() const { return mPolicyAudioPort->asAudioPort(); }
 
-    virtual void toAudioPort(struct audio_port *port) const;
+    virtual void toAudioPort(struct audio_port_v7 *port) const;
 
     audio_module_handle_t getModuleHandle() const;
 
@@ -338,6 +338,8 @@
     bool sharesHwModuleWith(const sp<SwAudioOutputDescriptor>& outputDesc);
     virtual DeviceVector supportedDevices() const;
     virtual bool devicesSupportEncodedFormats(const DeviceTypeSet& deviceTypes);
+    virtual bool containsSingleDeviceSupportingEncodedFormats(
+            const sp<DeviceDescriptor>& device) const;
     virtual uint32_t latency();
     virtual bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); }
     virtual bool isFixedVolume(const DeviceTypeSet& deviceTypes);
@@ -358,7 +360,7 @@
 
     virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
                            const struct audio_port_config *srcConfig = NULL) const;
-    virtual void toAudioPort(struct audio_port *port) const;
+    virtual void toAudioPort(struct audio_port_v7 *port) const;
 
         status_t open(const audio_config_t *config,
                       const DeviceVector &devices,
@@ -396,6 +398,14 @@
     bool supportsAllDevices(const DeviceVector &devices) const;
 
     /**
+     * @brief supportsDevicesForPlayback
+     * @param devices to be checked against
+     * @return true if the devices is a supported combo for playback
+     *         false otherwise
+     */
+    bool supportsDevicesForPlayback(const DeviceVector &devices) const;
+
+    /**
      * @brief filterSupportedDevices takes a vector of devices and filters them according to the
      * device supported by this output (the profile from which this output derives from)
      * @param devices reference device vector to be filtered
@@ -412,6 +422,7 @@
     sp<SwAudioOutputDescriptor> mOutput2;    // used by duplicated outputs: second output
     uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only)
     audio_session_t mDirectClientSession; // session id of the direct output client
+    bool mPendingReopenToQueryProfiles = false;
 };
 
 // Audio output driven by an input device directly.
@@ -432,7 +443,7 @@
 
     virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
                            const struct audio_port_config *srcConfig = NULL) const;
-    virtual void toAudioPort(struct audio_port *port) const;
+    virtual void toAudioPort(struct audio_port_v7 *port) const;
 
     const sp<SourceClientDescriptor> mSource;
 
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index 80afe9d..59876c6 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -198,10 +198,18 @@
 
     ~SourceClientDescriptor() override = default;
 
+    void connect(audio_patch_handle_t patchHandle, const sp<DeviceDescriptor>& sinkDevice) {
+        mPatchHandle = patchHandle;
+        mSinkDevice = sinkDevice;
+    }
+    void disconnect() {
+        mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
+        mSinkDevice = nullptr;
+    }
+    bool isConnected() const { return mPatchHandle != AUDIO_PATCH_HANDLE_NONE; }
     audio_patch_handle_t getPatchHandle() const { return mPatchHandle; }
-    void setPatchHandle(audio_patch_handle_t patchHandle) { mPatchHandle = patchHandle; }
-
     sp<DeviceDescriptor> srcDevice() const { return mSrcDevice; }
+    sp<DeviceDescriptor> sinkDevice() const { return mSinkDevice; }
     wp<SwAudioOutputDescriptor> swOutput() const { return mSwOutput; }
     void setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput);
     wp<HwAudioOutputDescriptor> hwOutput() const { return mHwOutput; }
@@ -213,6 +221,7 @@
  private:
     audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
     const sp<DeviceDescriptor> mSrcDevice;
+    sp<DeviceDescriptor> mSinkDevice;
     wp<SwAudioOutputDescriptor> mSwOutput;
     wp<HwAudioOutputDescriptor> mHwOutput;
 };
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 80190b7..3d338ea 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -65,9 +65,6 @@
 
     bool supportsFormat(audio_format_t format);
 
-    void setDynamic() { mIsDynamic = true; }
-    bool isDynamic() const { return mIsDynamic; }
-
     // PolicyAudioPortConfig
     virtual sp<PolicyAudioPort> getPolicyAudioPort() const {
         return static_cast<PolicyAudioPort*>(const_cast<DeviceDescriptor*>(this));
@@ -108,8 +105,6 @@
     std::string mTagName; // Unique human readable identifier for a device port found in conf file.
     FormatVector        mEncodedFormats;
     audio_format_t      mCurrentEncodedFormat;
-    bool                mIsDynamic = false;
-    const std::string   mDeclaredAddress; // Original device address
 };
 
 class DeviceVector : public SortedVector<sp<DeviceDescriptor> >
@@ -270,6 +265,8 @@
         return String8("");
     }
 
+    const AudioProfileVector& getSupportedProfiles() { return mSupportedProfiles; }
+
     // Return a string to describe the DeviceVector. The sensitive information will only be
     // added to the string if `includeSensitiveInfo` is true.
     std::string toString(bool includeSensitiveInfo = false) const;
@@ -278,7 +275,9 @@
 
 private:
     void refreshTypes();
+    void refreshAudioProfiles();
     DeviceTypeSet mDeviceTypes;
+    AudioProfileVector mSupportedProfiles;
 };
 
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index b5b10f3..23f0c9a 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -131,17 +131,8 @@
 public:
     sp<HwModule> getModuleFromName(const char *name) const;
 
-    /**
-     * @brief getModuleForDeviceType try to get a device from type / format on all modules
-     * @param device type to consider
-     * @param encodedFormat to consider
-     * @param[out] tagName if not null, if a matching device is found, will return the tagName
-     * of original device from XML file so that audio routes matchin rules work.
-     * @return valid module if considered device found, nullptr otherwise.
-     */
     sp<HwModule> getModuleForDeviceType(audio_devices_t device,
-                                        audio_format_t encodedFormat,
-                                        std::string *tagName = nullptr) const;
+                                        audio_format_t encodedFormat) const;
 
     sp<HwModule> getModuleForDevice(const sp<DeviceDescriptor> &device,
                                     audio_format_t encodedFormat) const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 11d3a99..a5cd534 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -112,19 +112,6 @@
     }
 
     /**
-     * @brief getTag
-     * @param deviceTypes to be considered
-     * @return tagName of first matching device for the considered types, empty string otherwise.
-     */
-    std::string getTag(const DeviceTypeSet& deviceTypes) const
-    {
-        if (supportsDeviceTypes(deviceTypes)) {
-            return mSupportedDevices.getDevicesFromTypes(deviceTypes).itemAt(0)->getTagName();
-        }
-        return {};
-    }
-
-    /**
      * @brief supportsDevice
      * @param device to be checked against
      *        forceCheckOnAddress if true, check on type and address whatever the type, otherwise
@@ -144,7 +131,7 @@
     bool devicesSupportEncodedFormats(DeviceTypeSet deviceTypes) const
     {
         if (deviceTypes.empty()) {
-            return true; // required for isOffloadSupported() check
+            return true; // required for getOffloadSupport() check
         }
         DeviceVector deviceList =
             mSupportedDevices.getDevicesFromTypes(deviceTypes);
@@ -156,6 +143,8 @@
         return false;
     }
 
+    bool containsSingleDeviceSupportingEncodedFormats(const sp<DeviceDescriptor>& device) const;
+
     void clearSupportedDevices() { mSupportedDevices.clear(); }
     void addSupportedDevice(const sp<DeviceDescriptor> &device)
     {
@@ -163,12 +152,6 @@
     }
     void removeSupportedDevice(const sp<DeviceDescriptor> &device)
     {
-        ssize_t ret = mSupportedDevices.indexOf(device);
-        if (ret >= 0 && !mSupportedDevices.itemAt(ret)->isDynamic()) {
-            // devices equality checks only type, address, name and format
-            // Prevents from removing non dynamically added devices
-            return;
-        }
         mSupportedDevices.remove(device);
     }
     void setSupportedDevices(const DeviceVector &devices)
diff --git a/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h b/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
index e6eef24..d2f6297 100644
--- a/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
@@ -42,11 +42,6 @@
 
     virtual const std::string getTagName() const = 0;
 
-    bool equals(const sp<PolicyAudioPort> &right) const
-    {
-        return getTagName() == right->getTagName();
-    }
-
     virtual sp<AudioPort> asAudioPort() const = 0;
 
     virtual void setFlags(uint32_t flags)
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 4922ebe..7016a08 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -92,7 +92,7 @@
     dstConfig->ext.mix.usecase.source = source();
 }
 
-void AudioInputDescriptor::toAudioPort(struct audio_port *port) const
+void AudioInputDescriptor::toAudioPort(struct audio_port_v7 *port) const
 {
     ALOG_ASSERT(mProfile != 0, "toAudioPort() called on input with null profile %d", mIoHandle);
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 1756021..b872709 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -215,7 +215,7 @@
     dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT;
 }
 
-void AudioOutputDescriptor::toAudioPort(struct audio_port *port) const
+void AudioOutputDescriptor::toAudioPort(struct audio_port_v7 *port) const
 {
     // Should not be called for duplicated ports, see SwAudioOutputDescriptor::toAudioPortConfig.
     mPolicyAudioPort->asAudioPort()->toAudioPort(port);
@@ -344,6 +344,13 @@
     return supportedDevices().containsAllDevices(devices);
 }
 
+bool SwAudioOutputDescriptor::supportsDevicesForPlayback(const DeviceVector &devices) const
+{
+    // No considering duplicated output
+    // TODO: need to verify if the profile supports the devices combo for playback.
+    return !isDuplicated() && supportsAllDevices(devices);
+}
+
 DeviceVector SwAudioOutputDescriptor::filterSupportedDevices(const DeviceVector &devices) const
 {
     DeviceVector filteredDevices = supportedDevices();
@@ -360,6 +367,16 @@
     }
 }
 
+bool SwAudioOutputDescriptor::containsSingleDeviceSupportingEncodedFormats(
+        const sp<DeviceDescriptor>& device) const
+{
+    if (isDuplicated()) {
+        return (mOutput1->containsSingleDeviceSupportingEncodedFormats(device) &&
+                mOutput2->containsSingleDeviceSupportingEncodedFormats(device));
+    }
+    return mProfile->containsSingleDeviceSupportingEncodedFormats(device);
+}
+
 uint32_t SwAudioOutputDescriptor::latency()
 {
     if (isDuplicated()) {
@@ -406,8 +423,7 @@
     dstConfig->ext.mix.handle = mIoHandle;
 }
 
-void SwAudioOutputDescriptor::toAudioPort(
-                                                    struct audio_port *port) const
+void SwAudioOutputDescriptor::toAudioPort(struct audio_port_v7 *port) const
 {
     ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle);
 
@@ -654,8 +670,7 @@
     mSource->srcDevice()->toAudioPortConfig(dstConfig, srcConfig);
 }
 
-void HwAudioOutputDescriptor::toAudioPort(
-                                                    struct audio_port *port) const
+void HwAudioOutputDescriptor::toAudioPort(struct audio_port_v7 *port) const
 {
     mSource->srcDevice()->toAudioPort(port);
 }
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
index c8e4e76..2a18f19 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
@@ -39,12 +39,12 @@
 bool AudioRoute::supportsPatch(const sp<PolicyAudioPort> &srcPort,
                                const sp<PolicyAudioPort> &dstPort) const
 {
-    if (mSink == 0 || dstPort == 0 || !dstPort->equals(mSink)) {
+    if (mSink == 0 || dstPort == 0 || dstPort != mSink) {
         return false;
     }
     ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().c_str());
     for (const auto &sourcePort : mSources) {
-        if (sourcePort->equals(srcPort)) {
+        if (sourcePort == srcPort) {
             ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().c_str());
             return true;
         }
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index e43ca0f..6c31b79 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -52,8 +52,7 @@
 DeviceDescriptor::DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr,
                                    const std::string &tagName,
                                    const FormatVector &encodedFormats) :
-        DeviceDescriptorBase(deviceTypeAddr), mTagName(tagName), mEncodedFormats(encodedFormats),
-        mDeclaredAddress(deviceTypeAddr.getAddress())
+        DeviceDescriptorBase(deviceTypeAddr), mTagName(tagName), mEncodedFormats(encodedFormats)
 {
     mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
     /* If framework runs against a pre 5.0 Audio HAL, encoded formats are absent from the config.
@@ -76,10 +75,6 @@
 void DeviceDescriptor::detach() {
     mId = AUDIO_PORT_HANDLE_NONE;
     PolicyAudioPort::detach();
-    // The device address may have been overwritten on device connection
-    setAddress(mDeclaredAddress);
-    // Device Port does not have a name unless provided by setDeviceConnectionState
-    setName("");
 }
 
 template<typename T>
@@ -222,6 +217,18 @@
     ALOGV("DeviceVector::refreshTypes() mDeviceTypes %s", dumpDeviceTypes(mDeviceTypes).c_str());
 }
 
+void DeviceVector::refreshAudioProfiles() {
+    if (empty()) {
+        mSupportedProfiles.clear();
+        return;
+    }
+    mSupportedProfiles = itemAt(0)->getAudioProfiles();
+    for (size_t i = 1; i < size(); ++i) {
+        mSupportedProfiles = intersectAudioProfiles(
+                mSupportedProfiles, itemAt(i)->getAudioProfiles());
+    }
+}
+
 ssize_t DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
 {
     for (size_t i = 0; i < size(); i++) {
@@ -243,6 +250,7 @@
     }
     if (added) {
         refreshTypes();
+        refreshAudioProfiles();
     }
 }
 
@@ -255,6 +263,7 @@
         ret = SortedVector::add(item);
         if (ret >= 0) {
             refreshTypes();
+            refreshAudioProfiles();
         }
     } else {
         ALOGW("DeviceVector::add device %08x already in", item->type());
@@ -273,6 +282,7 @@
         ret = SortedVector::removeAt(ret);
         if (ret >= 0) {
             refreshTypes();
+            refreshAudioProfiles();
         }
     }
     return ret;
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 2967014..d31e443 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -271,9 +271,8 @@
     return nullptr;
 }
 
-sp<HwModule> HwModuleCollection::getModuleForDeviceType(audio_devices_t type,
-                                                        audio_format_t encodedFormat,
-                                                        std::string *tagName) const
+sp <HwModule> HwModuleCollection::getModuleForDeviceType(audio_devices_t type,
+                                                         audio_format_t encodedFormat) const
 {
     for (const auto& module : *this) {
         const auto& profiles = audio_is_output_device(type) ?
@@ -285,15 +284,9 @@
                     sp <DeviceDescriptor> deviceDesc =
                             declaredDevices.getDevice(type, String8(), encodedFormat);
                     if (deviceDesc) {
-                        if (tagName != nullptr) {
-                            *tagName = deviceDesc->getTagName();
-                        }
                         return module;
                     }
                 } else {
-                    if (tagName != nullptr) {
-                        *tagName = profile->getTag({type});
-                    }
                     return module;
                 }
             }
@@ -332,32 +325,15 @@
     }
 
     for (const auto& hwModule : *this) {
-        if (!allowToCreate) {
-            auto dynamicDevices = hwModule->getDynamicDevices();
-            auto dynamicDevice = dynamicDevices.getDevice(deviceType, devAddress, encodedFormat);
-            if (dynamicDevice) {
-                return dynamicDevice;
-            }
-        }
         DeviceVector moduleDevices = hwModule->getAllDevices();
         auto moduleDevice = moduleDevices.getDevice(deviceType, devAddress, encodedFormat);
-
-        // Prevent overwritting moduleDevice address if connected device does not have the same
-        // address (since getDevice with empty address ignores match on address), use dynamic device
-        if (moduleDevice && allowToCreate &&
-                (!moduleDevice->address().empty() &&
-                 (moduleDevice->address().compare(devAddress.c_str()) != 0))) {
-            break;
-        }
         if (moduleDevice) {
             if (encodedFormat != AUDIO_FORMAT_DEFAULT) {
                 moduleDevice->setEncodedFormat(encodedFormat);
             }
             if (allowToCreate) {
                 moduleDevice->attach(hwModule);
-                // Name may be overwritten, restored on detach.
                 moduleDevice->setAddress(devAddress.string());
-                // Name may be overwritten, restored on detach.
                 moduleDevice->setName(name);
             }
             return moduleDevice;
@@ -376,19 +352,18 @@
                                                       const char *name,
                                                       const audio_format_t encodedFormat) const
 {
-    std::string tagName = {};
-    sp<HwModule> hwModule = getModuleForDeviceType(type, encodedFormat, &tagName);
+    sp<HwModule> hwModule = getModuleForDeviceType(type, encodedFormat);
     if (hwModule == 0) {
         ALOGE("%s: could not find HW module for device %04x address %s", __FUNCTION__, type,
               address);
         return nullptr;
     }
 
-    sp<DeviceDescriptor> device = new DeviceDescriptor(type, tagName, address);
+    sp<DeviceDescriptor> device = new DeviceDescriptor(type, name, address);
     device->setName(name);
     device->setEncodedFormat(encodedFormat);
-    device->setDynamic();
-    // Add the device to the list of dynamic devices
+
+  // Add the device to the list of dynamic devices
     hwModule->addDynamicDevice(device);
     // Reciprocally attach the device to the module
     device->attach(hwModule);
@@ -400,7 +375,7 @@
     for (const auto &profile : profiles) {
         // Add the device as supported to all profile supporting "weakly" or not the device
         // according to its type
-        if (profile->supportsDevice(device, false /*matchAddress*/)) {
+        if (profile->supportsDevice(device, false /*matchAdress*/)) {
 
             // @todo quid of audio profile? import the profile from device of the same type?
             const auto &isoTypeDeviceForProfile =
@@ -431,9 +406,10 @@
 
         device->detach();
         // Only remove from dynamic list, not from declared list!!!
-        if (!hwModule->removeDynamicDevice(device)) {
+        if (!hwModule->getDynamicDevices().contains(device)) {
             return;
         }
+        hwModule->removeDynamicDevice(device);
         ALOGV("%s: removed dynamic device %s from module %s", __FUNCTION__,
               device->toString().c_str(), hwModule->getName());
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index ae92b40..09b614d 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -105,6 +105,17 @@
     return true;
 }
 
+bool IOProfile::containsSingleDeviceSupportingEncodedFormats(
+        const sp<DeviceDescriptor>& device) const {
+    if (device == nullptr) {
+        return false;
+    }
+    DeviceVector deviceList = mSupportedDevices.getDevicesFromType(device->type());
+    return std::count_if(deviceList.begin(), deviceList.end(),
+            [&device](sp<DeviceDescriptor> deviceDesc) {
+                return device == deviceDesc && deviceDesc->hasCurrentEncodedFormat(); }) == 1;
+}
+
 void IOProfile::dump(String8 *dst) const
 {
     std::string portStr;
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index eccde7b..d038ce5 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -184,16 +184,7 @@
         break;
 
     case STRATEGY_DTMF:
-        if (!isInCall()) {
-            // when off call, DTMF strategy follows the same rules as MEDIA strategy
-            devices = getDevicesForStrategyInt(
-                    STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
-            break;
-        }
-        // when in call, DTMF and PHONE strategies follow the same rules
-        FALLTHROUGH_INTENDED;
-
-    case STRATEGY_PHONE:
+    case STRATEGY_PHONE: {
         // Force use of only devices on primary output if:
         // - in call AND
         //   - cannot route from voice call RX OR
@@ -216,84 +207,24 @@
                     availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID));
 
             if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
-                    String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
-                    ((availPrimaryInputDevices.getDevice(
-                            txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
-                            (primaryOutput->getPolicyAudioPort()->getModuleVersionMajor() < 3))) {
+                                                 String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
+                ((availPrimaryInputDevices.getDevice(
+                        txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
+                 (primaryOutput->getPolicyAudioPort()->getModuleVersionMajor() < 3))) {
                 availableOutputDevices = availPrimaryOutputDevices;
             }
         }
-        // for phone strategy, we first consider the forced use and then the available devices by
-        // order of priority
-        switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
-        case AUDIO_POLICY_FORCE_BT_SCO:
-            if (!isInCall() || strategy != STRATEGY_DTMF) {
-                devices = availableOutputDevices.getDevicesFromType(
-                        AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
-                if (!devices.isEmpty()) break;
-            }
-            devices = availableOutputDevices.getFirstDevicesFromTypes({
-                    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
-            if (!devices.isEmpty()) break;
-            // if SCO device is requested but no SCO device is available, fall back to default case
-            FALLTHROUGH_INTENDED;
-
-        default:    // FORCE_NONE
-            devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
-            if (!devices.isEmpty()) break;
-
-            // TODO (b/161358428): remove when preferred device
-            //  for strategy phone will be used instead of AUDIO_POLICY_FORCE_FOR_COMMUNICATION
-            devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_BLE_HEADSET);
-            if (!devices.isEmpty()) break;
-
-            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
-            if (!isInCall() &&
-                    (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
-                devices = availableOutputDevices.getFirstDevicesFromTypes({
-                        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
-                        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES});
-                if (!devices.isEmpty()) break;
-            }
-            devices = availableOutputDevices.getFirstDevicesFromTypes({
-                    AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADSET,
-                    AUDIO_DEVICE_OUT_LINE, AUDIO_DEVICE_OUT_USB_HEADSET,
-                    AUDIO_DEVICE_OUT_USB_DEVICE});
-            if (!devices.isEmpty()) break;
-            if (!isInCall()) {
-                devices = availableOutputDevices.getFirstDevicesFromTypes({
-                        AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
-                        AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
-                if (!devices.isEmpty()) break;
-            }
-            devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_EARPIECE);
-            break;
-
-        case AUDIO_POLICY_FORCE_SPEAKER:
-            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
-            // A2DP speaker when forcing to speaker output
-            if (!isInCall()) {
-                devices = availableOutputDevices.getDevicesFromType(
-                        AUDIO_DEVICE_OUT_BLE_SPEAKER);
-                if (!devices.isEmpty()) break;
-
-                if ((getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
-                    devices = availableOutputDevices.getDevicesFromType(
-                            AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
-                    if (!devices.isEmpty()) break;
-                }
-            }
-            if (!isInCall()) {
-                devices = availableOutputDevices.getFirstDevicesFromTypes({
-                        AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_DEVICE,
-                        AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_AUX_DIGITAL,
-                        AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
-                if (!devices.isEmpty()) break;
-            }
-            devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
-            break;
-        }
-    break;
+        devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
+        if (!devices.isEmpty()) break;
+        devices = availableOutputDevices.getFirstDevicesFromTypes({
+                                                                  AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+                                                                  AUDIO_DEVICE_OUT_WIRED_HEADSET,
+                                                                  AUDIO_DEVICE_OUT_LINE,
+                                                                  AUDIO_DEVICE_OUT_USB_HEADSET,
+                                                                  AUDIO_DEVICE_OUT_USB_DEVICE});
+        if (!devices.isEmpty()) break;
+        devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_EARPIECE);
+    } break;
 
     case STRATEGY_SONIFICATION:
 
@@ -336,7 +267,8 @@
                 }
             }
             // Use both Bluetooth SCO and phone default output when ringing in normal mode
-            if (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) == AUDIO_POLICY_FORCE_BT_SCO) {
+            if (audio_is_bluetooth_out_sco_device(getPreferredDeviceTypeForLegacyStrategy(
+                    availableOutputDevices, STRATEGY_PHONE))) {
                 if (strategy == STRATEGY_SONIFICATION) {
                     devices.replaceDevicesByType(
                             AUDIO_DEVICE_OUT_SPEAKER,
@@ -510,13 +442,16 @@
         }
     }
 
+    audio_devices_t commDeviceType =
+        getPreferredDeviceTypeForLegacyStrategy(availableOutputDevices, STRATEGY_PHONE);
+
     switch (inputSource) {
     case AUDIO_SOURCE_DEFAULT:
     case AUDIO_SOURCE_MIC:
         device = availableDevices.getDevice(
                 AUDIO_DEVICE_IN_BLUETOOTH_A2DP, String8(""), AUDIO_FORMAT_DEFAULT);
         if (device != nullptr) break;
-        if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
+        if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
             device = availableDevices.getDevice(
                     AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
             if (device != nullptr) break;
@@ -524,7 +459,7 @@
         device = availableDevices.getFirstExistingDevice({
                 AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET,
                 AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_IN_USB_DEVICE,
-                AUDIO_DEVICE_IN_BUILTIN_MIC});
+                AUDIO_DEVICE_IN_BLUETOOTH_BLE, AUDIO_DEVICE_IN_BUILTIN_MIC});
         break;
 
     case AUDIO_SOURCE_VOICE_COMMUNICATION:
@@ -537,43 +472,56 @@
             availableDevices = availablePrimaryDevices;
         }
 
-        switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
-        case AUDIO_POLICY_FORCE_BT_SCO:
+        if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
             // if SCO device is requested but no SCO device is available, fall back to default case
             device = availableDevices.getDevice(
                     AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
             if (device != nullptr) {
                 break;
             }
-            FALLTHROUGH_INTENDED;
-
-        default:    // FORCE_NONE
-            // TODO (b/161358428): remove AUDIO_DEVICE_IN_BLE_HEADSET from the list
-            //  when preferred device for strategy phone will be used instead of
-            //  AUDIO_POLICY_FORCE_FOR_COMMUNICATION.
+        }
+        switch (commDeviceType) {
+        case AUDIO_DEVICE_OUT_BLE_HEADSET:
+            device = availableDevices.getDevice(
+                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+            break;
+        case AUDIO_DEVICE_OUT_SPEAKER:
             device = availableDevices.getFirstExistingDevice({
-                    AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET,
-                    AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_IN_USB_DEVICE,
+                    AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC,
+                    AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_USB_HEADSET});
+            break;
+        default:    // FORCE_NONE
+            device = availableDevices.getFirstExistingDevice({
+                    AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
+                    AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BLUETOOTH_BLE,
                     AUDIO_DEVICE_IN_BUILTIN_MIC});
             break;
 
-        case AUDIO_POLICY_FORCE_SPEAKER:
-            device = availableDevices.getFirstExistingDevice({
-                    AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC});
-            break;
         }
         break;
 
     case AUDIO_SOURCE_VOICE_RECOGNITION:
     case AUDIO_SOURCE_UNPROCESSED:
-    case AUDIO_SOURCE_HOTWORD:
-        if (inputSource == AUDIO_SOURCE_HOTWORD) {
-            // We should not use primary output criteria for Hotword but rather limit
-            // to devices attached to the same HW module as the build in mic
-            LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
-            availableDevices = availablePrimaryDevices;
+        if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
+            device = availableDevices.getDevice(
+                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+            if (device != nullptr) break;
         }
-        if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
+        // we need to make BLUETOOTH_BLE has higher priority than BUILTIN_MIC,
+        // because sometimes user want to do voice search by bt remote
+        // even if BUILDIN_MIC is available.
+        device = availableDevices.getFirstExistingDevice({
+                AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET,
+                AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_IN_USB_DEVICE,
+                AUDIO_DEVICE_IN_BLUETOOTH_BLE, AUDIO_DEVICE_IN_BUILTIN_MIC});
+
+        break;
+    case AUDIO_SOURCE_HOTWORD:
+        // We should not use primary output criteria for Hotword but rather limit
+        // to devices attached to the same HW module as the build in mic
+        LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
+        availableDevices = availablePrimaryDevices;
+        if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
             device = availableDevices.getDevice(
                     AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
             if (device != nullptr) break;
@@ -598,7 +546,8 @@
     case AUDIO_SOURCE_VOICE_PERFORMANCE:
         device = availableDevices.getFirstExistingDevice({
                 AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
-                AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
+                AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BLUETOOTH_BLE,
+                AUDIO_DEVICE_IN_BUILTIN_MIC});
         break;
     case AUDIO_SOURCE_REMOTE_SUBMIX:
         device = availableDevices.getDevice(
@@ -623,6 +572,7 @@
         ALOGE_IF(device == nullptr,
                  "getDeviceForInputSource() no default device defined");
     }
+
     ALOGV_IF(device != nullptr,
              "getDeviceForInputSource()input source %d, device %08x",
              inputSource, device->type());
@@ -640,17 +590,35 @@
     }
 }
 
-DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
-    DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
+product_strategy_t Engine::getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const {
+    for (const auto& strategyMap : mLegacyStrategyMap) {
+        if (strategyMap.second == legacyStrategy) {
+            return strategyMap.first;
+        }
+    }
+    return PRODUCT_STRATEGY_NONE;
+}
 
-    // check if this strategy has a preferred device that is available,
-    // if yes, give priority to it
+audio_devices_t Engine::getPreferredDeviceTypeForLegacyStrategy(
+        const DeviceVector& availableOutputDevices, legacy_strategy legacyStrategy) const {
+    product_strategy_t strategy = getProductStrategyFromLegacy(legacyStrategy);
+    DeviceVector devices = getPreferredAvailableDevicesForProductStrategy(
+            availableOutputDevices, strategy);
+    if (devices.size() > 0) {
+        return devices[0]->type();
+    }
+    return AUDIO_DEVICE_NONE;
+}
+
+DeviceVector Engine::getPreferredAvailableDevicesForProductStrategy(
+        const DeviceVector& availableOutputDevices, product_strategy_t strategy) const {
+    DeviceVector preferredAvailableDevVec = {};
     AudioDeviceTypeAddrVector preferredStrategyDevices;
     const status_t status = getDevicesForRoleAndStrategy(
             strategy, DEVICE_ROLE_PREFERRED, preferredStrategyDevices);
     if (status == NO_ERROR) {
         // there is a preferred device, is it available?
-        DeviceVector preferredAvailableDevVec =
+        preferredAvailableDevVec =
                 availableOutputDevices.getDevicesFromDeviceTypeAddrVec(preferredStrategyDevices);
         if (preferredAvailableDevVec.size() == preferredAvailableDevVec.size()) {
             ALOGVV("%s using pref device %s for strategy %u",
@@ -658,11 +626,30 @@
             return preferredAvailableDevVec;
         }
     }
+    return preferredAvailableDevVec;
+}
+
+DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
+    DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
+    auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
+                          mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
+
+    // When not in call, STRATEGY_PHONE and STRATEGY_DTMF follow STRATEGY_MEDIA
+    if (!isInCall() && (legacyStrategy == STRATEGY_PHONE || legacyStrategy == STRATEGY_DTMF)) {
+        legacyStrategy = STRATEGY_MEDIA;
+        strategy = getProductStrategyFromLegacy(STRATEGY_MEDIA);
+    }
+    // check if this strategy has a preferred device that is available,
+    // if yes, give priority to it.
+    DeviceVector preferredAvailableDevVec =
+            getPreferredAvailableDevicesForProductStrategy(availableOutputDevices, strategy);
+    if (!preferredAvailableDevVec.isEmpty()) {
+        return preferredAvailableDevVec;
+    }
 
     DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
     const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();
-    auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
-                          mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
+
     return getDevicesForStrategyInt(legacyStrategy,
                                     availableOutputDevices,
                                     availableInputDevices, outputs);
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index bb9e2df..6214fe7 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -83,6 +83,12 @@
 
     sp<DeviceDescriptor> getDeviceForInputSource(audio_source_t inputSource) const;
 
+    product_strategy_t getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const;
+    audio_devices_t getPreferredDeviceTypeForLegacyStrategy(
+        const DeviceVector& availableOutputDevices, legacy_strategy legacyStrategy) const;
+    DeviceVector getPreferredAvailableDevicesForProductStrategy(
+        const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
+
     DeviceStrategyMap mDevicesForStrategies;
 
     std::map<product_strategy_t, legacy_strategy> mLegacyStrategyMap;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index cc4ec36..51abef1 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -206,6 +206,9 @@
             // Reset active device codec
             device->setEncodedFormat(AUDIO_FORMAT_DEFAULT);
 
+            // remove device from mReportedFormatsMap cache
+            mReportedFormatsMap.erase(device);
+
             } break;
 
         default:
@@ -243,6 +246,7 @@
                     if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) ||
                             (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
                                 (desc->mDirectOpenCount == 0))) {
+                        clearAudioSourcesForOutput(output);
                         closeOutput(output);
                     }
                 }
@@ -262,7 +266,10 @@
             DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
             updateCallRouting(newDevices);
         }
+        std::vector<audio_io_handle_t> outputsToReopen;
         const DeviceVector msdOutDevices = getMsdAudioOutDevices();
+        const DeviceVector activeMediaDevices =
+                mEngine->getActiveMediaDevices(mAvailableOutputDevices);
         for (size_t i = 0; i < mOutputs.size(); i++) {
             sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
             if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (desc != mPrimaryOutput)) {
@@ -277,6 +284,28 @@
                                 || (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
                 setOutputDevices(desc, newDevices, force, 0);
             }
+            if (!desc->isDuplicated() && desc->mProfile->hasDynamicAudioProfile() &&
+                    desc->devices() != activeMediaDevices &&
+                    desc->supportsDevicesForPlayback(activeMediaDevices)) {
+                // Reopen the output to query the dynamic profiles when there is not active
+                // clients or all active clients will be rerouted. Otherwise, set the flag
+                // `mPendingReopenToQueryProfiles` in the SwOutputDescriptor so that the output
+                // can be reopened to query dynamic profiles when all clients are inactive.
+                if (areAllActiveTracksRerouted(desc)) {
+                    outputsToReopen.push_back(mOutputs.keyAt(i));
+                } else {
+                    desc->mPendingReopenToQueryProfiles = true;
+                }
+            }
+            if (!desc->supportsDevicesForPlayback(activeMediaDevices)) {
+                // Clear the flag that previously set for re-querying profiles.
+                desc->mPendingReopenToQueryProfiles = false;
+            }
+        }
+        for (const auto& output : outputsToReopen) {
+            sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
+            closeOutput(output);
+            openOutputWithProfileAndDevice(desc->mProfile, activeMediaDevices);
         }
 
         if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
@@ -334,6 +363,9 @@
             mAvailableInputDevices.remove(device);
 
             checkInputsForDevice(device, state);
+
+            // remove device from mReportedFormatsMap cache
+            mReportedFormatsMap.erase(device);
         } break;
 
         default:
@@ -353,7 +385,11 @@
             DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
             updateCallRouting(newDevices);
         }
-
+        // Reconnect Audio Source
+        for (const auto &strategy : mEngine->getOrderedProductStrategies()) {
+            auto attributes = mEngine->getAllAttributesForProductStrategy(strategy).front();
+            checkAudioSourceForAttributes(attributes);
+        }
         if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
             cleanUpForDevice(device);
         }
@@ -438,7 +474,7 @@
     // Case 1: A2DP active device switches from primary to primary
     // module
     // Case 2: A2DP device config changes on primary module.
-    if (audio_is_a2dp_out_device(device)) {
+    if (audio_is_a2dp_out_device(device) && hasPrimaryOutput()) {
         sp<HwModule> module = mHwModules.getModuleForDeviceType(device, encodedFormat);
         audio_module_handle_t primaryHandle = mPrimaryOutput->getModuleHandle();
         if (availablePrimaryOutputDevices().contains(devDesc) &&
@@ -532,11 +568,7 @@
     ALOGV("updateCallRouting device rxDevice %s txDevice %s",
           rxDevices.itemAt(0)->toString().c_str(), txSourceDevice->toString().c_str());
 
-    // release existing RX patch if any
-    if (mCallRxPatch != 0) {
-        releaseAudioPatchInternal(mCallRxPatch->getHandle());
-        mCallRxPatch.clear();
-    }
+    disconnectTelephonyRxAudioSource();
     // release TX patch if any
     if (mCallTxPatch != 0) {
         releaseAudioPatchInternal(mCallTxPatch->getHandle());
@@ -584,8 +616,7 @@
     if (!createRxPatch) {
         muteWaitMs = setOutputDevices(mPrimaryOutput, rxDevices, true, delayMs);
     } else { // create RX path audio patch
-        mCallRxPatch = createTelephonyPatch(true /*isRx*/, rxDevices.itemAt(0), delayMs);
-
+        connectTelephonyRxAudioSource();
         // If the TX device is on the primary HW module but RX device is
         // on other HW module, SinkMetaData of telephony input should handle it
         // assuming the device uses audio HAL V5.0 and above
@@ -648,6 +679,24 @@
     return false;
 }
 
+void AudioPolicyManager::connectTelephonyRxAudioSource()
+{
+    disconnectTelephonyRxAudioSource();
+    const struct audio_port_config source = {
+        .role = AUDIO_PORT_ROLE_SOURCE, .type = AUDIO_PORT_TYPE_DEVICE,
+        .ext.device.type = AUDIO_DEVICE_IN_TELEPHONY_RX, .ext.device.address = ""
+    };
+    const auto aa = mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL);
+    status_t status = startAudioSource(&source, &aa, &mCallRxSourceClientPort, 0/*uid*/);
+    ALOGE_IF(status != NO_ERROR, "%s failed to start Telephony Rx AudioSource", __func__);
+}
+
+void AudioPolicyManager::disconnectTelephonyRxAudioSource()
+{
+    stopAudioSource(mCallRxSourceClientPort);
+    mCallRxSourceClientPort = AUDIO_PORT_HANDLE_NONE;
+}
+
 void AudioPolicyManager::setPhoneState(audio_mode_t state)
 {
     ALOGV("setPhoneState() state %d", state);
@@ -715,10 +764,7 @@
         if (state == AUDIO_MODE_IN_CALL) {
             updateCallRouting(rxDevices, delayMs);
         } else if (oldState == AUDIO_MODE_IN_CALL) {
-            if (mCallRxPatch != 0) {
-                releaseAudioPatchInternal(mCallRxPatch->getHandle());
-                mCallRxPatch.clear();
-            }
+            disconnectTelephonyRxAudioSource();
             if (mCallTxPatch != 0) {
                 releaseAudioPatchInternal(mCallTxPatch->getHandle());
                 mCallTxPatch.clear();
@@ -786,16 +832,7 @@
     }
 
     updateCallAndOutputRouting(forceVolumeReeval, delayMs);
-
-    for (const auto& activeDesc : mInputs.getActiveInputs()) {
-        auto newDevice = getNewInputDevice(activeDesc);
-        // Force new input selection if the new device can not be reached via current input
-        if (activeDesc->mProfile->getSupportedDevices().contains(newDevice)) {
-            setInputDevice(activeDesc->mIoHandle, newDevice);
-        } else {
-            closeInput(activeDesc->mIoHandle);
-        }
-    }
+    updateInputRouting();
 }
 
 void AudioPolicyManager::setSystemProperty(const char* property, const char* value)
@@ -1031,7 +1068,6 @@
         if (*output != AUDIO_IO_HANDLE_NONE && setMsdPatch(device) == NO_ERROR) {
             ALOGV("%s() Using MSD devices %s instead of devices %s",
                   __func__, msdDevices.toString().c_str(), outputDevices.toString().c_str());
-            outputDevices = msdDevices;
         } else {
             *output = AUDIO_IO_HANDLE_NONE;
         }
@@ -1936,7 +1972,7 @@
     }
 }
 
-void AudioPolicyManager::releaseOutput(audio_port_handle_t portId)
+bool AudioPolicyManager::releaseOutput(audio_port_handle_t portId)
 {
     ALOGV("%s portId %d", __FUNCTION__, portId);
 
@@ -1949,7 +1985,7 @@
         //
         // Here we just log a warning, instead of a fatal error.
         ALOGW("releaseOutput() no output for client %d", portId);
-        return;
+        return false;
     }
 
     ALOGV("releaseOutput() %d", outputDesc->mIoHandle);
@@ -1964,7 +2000,7 @@
         if (outputDesc->mDirectOpenCount <= 0) {
             ALOGW("releaseOutput() invalid open count %d for output %d",
                   outputDesc->mDirectOpenCount, outputDesc->mIoHandle);
-            return;
+            return false;
         }
         if (--outputDesc->mDirectOpenCount == 0) {
             closeOutput(outputDesc->mIoHandle);
@@ -1973,6 +2009,18 @@
     }
 
     outputDesc->removeClient(portId);
+    if (outputDesc->mPendingReopenToQueryProfiles && outputDesc->getClientCount() == 0) {
+        // The output is pending reopened to query dynamic profiles and
+        // there is no active clients
+        closeOutput(outputDesc->mIoHandle);
+        sp<SwAudioOutputDescriptor> newOutputDesc = openOutputWithProfileAndDevice(
+                outputDesc->mProfile, mEngine->getActiveMediaDevices(mAvailableOutputDevices));
+        if (newOutputDesc == nullptr) {
+            ALOGE("%s failed to open output", __func__);
+        }
+        return true;
+    }
+    return false;
 }
 
 status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
@@ -3158,6 +3206,7 @@
     return res;
 }
 
+
 status_t AudioPolicyManager::setDevicesRoleForStrategy(product_strategy_t strategy,
                                                        device_role_t role,
                                                        const AudioDeviceTypeAddrVector &devices) {
@@ -3175,7 +3224,17 @@
     }
 
     checkForDeviceAndOutputChanges();
-    updateCallAndOutputRouting();
+
+    bool forceVolumeReeval = false;
+    // FIXME: workaround for truncated touch sounds
+    // to be removed when the problem is handled by system UI
+    uint32_t delayMs = 0;
+    if (strategy == mCommunnicationStrategy) {
+        forceVolumeReeval = true;
+        delayMs = TOUCH_SOUND_FIXED_DELAY_MS;
+        updateInputRouting();
+    }
+    updateCallAndOutputRouting(forceVolumeReeval, delayMs);
 
     return NO_ERROR;
 }
@@ -3206,6 +3265,18 @@
     }
 }
 
+void AudioPolicyManager::updateInputRouting() {
+    for (const auto& activeDesc : mInputs.getActiveInputs()) {
+        auto newDevice = getNewInputDevice(activeDesc);
+        // Force new input selection if the new device can not be reached via current input
+        if (activeDesc->mProfile->getSupportedDevices().contains(newDevice)) {
+            setInputDevice(activeDesc->mIoHandle, newDevice);
+        } else {
+            closeInput(activeDesc->mIoHandle);
+        }
+    }
+}
+
 status_t AudioPolicyManager::removeDevicesRoleForStrategy(product_strategy_t strategy,
                                                           device_role_t role)
 {
@@ -3213,12 +3284,23 @@
 
     status_t status = mEngine->removeDevicesRoleForStrategy(strategy, role);
     if (status != NO_ERROR) {
-        ALOGW("Engine could not remove preferred device for strategy %d", strategy);
+        ALOGV("Engine could not remove preferred device for strategy %d status %d",
+                strategy, status);
         return status;
     }
 
     checkForDeviceAndOutputChanges();
-    updateCallAndOutputRouting();
+
+    bool forceVolumeReeval = false;
+    // FIXME: workaround for truncated touch sounds
+    // to be removed when the problem is handled by system UI
+    uint32_t delayMs = 0;
+    if (strategy == mCommunnicationStrategy) {
+        forceVolumeReeval = true;
+        delayMs = TOUCH_SOUND_FIXED_DELAY_MS;
+        updateInputRouting();
+    }
+    updateCallAndOutputRouting(forceVolumeReeval, delayMs);
 
     return NO_ERROR;
 }
@@ -3258,6 +3340,7 @@
             "Engine could not add preferred devices %s for audio source %d role %d",
             dumpAudioDeviceTypeAddrVector(devices).c_str(), audioSource, role);
 
+    updateInputRouting();
     return status;
 }
 
@@ -3276,6 +3359,7 @@
     ALOGW_IF(status != NO_ERROR,
             "Engine could not remove devices role (%d) for capture preset %d", role, audioSource);
 
+    updateInputRouting();
     return status;
 }
 
@@ -3287,6 +3371,7 @@
     ALOGW_IF(status != NO_ERROR,
             "Engine could not clear devices role (%d) for capture preset %d", role, audioSource);
 
+    updateInputRouting();
     return status;
 }
 
@@ -3356,7 +3441,9 @@
     }
     dst->appendFormat(" TTS output %savailable\n", mTtsOutputAvailable ? "" : "not ");
     dst->appendFormat(" Master mono: %s\n", mMasterMono ? "on" : "off");
+    dst->appendFormat(" Communnication Strategy: %d\n", mCommunnicationStrategy);
     dst->appendFormat(" Config source: %s\n", mConfig.getSource().c_str()); // getConfig not const
+
     mAvailableOutputDevices.dump(dst, String8("Available output"));
     mAvailableInputDevices.dump(dst, String8("Available input"));
     mHwModulesAll.dump(dst);
@@ -3393,38 +3480,38 @@
 // This function checks for the parameters which can be offloaded.
 // This can be enhanced depending on the capability of the DSP and policy
 // of the system.
-bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadInfo)
+audio_offload_mode_t AudioPolicyManager::getOffloadSupport(const audio_offload_info_t& offloadInfo)
 {
-    ALOGV("isOffloadSupported: SR=%u, CM=0x%x, Format=0x%x, StreamType=%d,"
+    ALOGV("%s: SR=%u, CM=0x%x, Format=0x%x, StreamType=%d,"
      " BitRate=%u, duration=%" PRId64 " us, has_video=%d",
-     offloadInfo.sample_rate, offloadInfo.channel_mask,
+     __func__, offloadInfo.sample_rate, offloadInfo.channel_mask,
      offloadInfo.format,
      offloadInfo.stream_type, offloadInfo.bit_rate, offloadInfo.duration_us,
      offloadInfo.has_video);
 
     if (mMasterMono) {
-        return false; // no offloading if mono is set.
+        return AUDIO_OFFLOAD_NOT_SUPPORTED; // no offloading if mono is set.
     }
 
     // Check if offload has been disabled
     if (property_get_bool("audio.offload.disable", false /* default_value */)) {
-        ALOGV("offload disabled by audio.offload.disable");
-        return false;
+        ALOGV("%s: offload disabled by audio.offload.disable", __func__);
+        return AUDIO_OFFLOAD_NOT_SUPPORTED;
     }
 
     // Check if stream type is music, then only allow offload as of now.
     if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC)
     {
-        ALOGV("isOffloadSupported: stream_type != MUSIC, returning false");
-        return false;
+        ALOGV("%s: stream_type != MUSIC, returning false", __func__);
+        return AUDIO_OFFLOAD_NOT_SUPPORTED;
     }
 
     //TODO: enable audio offloading with video when ready
     const bool allowOffloadWithVideo =
             property_get_bool("audio.offload.video", false /* default_value */);
     if (offloadInfo.has_video && !allowOffloadWithVideo) {
-        ALOGV("isOffloadSupported: has_video == true, returning false");
-        return false;
+        ALOGV("%s: has_video == true, returning false", __func__);
+        return AUDIO_OFFLOAD_NOT_SUPPORTED;
     }
 
     //If duration is less than minimum value defined in property, return false
@@ -3432,13 +3519,14 @@
             "audio.offload.min.duration.secs", -1 /* default_value */);
     if (min_duration_secs >= 0) {
         if (offloadInfo.duration_us < min_duration_secs * 1000000LL) {
-            ALOGV("Offload denied by duration < audio.offload.min.duration.secs(=%d)",
-                    min_duration_secs);
-            return false;
+            ALOGV("%s: Offload denied by duration < audio.offload.min.duration.secs(=%d)",
+                    __func__, min_duration_secs);
+            return AUDIO_OFFLOAD_NOT_SUPPORTED;
         }
     } else if (offloadInfo.duration_us < OFFLOAD_DEFAULT_MIN_DURATION_SECS * 1000000) {
-        ALOGV("Offload denied by duration < default min(=%u)", OFFLOAD_DEFAULT_MIN_DURATION_SECS);
-        return false;
+        ALOGV("%s: Offload denied by duration < default min(=%u)",
+                __func__, OFFLOAD_DEFAULT_MIN_DURATION_SECS);
+        return AUDIO_OFFLOAD_NOT_SUPPORTED;
     }
 
     // Do not allow offloading if one non offloadable effect is enabled. This prevents from
@@ -3448,7 +3536,7 @@
     // This may prevent offloading in rare situations where effects are left active by apps
     // in the background.
     if (mEffects.isNonOffloadableEffectEnabled()) {
-        return false;
+        return AUDIO_OFFLOAD_NOT_SUPPORTED;
     }
 
     // See if there is a profile to support this.
@@ -3459,8 +3547,14 @@
                                             offloadInfo.channel_mask,
                                             AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD,
                                             true /* directOnly */);
-    ALOGV("isOffloadSupported() profile %sfound", profile != 0 ? "" : "NOT ");
-    return (profile != 0);
+    ALOGV("%s: profile %sfound", __func__, profile != 0 ? "" : "NOT ");
+    if (profile == nullptr) {
+        return AUDIO_OFFLOAD_NOT_SUPPORTED;
+    }
+    if ((profile->getFlags() & AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD) != 0) {
+        return AUDIO_OFFLOAD_GAPLESS_SUPPORTED;
+    }
+    return AUDIO_OFFLOAD_SUPPORTED;
 }
 
 bool AudioPolicyManager::isDirectOutputSupported(const audio_config_base_t& config,
@@ -3484,15 +3578,15 @@
 status_t AudioPolicyManager::listAudioPorts(audio_port_role_t role,
                                             audio_port_type_t type,
                                             unsigned int *num_ports,
-                                            struct audio_port *ports,
+                                            struct audio_port_v7 *ports,
                                             unsigned int *generation)
 {
-    if (num_ports == NULL || (*num_ports != 0 && ports == NULL) ||
-            generation == NULL) {
+    if (num_ports == nullptr || (*num_ports != 0 && ports == nullptr) ||
+            generation == nullptr) {
         return BAD_VALUE;
     }
     ALOGV("listAudioPorts() role %d type %d num_ports %d ports %p", role, type, *num_ports, ports);
-    if (ports == NULL) {
+    if (ports == nullptr) {
         *num_ports = 0;
     }
 
@@ -3550,7 +3644,7 @@
     return NO_ERROR;
 }
 
-status_t AudioPolicyManager::getAudioPort(struct audio_port *port)
+status_t AudioPolicyManager::getAudioPort(struct audio_port_v7 *port)
 {
     if (port == nullptr || port->id == AUDIO_PORT_HANDLE_NONE) {
         return BAD_VALUE;
@@ -3779,6 +3873,41 @@
                 sinkDevice->toAudioPortConfig(&sinkPortConfig, &patch->sinks[i]);
                 patchBuilder.addSink(sinkPortConfig);
 
+                // Whatever Sw or Hw bridge, we do attach an SwOutput to an Audio Source for
+                // volume management purpose (tracking activity)
+                // In case of Hw bridge, it is a Work Around. The mixPort used is the one declared
+                // in config XML to reach the sink so that is can be declared as available.
+                audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+                sp<SwAudioOutputDescriptor> outputDesc = nullptr;
+                if (sourceDesc != nullptr) {
+                    // take care of dynamic routing for SwOutput selection,
+                    audio_attributes_t attributes = sourceDesc->attributes();
+                    audio_stream_type_t stream = sourceDesc->stream();
+                    audio_attributes_t resultAttr;
+                    audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+                    config.sample_rate = sourceDesc->config().sample_rate;
+                    config.channel_mask = sourceDesc->config().channel_mask;
+                    config.format = sourceDesc->config().format;
+                    audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
+                    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+                    bool isRequestedDeviceForExclusiveUse = false;
+                    output_type_t outputType;
+                    getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
+                                        &stream, sourceDesc->uid(), &config, &flags,
+                                        &selectedDeviceId, &isRequestedDeviceForExclusiveUse,
+                                        nullptr, &outputType);
+                    if (output == AUDIO_IO_HANDLE_NONE) {
+                        ALOGV("%s no output for device %s",
+                              __FUNCTION__, sinkDevice->toString().c_str());
+                        return INVALID_OPERATION;
+                    }
+                    outputDesc = mOutputs.valueFor(output);
+                    if (outputDesc->isDuplicated()) {
+                        ALOGE("%s output is duplicated", __func__);
+                        return INVALID_OPERATION;
+                    }
+                    sourceDesc->setSwOutput(outputDesc);
+                }
                 // create a software bridge in PatchPanel if:
                 // - source and sink devices are on different HW modules OR
                 // - audio HAL version is < 3.0
@@ -3794,49 +3923,25 @@
                     if (patch->num_sinks > 1) {
                         return INVALID_OPERATION;
                     }
-                    audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
-                    if (sourceDesc != nullptr) {
-                        // take care of dynamic routing for SwOutput selection,
-                        audio_attributes_t attributes = sourceDesc->attributes();
-                        audio_stream_type_t stream = sourceDesc->stream();
-                        audio_attributes_t resultAttr;
-                        audio_config_t config = AUDIO_CONFIG_INITIALIZER;
-                        config.sample_rate = sourceDesc->config().sample_rate;
-                        config.channel_mask = sourceDesc->config().channel_mask;
-                        config.format = sourceDesc->config().format;
-                        audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
-                        audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
-                        bool isRequestedDeviceForExclusiveUse = false;
-                        output_type_t outputType;
-                        getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
-                                            &stream, sourceDesc->uid(), &config, &flags,
-                                            &selectedDeviceId, &isRequestedDeviceForExclusiveUse,
-                                            nullptr, &outputType);
-                        if (output == AUDIO_IO_HANDLE_NONE) {
-                            ALOGV("%s no output for device %s",
-                                  __FUNCTION__, sinkDevice->toString().c_str());
-                            return INVALID_OPERATION;
-                        }
-                    } else {
+                    if (sourceDesc == nullptr) {
                         SortedVector<audio_io_handle_t> outputs =
                                 getOutputsForDevices(DeviceVector(sinkDevice), mOutputs);
                         // if the sink device is reachable via an opened output stream, request to
                         // go via this output stream by adding a second source to the patch
                         // description
                         output = selectOutput(outputs);
-                    }
-                    if (output != AUDIO_IO_HANDLE_NONE) {
-                        sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
-                        if (outputDesc->isDuplicated()) {
-                            ALOGV("%s output for device %s is duplicated",
-                                  __FUNCTION__, sinkDevice->toString().c_str());
-                            return INVALID_OPERATION;
+                        if (output != AUDIO_IO_HANDLE_NONE) {
+                            outputDesc = mOutputs.valueFor(output);
+                            if (outputDesc->isDuplicated()) {
+                                ALOGV("%s output for device %s is duplicated",
+                                      __FUNCTION__, sinkDevice->toString().c_str());
+                                return INVALID_OPERATION;
+                            }
                         }
+                    }
+                    if (outputDesc != nullptr) {
                         audio_port_config srcMixPortConfig = {};
                         outputDesc->toAudioPortConfig(&srcMixPortConfig, &patch->sources[0]);
-                        if (sourceDesc != nullptr) {
-                            sourceDesc->setSwOutput(outputDesc);
-                        }
                         // for volume control, we may need a valid stream
                         srcMixPortConfig.ext.mix.usecase.stream = sourceDesc != nullptr ?
                                     sourceDesc->stream() : AUDIO_STREAM_PATCH;
@@ -3927,8 +4032,9 @@
                 sp<SwAudioOutputDescriptor> outputDesc =
                         mOutputs.getOutputFromId(patch->sources[1].id);
                 if (outputDesc == NULL) {
-                    ALOGE("%s output not found for id %d", __func__, patch->sources[0].id);
-                    return BAD_VALUE;
+                    ALOGW("%s output not found for id %d", __func__, patch->sources[0].id);
+                    // releaseOutput has already called closeOuput in case of direct output
+                    return NO_ERROR;
                 }
                 if (patchDesc->getHandle() != outputDesc->getPatchHandle()) {
                     // force SwOutput patch removal as AF counter part patch has already gone.
@@ -4194,15 +4300,19 @@
     disconnectAudioSource(sourceDesc);
 
     audio_attributes_t attributes = sourceDesc->attributes();
-    sp<DeviceDescriptor> srcDevice = sourceDesc->srcDevice();
-
+    // May the device (dynamic) have been disconnected/reconnected, id has changed.
+    sp<DeviceDescriptor> srcDevice = mAvailableInputDevices.getDevice(
+                sourceDesc->srcDevice()->type(),
+                String8(sourceDesc->srcDevice()->address().c_str()),
+                AUDIO_FORMAT_DEFAULT);
     DeviceVector sinkDevices =
-            mEngine->getOutputDevicesForAttributes(attributes, nullptr, true);
+            mEngine->getOutputDevicesForAttributes(attributes, nullptr, false /*fromCache*/);
     ALOG_ASSERT(!sinkDevices.isEmpty(), "connectAudioSource(): no device found for attributes");
     sp<DeviceDescriptor> sinkDevice = sinkDevices.itemAt(0);
-    ALOG_ASSERT(mAvailableOutputDevices.contains(sinkDevice), "%s: Device %s not available",
-                __FUNCTION__, sinkDevice->toString().c_str());
-
+    if (!mAvailableOutputDevices.contains(sinkDevice)) {
+        ALOGE("%s Device %s not available", __func__, sinkDevice->toString().c_str());
+        return INVALID_OPERATION;
+    }
     PatchBuilder patchBuilder;
     patchBuilder.addSink(sinkDevice).addSource(srcDevice);
     audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
@@ -4212,7 +4322,7 @@
         ALOGW("%s patch panel could not connect device patch, error %d", __func__, status);
         return INVALID_OPERATION;
     }
-    sourceDesc->setPatchHandle(handle);
+    sourceDesc->connect(handle, sinkDevice);
     // SW Bridge? (@todo: HW bridge, keep track of HwOutput for device selection "reconsideration")
     sp<SwAudioOutputDescriptor> swOutput = sourceDesc->swOutput().promote();
     if (swOutput != 0) {
@@ -4332,14 +4442,28 @@
         // checkOutputsForDevice().
         for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) {
             sp<DeviceDescriptor> device = mAvailableOutputDevices[i];
-            FormatVector supportedFormats =
-                    device->getAudioPort()->getAudioProfiles().getSupportedFormats();
-            for (size_t j = 0; j < supportedFormats.size(); j++) {
-                if (mConfig.getSurroundFormats().count(supportedFormats[j]) != 0) {
-                    formats.insert(supportedFormats[j]);
+            audio_devices_t deviceType = device->type();
+            // Enabling/disabling formats are applied to only HDMI devices. So, this function
+            // returns formats reported by HDMI devices.
+            if (deviceType != AUDIO_DEVICE_OUT_HDMI) {
+                continue;
+            }
+            // Formats reported by sink devices
+            std::unordered_set<audio_format_t> formatset;
+            if (auto it = mReportedFormatsMap.find(device); it != mReportedFormatsMap.end()) {
+                formatset.insert(it->second.begin(), it->second.end());
+            }
+
+            // Formats hard-coded in the in policy configuration file (if any).
+            FormatVector encodedFormats = device->encodedFormats();
+            formatset.insert(encodedFormats.begin(), encodedFormats.end());
+            // Filter the formats which are supported by the vendor hardware.
+            for (auto it = formatset.begin(); it != formatset.end(); ++it) {
+                if (mConfig.getSurroundFormats().count(*it) != 0) {
+                    formats.insert(*it);
                 } else {
                     for (const auto& pair : mConfig.getSurroundFormats()) {
-                        if (pair.second.count(supportedFormats[j]) != 0) {
+                        if (pair.second.count(*it) != 0) {
                             formats.insert(pair.first);
                             break;
                         }
@@ -4495,13 +4619,21 @@
 status_t AudioPolicyManager::disconnectAudioSource(const sp<SourceClientDescriptor>& sourceDesc)
 {
     ALOGV("%s port Id %d", __FUNCTION__, sourceDesc->portId());
+    if (!sourceDesc->isConnected()) {
+        ALOGV("%s port Id %d already disconnected", __FUNCTION__, sourceDesc->portId());
+        return NO_ERROR;
+    }
     sp<SwAudioOutputDescriptor> swOutput = sourceDesc->swOutput().promote();
     if (swOutput != 0) {
         status_t status = stopSource(swOutput, sourceDesc);
         if (status == NO_ERROR) {
             swOutput->stop();
         }
-        releaseOutput(sourceDesc->portId());
+        if (releaseOutput(sourceDesc->portId())) {
+            // The output descriptor is reopened to query dynamic profiles. In that case, there is
+            // no need to release audio patch here but just return NO_ERROR.
+            return NO_ERROR;
+        }
     } else {
         sp<HwAudioOutputDescriptor> hwOutputDesc = sourceDesc->hwOutput().promote();
         if (hwOutputDesc != 0) {
@@ -4510,7 +4642,9 @@
             ALOGW("%s source has neither SW nor HW output", __FUNCTION__);
         }
     }
-    return releaseAudioPatchInternal(sourceDesc->getPatchHandle());
+    status_t status = releaseAudioPatchInternal(sourceDesc->getPatchHandle());
+    sourceDesc->disconnect();
+    return status;
 }
 
 sp<SourceClientDescriptor> AudioPolicyManager::getSourceForAttributesOnOutput(
@@ -4601,6 +4735,9 @@
         return status;
     }
 
+    mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
+        mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
+
     // after parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices;
     // open all output streams needed to access attached devices
     onNewAudioModulesAvailableInt(nullptr /*newDevices*/);
@@ -4622,10 +4759,7 @@
         }
     }
 
-    if (mPrimaryOutput == 0) {
-        ALOGE("Failed to open primary output");
-        status = NO_INIT;
-    }
+    ALOGW_IF(mPrimaryOutput == nullptr, "The policy configuration does not declare a primary output");
 
     // Silence ALOGV statements
     property_set("log.tag." LOG_TAG, "D");
@@ -4735,7 +4869,7 @@
                     setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
                 }
             }
-            if (mPrimaryOutput == 0 &&
+            if (mPrimaryOutput == nullptr &&
                     outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
                 mPrimaryOutput = outputDesc;
             }
@@ -4812,6 +4946,10 @@
 
 void AudioPolicyManager::removeOutput(audio_io_handle_t output)
 {
+    if (mPrimaryOutput != 0 && mPrimaryOutput == mOutputs.valueFor(output)) {
+        ALOGV("%s: removing primary output", __func__);
+        mPrimaryOutput = nullptr;
+    }
     mOutputs.removeItem(output);
     selectOutputForMusicEffects();
 }
@@ -4905,82 +5043,8 @@
 
             ALOGV("opening output for device %08x with params %s profile %p name %s",
                   deviceType, address.string(), profile.get(), profile->getName().c_str());
-            desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
-            audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
-            status = desc->open(nullptr, DeviceVector(device),
-                                AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
-
-            if (status == NO_ERROR) {
-                // Here is where the out_set_parameters() for card & device gets called
-                if (!address.isEmpty()) {
-                    char *param = audio_device_address_to_parameter(deviceType, address);
-                    mpClientInterface->setParameters(output, String8(param));
-                    free(param);
-                }
-                updateAudioProfiles(device, output, profile->getAudioProfiles());
-                if (!profile->hasValidAudioProfile()) {
-                    ALOGW("checkOutputsForDevice() missing param");
-                    desc->close();
-                    output = AUDIO_IO_HANDLE_NONE;
-                } else if (profile->hasDynamicAudioProfile()) {
-                    desc->close();
-                    output = AUDIO_IO_HANDLE_NONE;
-                    audio_config_t config = AUDIO_CONFIG_INITIALIZER;
-                    profile->pickAudioProfile(
-                            config.sample_rate, config.channel_mask, config.format);
-                    config.offload_info.sample_rate = config.sample_rate;
-                    config.offload_info.channel_mask = config.channel_mask;
-                    config.offload_info.format = config.format;
-
-                    status = desc->open(&config, DeviceVector(device),
-                                        AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
-                    if (status != NO_ERROR) {
-                        output = AUDIO_IO_HANDLE_NONE;
-                    }
-                }
-
-                if (output != AUDIO_IO_HANDLE_NONE) {
-                    addOutput(output, desc);
-                    if (audio_is_remote_submix_device(deviceType) && address != "0") {
-                        sp<AudioPolicyMix> policyMix;
-                        if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix)
-                                == NO_ERROR) {
-                            policyMix->setOutput(desc);
-                            desc->mPolicyMix = policyMix;
-                        } else {
-                            ALOGW("checkOutputsForDevice() cannot find policy for address %s",
-                                  address.string());
-                        }
-
-                    } else if (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
-                                    hasPrimaryOutput()) {
-                        // no duplicated output for direct outputs and
-                        // outputs used by dynamic policy mixes
-                        audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE;
-
-                        //TODO: configure audio effect output stage here
-
-                        // open a duplicating output thread for the new output and the primary output
-                        sp<SwAudioOutputDescriptor> dupOutputDesc =
-                                new SwAudioOutputDescriptor(NULL, mpClientInterface);
-                        status = dupOutputDesc->openDuplicating(mPrimaryOutput, desc,
-                                                                &duplicatedOutput);
-                        if (status == NO_ERROR) {
-                            // add duplicated output descriptor
-                            addOutput(duplicatedOutput, dupOutputDesc);
-                        } else {
-                            ALOGW("checkOutputsForDevice() could not open dup output for %d and %d",
-                                    mPrimaryOutput->mIoHandle, output);
-                            desc->close();
-                            removeOutput(output);
-                            nextAudioPortGeneration();
-                            output = AUDIO_IO_HANDLE_NONE;
-                        }
-                    }
-                }
-            } else {
-                output = AUDIO_IO_HANDLE_NONE;
-            }
+            desc = openOutputWithProfileAndDevice(profile, DeviceVector(device));
+            audio_io_handle_t output = desc == nullptr ? AUDIO_IO_HANDLE_NONE : desc->mIoHandle;
             if (output == AUDIO_IO_HANDLE_NONE) {
                 ALOGW("checkOutputsForDevice() could not open output for device %x", deviceType);
                 profiles.removeAt(profile_index);
@@ -4989,6 +5053,8 @@
                 outputs.add(output);
                 // Load digital format info only for digital devices
                 if (audio_device_is_digital(deviceType)) {
+                    // TODO: when getAudioPort is ready, it may not be needed to import the audio
+                    // port but just pick audio profile
                     device->importAudioPortAndPickAudioProfile(profile);
                 }
 
@@ -5013,7 +5079,7 @@
             if (!desc->isDuplicated()) {
                 // exact match on device
                 if (device_distinguishes_on_address(deviceType) && desc->supportsDevice(device)
-                        && desc->devicesSupportEncodedFormats({deviceType})) {
+                        && desc->containsSingleDeviceSupportingEncodedFormats(device)) {
                     outputs.add(mOutputs.keyAt(i));
                 } else if (!mAvailableOutputDevices.containsAtLeastOne(desc->supportedDevices())) {
                     ALOGV("checkOutputsForDevice(): disconnecting adding output %d",
@@ -5026,11 +5092,30 @@
         for (const auto& hwModule : mHwModules) {
             for (size_t j = 0; j < hwModule->getOutputProfiles().size(); j++) {
                 sp<IOProfile> profile = hwModule->getOutputProfiles()[j];
-                if (profile->supportsDevice(device)) {
-                    ALOGV("checkOutputsForDevice(): "
-                            "clearing direct output profile %zu on module %s",
-                            j, hwModule->getName());
-                    profile->clearAudioProfiles();
+                if (!profile->supportsDevice(device)) {
+                    continue;
+                }
+                ALOGV("checkOutputsForDevice(): "
+                        "clearing direct output profile %zu on module %s",
+                        j, hwModule->getName());
+                profile->clearAudioProfiles();
+                if (!profile->hasDynamicAudioProfile()) {
+                    continue;
+                }
+                // When a device is disconnected, if there is an IOProfile that contains dynamic
+                // profiles and supports the disconnected device, call getAudioPort to repopulate
+                // the capabilities of the devices that is supported by the IOProfile.
+                for (const auto& supportedDevice : profile->getSupportedDevices()) {
+                    if (supportedDevice == device ||
+                            !mAvailableOutputDevices.contains(supportedDevice)) {
+                        continue;
+                    }
+                    struct audio_port_v7 port;
+                    supportedDevice->toAudioPort(&port);
+                    status_t status = mpClientInterface->getAudioPort(&port);
+                    if (status == NO_ERROR) {
+                        supportedDevice->importAudioPort(port);
+                    }
                 }
             }
         }
@@ -5302,6 +5387,8 @@
     if (mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD) != 0) {
         setMsdPatch();
     }
+    // an event that changed routing likely occurred, inform upper layers
+    mpClientInterface->onRoutingUpdated();
 }
 
 bool AudioPolicyManager::followsSameRouting(const audio_attributes_t &lAttr,
@@ -5311,6 +5398,29 @@
             mEngine->getProductStrategyForAttributes(rAttr);
 }
 
+void AudioPolicyManager::checkAudioSourceForAttributes(const audio_attributes_t &attr)
+{
+    for (size_t i = 0; i < mAudioSources.size(); i++)  {
+        sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
+        if (sourceDesc != nullptr && followsSameRouting(attr, sourceDesc->attributes())
+                && sourceDesc->getPatchHandle() == AUDIO_PATCH_HANDLE_NONE
+                && !isCallRxAudioSource(sourceDesc)) {
+            connectAudioSource(sourceDesc);
+        }
+    }
+}
+
+void AudioPolicyManager::clearAudioSourcesForOutput(audio_io_handle_t output)
+{
+    for (size_t i = 0; i < mAudioSources.size(); i++)  {
+        sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
+        if (sourceDesc != nullptr && sourceDesc->swOutput().promote() != nullptr
+                && sourceDesc->swOutput().promote()->mIoHandle == output) {
+            disconnectAudioSource(sourceDesc);
+        }
+    }
+}
+
 void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr)
 {
     auto psId = mEngine->getProductStrategyForAttributes(attr);
@@ -5407,7 +5517,7 @@
                                 newDevices.types());
             }
             sp<SourceClientDescriptor> source = getSourceForAttributesOnOutput(srcOut, attr);
-            if (source != 0){
+            if (source != nullptr && !isCallRxAudioSource(source)) {
                 connectAudioSource(source);
             }
         }
@@ -5430,6 +5540,7 @@
     for (const auto &strategy : mEngine->getOrderedProductStrategies()) {
         auto attributes = mEngine->getAllAttributesForProductStrategy(strategy).front();
         checkOutputForAttributes(attributes);
+        checkAudioSourceForAttributes(attributes);
     }
 }
 
@@ -5465,6 +5576,17 @@
     }
 }
 
+bool AudioPolicyManager::isScoRequestedForComm() const {
+    AudioDeviceTypeAddrVector devices;
+    mEngine->getDevicesForRoleAndStrategy(mCommunnicationStrategy, DEVICE_ROLE_PREFERRED, devices);
+    for (const auto &device : devices) {
+        if (audio_is_bluetooth_out_sco_device(device.mType)) {
+            return true;
+        }
+    }
+    return false;
+}
+
 void AudioPolicyManager::checkA2dpSuspend()
 {
     audio_io_handle_t a2dpOutput = mOutputs.getA2dpOutput();
@@ -5476,23 +5598,21 @@
     bool isScoConnected =
             (mAvailableInputDevices.types().count(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) != 0 ||
              !Intersection(mAvailableOutputDevices.types(), getAudioDeviceOutAllScoSet()).empty());
+    bool isScoRequested = isScoRequestedForComm();
 
     // if suspended, restore A2DP output if:
     //      ((SCO device is NOT connected) ||
-    //       ((forced usage communication is NOT SCO) && (forced usage for record is NOT SCO) &&
+    //       ((SCO is not requested) &&
     //        (phone state is NOT in call) && (phone state is NOT ringing)))
     //
     // if not suspended, suspend A2DP output if:
     //      (SCO device is connected) &&
-    //       ((forced usage for communication is SCO) || (forced usage for record is SCO) ||
+    //       ((SCO is requested) ||
     //       ((phone state is in call) || (phone state is ringing)))
     //
     if (mA2dpSuspended) {
         if (!isScoConnected ||
-             ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) !=
-                     AUDIO_POLICY_FORCE_BT_SCO) &&
-              (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) !=
-                      AUDIO_POLICY_FORCE_BT_SCO) &&
+             (!isScoRequested &&
               (mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) &&
               (mEngine->getPhoneState() != AUDIO_MODE_RINGTONE))) {
 
@@ -5501,10 +5621,7 @@
         }
     } else {
         if (isScoConnected &&
-             ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) ==
-                     AUDIO_POLICY_FORCE_BT_SCO) ||
-              (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) ==
-                      AUDIO_POLICY_FORCE_BT_SCO) ||
+             (isScoRequested ||
               (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) ||
               (mEngine->getPhoneState() == AUDIO_MODE_RINGTONE))) {
 
@@ -6216,15 +6333,14 @@
     bool isVoiceVolSrc = callVolSrc == volumeSource;
     bool isBtScoVolSrc = btScoVolSrc == volumeSource;
 
-    audio_policy_forced_cfg_t forceUseForComm =
-            mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION);
+    bool isScoRequested = isScoRequestedForComm();
     // do not change in call volume if bluetooth is connected and vice versa
     // if sco and call follow same curves, bypass forceUseForComm
     if ((callVolSrc != btScoVolSrc) &&
-            ((isVoiceVolSrc && forceUseForComm == AUDIO_POLICY_FORCE_BT_SCO) ||
-             (isBtScoVolSrc && forceUseForComm != AUDIO_POLICY_FORCE_BT_SCO))) {
-        ALOGV("%s cannot set volume group %d volume with force use = %d for comm", __func__,
-             volumeSource, forceUseForComm);
+            ((isVoiceVolSrc && isScoRequested) ||
+             (isBtScoVolSrc && !isScoRequested))) {
+        ALOGV("%s cannot set volume group %d volume when is%srequested for comm", __func__,
+             volumeSource, isScoRequested ? " " : "n ot ");
         // Do not return an error here as AudioService will always set both voice call
         // and bluetooth SCO volumes due to stream aliasing.
         return NO_ERROR;
@@ -6396,9 +6512,10 @@
 {
     for (ssize_t i = (ssize_t)mAudioSources.size() - 1; i >= 0; i--)  {
         sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
-        if (sourceDesc->srcDevice()->equals(deviceDesc)) {
-            ALOGV("%s releasing audio source %d", __FUNCTION__, sourceDesc->portId());
-            stopAudioSource(sourceDesc->portId());
+        if (sourceDesc->isConnected() && (sourceDesc->srcDevice()->equals(deviceDesc) ||
+                                          sourceDesc->sinkDevice()->equals(deviceDesc))
+                && !isCallRxAudioSource(sourceDesc)) {
+            disconnectAudioSource(sourceDesc);
         }
     }
 
@@ -6412,10 +6529,14 @@
                 release = true;
             }
         }
+        const char *address = deviceDesc->address().c_str();
         for (size_t j = 0; j < patchDesc->mPatch.num_sinks && !release; j++)  {
             const struct audio_port_config *sink = &patchDesc->mPatch.sinks[j];
             if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
-                    sink->ext.device.type == deviceDesc->type()) {
+                    sink->ext.device.type == deviceDesc->type() &&
+                    (strnlen(address, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0
+                     || strncmp(sink->ext.device.address, address,
+                                 AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
                 release = true;
             }
         }
@@ -6538,6 +6659,7 @@
             return;
         }
         FormatVector formats = formatsFromString(reply.string());
+        mReportedFormatsMap[devDesc] = formats;
         if (device == AUDIO_DEVICE_OUT_HDMI
                 || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD)) {
             modifySurroundFormats(devDesc, &formats);
@@ -6637,4 +6759,129 @@
     return status;
 }
 
+bool AudioPolicyManager::areAllActiveTracksRerouted(const sp<SwAudioOutputDescriptor>& output)
+{
+    const TrackClientVector activeClients = output->getActiveClients();
+    if (activeClients.empty()) {
+        return true;
+    }
+    ssize_t index = mAudioPatches.indexOfKey(output->getPatchHandle());
+    if (index < 0) {
+        ALOGE("%s, no audio patch found while there are active clients on output %d",
+                __func__, output->getId());
+        return false;
+    }
+    sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
+    DeviceVector routedDevices;
+    for (int i = 0; i < patchDesc->mPatch.num_sinks; ++i) {
+        sp<DeviceDescriptor> device = mAvailableOutputDevices.getDeviceFromId(
+                patchDesc->mPatch.sinks[i].id);
+        if (device == nullptr) {
+            ALOGE("%s, no audio device found with id(%d)",
+                    __func__, patchDesc->mPatch.sinks[i].id);
+            return false;
+        }
+        routedDevices.add(device);
+    }
+    for (const auto& client : activeClients) {
+        // TODO: b/175343099 only travel the valid client
+        sp<DeviceDescriptor> preferredDevice =
+                mAvailableOutputDevices.getDeviceFromId(client->preferredDeviceId());
+        if (mEngine->getOutputDevicesForAttributes(
+                client->attributes(), preferredDevice, false) == routedDevices) {
+            return false;
+        }
+    }
+    return true;
+}
+
+sp<SwAudioOutputDescriptor> AudioPolicyManager::openOutputWithProfileAndDevice(
+        const sp<IOProfile>& profile, const DeviceVector& devices)
+{
+    for (const auto& device : devices) {
+        // TODO: This should be checking if the profile supports the device combo.
+        if (!profile->supportsDevice(device)) {
+            return nullptr;
+        }
+    }
+    sp<SwAudioOutputDescriptor> desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
+    audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+    status_t status = desc->open(nullptr, devices,
+            AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
+    if (status != NO_ERROR) {
+        return nullptr;
+    }
+
+    // Here is where the out_set_parameters() for card & device gets called
+    sp<DeviceDescriptor> device = devices.getDeviceForOpening();
+    const audio_devices_t deviceType = device->type();
+    const String8 &address = String8(device->address().c_str());
+    if (!address.isEmpty()) {
+        char *param = audio_device_address_to_parameter(deviceType, address.c_str());
+        mpClientInterface->setParameters(output, String8(param));
+        free(param);
+    }
+    updateAudioProfiles(device, output, profile->getAudioProfiles());
+    if (!profile->hasValidAudioProfile()) {
+        ALOGW("%s() missing param", __func__);
+        desc->close();
+        return nullptr;
+    } else if (profile->hasDynamicAudioProfile()) {
+        desc->close();
+        output = AUDIO_IO_HANDLE_NONE;
+        audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+        profile->pickAudioProfile(
+                config.sample_rate, config.channel_mask, config.format);
+        config.offload_info.sample_rate = config.sample_rate;
+        config.offload_info.channel_mask = config.channel_mask;
+        config.offload_info.format = config.format;
+
+        status = desc->open(&config, devices,
+                            AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
+        if (status != NO_ERROR) {
+            return nullptr;
+        }
+    }
+
+    addOutput(output, desc);
+    if (audio_is_remote_submix_device(deviceType) && address != "0") {
+        sp<AudioPolicyMix> policyMix;
+        if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix) == NO_ERROR) {
+            policyMix->setOutput(desc);
+            desc->mPolicyMix = policyMix;
+        } else {
+            ALOGW("checkOutputsForDevice() cannot find policy for address %s",
+                    address.string());
+        }
+
+    } else if (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) && hasPrimaryOutput()) {
+        // no duplicated output for direct outputs and
+        // outputs used by dynamic policy mixes
+        audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE;
+
+        //TODO: configure audio effect output stage here
+
+        // open a duplicating output thread for the new output and the primary output
+        sp<SwAudioOutputDescriptor> dupOutputDesc =
+                new SwAudioOutputDescriptor(nullptr, mpClientInterface);
+        status = dupOutputDesc->openDuplicating(mPrimaryOutput, desc, &duplicatedOutput);
+        if (status == NO_ERROR) {
+            // add duplicated output descriptor
+            addOutput(duplicatedOutput, dupOutputDesc);
+        } else {
+            ALOGW("checkOutputsForDevice() could not open dup output for %d and %d",
+                  mPrimaryOutput->mIoHandle, output);
+            desc->close();
+            removeOutput(output);
+            nextAudioPortGeneration();
+            return nullptr;
+        }
+    }
+    if (mPrimaryOutput == nullptr && profile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
+        ALOGV("%s(): re-assigning mPrimaryOutput", __func__);
+        mPrimaryOutput = desc;
+    }
+    return desc;
+}
+
 } // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 217013f..eba0c44 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -125,7 +125,7 @@
                                   output_type_t *outputType) override;
         virtual status_t startOutput(audio_port_handle_t portId);
         virtual status_t stopOutput(audio_port_handle_t portId);
-        virtual void releaseOutput(audio_port_handle_t portId);
+        virtual bool releaseOutput(audio_port_handle_t portId);
         virtual status_t getInputForAttr(const audio_attributes_t *attr,
                                          audio_io_handle_t *input,
                                          audio_unique_id_t riid,
@@ -225,7 +225,7 @@
         status_t dump(int fd) override;
 
         status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t capturePolicy) override;
-        virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo);
+        virtual audio_offload_mode_t getOffloadSupport(const audio_offload_info_t& offloadInfo);
 
         virtual bool isDirectOutputSupported(const audio_config_base_t& config,
                                              const audio_attributes_t& attributes);
@@ -233,9 +233,9 @@
         virtual status_t listAudioPorts(audio_port_role_t role,
                                         audio_port_type_t type,
                                         unsigned int *num_ports,
-                                        struct audio_port *ports,
+                                        struct audio_port_v7 *ports,
                                         unsigned int *generation);
-        virtual status_t getAudioPort(struct audio_port *port);
+        virtual status_t getAudioPort(struct audio_port_v7 *port);
         virtual status_t createAudioPatch(const struct audio_patch *patch,
                                            audio_patch_handle_t *handle,
                                            uid_t uid) {
@@ -556,6 +556,20 @@
          */
         void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0);
 
+        bool isCallRxAudioSource(const sp<SourceClientDescriptor> &source) {
+            return mCallRxSourceClientPort != AUDIO_PORT_HANDLE_NONE
+                && source == mAudioSources.valueFor(mCallRxSourceClientPort);
+        }
+
+        void connectTelephonyRxAudioSource();
+
+        void disconnectTelephonyRxAudioSource();
+
+        /**
+         * @brief updates routing for all inputs.
+         */
+        void updateInputRouting();
+
         /**
          * @brief checkOutputForAttributes checks and if necessary changes outputs used for the
          * given audio attributes.
@@ -566,6 +580,16 @@
          */
         void checkOutputForAttributes(const audio_attributes_t &attr);
 
+        /**
+         * @brief checkAudioSourceForAttributes checks if any AudioSource following the same routing
+         * as the given audio attributes is not routed and try to connect it.
+         * It must be called once checkOutputForAttributes has been called for orphans AudioSource,
+         * aka AudioSource not attached to any Audio Output (e.g. AudioSource connected to direct
+         * Output which has been disconnected (and output closed) due to sink device unavailable).
+         * @param attr to be considered
+         */
+        void checkAudioSourceForAttributes(const audio_attributes_t &attr);
+
         bool followsSameRouting(const audio_attributes_t &lAttr,
                                 const audio_attributes_t &rAttr) const;
 
@@ -735,6 +759,7 @@
 
         sp<SourceClientDescriptor> getSourceForAttributesOnOutput(audio_io_handle_t output,
                                                                   const audio_attributes_t &attr);
+        void clearAudioSourcesForOutput(audio_io_handle_t output);
 
         void cleanUpForDevice(const sp<DeviceDescriptor>& deviceDesc);
 
@@ -781,7 +806,6 @@
         SoundTriggerSessionCollection mSoundTriggerSessions;
 
         sp<AudioPatch> mCallTxPatch;
-        sp<AudioPatch> mCallRxPatch;
 
         HwAudioOutputCollection mHwOutputs;
         SourceClientCollection mAudioSources;
@@ -813,6 +837,17 @@
         std::unordered_set<audio_format_t> mManualSurroundFormats;
 
         std::unordered_map<uid_t, audio_flags_mask_t> mAllowedCapturePolicies;
+
+        // The map of device descriptor and formats reported by the device.
+        std::map<wp<DeviceDescriptor>, FormatVector> mReportedFormatsMap;
+
+        // Cached product strategy ID corresponding to legacy strategy STRATEGY_PHONE
+        product_strategy_t mCommunnicationStrategy;
+
+        // The port handle of the hardware audio source created internally for the Call RX audio
+        // end point.
+        audio_port_handle_t mCallRxSourceClientPort = AUDIO_PORT_HANDLE_NONE;
+
 private:
         void onNewAudioModulesAvailableInt(DeviceVector *newDevices);
 
@@ -968,6 +1003,13 @@
                 std::function<bool(audio_devices_t)> predicate,
                 const char* context);
 
+        bool isScoRequestedForComm() const;
+
+        bool areAllActiveTracksRerouted(const sp<SwAudioOutputDescriptor>& output);
+
+        sp<SwAudioOutputDescriptor> openOutputWithProfileAndDevice(const sp<IOProfile>& profile,
+                                                                   const DeviceVector& devices);
+
 };
 
 };
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index e823efa..ceddb7e 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -31,6 +31,7 @@
         "libutils",
         "audioclient-types-aidl-unstable-cpp",
         "audioflinger-aidl-unstable-cpp",
+        "audiopolicy-aidl-unstable-cpp",
         "capture_state_listener-aidl-cpp",
     ],
 
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index dd128a2..77b5200 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -57,7 +57,7 @@
     request.module = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_module_handle_t_int32_t(module));
     request.config = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_config_t_AudioConfig(*config));
     request.device = VALUE_OR_RETURN_STATUS(legacy2aidl_DeviceDescriptorBase(device));
-    request.flags = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_output_flags_mask(flags));
+    request.flags = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
 
     status_t status = af->openOutput(request, &response);
     if (status == OK) {
@@ -134,7 +134,7 @@
     request.config = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_config_t_AudioConfig(*config));
     request.device = VALUE_OR_RETURN_STATUS(legacy2aidl_AudioDeviceTypeAddress(deviceTypeAddr));
     request.source = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_source_t_AudioSourceType(source));
-    request.flags = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_input_flags_mask(flags));
+    request.flags = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
 
     media::OpenInputResponse response;
     status_t status = af->openInput(request, &response);
@@ -266,6 +266,11 @@
     mAudioPolicyService->onAudioVolumeGroupChanged(group, flags);
 }
 
+void AudioPolicyService::AudioPolicyClient::onRoutingUpdated()
+{
+    mAudioPolicyService->onRoutingUpdated();
+}
+
 audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId(audio_unique_id_use_t use)
 {
     return AudioSystem::newAudioUniqueId(use);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index df8e4c5..10bf707 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -454,8 +454,9 @@
     }
 
     // check calling permissions.
-    // Capturing from FM_TUNER source is controlled by captureAudioOutputAllowed() only as this
-    // does not affect users privacy as does capturing from an actual microphone.
+    // Capturing from FM_TUNER source is controlled by captureTunerAudioInputAllowed() and
+    // captureAudioOutputAllowed() (deprecated) as this does not affect users privacy
+    // as does capturing from an actual microphone.
     if (!(recordingAllowed(opPackageName, pid, uid) || attr->source == AUDIO_SOURCE_FM_TUNER)) {
         ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
                 __func__, uid, pid);
@@ -466,9 +467,14 @@
     if ((inputSource == AUDIO_SOURCE_VOICE_UPLINK ||
         inputSource == AUDIO_SOURCE_VOICE_DOWNLINK ||
         inputSource == AUDIO_SOURCE_VOICE_CALL ||
-        inputSource == AUDIO_SOURCE_ECHO_REFERENCE||
-        inputSource == AUDIO_SOURCE_FM_TUNER) &&
-        !canCaptureOutput) {
+        inputSource == AUDIO_SOURCE_ECHO_REFERENCE)
+        && !canCaptureOutput) {
+        return PERMISSION_DENIED;
+    }
+
+    if (inputSource == AUDIO_SOURCE_FM_TUNER
+        && !captureTunerAudioInputAllowed(pid, uid)
+        && !canCaptureOutput) {
         return PERMISSION_DENIED;
     }
 
@@ -547,7 +553,7 @@
 }
 
 std::string AudioPolicyService::getDeviceTypeStrForPortId(audio_port_handle_t portId) {
-    struct audio_port port = {};
+    struct audio_port_v7 port = {};
     port.id = portId;
     status_t status = mAudioPolicyManager->getAudioPort(&port);
     if (status == NO_ERROR && port.type == AUDIO_PORT_TYPE_DEVICE) {
@@ -573,7 +579,8 @@
     }
 
     // check calling permissions
-    if (!(startRecording(client->opPackageName, client->pid, client->uid)
+    if (!(startRecording(client->opPackageName, client->pid, client->uid,
+            client->attributes.source)
             || client->attributes.source == AUDIO_SOURCE_FM_TUNER)) {
         ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
                 __func__, client->uid, client->pid);
@@ -661,7 +668,8 @@
         client->active = false;
         client->startTimeNs = 0;
         updateUidStates_l();
-        finishRecording(client->opPackageName, client->uid);
+        finishRecording(client->opPackageName, client->uid,
+                        client->attributes.source);
     }
 
     return status;
@@ -687,7 +695,8 @@
     updateUidStates_l();
 
     // finish the recording app op
-    finishRecording(client->opPackageName, client->uid);
+    finishRecording(client->opPackageName, client->uid,
+                    client->attributes.source);
     AutoCallerClear acc;
     return mAudioPolicyManager->stopInput(portId);
 }
@@ -1086,15 +1095,15 @@
     return mAudioPolicyManager->setAllowedCapturePolicy(uid, capturePolicy);
 }
 
-bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info)
+audio_offload_mode_t AudioPolicyService::getOffloadSupport(const audio_offload_info_t& info)
 {
     if (mAudioPolicyManager == NULL) {
         ALOGV("mAudioPolicyManager == NULL");
-        return false;
+        return AUDIO_OFFLOAD_NOT_SUPPORTED;
     }
     Mutex::Autolock _l(mLock);
     AutoCallerClear acc;
-    return mAudioPolicyManager->isOffloadSupported(info);
+    return mAudioPolicyManager->getOffloadSupport(info);
 }
 
 bool AudioPolicyService::isDirectOutputSupported(const audio_config_base_t& config,
@@ -1117,7 +1126,7 @@
 status_t AudioPolicyService::listAudioPorts(audio_port_role_t role,
                                             audio_port_type_t type,
                                             unsigned int *num_ports,
-                                            struct audio_port *ports,
+                                            struct audio_port_v7 *ports,
                                             unsigned int *generation)
 {
     Mutex::Autolock _l(mLock);
@@ -1128,7 +1137,7 @@
     return mAudioPolicyManager->listAudioPorts(role, type, num_ports, ports, generation);
 }
 
-status_t AudioPolicyService::getAudioPort(struct audio_port *port)
+status_t AudioPolicyService::getAudioPort(struct audio_port_v7 *port)
 {
     Mutex::Autolock _l(mLock);
     if (mAudioPolicyManager == NULL) {
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index a6e8989..a898dff 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -35,6 +35,7 @@
 #include <utils/threads.h>
 #include "AudioPolicyService.h"
 #include <hardware_legacy/power.h>
+#include <media/AidlConversion.h>
 #include <media/AudioEffect.h>
 #include <media/AudioParameter.h>
 #include <mediautils/ServiceUtilities.h>
@@ -111,7 +112,7 @@
 
 // A notification client is always registered by AudioSystem when the client process
 // connects to AudioPolicyService.
-void AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client)
+void AudioPolicyService::registerClient(const sp<media::IAudioPolicyServiceClient>& client)
 {
     if (client == 0) {
         ALOGW("%s got NULL client", __FUNCTION__);
@@ -274,6 +275,19 @@
     }
 }
 
+void AudioPolicyService::onRoutingUpdated()
+{
+    mOutputCommandThread->routingChangedCommand();
+}
+
+void AudioPolicyService::doOnRoutingUpdated()
+{
+  Mutex::Autolock _l(mNotificationClientsLock);
+    for (size_t i = 0; i < mNotificationClients.size(); i++) {
+        mNotificationClients.valueAt(i)->onRoutingUpdated();
+    }
+}
+
 status_t AudioPolicyService::clientCreateAudioPatch(const struct audio_patch *patch,
                                                 audio_patch_handle_t *handle,
                                                 int delayMs)
@@ -293,10 +307,11 @@
     return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs);
 }
 
-AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service,
-                                                     const sp<IAudioPolicyServiceClient>& client,
-                                                     uid_t uid,
-                                                     pid_t pid)
+AudioPolicyService::NotificationClient::NotificationClient(
+        const sp<AudioPolicyService>& service,
+        const sp<media::IAudioPolicyServiceClient>& client,
+        uid_t uid,
+        pid_t pid)
     : mService(service), mUid(uid), mPid(pid), mAudioPolicyServiceClient(client),
       mAudioPortCallbacksEnabled(false), mAudioVolumeGroupCallbacksEnabled(false)
 {
@@ -342,7 +357,8 @@
         const String8& regId, int32_t state)
 {
     if (mAudioPolicyServiceClient != 0 && isServiceUid(mUid)) {
-        mAudioPolicyServiceClient->onDynamicPolicyMixStateUpdate(regId, state);
+        mAudioPolicyServiceClient->onDynamicPolicyMixStateUpdate(
+                legacy2aidl_String8_string(regId).value(), state);
     }
 }
 
@@ -357,8 +373,37 @@
                                             audio_source_t source)
 {
     if (mAudioPolicyServiceClient != 0 && isServiceUid(mUid)) {
-        mAudioPolicyServiceClient->onRecordingConfigurationUpdate(event, clientInfo,
-                clientConfig, clientEffects, deviceConfig, effects, patchHandle, source);
+        status_t status = [&]() -> status_t {
+            int32_t eventAidl = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(event));
+            media::RecordClientInfo clientInfoAidl = VALUE_OR_RETURN_STATUS(
+                    legacy2aidl_record_client_info_t_RecordClientInfo(*clientInfo));
+            media::AudioConfigBase clientConfigAidl = VALUE_OR_RETURN_STATUS(
+                    legacy2aidl_audio_config_base_t_AudioConfigBase(*clientConfig));
+            std::vector<media::EffectDescriptor> clientEffectsAidl = VALUE_OR_RETURN_STATUS(
+                    convertContainer<std::vector<media::EffectDescriptor>>(
+                            clientEffects,
+                            legacy2aidl_effect_descriptor_t_EffectDescriptor));
+            media::AudioConfigBase deviceConfigAidl = VALUE_OR_RETURN_STATUS(
+                    legacy2aidl_audio_config_base_t_AudioConfigBase(*deviceConfig));
+            std::vector<media::EffectDescriptor> effectsAidl = VALUE_OR_RETURN_STATUS(
+                    convertContainer<std::vector<media::EffectDescriptor>>(
+                            effects,
+                            legacy2aidl_effect_descriptor_t_EffectDescriptor));
+            int32_t patchHandleAidl = VALUE_OR_RETURN_STATUS(
+                    legacy2aidl_audio_patch_handle_t_int32_t(patchHandle));
+            media::AudioSourceType sourceAidl = VALUE_OR_RETURN_STATUS(
+                    legacy2aidl_audio_source_t_AudioSourceType(source));
+            return aidl_utils::statusTFromBinderStatus(
+                    mAudioPolicyServiceClient->onRecordingConfigurationUpdate(eventAidl,
+                                                                              clientInfoAidl,
+                                                                              clientConfigAidl,
+                                                                              clientEffectsAidl,
+                                                                              deviceConfigAidl,
+                                                                              effectsAidl,
+                                                                              patchHandleAidl,
+                                                                              sourceAidl));
+        }();
+        ALOGW_IF(status != OK, "onRecordingConfigurationUpdate() failed: %d", status);
     }
 }
 
@@ -372,6 +417,13 @@
     mAudioVolumeGroupCallbacksEnabled = enabled;
 }
 
+void AudioPolicyService::NotificationClient::onRoutingUpdated()
+{
+    if (mAudioPolicyServiceClient != 0 && isServiceUid(mUid)) {
+        mAudioPolicyServiceClient->onRoutingUpdated();
+    }
+}
+
 void AudioPolicyService::binderDied(const wp<IBinder>& who) {
     ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
             IPCThreadState::self()->getCallingPid());
@@ -453,7 +505,7 @@
     sp<AudioRecordClient> topActive;
     sp<AudioRecordClient> latestActive;
     sp<AudioRecordClient> topSensitiveActive;
-    sp<AudioRecordClient> latestSensitiveActive;
+    sp<AudioRecordClient> latestSensitiveActiveOrComm;
 
     nsecs_t topStartNs = 0;
     nsecs_t latestStartNs = 0;
@@ -467,6 +519,7 @@
     bool rttCallActive = (isInCall || isInCommunication)
             && mUidPolicy->isRttEnabled();
     bool onlyHotwordActive = true;
+    bool isPhoneStateOwnerActive = false;
 
     // if Sensor Privacy is enabled then all recordings should be silenced.
     if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -494,6 +547,7 @@
             bool isAssistant = mUidPolicy->isAssistantUid(current->uid);
             bool isPrivacySensitive =
                     (current->attributes.flags & AUDIO_FLAG_CAPTURE_PRIVATE) != 0;
+
             if (appState == APP_STATE_TOP) {
                 if (isPrivacySensitive) {
                     if (current->startTimeNs > topSensitiveStartNs) {
@@ -515,9 +569,15 @@
             if (!(current->attributes.source == AUDIO_SOURCE_HOTWORD
                     || ((isA11yOnTop || rttCallActive) && isAssistant))) {
                 if (isPrivacySensitive) {
-                    if (current->startTimeNs > latestSensitiveStartNs) {
-                        latestSensitiveActive = current;
-                        latestSensitiveStartNs = current->startTimeNs;
+                    // if audio mode is IN_COMMUNICATION, make sure the audio mode owner
+                    // is marked latest sensitive active even if another app qualifies.
+                    if (current->startTimeNs > latestSensitiveStartNs
+                            || (isInCommunication && current->uid == mPhoneStateOwnerUid)) {
+                        if (!isInCommunication || latestSensitiveActiveOrComm == nullptr
+                                || latestSensitiveActiveOrComm->uid != mPhoneStateOwnerUid) {
+                            latestSensitiveActiveOrComm = current;
+                            latestSensitiveStartNs = current->startTimeNs;
+                        }
                     }
                     isSensitiveActive = true;
                 } else {
@@ -531,6 +591,9 @@
         if (current->attributes.source != AUDIO_SOURCE_HOTWORD) {
             onlyHotwordActive = false;
         }
+        if (current->uid == mPhoneStateOwnerUid) {
+            isPhoneStateOwnerActive = true;
+        }
     }
 
     // if no active client with UI on Top, consider latest active as top
@@ -539,8 +602,15 @@
         topStartNs = latestStartNs;
     }
     if (topSensitiveActive == nullptr) {
-        topSensitiveActive = latestSensitiveActive;
+        topSensitiveActive = latestSensitiveActiveOrComm;
         topSensitiveStartNs = latestSensitiveStartNs;
+    } else if (latestSensitiveActiveOrComm != nullptr) {
+        // if audio mode is IN_COMMUNICATION, favor audio mode owner over an app with
+        // foreground UI in case both are capturing with privacy sensitive flag.
+        if (isInCommunication && latestSensitiveActiveOrComm->uid == mPhoneStateOwnerUid) {
+            topSensitiveActive = latestSensitiveActiveOrComm;
+            topSensitiveStartNs = latestSensitiveStartNs;
+        }
     }
 
     // If both privacy sensitive and regular capture are active:
@@ -566,13 +636,11 @@
 
         auto canCaptureIfInCallOrCommunication = [&](const auto &recordClient) REQUIRES(mLock) {
             bool canCaptureCall = recordClient->canCaptureOutput;
-            return !(isInCall && !canCaptureCall);
-//TODO(b/160260850): restore restriction to mode owner once fix for misbehaving apps is merged
-//            bool canCaptureCommunication = recordClient->canCaptureOutput
-//                || recordClient->uid == mPhoneStateOwnerUid
-//                || isServiceUid(mPhoneStateOwnerUid);
-//            return !(isInCall && !canCaptureCall)
-//                && !(isInCommunication && !canCaptureCommunication);
+            bool canCaptureCommunication = recordClient->canCaptureOutput
+                || !isPhoneStateOwnerActive
+                || recordClient->uid == mPhoneStateOwnerUid;
+            return !(isInCall && !canCaptureCall)
+                && !(isInCommunication && !canCaptureCommunication);
         };
 
         // By default allow capture if:
@@ -1366,6 +1434,16 @@
                     svc->doOnNewAudioModulesAvailable();
                     mLock.lock();
                     } break;
+                case ROUTING_UPDATED: {
+                    ALOGV("AudioCommandThread() processing routing update");
+                    svc = mService.promote();
+                    if (svc == 0) {
+                        break;
+                    }
+                    mLock.unlock();
+                    svc->doOnRoutingUpdated();
+                    mLock.lock();
+                    } break;
 
                 default:
                     ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
@@ -1662,6 +1740,14 @@
     sendCommand(command);
 }
 
+void AudioPolicyService::AudioCommandThread::routingChangedCommand()
+{
+    sp<AudioCommand>command = new AudioCommand();
+    command->mCommand = ROUTING_UPDATED;
+    ALOGV("AudioCommandThread() adding routing update");
+    sendCommand(command);
+}
+
 status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
 {
     {
@@ -1825,6 +1911,10 @@
 
         } break;
 
+        case ROUTING_UPDATED: {
+
+        } break;
+
         default:
             break;
         }
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 70a0e3a..db84d54 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -192,16 +192,16 @@
     virtual status_t setVoiceVolume(float volume, int delayMs = 0);
     status_t setSupportedSystemUsages(const std::vector<audio_usage_t>& systemUsages);
     status_t setAllowedCapturePolicy(uint_t uid, audio_flags_mask_t capturePolicy) override;
-    virtual bool isOffloadSupported(const audio_offload_info_t &config);
+    virtual audio_offload_mode_t getOffloadSupport(const audio_offload_info_t &config);
     virtual bool isDirectOutputSupported(const audio_config_base_t& config,
                                          const audio_attributes_t& attributes);
 
     virtual status_t listAudioPorts(audio_port_role_t role,
                                     audio_port_type_t type,
                                     unsigned int *num_ports,
-                                    struct audio_port *ports,
+                                    struct audio_port_v7 *ports,
                                     unsigned int *generation);
-    virtual status_t getAudioPort(struct audio_port *port);
+    virtual status_t getAudioPort(struct audio_port_v7 *port);
     virtual status_t createAudioPatch(const struct audio_patch *patch,
                                        audio_patch_handle_t *handle);
     virtual status_t releaseAudioPatch(audio_patch_handle_t handle);
@@ -210,7 +210,7 @@
                                       unsigned int *generation);
     virtual status_t setAudioPortConfig(const struct audio_port_config *config);
 
-    virtual void registerClient(const sp<IAudioPolicyServiceClient>& client);
+    virtual void registerClient(const sp<media::IAudioPolicyServiceClient>& client);
 
     virtual void setAudioPortCallbacksEnabled(bool enabled);
 
@@ -345,6 +345,10 @@
 
             void onAudioVolumeGroupChanged(volume_group_t group, int flags);
             void doOnAudioVolumeGroupChanged(volume_group_t group, int flags);
+
+            void onRoutingUpdated();
+            void doOnRoutingUpdated();
+
             void setEffectSuspended(int effectId,
                                     audio_session_t sessionId,
                                     bool suspended);
@@ -497,6 +501,7 @@
             RECORDING_CONFIGURATION_UPDATE,
             SET_EFFECT_SUSPENDED,
             AUDIO_MODULES_UPDATE,
+            ROUTING_UPDATED,
         };
 
         AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -543,6 +548,7 @@
                                                           audio_session_t sessionId,
                                                           bool suspended);
                     void        audioModulesUpdateCommand();
+                    void        routingChangedCommand();
                     void        insertCommand_l(AudioCommand *command, int delayMs = 0);
     private:
         class AudioCommandData;
@@ -761,6 +767,8 @@
 
         virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags);
 
+        virtual void onRoutingUpdated();
+
         virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
 
         void setSoundTriggerCaptureState(bool active) override;
@@ -775,7 +783,7 @@
     class NotificationClient : public IBinder::DeathRecipient {
     public:
                             NotificationClient(const sp<AudioPolicyService>& service,
-                                                const sp<IAudioPolicyServiceClient>& client,
+                                                const sp<media::IAudioPolicyServiceClient>& client,
                                                 uid_t uid, pid_t pid);
         virtual             ~NotificationClient();
 
@@ -793,6 +801,7 @@
                                                     std::vector<effect_descriptor_t> effects,
                                                     audio_patch_handle_t patchHandle,
                                                     audio_source_t source);
+                            void      onRoutingUpdated();
                             void      setAudioPortCallbacksEnabled(bool enabled);
                             void setAudioVolumeGroupCallbacksEnabled(bool enabled);
 
@@ -807,12 +816,12 @@
                             NotificationClient(const NotificationClient&);
                             NotificationClient& operator = (const NotificationClient&);
 
-        const wp<AudioPolicyService>        mService;
-        const uid_t                         mUid;
-        const pid_t                         mPid;
-        const sp<IAudioPolicyServiceClient> mAudioPolicyServiceClient;
-              bool                          mAudioPortCallbacksEnabled;
-              bool                          mAudioVolumeGroupCallbacksEnabled;
+        const wp<AudioPolicyService>               mService;
+        const uid_t                                mUid;
+        const pid_t                                mPid;
+        const sp<media::IAudioPolicyServiceClient> mAudioPolicyServiceClient;
+              bool                                 mAudioPortCallbacksEnabled;
+              bool                                 mAudioVolumeGroupCallbacksEnabled;
     };
 
     class AudioClient : public virtual RefBase {
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index bdddf06..e2d7d17 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -121,6 +121,19 @@
 
     size_t getAudioPortListUpdateCount() const { return mAudioPortListUpdateCount; }
 
+    virtual void addSupportedFormat(audio_format_t /* format */) {}
+
+    void onRoutingUpdated() override {
+        mRoutingUpdatedUpdateCount++;
+    }
+
+    void resetRoutingUpdatedCounter() {
+        mRoutingUpdatedUpdateCount = 0;
+    }
+
+    size_t getRoutingUpdatedCounter() const {
+        return mRoutingUpdatedUpdateCount; }
+
 private:
     audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
     audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
@@ -128,6 +141,7 @@
     std::map<audio_patch_handle_t, struct audio_patch> mActivePatches;
     std::set<std::string> mAllowedModuleNames;
     size_t mAudioPortListUpdateCount = 0;
+    size_t mRoutingUpdatedUpdateCount = 0;
 };
 
 } // namespace android
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClientForHdmi.h b/services/audiopolicy/tests/AudioPolicyManagerTestClientForHdmi.h
new file mode 100644
index 0000000..a5ad9b1
--- /dev/null
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClientForHdmi.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#include <map>
+#include <set>
+
+#include <system/audio.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include "AudioPolicyTestClient.h"
+
+namespace android {
+
+class AudioPolicyManagerTestClientForHdmi : public AudioPolicyManagerTestClient {
+public:
+    String8 getParameters(audio_io_handle_t /* ioHandle */, const String8&  /* keys*/ ) override {
+        return mAudioParameters.toString();
+    }
+
+    void addSupportedFormat(audio_format_t format) override {
+        mAudioParameters.add(
+                String8(AudioParameter::keyStreamSupportedFormats),
+                String8(audio_format_to_string(format)));
+        mAudioParameters.addInt(String8(AudioParameter::keyStreamSupportedSamplingRates), 48000);
+        mAudioParameters.add(String8(AudioParameter::keyStreamSupportedChannels), String8(""));
+    }
+
+private:
+    AudioParameter mAudioParameters;
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index fa6b90f..d289e15 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -83,6 +83,7 @@
                                         std::vector<effect_descriptor_t> effects __unused,
                                         audio_patch_handle_t patchHandle __unused,
                                         audio_source_t source __unused) override { }
+    void onRoutingUpdated() override { }
     void setEffectSuspended(int effectId __unused,
                             audio_session_t sessionId __unused,
                             bool suspended __unused) {}
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index 8bab020..be860e5 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -29,6 +29,7 @@
     using AudioPolicyManager::getOutputs;
     using AudioPolicyManager::getAvailableOutputDevices;
     using AudioPolicyManager::getAvailableInputDevices;
+    using AudioPolicyManager::setSurroundFormatEnabled;
     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 9a62e72..ca2f0c6 100644
--- a/services/audiopolicy/tests/audio_health_tests.cpp
+++ b/services/audiopolicy/tests/audio_health_tests.cpp
@@ -34,7 +34,7 @@
     unsigned int numPorts;
     unsigned int generation1;
     unsigned int generation;
-    struct audio_port *audioPorts = NULL;
+    struct audio_port_v7 *audioPorts = nullptr;
     int attempts = 10;
     do {
         if (attempts-- < 0) {
@@ -43,13 +43,14 @@
         }
         numPorts = 0;
         ASSERT_EQ(NO_ERROR, AudioSystem::listAudioPorts(
-                AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_DEVICE, &numPorts, NULL, &generation1));
+                AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_DEVICE, &numPorts, nullptr, &generation1));
         if (numPorts == 0) {
             free(audioPorts);
             GTEST_FAIL() << "Number of audio ports should not be zero";
         }
 
-        audioPorts = (struct audio_port *)realloc(audioPorts, numPorts * sizeof(struct audio_port));
+        audioPorts = (struct audio_port_v7 *)realloc(
+                audioPorts, numPorts * sizeof(struct audio_port_v7));
         status_t status = AudioSystem::listAudioPorts(
                 AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_DEVICE, &numPorts, audioPorts, &generation);
         if (status != NO_ERROR) {
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 7972dbf..3032589 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -33,6 +33,7 @@
 
 #include "AudioPolicyInterface.h"
 #include "AudioPolicyManagerTestClient.h"
+#include "AudioPolicyManagerTestClientForHdmi.h"
 #include "AudioPolicyTestClient.h"
 #include "AudioPolicyTestManager.h"
 
@@ -137,15 +138,16 @@
     // Tries to find a device port. If 'foundPort' isn't nullptr,
     // will generate a failure if the port hasn't been found.
     bool findDevicePort(audio_port_role_t role, audio_devices_t deviceType,
-            const std::string &address, audio_port *foundPort);
+            const std::string &address, audio_port_v7 *foundPort);
     static audio_port_handle_t getDeviceIdFromPatch(const struct audio_patch* patch);
+    virtual AudioPolicyManagerTestClient* getClient() { return new AudioPolicyManagerTestClient; }
 
     std::unique_ptr<AudioPolicyManagerTestClient> mClient;
     std::unique_ptr<AudioPolicyTestManager> mManager;
 };
 
 void AudioPolicyManagerTest::SetUp() {
-    mClient.reset(new AudioPolicyManagerTestClient);
+    mClient.reset(getClient());
     mManager.reset(new AudioPolicyTestManager(mClient.get()));
     SetUpManagerConfig();  // Subclasses may want to customize the config.
     ASSERT_EQ(NO_ERROR, mManager->initialize());
@@ -244,7 +246,7 @@
 }
 
 bool AudioPolicyManagerTest::findDevicePort(audio_port_role_t role,
-        audio_devices_t deviceType, const std::string &address, audio_port *foundPort) {
+        audio_devices_t deviceType, const std::string &address, audio_port_v7 *foundPort) {
     uint32_t numPorts = 0;
     uint32_t generation1;
     status_t ret;
@@ -254,7 +256,7 @@
     if (HasFailure()) return false;
 
     uint32_t generation2;
-    struct audio_port ports[numPorts];
+    struct audio_port_v7 ports[numPorts];
     ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, ports, &generation2);
     EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
     EXPECT_EQ(generation1, generation2) << "Generations changed during ports retrieval";
@@ -354,6 +356,7 @@
 
     sp<DeviceDescriptor> mMsdOutputDevice;
     sp<DeviceDescriptor> mMsdInputDevice;
+    sp<DeviceDescriptor> mDefaultOutputDevice;
 };
 
 void AudioPolicyManagerTestMsd::SetUpManagerConfig() {
@@ -408,17 +411,21 @@
     primaryEncodedOutputProfile->addSupportedDevice(config.getDefaultOutputDevice());
     config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
             addOutputProfile(primaryEncodedOutputProfile);
+
+    mDefaultOutputDevice = config.getDefaultOutputDevice();
 }
 
 void AudioPolicyManagerTestMsd::TearDown() {
     mMsdOutputDevice.clear();
     mMsdInputDevice.clear();
+    mDefaultOutputDevice.clear();
     AudioPolicyManagerTest::TearDown();
 }
 
 TEST_F(AudioPolicyManagerTestMsd, InitSuccess) {
     ASSERT_TRUE(mMsdOutputDevice);
     ASSERT_TRUE(mMsdInputDevice);
+    ASSERT_TRUE(mDefaultOutputDevice);
 }
 
 TEST_F(AudioPolicyManagerTestMsd, Dump) {
@@ -437,7 +444,7 @@
     audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
     getOutputForAttr(&selectedDeviceId,
             AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
-    ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+    ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
     ASSERT_EQ(1, patchCount.deltaFromSnapshot());
 }
 
@@ -446,7 +453,7 @@
     audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
     getOutputForAttr(&selectedDeviceId,
             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
-    ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+    ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
     ASSERT_EQ(1, patchCount.deltaFromSnapshot());
 }
 
@@ -455,11 +462,11 @@
     audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
     getOutputForAttr(&selectedDeviceId,
             AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
-    ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+    ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
     ASSERT_EQ(1, patchCount.deltaFromSnapshot());
     getOutputForAttr(&selectedDeviceId,
             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
-    ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+    ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
     ASSERT_EQ(1, patchCount.deltaFromSnapshot());
 }
 
@@ -481,7 +488,7 @@
         getOutputForAttr(&selectedDeviceId,
                 AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
                 nullptr /*output*/, &portId);
-        ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+        ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
         ASSERT_EQ(1, patchCount.deltaFromSnapshot());
         mManager->releaseOutput(portId);
         ASSERT_EQ(1, patchCount.deltaFromSnapshot());
@@ -503,7 +510,7 @@
         audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
         getOutputForAttr(&selectedDeviceId,
                 AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
-        ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+        ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
         ASSERT_EQ(0, patchCount.deltaFromSnapshot());
     }
 }
@@ -668,6 +675,165 @@
     ASSERT_EQ(INVALID_OPERATION, ret);
 }
 
+class AudioPolicyManagerTestForHdmi
+        : public AudioPolicyManagerTestWithConfigurationFile {
+protected:
+    void SetUp() override;
+    std::string getConfigFile() override { return sTvConfig; }
+    std::map<audio_format_t, bool> getSurroundFormatsHelper(bool reported);
+    std::unordered_set<audio_format_t> getFormatsFromPorts();
+    AudioPolicyManagerTestClient* getClient() override {
+        return new AudioPolicyManagerTestClientForHdmi;
+    }
+    void TearDown() override;
+
+    static const std::string sTvConfig;
+
+};
+
+const std::string AudioPolicyManagerTestForHdmi::sTvConfig =
+        AudioPolicyManagerTestForHdmi::sExecutableDir +
+        "test_settop_box_surround_configuration.xml";
+
+void AudioPolicyManagerTestForHdmi::SetUp() {
+    AudioPolicyManagerTest::SetUp();
+    mClient->addSupportedFormat(AUDIO_FORMAT_E_AC3);
+    mManager->setDeviceConnectionState(
+            AUDIO_DEVICE_OUT_HDMI, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+            "" /*address*/, "" /*name*/, AUDIO_FORMAT_DEFAULT);
+}
+
+void AudioPolicyManagerTestForHdmi::TearDown() {
+    mManager->setDeviceConnectionState(
+            AUDIO_DEVICE_OUT_HDMI, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+            "" /*address*/, "" /*name*/, AUDIO_FORMAT_DEFAULT);
+    AudioPolicyManagerTest::TearDown();
+}
+
+std::map<audio_format_t, bool>
+        AudioPolicyManagerTestForHdmi::getSurroundFormatsHelper(bool reported) {
+    unsigned int numSurroundFormats = 0;
+    std::map<audio_format_t, bool> surroundFormatsMap;
+    status_t ret = mManager->getSurroundFormats(
+            &numSurroundFormats, nullptr /* surroundFormats */,
+            nullptr /* surroundFormatsEnabled */, reported);
+    EXPECT_EQ(NO_ERROR, ret);
+    if (ret != NO_ERROR) {
+        return surroundFormatsMap;
+    }
+    audio_format_t surroundFormats[numSurroundFormats];
+    memset(surroundFormats, 0, sizeof(audio_format_t) * numSurroundFormats);
+    bool surroundFormatsEnabled[numSurroundFormats];
+    memset(surroundFormatsEnabled, 0, sizeof(bool) * numSurroundFormats);
+    ret = mManager->getSurroundFormats(
+            &numSurroundFormats, surroundFormats, surroundFormatsEnabled, reported);
+    EXPECT_EQ(NO_ERROR, ret);
+    if (ret != NO_ERROR) {
+        return surroundFormatsMap;
+    }
+    for (int i = 0; i< numSurroundFormats; i++) {
+        surroundFormatsMap[surroundFormats[i]] = surroundFormatsEnabled[i];
+    }
+    return surroundFormatsMap;
+}
+
+std::unordered_set<audio_format_t>
+        AudioPolicyManagerTestForHdmi::getFormatsFromPorts() {
+    uint32_t numPorts = 0;
+    uint32_t generation1;
+    status_t ret;
+    std::unordered_set<audio_format_t> formats;
+    ret = mManager->listAudioPorts(
+            AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE, &numPorts, nullptr, &generation1);
+    EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
+    if (ret != NO_ERROR) {
+        return formats;
+    }
+    struct audio_port_v7 ports[numPorts];
+    ret = mManager->listAudioPorts(
+            AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE, &numPorts, ports, &generation1);
+    EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
+    if (ret != NO_ERROR) {
+        return formats;
+    }
+    for (const auto &port : ports) {
+        for (size_t i = 0; i < port.num_audio_profiles; ++i) {
+            formats.insert(port.audio_profiles[i].format);
+        }
+    }
+    return formats;
+}
+
+TEST_F(AudioPolicyManagerTestForHdmi, GetSurroundFormatsReturnsSupportedFormats) {
+    mManager->setForceUse(
+            AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND, AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS);
+    auto surroundFormats = getSurroundFormatsHelper(false /*reported*/);
+    ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+}
+
+TEST_F(AudioPolicyManagerTestForHdmi,
+        GetSurroundFormatsReturnsManipulatedFormats) {
+    mManager->setForceUse(
+            AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND, AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL);
+
+    status_t ret =
+            mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, false /*enabled*/);
+    ASSERT_EQ(NO_ERROR, ret);
+    auto surroundFormats = getSurroundFormatsHelper(false /*reported*/);
+    ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+    ASSERT_FALSE(surroundFormats[AUDIO_FORMAT_E_AC3]);
+
+    ret = mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, true /*enabled*/);
+    ASSERT_EQ(NO_ERROR, ret);
+    surroundFormats = getSurroundFormatsHelper(false /*reported*/);
+    ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+    ASSERT_TRUE(surroundFormats[AUDIO_FORMAT_E_AC3]);
+
+    ret = mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, false /*enabled*/);
+    ASSERT_EQ(NO_ERROR, ret);
+    surroundFormats = getSurroundFormatsHelper(false /*reported*/);
+    ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+    ASSERT_FALSE(surroundFormats[AUDIO_FORMAT_E_AC3]);
+}
+
+TEST_F(AudioPolicyManagerTestForHdmi,
+        ListAudioPortsReturnManipulatedHdmiFormats) {
+    mManager->setForceUse(
+            AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND, AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL);
+
+    ASSERT_EQ(NO_ERROR, mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, false /*enabled*/));
+    auto formats = getFormatsFromPorts();
+    ASSERT_EQ(0, formats.count(AUDIO_FORMAT_E_AC3));
+
+    ASSERT_EQ(NO_ERROR, mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, true /*enabled*/));
+    formats = getFormatsFromPorts();
+    ASSERT_EQ(1, formats.count(AUDIO_FORMAT_E_AC3));
+}
+
+TEST_F(AudioPolicyManagerTestForHdmi,
+        GetReportedSurroundFormatsReturnsHdmiReportedFormats) {
+    mManager->setForceUse(
+            AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND, AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS);
+    auto surroundFormats = getSurroundFormatsHelper(true /*reported*/);
+    ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+}
+
+TEST_F(AudioPolicyManagerTestForHdmi,
+        GetReportedSurroundFormatsReturnsNonManipulatedHdmiReportedFormats) {
+    mManager->setForceUse(
+            AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND, AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL);
+
+    status_t ret = mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, false /*enabled*/);
+    ASSERT_EQ(NO_ERROR, ret);
+    auto surroundFormats = getSurroundFormatsHelper(true /*reported*/);
+    ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+
+    ret = mManager->setSurroundFormatEnabled(AUDIO_FORMAT_E_AC3, true /*enabled*/);
+    ASSERT_EQ(NO_ERROR, ret);
+    surroundFormats = getSurroundFormatsHelper(true /*reported*/);
+    ASSERT_EQ(1, surroundFormats.count(AUDIO_FORMAT_E_AC3));
+}
+
 class AudioPolicyManagerTestDPNoRemoteSubmixModule : public AudioPolicyManagerTestDynamicPolicy {
 protected:
     std::string getConfigFile() override { return sPrimaryOnlyConfig; }
@@ -714,7 +880,7 @@
             {AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT, RULE_MATCH_ATTRIBUTE_USAGE}
     };
 
-    struct audio_port mInjectionPort;
+    struct audio_port_v7 mInjectionPort;
     audio_port_handle_t mPortId = AUDIO_PORT_HANDLE_NONE;
 };
 
@@ -731,7 +897,7 @@
             AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig, mUsageRules);
     ASSERT_EQ(NO_ERROR, ret);
 
-    struct audio_port extractionPort;
+    struct audio_port_v7 extractionPort;
     ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                     mMixAddress, &extractionPort));
 
@@ -900,7 +1066,7 @@
         {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_VOICE_COMMUNICATION, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}
     };
 
-    struct audio_port mExtractionPort;
+    struct audio_port_v7 mExtractionPort;
     audio_port_handle_t mPortId = AUDIO_PORT_HANDLE_NONE;
 };
 
@@ -917,7 +1083,7 @@
             AUDIO_DEVICE_IN_REMOTE_SUBMIX, mMixAddress, audioConfig, mSourceRules);
     ASSERT_EQ(NO_ERROR, ret);
 
-    struct audio_port injectionPort;
+    struct audio_port_v7 injectionPort;
     ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
                     mMixAddress, &injectionPort));
 
@@ -1023,6 +1189,34 @@
     dumpToLog();
 }
 
+TEST_F(AudioPolicyManagerTestDeviceConnection, RoutingUpdate) {
+    mClient->resetRoutingUpdatedCounter();
+    // Connecting a valid output device with valid parameters should trigger a routing update
+    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+            AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+            "a", "b", AUDIO_FORMAT_DEFAULT));
+    ASSERT_EQ(1, mClient->getRoutingUpdatedCounter());
+
+    // Disconnecting a connected device should succeed and trigger a routing update
+    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+            AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+            "a", "b", AUDIO_FORMAT_DEFAULT));
+    ASSERT_EQ(2, mClient->getRoutingUpdatedCounter());
+
+    // Disconnecting a disconnected device should fail and not trigger a routing update
+    ASSERT_EQ(INVALID_OPERATION, mManager->setDeviceConnectionState(
+            AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+            "a", "b",  AUDIO_FORMAT_DEFAULT));
+    ASSERT_EQ(2, mClient->getRoutingUpdatedCounter());
+
+    // Changing force use should trigger an update
+    auto config = mManager->getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA);
+    auto newConfig = config == AUDIO_POLICY_FORCE_BT_A2DP ?
+            AUDIO_POLICY_FORCE_NONE : AUDIO_POLICY_FORCE_BT_A2DP;
+    mManager->setForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA, newConfig);
+    ASSERT_EQ(3, mClient->getRoutingUpdatedCounter());
+}
+
 TEST_P(AudioPolicyManagerTestDeviceConnection, SetDeviceConnectionState) {
     const audio_devices_t type = std::get<0>(GetParam());
     const std::string name = std::get<1>(GetParam());
@@ -1068,7 +1262,7 @@
             type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
             address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
 
-    audio_port devicePort;
+    audio_port_v7 devicePort;
     const audio_port_role_t role = audio_is_output_device(type)
             ? AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
     ASSERT_TRUE(findDevicePort(role, type, address, &devicePort));
@@ -1129,7 +1323,7 @@
             flags, &output, &portId);
     sp<SwAudioOutputDescriptor> outDesc = mManager->getOutputs().valueFor(output);
     ASSERT_NE(nullptr, outDesc.get());
-    audio_port port = {};
+    audio_port_v7 port = {};
     outDesc->toAudioPort(&port);
     mManager->releaseOutput(portId);
     ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
@@ -1211,7 +1405,7 @@
             findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", nullptr));
     mClient->swapAllowedModuleNames({"primary", "r_submix"});
     mManager->onNewAudioModulesAvailable();
-    struct audio_port port;
+    struct audio_port_v7 port;
     ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", &port));
 }
 
diff --git a/services/audiopolicy/tests/resources/Android.bp b/services/audiopolicy/tests/resources/Android.bp
index 4f50dad..2f6e925 100644
--- a/services/audiopolicy/tests/resources/Android.bp
+++ b/services/audiopolicy/tests/resources/Android.bp
@@ -5,5 +5,6 @@
         "test_audio_policy_primary_only_configuration.xml",
         "test_invalid_audio_policy_configuration.xml",
         "test_tv_apm_configuration.xml",
+        "test_settop_box_surround_configuration.xml",
     ],
 }
diff --git a/services/audiopolicy/tests/resources/test_settop_box_surround_configuration.xml b/services/audiopolicy/tests/resources/test_settop_box_surround_configuration.xml
new file mode 100644
index 0000000..6f7375e
--- /dev/null
+++ b/services/audiopolicy/tests/resources/test_settop_box_surround_configuration.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ 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.
+  -->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <globalConfiguration speaker_drc_enabled="false"/>
+    <modules>
+        <module name="primary" halVersion="2.0">
+            <attachedDevices>
+                <item>Stub</item>
+            </attachedDevices>
+            <defaultOutputDevice>Stub</defaultOutputDevice>
+            <mixPorts>
+                <mixPort name="primary pcm" role="source"
+                         flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="multichannel output" role="source"
+                         flags="AUDIO_OUTPUT_FLAG_DIRECT">
+                    <profile name="" />
+                </mixPort>
+            </mixPorts>
+            <devicePorts>
+                <devicePort tagName="Stub" type="AUDIO_DEVICE_OUT_STUB" role="sink" />
+                <devicePort tagName="HDMI" type="AUDIO_DEVICE_OUT_HDMI" role="sink" />
+            </devicePorts>
+            <routes>
+                <route type="mix" sink="Stub" sources="primary pcm"/>
+                <route type="mix" sink="HDMI" sources="primary pcm,multichannel output"/>
+            </routes>
+        </module>
+    </modules>
+</audioPolicyConfiguration>
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 8400dae..b4c0da3 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -21,6 +21,7 @@
 #include <algorithm>
 #include <climits>
 #include <stdio.h>
+#include <cstdlib>
 #include <cstring>
 #include <ctime>
 #include <string>
@@ -1694,6 +1695,8 @@
             // Otherwise, add client to active clients list
             finishConnectLocked(client, partial);
         }
+
+        client->setImageDumpMask(mImageDumpMask);
     } // lock is destroyed, allow further connect calls
 
     // Important: release the mutex here so the client can call back into the service from its
@@ -3880,6 +3883,10 @@
         return handleSetRotateAndCrop(args);
     } else if (args.size() >= 1 && args[0] == String16("get-rotate-and-crop")) {
         return handleGetRotateAndCrop(out);
+    } else if (args.size() >= 2 && args[0] == String16("set-image-dump-mask")) {
+        return handleSetImageDumpMask(args);
+    } else if (args.size() >= 1 && args[0] == String16("get-image-dump-mask")) {
+        return handleGetImageDumpMask(out);
     } else if (args.size() == 1 && args[0] == String16("help")) {
         printHelp(out);
         return NO_ERROR;
@@ -3979,6 +3986,30 @@
     return dprintf(out, "rotateAndCrop override: %d\n", mOverrideRotateAndCropMode);
 }
 
+status_t CameraService::handleSetImageDumpMask(const Vector<String16>& args) {
+    char *endPtr;
+    errno = 0;
+    String8 maskString8 = String8(args[1]);
+    long maskValue = strtol(maskString8.c_str(), &endPtr, 10);
+
+    if (errno != 0) return BAD_VALUE;
+    if (endPtr != maskString8.c_str() + maskString8.size()) return BAD_VALUE;
+    if (maskValue < 0 || maskValue > 1) return BAD_VALUE;
+
+    Mutex::Autolock lock(mServiceLock);
+
+    mImageDumpMask = maskValue;
+
+    return OK;
+}
+
+status_t CameraService::handleGetImageDumpMask(int out) {
+    Mutex::Autolock lock(mServiceLock);
+
+    return dprintf(out, "Image dump mask: %d\n", mImageDumpMask);
+}
+
+
 status_t CameraService::printHelp(int out) {
     return dprintf(out, "Camera service commands:\n"
         "  get-uid-state <PACKAGE> [--user USER_ID] gets the uid state\n"
@@ -3987,6 +4018,9 @@
         "  set-rotate-and-crop <ROTATION> overrides the rotate-and-crop value for AUTO backcompat\n"
         "      Valid values 0=0 deg, 1=90 deg, 2=180 deg, 3=270 deg, 4=No override\n"
         "  get-rotate-and-crop returns the current override rotate-and-crop value\n"
+        "  set-image-dump-mask <MASK> specifies the formats to be saved to disk\n"
+        "      Valid values 0=OFF, 1=ON for JPEG\n"
+        "  get-image-dump-mask returns the current image-dump-mask value\n"
         "  help print this message\n");
 }
 
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d26c62d..43b03e6 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -398,6 +398,8 @@
         // Check what API level is used for this client. This is used to determine which
         // superclass this can be cast to.
         virtual bool canCastToApiClient(apiLevel level) const;
+
+        void setImageDumpMask(int /*mask*/) { }
     protected:
         // Initialized in constructor
 
@@ -1036,6 +1038,12 @@
     // Get the rotate-and-crop AUTO override behavior
     status_t handleGetRotateAndCrop(int out);
 
+    // Set the mask for image dump to disk
+    status_t handleSetImageDumpMask(const Vector<String16>& args);
+
+    // Get the mask for image dump to disk
+    status_t handleGetImageDumpMask(int out);
+
     // Prints the shell command help
     status_t printHelp(int out);
 
@@ -1077,6 +1085,9 @@
 
     // Current override rotate-and-crop mode
     uint8_t mOverrideRotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_AUTO;
+
+    // Current image dump mask
+    uint8_t mImageDumpMask = 0;
 };
 
 } // namespace android
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 662b58f..2494302 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -76,7 +76,8 @@
 bool Camera2Client::isZslEnabledInStillTemplate() {
     bool zslEnabled = false;
     CameraMetadata stillTemplate;
-    status_t res = mDevice->createDefaultRequest(CAMERA2_TEMPLATE_STILL_CAPTURE, &stillTemplate);
+    status_t res = mDevice->createDefaultRequest(
+            camera_request_template_t::CAMERA_TEMPLATE_STILL_CAPTURE, &stillTemplate);
     if (res == OK) {
         camera_metadata_entry_t enableZsl = stillTemplate.find(ANDROID_CONTROL_ENABLE_ZSL);
         if (enableZsl.count == 1) {
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index a71a732..744aaee 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -31,6 +31,8 @@
 namespace android {
 namespace camera2 {
 
+using android::camera3::CAMERA_STREAM_ROTATION_0;
+
 CallbackProcessor::CallbackProcessor(sp<Camera2Client> client):
         Thread(false),
         mClient(client),
@@ -154,7 +156,7 @@
                 callbackFormat, params.previewFormat);
         res = device->createStream(mCallbackWindow,
                 params.previewWidth, params.previewHeight, callbackFormat,
-                HAL_DATASPACE_V0_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId,
+                HAL_DATASPACE_V0_JFIF, CAMERA_STREAM_ROTATION_0, &mCallbackStreamId,
                 String8());
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
index 0c01a91..4c9b7ed 100644
--- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
@@ -706,7 +706,7 @@
 
     if (mCaptureRequest.entryCount() == 0) {
         res = client->getCameraDevice()->createDefaultRequest(
-                CAMERA2_TEMPLATE_STILL_CAPTURE,
+                camera_request_template_t::CAMERA_TEMPLATE_STILL_CAPTURE,
                 &mCaptureRequest);
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to create default still image request:"
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index ddfe5e3..ff2e398 100755
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -35,6 +35,8 @@
 namespace android {
 namespace camera2 {
 
+using android::camera3::CAMERA_STREAM_ROTATION_0;
+
 JpegProcessor::JpegProcessor(
     sp<Camera2Client> client,
     wp<CaptureSequencer> sequencer):
@@ -148,7 +150,7 @@
         res = device->createStream(mCaptureWindow,
                 params.pictureWidth, params.pictureHeight,
                 HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_V0_JFIF,
-                CAMERA3_STREAM_ROTATION_0, &mCaptureStreamId,
+                CAMERA_STREAM_ROTATION_0, &mCaptureStreamId,
                 String8());
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for capture: "
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index d543cab..e062c14 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -37,6 +37,8 @@
 namespace android {
 namespace camera2 {
 
+using android::camera3::CAMERA_TEMPLATE_PREVIEW;
+
 Parameters::Parameters(int cameraId,
         int cameraFacing) :
         cameraId(cameraId),
@@ -2468,7 +2470,7 @@
 
         // Use focal length in preview template if it exists
         CameraMetadata previewTemplate;
-        status_t res = device->createDefaultRequest(CAMERA3_TEMPLATE_PREVIEW, &previewTemplate);
+        status_t res = device->createDefaultRequest(CAMERA_TEMPLATE_PREVIEW, &previewTemplate);
         if (res != OK) {
             ALOGE("%s: Failed to create default PREVIEW request: %s (%d)",
                     __FUNCTION__, strerror(-res), res);
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index 0786f53..8b1eb28 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -40,6 +40,10 @@
 namespace android {
 namespace camera2 {
 
+using android::camera3::CAMERA_STREAM_ROTATION_0;
+using android::camera3::CAMERA_TEMPLATE_PREVIEW;
+using android::camera3::CAMERA_TEMPLATE_ZERO_SHUTTER_LAG;
+
 StreamingProcessor::StreamingProcessor(sp<Camera2Client> client):
         mClient(client),
         mDevice(client->getCameraDevice()),
@@ -113,12 +117,12 @@
             return INVALID_OPERATION;
         }
 
-        // Use CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG for ZSL streaming case.
+        // Use CAMERA_TEMPLATE_ZERO_SHUTTER_LAG for ZSL streaming case.
         if (params.useZeroShutterLag() && !params.recordingHint) {
             res = device->createDefaultRequest(
-                    CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG, &mPreviewRequest);
+                    CAMERA_TEMPLATE_ZERO_SHUTTER_LAG, &mPreviewRequest);
         } else {
-            res = device->createDefaultRequest(CAMERA3_TEMPLATE_PREVIEW,
+            res = device->createDefaultRequest(CAMERA_TEMPLATE_PREVIEW,
                     &mPreviewRequest);
         }
 
@@ -194,7 +198,7 @@
         res = device->createStream(mPreviewWindow,
                 params.previewWidth, params.previewHeight,
                 CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, HAL_DATASPACE_UNKNOWN,
-                CAMERA3_STREAM_ROTATION_0, &mPreviewStreamId, String8());
+                CAMERA_STREAM_ROTATION_0, &mPreviewStreamId, String8());
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
                     __FUNCTION__, mId, strerror(-res), res);
@@ -263,7 +267,7 @@
     }
 
     if (mRecordingRequest.entryCount() == 0) {
-        res = device->createDefaultRequest(CAMERA2_TEMPLATE_VIDEO_RECORD,
+        res = device->createDefaultRequest(camera_request_template_t::CAMERA_TEMPLATE_VIDEO_RECORD,
                 &mRecordingRequest);
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to create default recording request:"
@@ -379,7 +383,7 @@
         res = device->createStream(mRecordingWindow,
                 params.videoWidth, params.videoHeight,
                 params.videoFormat, params.videoDataSpace,
-                CAMERA3_STREAM_ROTATION_0, &mRecordingStreamId,
+                CAMERA_STREAM_ROTATION_0, &mRecordingStreamId,
                 String8());
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for recording: "
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 8753dcf..0701b6f 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -42,6 +42,9 @@
 namespace android {
 namespace camera2 {
 
+using android::camera3::CAMERA_STREAM_ROTATION_0;
+using android::camera3::CAMERA_TEMPLATE_STILL_CAPTURE;
+
 namespace {
 struct TimestampFinder : public RingBufferConsumer::RingBufferComparator {
     typedef RingBufferConsumer::BufferInfo BufferInfo;
@@ -257,7 +260,7 @@
 
         res = device->createStream(outSurface, params.fastInfo.maxZslSize.width,
             params.fastInfo.maxZslSize.height, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
-            HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mZslStreamId,
+            HAL_DATASPACE_UNKNOWN, CAMERA_STREAM_ROTATION_0, &mZslStreamId,
             String8());
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create ZSL stream: "
@@ -348,7 +351,7 @@
     }
 
     CameraMetadata stillTemplate;
-    device->createDefaultRequest(CAMERA3_TEMPLATE_STILL_CAPTURE, &stillTemplate);
+    device->createDefaultRequest(CAMERA_TEMPLATE_STILL_CAPTURE, &stillTemplate);
 
     // Find some of the post-processing tags, and assign the value from template to the request.
     // Only check the aberration mode and noise reduction mode for now, as they are very important
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 66eda5d..6e1aba9 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -51,6 +51,7 @@
 
 namespace android {
 using namespace camera2;
+using camera3::camera_stream_rotation_t::CAMERA_STREAM_ROTATION_0;
 
 CameraDeviceClientBase::CameraDeviceClientBase(
         const sp<CameraService>& cameraService,
@@ -170,7 +171,6 @@
 
     const StreamSurfaceId& streamSurfaceId = mStreamMap.valueAt(idx);
     if (outSurfaceMap->find(streamSurfaceId.streamId()) == outSurfaceMap->end()) {
-        (*outSurfaceMap)[streamSurfaceId.streamId()] = std::vector<size_t>();
         outputStreamIds->push_back(streamSurfaceId.streamId());
     }
     (*outSurfaceMap)[streamSurfaceId.streamId()].push_back(streamSurfaceId.surfaceId());
@@ -807,7 +807,7 @@
 
         err = compositeStream->createStream(surfaces, deferredConsumer, streamInfo.width,
                 streamInfo.height, streamInfo.format,
-                static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
+                static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
                 &streamId, physicalCameraId, &surfaceIds, outputConfiguration.getSurfaceSetID(),
                 isShared);
         if (err == OK) {
@@ -817,7 +817,7 @@
     } else {
         err = mDevice->createStream(surfaces, deferredConsumer, streamInfo.width,
                 streamInfo.height, streamInfo.format, streamInfo.dataSpace,
-                static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
+                static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
                 &streamId, physicalCameraId, &surfaceIds, outputConfiguration.getSurfaceSetID(),
                 isShared);
     }
@@ -885,7 +885,7 @@
     String8 physicalCameraId(outputConfiguration.getPhysicalCameraId());
     err = mDevice->createStream(noSurface, /*hasDeferredConsumer*/true, width,
             height, format, dataSpace,
-            static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
+            static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
             &streamId, physicalCameraId, &surfaceIds,
             outputConfiguration.getSurfaceSetID(), isShared,
             consumerUsage);
@@ -1152,9 +1152,12 @@
         return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
     }
 
-    CameraMetadata metadata;
     status_t err;
-    if ( (err = mDevice->createDefaultRequest(templateId, &metadata) ) == OK &&
+    camera_request_template_t tempId = camera_request_template_t::CAMERA_TEMPLATE_COUNT;
+    if (!(res = mapRequestTemplate(templateId, &tempId)).isOk()) return res;
+
+    CameraMetadata metadata;
+    if ( (err = mDevice->createDefaultRequest(tempId, &metadata) ) == OK &&
         request != NULL) {
 
         request->swap(metadata);
@@ -1886,4 +1889,41 @@
     return CameraUtils::getRotationTransform(staticInfo, transform);
 }
 
+binder::Status CameraDeviceClient::mapRequestTemplate(int templateId,
+        camera_request_template_t* tempId /*out*/) {
+    binder::Status ret = binder::Status::ok();
+
+    if (tempId == nullptr) {
+        ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                "Camera %s: Invalid template argument", mCameraIdStr.string());
+        return ret;
+    }
+    switch(templateId) {
+        case ICameraDeviceUser::TEMPLATE_PREVIEW:
+            *tempId = camera_request_template_t::CAMERA_TEMPLATE_PREVIEW;
+            break;
+        case ICameraDeviceUser::TEMPLATE_RECORD:
+            *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_RECORD;
+            break;
+        case ICameraDeviceUser::TEMPLATE_STILL_CAPTURE:
+            *tempId = camera_request_template_t::CAMERA_TEMPLATE_STILL_CAPTURE;
+            break;
+        case ICameraDeviceUser::TEMPLATE_VIDEO_SNAPSHOT:
+            *tempId = camera_request_template_t::CAMERA_TEMPLATE_VIDEO_SNAPSHOT;
+            break;
+        case ICameraDeviceUser::TEMPLATE_ZERO_SHUTTER_LAG:
+            *tempId = camera_request_template_t::CAMERA_TEMPLATE_ZERO_SHUTTER_LAG;
+            break;
+        case ICameraDeviceUser::TEMPLATE_MANUAL:
+            *tempId = camera_request_template_t::CAMERA_TEMPLATE_MANUAL;
+            break;
+        default:
+            ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                    "Camera %s: Template ID %d is invalid or not supported",
+                    mCameraIdStr.string(), templateId);
+            return ret;
+    }
+
+    return ret;
+}
 } // namespace android
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 5d40b82..57688a0 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -206,6 +206,7 @@
     virtual void notifyRequestQueueEmpty();
     virtual void notifyRepeatingRequestError(long lastFrameNumber);
 
+    void setImageDumpMask(int mask) { if (mDevice != nullptr) mDevice->setImageDumpMask(mask); }
     /**
      * Interface used by independent components of CameraDeviceClient.
      */
@@ -275,6 +276,10 @@
             /*out*/SurfaceMap* surfaceMap, /*out*/Vector<int32_t>* streamIds,
             /*out*/int32_t*  currentStreamId);
 
+    // Utility method that maps AIDL request templates.
+    binder::Status mapRequestTemplate(int templateId,
+            camera_request_template_t* tempId /*out*/);
+
     // IGraphicsBufferProducer binder -> Stream ID + Surface ID for output streams
     KeyedVector<sp<IBinder>, StreamSurfaceId> mStreamMap;
 
diff --git a/services/camera/libcameraservice/api2/CompositeStream.cpp b/services/camera/libcameraservice/api2/CompositeStream.cpp
index a61dac7..2f8ca6b 100644
--- a/services/camera/libcameraservice/api2/CompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/CompositeStream.cpp
@@ -46,7 +46,7 @@
 
 status_t CompositeStream::createStream(const std::vector<sp<Surface>>& consumers,
         bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
-        camera3_stream_rotation_t rotation, int * id, const String8& physicalCameraId,
+        camera_stream_rotation_t rotation, int * id, const String8& physicalCameraId,
         std::vector<int> * surfaceIds, int streamSetId, bool isShared) {
     if (hasDeferredConsumer) {
         ALOGE("%s: Deferred consumers not supported in case of composite streams!",
diff --git a/services/camera/libcameraservice/api2/CompositeStream.h b/services/camera/libcameraservice/api2/CompositeStream.h
index 5f62d47..2a934df 100644
--- a/services/camera/libcameraservice/api2/CompositeStream.h
+++ b/services/camera/libcameraservice/api2/CompositeStream.h
@@ -43,7 +43,7 @@
 
     status_t createStream(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
-            camera3_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+            camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
             std::vector<int> *surfaceIds, int streamSetId, bool isShared);
 
     status_t deleteStream();
@@ -54,7 +54,7 @@
     // Create and register all internal camera streams.
     virtual status_t createInternalStreams(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
-            camera3_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+            camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
             std::vector<int> *surfaceIds, int streamSetId, bool isShared) = 0;
 
     // Release all internal streams and corresponding resources.
diff --git a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
index c6859be..2c553f3 100644
--- a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
@@ -341,7 +341,7 @@
         return res;
     }
 
-    size_t finalJpegSize = actualJpegSize + sizeof(struct camera3_jpeg_blob);
+    size_t finalJpegSize = actualJpegSize + sizeof(struct camera_jpeg_blob);
     if (finalJpegSize > finalJpegBufferSize) {
         ALOGE("%s: Final jpeg buffer not large enough for the jpeg blob header", __FUNCTION__);
         outputANW->cancelBuffer(mOutputSurface.get(), anb, /*fence*/ -1);
@@ -357,9 +357,9 @@
 
     ALOGV("%s: Final jpeg size: %zu", __func__, finalJpegSize);
     uint8_t* header = static_cast<uint8_t *> (dstBuffer) +
-        (gb->getWidth() - sizeof(struct camera3_jpeg_blob));
-    struct camera3_jpeg_blob *blob = reinterpret_cast<struct camera3_jpeg_blob*> (header);
-    blob->jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
+        (gb->getWidth() - sizeof(struct camera_jpeg_blob));
+    struct camera_jpeg_blob *blob = reinterpret_cast<struct camera_jpeg_blob*> (header);
+    blob->jpeg_blob_id = CAMERA_JPEG_BLOB_ID;
     blob->jpeg_size = actualJpegSize;
     outputANW->queueBuffer(mOutputSurface.get(), anb, /*fence*/ -1);
 
@@ -486,7 +486,7 @@
 
 status_t DepthCompositeStream::createInternalStreams(const std::vector<sp<Surface>>& consumers,
         bool /*hasDeferredConsumer*/, uint32_t width, uint32_t height, int format,
-        camera3_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+        camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
         std::vector<int> *surfaceIds, int /*streamSetId*/, bool /*isShared*/) {
     if (mSupportedDepthSizes.empty()) {
         ALOGE("%s: This camera device doesn't support any depth map streams!", __FUNCTION__);
@@ -666,13 +666,11 @@
 status_t DepthCompositeStream::insertGbp(SurfaceMap* /*out*/outSurfaceMap,
         Vector<int32_t> * /*out*/outputStreamIds, int32_t* /*out*/currentStreamId) {
     if (outSurfaceMap->find(mDepthStreamId) == outSurfaceMap->end()) {
-        (*outSurfaceMap)[mDepthStreamId] = std::vector<size_t>();
         outputStreamIds->push_back(mDepthStreamId);
     }
     (*outSurfaceMap)[mDepthStreamId].push_back(mDepthSurfaceId);
 
     if (outSurfaceMap->find(mBlobStreamId) == outSurfaceMap->end()) {
-        (*outSurfaceMap)[mBlobStreamId] = std::vector<size_t>();
         outputStreamIds->push_back(mBlobStreamId);
     }
     (*outSurfaceMap)[mBlobStreamId].push_back(mBlobSurfaceId);
diff --git a/services/camera/libcameraservice/api2/DepthCompositeStream.h b/services/camera/libcameraservice/api2/DepthCompositeStream.h
index cab52b6..05bc504 100644
--- a/services/camera/libcameraservice/api2/DepthCompositeStream.h
+++ b/services/camera/libcameraservice/api2/DepthCompositeStream.h
@@ -50,7 +50,7 @@
     // CompositeStream overrides
     status_t createInternalStreams(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
-            camera3_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+            camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
             std::vector<int> *surfaceIds, int streamSetId, bool isShared) override;
     status_t deleteInternalStreams() override;
     status_t configureStream() override;
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index 4fe5adf..7d68485 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -65,7 +65,6 @@
         mYuvBufferAcquired(false),
         mProducerListener(new ProducerListener()),
         mDequeuedOutputBufferCnt(0),
-        mLockedAppSegmentBufferCnt(0),
         mCodecOutputCounter(0),
         mQuality(-1),
         mGridTimestampUs(0),
@@ -115,7 +114,7 @@
 
 status_t HeicCompositeStream::createInternalStreams(const std::vector<sp<Surface>>& consumers,
         bool /*hasDeferredConsumer*/, uint32_t width, uint32_t height, int format,
-        camera3_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+        camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
         std::vector<int> *surfaceIds, int /*streamSetId*/, bool /*isShared*/) {
 
     sp<CameraDeviceBase> device = mDevice.promote();
@@ -522,13 +521,11 @@
 status_t HeicCompositeStream::insertGbp(SurfaceMap* /*out*/outSurfaceMap,
         Vector<int32_t>* /*out*/outputStreamIds, int32_t* /*out*/currentStreamId) {
     if (outSurfaceMap->find(mAppSegmentStreamId) == outSurfaceMap->end()) {
-        (*outSurfaceMap)[mAppSegmentStreamId] = std::vector<size_t>();
         outputStreamIds->push_back(mAppSegmentStreamId);
     }
     (*outSurfaceMap)[mAppSegmentStreamId].push_back(mAppSegmentSurfaceId);
 
     if (outSurfaceMap->find(mMainImageStreamId) == outSurfaceMap->end()) {
-        (*outSurfaceMap)[mMainImageStreamId] = std::vector<size_t>();
         outputStreamIds->push_back(mMainImageStreamId);
     }
     (*outSurfaceMap)[mMainImageStreamId].push_back(mMainImageSurfaceId);
@@ -635,7 +632,6 @@
             mAppSegmentConsumer->unlockBuffer(imgBuffer);
         } else {
             mPendingInputFrames[frameNumber].appSegmentBuffer = imgBuffer;
-            mLockedAppSegmentBufferCnt++;
         }
         mInputAppSegmentBuffers.erase(it);
         mAppSegmentFrameNumbers.pop();
@@ -898,10 +894,6 @@
                         strerror(-res), res);
                 return res;
             }
-        } else if (mLockedAppSegmentBufferCnt == kMaxAcquiredAppSegment) {
-            ALOGE("%s: Out-of-order app segment buffers reaches limit %u", __FUNCTION__,
-                    kMaxAcquiredAppSegment);
-            return INVALID_OPERATION;
         }
     }
 
@@ -1039,7 +1031,6 @@
     mAppSegmentConsumer->unlockBuffer(inputFrame.appSegmentBuffer);
     inputFrame.appSegmentBuffer.data = nullptr;
     inputFrame.exifError = false;
-    mLockedAppSegmentBufferCnt--;
 
     return OK;
 }
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.h b/services/camera/libcameraservice/api2/HeicCompositeStream.h
index 33ca69a..cbd9d21 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.h
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.h
@@ -45,7 +45,7 @@
 
     status_t createInternalStreams(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
-            camera3_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+            camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
             std::vector<int> *surfaceIds, int streamSetId, bool isShared) override;
 
     status_t deleteInternalStreams() override;
@@ -253,7 +253,6 @@
 
     // Keep all incoming APP segment Blob buffer pending further processing.
     std::vector<int64_t> mInputAppSegmentBuffers;
-    int32_t           mLockedAppSegmentBufferCnt;
 
     // Keep all incoming HEIC blob buffer pending further processing.
     std::vector<CodecOutputBufferInfo> mCodecOutputBuffers;
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index a537ef5..5e46f08 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -28,7 +28,6 @@
 #include <utils/List.h>
 
 #include "hardware/camera2.h"
-#include "hardware/camera3.h"
 #include "camera/CameraMetadata.h"
 #include "camera/CaptureResult.h"
 #include "gui/IGraphicBufferProducer.h"
@@ -41,6 +40,41 @@
 
 namespace android {
 
+namespace camera3 {
+
+typedef enum camera_request_template {
+    CAMERA_TEMPLATE_PREVIEW = 1,
+    CAMERA_TEMPLATE_STILL_CAPTURE = 2,
+    CAMERA_TEMPLATE_VIDEO_RECORD = 3,
+    CAMERA_TEMPLATE_VIDEO_SNAPSHOT = 4,
+    CAMERA_TEMPLATE_ZERO_SHUTTER_LAG = 5,
+    CAMERA_TEMPLATE_MANUAL = 6,
+    CAMERA_TEMPLATE_COUNT,
+    CAMERA_VENDOR_TEMPLATE_START = 0x40000000
+} camera_request_template_t;
+
+typedef enum camera_stream_configuration_mode {
+    CAMERA_STREAM_CONFIGURATION_NORMAL_MODE = 0,
+    CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE = 1,
+    CAMERA_VENDOR_STREAM_CONFIGURATION_MODE_START = 0x8000
+} camera_stream_configuration_mode_t;
+
+typedef struct camera_jpeg_blob {
+    uint16_t jpeg_blob_id;
+    uint32_t jpeg_size;
+} camera_jpeg_blob_t;
+
+enum {
+    CAMERA_JPEG_BLOB_ID = 0x00FF,
+    CAMERA_JPEG_APP_SEGMENTS_BLOB_ID = 0x0100,
+};
+
+} // namespace camera3
+
+using camera3::camera_request_template_t;;
+using camera3::camera_stream_configuration_mode_t;
+using camera3::camera_stream_rotation_t;
+
 class CameraProviderManager;
 
 // Mapping of output stream index to surface ids
@@ -128,7 +162,7 @@
      */
     virtual status_t createStream(sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
-            android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+            android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
             const String8& physicalCameraId,
             std::vector<int> *surfaceIds = nullptr,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
@@ -143,7 +177,7 @@
      */
     virtual status_t createStream(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
-            android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+            android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
             const String8& physicalCameraId,
             std::vector<int> *surfaceIds = nullptr,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
@@ -225,7 +259,8 @@
      * - INVALID_OPERATION if the device was in the wrong state
      */
     virtual status_t configureStreams(const CameraMetadata& sessionParams,
-            int operatingMode = 0) = 0;
+            int operatingMode =
+            camera_stream_configuration_mode_t::CAMERA_STREAM_CONFIGURATION_NORMAL_MODE) = 0;
 
     /**
      * Retrieve a list of all stream ids that were advertised as capable of
@@ -241,7 +276,7 @@
      * Create a metadata buffer with fields that the HAL device believes are
      * best for the given use case
      */
-    virtual status_t createDefaultRequest(int templateId,
+    virtual status_t createDefaultRequest(camera_request_template_t templateId,
             CameraMetadata *request) = 0;
 
     /**
@@ -367,6 +402,14 @@
      * Get the status tracker of the camera device
      */
     virtual wp<camera3::StatusTracker> getStatusTracker() = 0;
+
+    /**
+     * Set bitmask for image dump flag
+     */
+    void setImageDumpMask(int mask) { mImageDumpMask = mask; }
+
+protected:
+    bool mImageDumpMask = 0;
 };
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/BufferUtils.cpp b/services/camera/libcameraservice/device3/BufferUtils.cpp
index cc29390..f3adf20 100644
--- a/services/camera/libcameraservice/device3/BufferUtils.cpp
+++ b/services/camera/libcameraservice/device3/BufferUtils.cpp
@@ -28,14 +28,14 @@
 namespace android {
 namespace camera3 {
 
-camera3_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status) {
+camera_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status) {
     using hardware::camera::device::V3_2::BufferStatus;
 
     switch (status) {
-        case BufferStatus::OK: return CAMERA3_BUFFER_STATUS_OK;
-        case BufferStatus::ERROR: return CAMERA3_BUFFER_STATUS_ERROR;
+        case BufferStatus::OK: return CAMERA_BUFFER_STATUS_OK;
+        case BufferStatus::ERROR: return CAMERA_BUFFER_STATUS_ERROR;
     }
-    return CAMERA3_BUFFER_STATUS_ERROR;
+    return CAMERA_BUFFER_STATUS_ERROR;
 }
 
 void BufferRecords::takeInflightBufferMap(BufferRecords& other) {
diff --git a/services/camera/libcameraservice/device3/BufferUtils.h b/services/camera/libcameraservice/device3/BufferUtils.h
index 452a908..1e1cd60 100644
--- a/services/camera/libcameraservice/device3/BufferUtils.h
+++ b/services/camera/libcameraservice/device3/BufferUtils.h
@@ -25,9 +25,6 @@
 
 #include <android/hardware/camera/device/3.2/ICameraDevice.h>
 
-// TODO: remove legacy camera3.h references
-#include "hardware/camera3.h"
-
 #include <device3/Camera3OutputInterface.h>
 
 namespace android {
@@ -158,7 +155,7 @@
 
     static const uint64_t BUFFER_ID_NO_BUFFER = 0;
 
-    camera3_buffer_status_t mapHidlBufferStatus(
+    camera_buffer_status_t mapHidlBufferStatus(
             hardware::camera::device::V3_2::BufferStatus status);
 } // namespace camera3
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 50ef953..92c8e30 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -547,15 +547,15 @@
     return usage;
 }
 
-StreamRotation Camera3Device::mapToStreamRotation(camera3_stream_rotation_t rotation) {
+StreamRotation Camera3Device::mapToStreamRotation(camera_stream_rotation_t rotation) {
     switch (rotation) {
-        case CAMERA3_STREAM_ROTATION_0:
+        case CAMERA_STREAM_ROTATION_0:
             return StreamRotation::ROTATION_0;
-        case CAMERA3_STREAM_ROTATION_90:
+        case CAMERA_STREAM_ROTATION_90:
             return StreamRotation::ROTATION_90;
-        case CAMERA3_STREAM_ROTATION_180:
+        case CAMERA_STREAM_ROTATION_180:
             return StreamRotation::ROTATION_180;
-        case CAMERA3_STREAM_ROTATION_270:
+        case CAMERA_STREAM_ROTATION_270:
             return StreamRotation::ROTATION_270;
     }
     ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
@@ -563,14 +563,14 @@
 }
 
 status_t Camera3Device::mapToStreamConfigurationMode(
-        camera3_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
+        camera_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
     if (mode == nullptr) return BAD_VALUE;
-    if (operationMode < CAMERA3_VENDOR_STREAM_CONFIGURATION_MODE_START) {
+    if (operationMode < CAMERA_VENDOR_STREAM_CONFIGURATION_MODE_START) {
         switch(operationMode) {
-            case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE:
+            case CAMERA_STREAM_CONFIGURATION_NORMAL_MODE:
                 *mode = StreamConfigurationMode::NORMAL_MODE;
                 break;
-            case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
+            case CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
                 *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
                 break;
             default:
@@ -779,7 +779,7 @@
     }
 
     if (dumpTemplates) {
-        const char *templateNames[CAMERA3_TEMPLATE_COUNT] = {
+        const char *templateNames[CAMERA_TEMPLATE_COUNT] = {
             "TEMPLATE_PREVIEW",
             "TEMPLATE_STILL_CAPTURE",
             "TEMPLATE_VIDEO_RECORD",
@@ -788,10 +788,10 @@
             "TEMPLATE_MANUAL",
         };
 
-        for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; i++) {
+        for (int i = 1; i < CAMERA_TEMPLATE_COUNT; i++) {
             camera_metadata_t *templateRequest = nullptr;
             mInterface->constructDefaultRequestSettings(
-                    (camera3_request_template_t) i, &templateRequest);
+                    (camera_request_template_t) i, &templateRequest);
             lines = String8::format("    HAL Request %s:\n", templateNames[i-1]);
             if (templateRequest == nullptr) {
                 lines.append("       Not supported\n");
@@ -1203,7 +1203,7 @@
         // This point should only be reached via API1 (API2 must explicitly call configureStreams)
         // so unilaterally select normal operating mode.
         res = filterParamsAndConfigureLocked(request.begin()->metadata,
-                CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
+                CAMERA_STREAM_CONFIGURATION_NORMAL_MODE);
         // Stream configuration failed. Client might try other configuraitons.
         if (res != OK) {
             CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
@@ -1322,7 +1322,7 @@
 
 status_t Camera3Device::createStream(sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
-            android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+            android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
             const String8& physicalCameraId,
             std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
     ATRACE_CALL();
@@ -1342,7 +1342,7 @@
 
 status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
         bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
-        android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+        android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
         const String8& physicalCameraId,
         std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
     ATRACE_CALL();
@@ -1456,6 +1456,8 @@
 
     newStream->setBufferManager(mBufferManager);
 
+    newStream->setImageDumpMask(mImageDumpMask);
+
     res = mOutputStreams.add(mNextStreamId, newStream);
     if (res < 0) {
         SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
@@ -1619,7 +1621,7 @@
     // speculative configuration using the values from the last cached
     // default request.
     if (sessionParams.isEmpty() &&
-            ((mLastTemplateId > 0) && (mLastTemplateId < CAMERA3_TEMPLATE_COUNT)) &&
+            ((mLastTemplateId > 0) && (mLastTemplateId < CAMERA_TEMPLATE_COUNT)) &&
             (!mRequestTemplateCache[mLastTemplateId].isEmpty())) {
         ALOGV("%s: Speculative session param configuration with template id: %d", __func__,
                 mLastTemplateId);
@@ -1669,12 +1671,12 @@
     return mInputStream->getInputBufferProducer(producer);
 }
 
-status_t Camera3Device::createDefaultRequest(int templateId,
+status_t Camera3Device::createDefaultRequest(camera_request_template_t templateId,
         CameraMetadata *request) {
     ATRACE_CALL();
     ALOGV("%s: for template %d", __FUNCTION__, templateId);
 
-    if (templateId <= 0 || templateId >= CAMERA3_TEMPLATE_COUNT) {
+    if (templateId <= 0 || templateId >= CAMERA_TEMPLATE_COUNT) {
         android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26866110",
                 CameraThreadState::getCallingUid(), nullptr, 0);
         return BAD_VALUE;
@@ -1710,7 +1712,7 @@
 
     camera_metadata_t *rawRequest;
     status_t res = mInterface->constructDefaultRequestSettings(
-            (camera3_request_template_t) templateId, &rawRequest);
+            (camera_request_template_t) templateId, &rawRequest);
 
     {
         Mutex::Autolock l(mLock);
@@ -2519,7 +2521,7 @@
     // any pending requests.
     if (mInputStream != NULL && notifyRequestThread) {
         while (true) {
-            camera3_stream_buffer_t inputBuffer;
+            camera_stream_buffer_t inputBuffer;
             status_t res = mInputStream->getInputBuffer(&inputBuffer,
                     /*respectHalLimit*/ false);
             if (res != OK) {
@@ -2527,7 +2529,7 @@
                 break;
             }
 
-            inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+            inputBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
             res = mInputStream->returnInputBuffer(inputBuffer);
             if (res != OK) {
                 ALOGE("%s: %d: couldn't return input buffer while clearing input queue: "
@@ -2555,17 +2557,17 @@
 
     mPreparerThread->pause();
 
-    camera3_stream_configuration config;
+    camera_stream_configuration config;
     config.operation_mode = mOperatingMode;
     config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
 
-    Vector<camera3_stream_t*> streams;
+    Vector<camera3::camera_stream_t*> streams;
     streams.setCapacity(config.num_streams);
     std::vector<uint32_t> bufferSizes(config.num_streams, 0);
 
 
     if (mInputStream != NULL) {
-        camera3_stream_t *inputStream;
+        camera3::camera_stream_t *inputStream;
         inputStream = mInputStream->startConfiguration();
         if (inputStream == NULL) {
             CLOGE("Can't start input stream configuration");
@@ -2585,7 +2587,7 @@
             continue;
         }
 
-        camera3_stream_t *outputStream;
+        camera3::camera_stream_t *outputStream;
         outputStream = mOutputStreams[i]->startConfiguration();
         if (outputStream == NULL) {
             CLOGE("Can't start output stream configuration");
@@ -3011,7 +3013,7 @@
 }
 
 status_t Camera3Device::HalInterface::constructDefaultRequestSettings(
-        camera3_request_template_t templateId,
+        camera_request_template_t templateId,
         /*out*/ camera_metadata_t **requestTemplate) {
     ATRACE_NAME("CameraHal::constructDefaultRequestSettings");
     if (!valid()) return INVALID_OPERATION;
@@ -3043,22 +3045,22 @@
     hardware::Return<void> err;
     RequestTemplate id;
     switch (templateId) {
-        case CAMERA3_TEMPLATE_PREVIEW:
+        case CAMERA_TEMPLATE_PREVIEW:
             id = RequestTemplate::PREVIEW;
             break;
-        case CAMERA3_TEMPLATE_STILL_CAPTURE:
+        case CAMERA_TEMPLATE_STILL_CAPTURE:
             id = RequestTemplate::STILL_CAPTURE;
             break;
-        case CAMERA3_TEMPLATE_VIDEO_RECORD:
+        case CAMERA_TEMPLATE_VIDEO_RECORD:
             id = RequestTemplate::VIDEO_RECORD;
             break;
-        case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
+        case CAMERA_TEMPLATE_VIDEO_SNAPSHOT:
             id = RequestTemplate::VIDEO_SNAPSHOT;
             break;
-        case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
+        case CAMERA_TEMPLATE_ZERO_SHUTTER_LAG:
             id = RequestTemplate::ZERO_SHUTTER_LAG;
             break;
-        case CAMERA3_TEMPLATE_MANUAL:
+        case CAMERA_TEMPLATE_MANUAL:
             id = RequestTemplate::MANUAL;
             break;
         default:
@@ -3124,7 +3126,7 @@
 }
 
 status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
-        camera3_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
+        camera_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
     ATRACE_NAME("CameraHal::configureStreams");
     if (!valid()) return INVALID_OPERATION;
     status_t res = OK;
@@ -3138,17 +3140,17 @@
     for (size_t i = 0; i < config->num_streams; i++) {
         device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
         device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
-        camera3_stream_t *src = config->streams[i];
+        camera3::camera_stream_t *src = config->streams[i];
 
         Camera3Stream* cam3stream = Camera3Stream::cast(src);
         cam3stream->setBufferFreedListener(this);
         int streamId = cam3stream->getId();
         StreamType streamType;
         switch (src->stream_type) {
-            case CAMERA3_STREAM_OUTPUT:
+            case CAMERA_STREAM_OUTPUT:
                 streamType = StreamType::OUTPUT;
                 break;
-            case CAMERA3_STREAM_INPUT:
+            case CAMERA_STREAM_INPUT:
                 streamType = StreamType::INPUT;
                 break;
             default:
@@ -3161,7 +3163,7 @@
         dst3_2.width = src->width;
         dst3_2.height = src->height;
         dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
-        dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
+        dst3_2.rotation = mapToStreamRotation((camera_stream_rotation_t) src->rotation);
         // For HidlSession version 3.5 or newer, the format and dataSpace sent
         // to HAL are original, not the overriden ones.
         if (mHidlSession_3_5 != nullptr) {
@@ -3188,7 +3190,7 @@
 
     StreamConfigurationMode operationMode;
     res = mapToStreamConfigurationMode(
-            (camera3_stream_configuration_mode_t) config->operation_mode,
+            (camera_stream_configuration_mode_t) config->operation_mode,
             /*out*/ &operationMode);
     if (res != OK) {
         return res;
@@ -3317,7 +3319,7 @@
     // And convert output stream configuration from HIDL
 
     for (size_t i = 0; i < config->num_streams; i++) {
-        camera3_stream_t *dst = config->streams[i];
+        camera3::camera_stream_t *dst = config->streams[i];
         int streamId = Camera3Stream::cast(dst)->getId();
 
         // Start scan at i, with the assumption that the stream order matches
@@ -3370,7 +3372,7 @@
             dst->data_space = overrideDataSpace;
         }
 
-        if (dst->stream_type == CAMERA3_STREAM_INPUT) {
+        if (dst->stream_type == CAMERA_STREAM_INPUT) {
             if (src.v3_2.producerUsage != 0) {
                 ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
                         __FUNCTION__, streamId);
@@ -3394,7 +3396,7 @@
     return res;
 }
 
-status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera3_capture_request_t* request,
+status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera_capture_request_t* request,
         /*out*/device::V3_2::CaptureRequest* captureRequest,
         /*out*/std::vector<native_handle_t*>* handlesCreated,
         /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
@@ -3439,7 +3441,7 @@
 
         captureRequest->outputBuffers.resize(request->num_output_buffers);
         for (size_t i = 0; i < request->num_output_buffers; i++) {
-            const camera3_stream_buffer_t *src = request->output_buffers + i;
+            const camera_stream_buffer_t *src = request->output_buffers + i;
             StreamBuffer &dst = captureRequest->outputBuffers[i];
             int32_t streamId = Camera3Stream::cast(src->stream)->getId();
             if (src->buffer != nullptr) {
@@ -3497,7 +3499,7 @@
 }
 
 status_t Camera3Device::HalInterface::processBatchCaptureRequests(
-        std::vector<camera3_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
+        std::vector<camera_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
     ATRACE_NAME("CameraHal::processBatchCaptureRequests");
     if (!valid()) return INVALID_OPERATION;
 
@@ -3551,7 +3553,7 @@
 
     // Write metadata to FMQ.
     for (size_t i = 0; i < batchSize; i++) {
-        camera3_capture_request_t* request = requests[i];
+        camera_capture_request_t* request = requests[i];
         device::V3_2::CaptureRequest* captureRequest;
         if (hidlSession_3_4 != nullptr) {
             captureRequest = &captureRequests_3_4[i].v3_2;
@@ -4023,14 +4025,14 @@
                  it != mRequestQueue.end(); ++it) {
             // Abort the input buffers for reprocess requests.
             if ((*it)->mInputStream != NULL) {
-                camera3_stream_buffer_t inputBuffer;
+                camera_stream_buffer_t inputBuffer;
                 status_t res = (*it)->mInputStream->getInputBuffer(&inputBuffer,
                         /*respectHalLimit*/ false);
                 if (res != OK) {
                     ALOGW("%s: %d: couldn't get input buffer while clearing the request "
                             "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
                 } else {
-                    inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+                    inputBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
                     res = (*it)->mInputStream->returnInputBuffer(inputBuffer);
                     if (res != OK) {
                         ALOGE("%s: %d: couldn't return input buffer while clearing the request "
@@ -4134,7 +4136,7 @@
     ATRACE_CALL();
     status_t res;
     size_t batchSize = mNextRequests.size();
-    std::vector<camera3_capture_request_t*> requests(batchSize);
+    std::vector<camera_capture_request_t*> requests(batchSize);
     uint32_t numRequestProcessed = 0;
     for (size_t i = 0; i < batchSize; i++) {
         requests[i] = &mNextRequests.editItemAt(i).halRequest;
@@ -4453,8 +4455,8 @@
     for (size_t i = 0; i < mNextRequests.size(); i++) {
         auto& nextRequest = mNextRequests.editItemAt(i);
         sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
-        camera3_capture_request_t* halRequest = &nextRequest.halRequest;
-        Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
+        camera_capture_request_t* halRequest = &nextRequest.halRequest;
+        Vector<camera_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
 
         // Prepare a request to HAL
         halRequest->frame_number = captureRequest->mResultExtras.frameNumber;
@@ -4622,7 +4624,7 @@
             halRequest->input_buffer = NULL;
         }
 
-        outputBuffers->insertAt(camera3_stream_buffer_t(), 0,
+        outputBuffers->insertAt(camera_stream_buffer_t(), 0,
                 captureRequest->mOutputStreams.size());
         halRequest->output_buffers = outputBuffers->array();
         std::set<String8> requestedPhysicalCameras;
@@ -4678,10 +4680,10 @@
                     return TIMED_OUT;
                 }
                 // HAL will request buffer through requestStreamBuffer API
-                camera3_stream_buffer_t& buffer = outputBuffers->editItemAt(j);
+                camera_stream_buffer_t& buffer = outputBuffers->editItemAt(j);
                 buffer.stream = outputStream->asHalStream();
                 buffer.buffer = nullptr;
-                buffer.status = CAMERA3_BUFFER_STATUS_OK;
+                buffer.status = CAMERA_BUFFER_STATUS_OK;
                 buffer.acquire_fence = -1;
                 buffer.release_fence = -1;
             } else {
@@ -4934,7 +4936,7 @@
 }
 
 void Camera3Device::RequestThread::cleanupPhysicalSettings(sp<CaptureRequest> request,
-        camera3_capture_request_t *halRequest) {
+        camera_capture_request_t *halRequest) {
     if ((request == nullptr) || (halRequest == nullptr)) {
         ALOGE("%s: Invalid request!", __FUNCTION__);
         return;
@@ -4969,8 +4971,8 @@
         }
 
         sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
-        camera3_capture_request_t* halRequest = &nextRequest.halRequest;
-        Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
+        camera_capture_request_t* halRequest = &nextRequest.halRequest;
+        Vector<camera_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
 
         if (halRequest->settings != NULL) {
             captureRequest->mSettingsList.begin()->metadata.unlock(halRequest->settings);
@@ -4979,7 +4981,7 @@
         cleanupPhysicalSettings(captureRequest, halRequest);
 
         if (captureRequest->mInputStream != NULL) {
-            captureRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+            captureRequest->mInputBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
             captureRequest->mInputStream->returnInputBuffer(captureRequest->mInputBuffer);
         }
 
@@ -4993,7 +4995,7 @@
                     close(acquireFence);
                     outputBuffers->editItemAt(i).acquire_fence = -1;
                 }
-                outputBuffers->editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
+                outputBuffers->editItemAt(i).status = CAMERA_BUFFER_STATUS_ERROR;
                 captureRequest->mOutputStreams.editItemAt(i)->returnBuffer((*outputBuffers)[i], 0,
                         /*timestampIncreasing*/true, std::vector<size_t> (),
                         captureRequest->mResultExtras.frameNumber);
@@ -5043,7 +5045,7 @@
         return;
     }
 
-    nextRequest.halRequest = camera3_capture_request_t();
+    nextRequest.halRequest = camera_capture_request_t();
     nextRequest.submitted = false;
     mNextRequests.add(nextRequest);
 
@@ -5057,7 +5059,7 @@
             break;
         }
 
-        additionalRequest.halRequest = camera3_capture_request_t();
+        additionalRequest.halRequest = camera_capture_request_t();
         additionalRequest.submitted = false;
         mNextRequests.add(additionalRequest);
     }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index de7df81..b06ce45 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -56,6 +56,13 @@
 #include "utils/LatencyHistogram.h"
 #include <camera_metadata_hidden.h>
 
+using android::camera3::camera_capture_request_t;
+using android::camera3::camera_jpeg_blob_t;
+using android::camera3::camera_request_template;
+using android::camera3::camera_stream_buffer_t;
+using android::camera3::camera_stream_configuration_t;
+using android::camera3::camera_stream_configuration_mode_t;
+using android::camera3::CAMERA_TEMPLATE_COUNT;
 using android::camera3::OutputStreamInfo;
 
 namespace android {
@@ -122,14 +129,14 @@
     // and finish the stream configuration before starting output streaming.
     status_t createStream(sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
-            android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+            android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
             const String8& physicalCameraId,
             std::vector<int> *surfaceIds = nullptr,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
             bool isShared = false, uint64_t consumerUsage = 0) override;
     status_t createStream(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
-            android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+            android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
             const String8& physicalCameraId,
             std::vector<int> *surfaceIds = nullptr,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
@@ -146,14 +153,14 @@
 
     status_t configureStreams(const CameraMetadata& sessionParams,
             int operatingMode =
-            static_cast<int>(hardware::camera::device::V3_2::StreamConfigurationMode::NORMAL_MODE))
-            override;
+            camera_stream_configuration_mode_t::CAMERA_STREAM_CONFIGURATION_NORMAL_MODE) override;
     status_t getInputBufferProducer(
             sp<IGraphicBufferProducer> *producer) override;
 
     void getOfflineStreamIds(std::vector<int> *offlineStreamIds) override;
 
-    status_t createDefaultRequest(int templateId, CameraMetadata *request) override;
+    status_t createDefaultRequest(camera_request_template_t templateId,
+            CameraMetadata *request) override;
 
     // Transitions to the idle state on success
     status_t waitUntilDrained() override;
@@ -242,9 +249,9 @@
             android_dataspace dataSpace);
     static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint64_t usage);
     static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
-            camera3_stream_rotation_t rotation);
+            camera_stream_rotation_t rotation);
     // Returns a negative error code if the passed-in operation mode is not valid.
-    static status_t mapToStreamConfigurationMode(camera3_stream_configuration_mode_t operationMode,
+    static status_t mapToStreamConfigurationMode(camera_stream_configuration_mode_t operationMode,
             /*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
     static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
     static android_dataspace mapToFrameworkDataspace(
@@ -255,7 +262,6 @@
             hardware::camera::device::V3_2::BufferUsageFlags usage);
 
   private:
-
     status_t disconnectImpl();
 
     // internal typedefs
@@ -275,7 +281,7 @@
 
     struct                     RequestTrigger;
     // minimal jpeg buffer size: 256KB + blob header
-    static const ssize_t       kMinJpegBufferSize = 256 * 1024 + sizeof(camera3_jpeg_blob);
+    static const ssize_t       kMinJpegBufferSize = 256 * 1024 + sizeof(camera_jpeg_blob_t);
     // Constant to use for stream ID when one doesn't exist
     static const int           NO_STREAM = -1;
 
@@ -330,10 +336,10 @@
         // Calls into the HAL interface
 
         // Caller takes ownership of requestTemplate
-        status_t constructDefaultRequestSettings(camera3_request_template_t templateId,
+        status_t constructDefaultRequestSettings(camera_request_template templateId,
                 /*out*/ camera_metadata_t **requestTemplate);
         status_t configureStreams(const camera_metadata_t *sessionParams,
-                /*inout*/ camera3_stream_configuration *config,
+                /*inout*/ camera_stream_configuration_t *config,
                 const std::vector<uint32_t>& bufferSizes);
 
         // When the call succeeds, the ownership of acquire fences in requests is transferred to
@@ -341,7 +347,7 @@
         // HAL process and close the FD in cameraserver process. When the call fails, the ownership
         // of the acquire fence still belongs to the caller.
         status_t processBatchCaptureRequests(
-                std::vector<camera3_capture_request_t*>& requests,
+                std::vector<camera_capture_request_t*>& requests,
                 /*out*/uint32_t* numRequestProcessed);
         status_t flush();
         status_t dump(int fd);
@@ -400,9 +406,9 @@
 
         std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
 
-        // The output HIDL request still depends on input camera3_capture_request_t
-        // Do not free input camera3_capture_request_t before output HIDL request
-        status_t wrapAsHidlRequest(camera3_capture_request_t* in,
+        // The output HIDL request still depends on input camera_capture_request_t
+        // Do not free input camera_capture_request_t before output HIDL request
+        status_t wrapAsHidlRequest(camera_capture_request_t* in,
                 /*out*/hardware::camera::device::V3_2::CaptureRequest* out,
                 /*out*/std::vector<native_handle_t*>* handlesCreated,
                 /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers);
@@ -442,7 +448,7 @@
     bool                       mSupportNativeZoomRatio;
     std::unordered_map<std::string, CameraMetadata> mPhysicalDeviceInfoMap;
 
-    CameraMetadata             mRequestTemplateCache[CAMERA3_TEMPLATE_COUNT];
+    CameraMetadata             mRequestTemplateCache[CAMERA_TEMPLATE_COUNT];
 
     struct Size {
         uint32_t width;
@@ -503,7 +509,7 @@
       public:
         PhysicalCameraSettingsList          mSettingsList;
         sp<camera3::Camera3Stream>          mInputStream;
-        camera3_stream_buffer_t             mInputBuffer;
+        camera_stream_buffer_t              mInputBuffer;
         Vector<sp<camera3::Camera3OutputStreamInterface> >
                                             mOutputStreams;
         SurfaceMap                          mOutputSurfaces;
@@ -891,8 +897,8 @@
         // Used to prepare a batch of requests.
         struct NextRequest {
             sp<CaptureRequest>              captureRequest;
-            camera3_capture_request_t       halRequest;
-            Vector<camera3_stream_buffer_t> outputBuffers;
+            camera_capture_request_t       halRequest;
+            Vector<camera_stream_buffer_t> outputBuffers;
             bool                            submitted;
         };
 
@@ -918,7 +924,7 @@
 
         // Release physical camera settings and camera id resources.
         void cleanupPhysicalSettings(sp<CaptureRequest> request,
-                /*out*/camera3_capture_request_t *halRequest);
+                /*out*/camera_capture_request_t *halRequest);
 
         // Pause handling
         bool               waitIfPaused();
diff --git a/services/camera/libcameraservice/device3/Camera3FakeStream.cpp b/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
index 230512a..ab5084e 100644
--- a/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
@@ -29,7 +29,7 @@
 const String8 Camera3FakeStream::FAKE_ID;
 
 Camera3FakeStream::Camera3FakeStream(int id) :
-        Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, FAKE_WIDTH, FAKE_HEIGHT,
+        Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, FAKE_WIDTH, FAKE_HEIGHT,
                 /*maxSize*/0, FAKE_FORMAT, FAKE_DATASPACE, FAKE_ROTATION,
                 FAKE_ID) {
 
@@ -39,7 +39,7 @@
 
 }
 
-status_t Camera3FakeStream::getBufferLocked(camera3_stream_buffer *,
+status_t Camera3FakeStream::getBufferLocked(camera_stream_buffer *,
         const std::vector<size_t>&) {
     ATRACE_CALL();
     ALOGE("%s: Stream %d: Fake stream cannot produce buffers!", __FUNCTION__, mId);
@@ -47,7 +47,7 @@
 }
 
 status_t Camera3FakeStream::returnBufferLocked(
-        const camera3_stream_buffer &,
+        const camera_stream_buffer &,
         nsecs_t, const std::vector<size_t>&) {
     ATRACE_CALL();
     ALOGE("%s: Stream %d: Fake stream cannot return buffers!", __FUNCTION__, mId);
@@ -55,7 +55,7 @@
 }
 
 status_t Camera3FakeStream::returnBufferCheckedLocked(
-            const camera3_stream_buffer &,
+            const camera_stream_buffer &,
             nsecs_t,
             bool,
             const std::vector<size_t>&,
diff --git a/services/camera/libcameraservice/device3/Camera3FakeStream.h b/services/camera/libcameraservice/device3/Camera3FakeStream.h
index fbf37e6..4a99079 100644
--- a/services/camera/libcameraservice/device3/Camera3FakeStream.h
+++ b/services/camera/libcameraservice/device3/Camera3FakeStream.h
@@ -104,7 +104,7 @@
      * Note that we release the lock briefly in this function
      */
     virtual status_t returnBufferCheckedLocked(
-            const camera3_stream_buffer &buffer,
+            const camera_stream_buffer &buffer,
             nsecs_t timestamp,
             bool output,
             const std::vector<size_t>& surface_ids,
@@ -121,17 +121,17 @@
     static const int FAKE_HEIGHT = 240;
     static const int FAKE_FORMAT = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
     static const android_dataspace FAKE_DATASPACE = HAL_DATASPACE_UNKNOWN;
-    static const camera3_stream_rotation_t FAKE_ROTATION = CAMERA3_STREAM_ROTATION_0;
+    static const camera_stream_rotation_t FAKE_ROTATION = CAMERA_STREAM_ROTATION_0;
     static const uint64_t FAKE_USAGE = GRALLOC_USAGE_HW_COMPOSER;
     static const String8 FAKE_ID;
 
     /**
      * Internal Camera3Stream interface
      */
-    virtual status_t getBufferLocked(camera3_stream_buffer *buffer,
+    virtual status_t getBufferLocked(camera_stream_buffer *buffer,
             const std::vector<size_t>& surface_ids = std::vector<size_t>());
     virtual status_t returnBufferLocked(
-            const camera3_stream_buffer &buffer,
+            const camera_stream_buffer &buffer,
             nsecs_t timestamp, const std::vector<size_t>& surface_ids);
 
     virtual status_t configureQueueLocked();
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index bda2961..f6acda8 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -29,9 +29,9 @@
 
 namespace camera3 {
 
-Camera3IOStreamBase::Camera3IOStreamBase(int id, camera3_stream_type_t type,
+Camera3IOStreamBase::Camera3IOStreamBase(int id, camera_stream_type_t type,
         uint32_t width, uint32_t height, size_t maxSize, int format,
-        android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+        android_dataspace dataSpace, camera_stream_rotation_t rotation,
         const String8& physicalCameraId, int setId) :
         Camera3Stream(id, type,
                 width, height, maxSize, format, dataSpace, rotation,
@@ -77,13 +77,13 @@
 
     lines.appendFormat("      State: %d\n", mState);
     lines.appendFormat("      Dims: %d x %d, format 0x%x, dataspace 0x%x\n",
-            camera3_stream::width, camera3_stream::height,
-            camera3_stream::format, camera3_stream::data_space);
+            camera_stream::width, camera_stream::height,
+            camera_stream::format, camera_stream::data_space);
     lines.appendFormat("      Max size: %zu\n", mMaxSize);
     lines.appendFormat("      Combined usage: %" PRIu64 ", max HAL buffers: %d\n",
-            mUsage | consumerUsage, camera3_stream::max_buffers);
-    if (strlen(camera3_stream::physical_camera_id) > 0) {
-        lines.appendFormat("      Physical camera id: %s\n", camera3_stream::physical_camera_id);
+            mUsage | consumerUsage, camera_stream::max_buffers);
+    if (strlen(camera_stream::physical_camera_id) > 0) {
+        lines.appendFormat("      Physical camera id: %s\n", camera_stream::physical_camera_id);
     }
     lines.appendFormat("      Frames produced: %d, last timestamp: %" PRId64 " ns\n",
             mFrameCount, mLastTimestamp);
@@ -150,11 +150,11 @@
    return OK;
 }
 
-void Camera3IOStreamBase::handoutBufferLocked(camera3_stream_buffer &buffer,
+void Camera3IOStreamBase::handoutBufferLocked(camera_stream_buffer &buffer,
                                               buffer_handle_t *handle,
                                               int acquireFence,
                                               int releaseFence,
-                                              camera3_buffer_status_t status,
+                                              camera_buffer_status_t status,
                                               bool output) {
     /**
      * Note that all fences are now owned by HAL.
@@ -220,7 +220,7 @@
 }
 
 status_t Camera3IOStreamBase::returnAnyBufferLocked(
-        const camera3_stream_buffer &buffer,
+        const camera_stream_buffer &buffer,
         nsecs_t timestamp,
         bool output,
         const std::vector<size_t>& surface_ids) {
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index ca62239..719fa14 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -32,9 +32,9 @@
 class Camera3IOStreamBase :
         public Camera3Stream {
   protected:
-    Camera3IOStreamBase(int id, camera3_stream_type_t type,
+    Camera3IOStreamBase(int id, camera_stream_type_t type,
             uint32_t width, uint32_t height, size_t maxSize, int format,
-            android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+            android_dataspace dataSpace, camera_stream_rotation_t rotation,
             const String8& physicalCameraId,
             int setId = CAMERA3_STREAM_SET_ID_INVALID);
 
@@ -64,13 +64,13 @@
     sp<Fence>         mCombinedFence;
 
     status_t         returnAnyBufferLocked(
-            const camera3_stream_buffer &buffer,
+            const camera_stream_buffer &buffer,
             nsecs_t timestamp,
             bool output,
             const std::vector<size_t>& surface_ids = std::vector<size_t>());
 
     virtual status_t returnBufferCheckedLocked(
-            const camera3_stream_buffer &buffer,
+            const camera_stream_buffer &buffer,
             nsecs_t timestamp,
             bool output,
             const std::vector<size_t>& surface_ids,
@@ -100,11 +100,11 @@
 
     // Hand out the buffer to a native location,
     //   incrementing the internal refcount and dequeued buffer count
-    void handoutBufferLocked(camera3_stream_buffer &buffer,
+    void handoutBufferLocked(camera_stream_buffer &buffer,
                              buffer_handle_t *handle,
                              int acquire_fence,
                              int release_fence,
-                             camera3_buffer_status_t status,
+                             camera_buffer_status_t status,
                              bool output);
 
 }; // class Camera3IOStreamBase
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index ebd33e9..ad70a3a 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -31,8 +31,8 @@
 
 Camera3InputStream::Camera3InputStream(int id,
         uint32_t width, uint32_t height, int format) :
-        Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height, /*maxSize*/0,
-                            format, HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0,
+        Camera3IOStreamBase(id, CAMERA_STREAM_INPUT, width, height, /*maxSize*/0,
+                            format, HAL_DATASPACE_UNKNOWN, CAMERA_STREAM_ROTATION_0,
                             FAKE_ID) {
 
     if (format == HAL_PIXEL_FORMAT_BLOB) {
@@ -46,7 +46,7 @@
 }
 
 status_t Camera3InputStream::getInputBufferLocked(
-        camera3_stream_buffer *buffer) {
+        camera_stream_buffer *buffer) {
     ATRACE_CALL();
     status_t res;
 
@@ -86,7 +86,7 @@
      * in which case we reassign it to acquire_fence
      */
     handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
-                        /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/false);
+                        /*releaseFence*/-1, CAMERA_BUFFER_STATUS_OK, /*output*/false);
     mBuffersInFlight.push_back(bufferItem);
 
     mFrameCount++;
@@ -96,7 +96,7 @@
 }
 
 status_t Camera3InputStream::returnBufferCheckedLocked(
-            const camera3_stream_buffer &buffer,
+            const camera_stream_buffer &buffer,
             nsecs_t timestamp,
             bool output,
             const std::vector<size_t>&,
@@ -134,7 +134,7 @@
         return INVALID_OPERATION;
     }
 
-    if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
+    if (buffer.status == CAMERA_BUFFER_STATUS_ERROR) {
         if (buffer.release_fence != -1) {
             ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when "
                   "there is an error", __FUNCTION__, mId, buffer.release_fence);
@@ -144,7 +144,7 @@
         /**
          * Reassign release fence as the acquire fence incase of error
          */
-        const_cast<camera3_stream_buffer*>(&buffer)->release_fence =
+        const_cast<camera_stream_buffer*>(&buffer)->release_fence =
                 buffer.acquire_fence;
     }
 
@@ -165,7 +165,7 @@
 }
 
 status_t Camera3InputStream::returnInputBufferLocked(
-        const camera3_stream_buffer &buffer) {
+        const camera_stream_buffer &buffer) {
     ATRACE_CALL();
 
     return returnAnyBufferLocked(buffer, /*timestamp*/0, /*output*/false);
@@ -224,7 +224,7 @@
     }
 
     assert(mMaxSize == 0);
-    assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB);
+    assert(camera_stream::format != HAL_PIXEL_FORMAT_BLOB);
 
     mHandoutTotalBufferCount = 0;
     mFrameCount = 0;
@@ -244,14 +244,14 @@
         }
         size_t minBufs = static_cast<size_t>(minUndequeuedBuffers);
 
-        if (camera3_stream::max_buffers == 0) {
+        if (camera_stream::max_buffers == 0) {
             ALOGE("%s: %d: HAL sets max_buffer to 0. Must be at least 1.",
                     __FUNCTION__, __LINE__);
             return INVALID_OPERATION;
         }
 
         /*
-         * We promise never to 'acquire' more than camera3_stream::max_buffers
+         * We promise never to 'acquire' more than camera_stream::max_buffers
          * at any one time.
          *
          * Boost the number up to meet the minimum required buffer count.
@@ -259,8 +259,8 @@
          * (Note that this sets consumer-side buffer count only,
          * and not the sum of producer+consumer side as in other camera streams).
          */
-        mTotalBufferCount = camera3_stream::max_buffers > minBufs ?
-            camera3_stream::max_buffers : minBufs;
+        mTotalBufferCount = camera_stream::max_buffers > minBufs ?
+            camera_stream::max_buffers : minBufs;
         // TODO: somehow set the total buffer count when producer connects?
 
         mConsumer = new BufferItemConsumer(consumer, mUsage,
@@ -272,17 +272,17 @@
         mConsumer->setBufferFreedListener(this);
     }
 
-    res = mConsumer->setDefaultBufferSize(camera3_stream::width,
-                                          camera3_stream::height);
+    res = mConsumer->setDefaultBufferSize(camera_stream::width,
+                                          camera_stream::height);
     if (res != OK) {
         ALOGE("%s: Stream %d: Could not set buffer dimensions %dx%d",
-              __FUNCTION__, mId, camera3_stream::width, camera3_stream::height);
+              __FUNCTION__, mId, camera_stream::width, camera_stream::height);
         return res;
     }
-    res = mConsumer->setDefaultBufferFormat(camera3_stream::format);
+    res = mConsumer->setDefaultBufferFormat(camera_stream::format);
     if (res != OK) {
         ALOGE("%s: Stream %d: Could not set buffer format %d",
-              __FUNCTION__, mId, camera3_stream::format);
+              __FUNCTION__, mId, camera_stream::format);
         return res;
     }
 
@@ -298,8 +298,8 @@
 void Camera3InputStream::onBufferFreed(const wp<GraphicBuffer>& gb) {
     const sp<GraphicBuffer> buffer = gb.promote();
     if (buffer != nullptr) {
-        camera3_stream_buffer streamBuffer =
-                {nullptr, &buffer->handle, 0, -1, -1};
+        camera_stream_buffer streamBuffer =
+                {nullptr, &buffer->handle, CAMERA_BUFFER_STATUS_OK, -1, -1};
         // Check if this buffer is outstanding.
         if (isOutstandingBuffer(streamBuffer)) {
             ALOGV("%s: Stream %d: Trying to free a buffer that is still being "
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index 22697b7..03afa17 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -59,7 +59,7 @@
      * Camera3IOStreamBase
      */
     virtual status_t returnBufferCheckedLocked(
-            const camera3_stream_buffer &buffer,
+            const camera_stream_buffer &buffer,
             nsecs_t timestamp,
             bool output,
             const std::vector<size_t>& surface_ids,
@@ -70,9 +70,9 @@
      * Camera3Stream interface
      */
 
-    virtual status_t getInputBufferLocked(camera3_stream_buffer *buffer);
+    virtual status_t getInputBufferLocked(camera_stream_buffer *buffer);
     virtual status_t returnInputBufferLocked(
-            const camera3_stream_buffer &buffer);
+            const camera_stream_buffer &buffer);
     virtual status_t getInputBufferProducerLocked(
             sp<IGraphicBufferProducer> *producer);
     virtual status_t disconnectLocked();
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 7b812f2..4b5889c 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -18,8 +18,15 @@
 #define ATRACE_TAG ATRACE_TAG_CAMERA
 //#define LOG_NDEBUG 0
 
+#include <ctime>
+#include <fstream>
+
+#include <android-base/unique_fd.h>
+#include <ui/GraphicBuffer.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
+
+#include "api1/client2/JpegProcessor.h"
 #include "Camera3OutputStream.h"
 #include "utils/TraceHFR.h"
 
@@ -35,10 +42,10 @@
 Camera3OutputStream::Camera3OutputStream(int id,
         sp<Surface> consumer,
         uint32_t width, uint32_t height, int format,
-        android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+        android_dataspace dataSpace, camera_stream_rotation_t rotation,
         nsecs_t timestampOffset, const String8& physicalCameraId,
         int setId) :
-        Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
+        Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
                             /*maxSize*/0, format, dataSpace, rotation,
                             physicalCameraId, setId),
         mConsumer(consumer),
@@ -62,9 +69,9 @@
 Camera3OutputStream::Camera3OutputStream(int id,
         sp<Surface> consumer,
         uint32_t width, uint32_t height, size_t maxSize, int format,
-        android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+        android_dataspace dataSpace, camera_stream_rotation_t rotation,
         nsecs_t timestampOffset, const String8& physicalCameraId, int setId) :
-        Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, maxSize,
+        Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height, maxSize,
                             format, dataSpace, rotation, physicalCameraId, setId),
         mConsumer(consumer),
         mTransform(0),
@@ -94,9 +101,9 @@
 Camera3OutputStream::Camera3OutputStream(int id,
         uint32_t width, uint32_t height, int format,
         uint64_t consumerUsage, android_dataspace dataSpace,
-        camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
+        camera_stream_rotation_t rotation, nsecs_t timestampOffset,
         const String8& physicalCameraId, int setId) :
-        Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
+        Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
                             /*maxSize*/0, format, dataSpace, rotation,
                             physicalCameraId, setId),
         mConsumer(nullptr),
@@ -127,11 +134,11 @@
     mBufferProducerListener = new BufferProducerListener(this, needsReleaseNotify);
 }
 
-Camera3OutputStream::Camera3OutputStream(int id, camera3_stream_type_t type,
+Camera3OutputStream::Camera3OutputStream(int id, camera_stream_type_t type,
                                          uint32_t width, uint32_t height,
                                          int format,
                                          android_dataspace dataSpace,
-                                         camera3_stream_rotation_t rotation,
+                                         camera_stream_rotation_t rotation,
                                          const String8& physicalCameraId,
                                          uint64_t consumerUsage, nsecs_t timestampOffset,
                                          int setId) :
@@ -159,7 +166,7 @@
     disconnectLocked();
 }
 
-status_t Camera3OutputStream::getBufferLocked(camera3_stream_buffer *buffer,
+status_t Camera3OutputStream::getBufferLocked(camera_stream_buffer *buffer,
         const std::vector<size_t>&) {
     ATRACE_HFR_CALL();
 
@@ -177,7 +184,7 @@
      * in which case we reassign it to acquire_fence
      */
     handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
-                        /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/true);
+                        /*releaseFence*/-1, CAMERA_BUFFER_STATUS_OK, /*output*/true);
 
     return OK;
 }
@@ -189,7 +196,7 @@
 }
 
 status_t Camera3OutputStream::returnBufferLocked(
-        const camera3_stream_buffer &buffer,
+        const camera_stream_buffer &buffer,
         nsecs_t timestamp, const std::vector<size_t>& surface_ids) {
     ATRACE_HFR_CALL();
 
@@ -206,7 +213,7 @@
 }
 
 status_t Camera3OutputStream::returnBufferCheckedLocked(
-            const camera3_stream_buffer &buffer,
+            const camera_stream_buffer &buffer,
             nsecs_t timestamp,
             bool output,
             const std::vector<size_t>& surface_ids,
@@ -236,11 +243,11 @@
     /**
      * Return buffer back to ANativeWindow
      */
-    if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR || mDropBuffers || timestamp == 0) {
+    if (buffer.status == CAMERA_BUFFER_STATUS_ERROR || mDropBuffers || timestamp == 0) {
         // Cancel buffer
         if (mDropBuffers) {
             ALOGV("%s: Dropping a frame for stream %d.", __FUNCTION__, mId);
-        } else if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
+        } else if (buffer.status == CAMERA_BUFFER_STATUS_ERROR) {
             ALOGV("%s: A frame is dropped for stream %d due to buffer error.", __FUNCTION__, mId);
         } else {
             ALOGE("%s: Stream %d: timestamp shouldn't be 0", __FUNCTION__, mId);
@@ -260,7 +267,7 @@
             mBufferProducerListener->onBufferReleased();
         }
     } else {
-        if (mTraceFirstBuffer && (stream_type == CAMERA3_STREAM_OUTPUT)) {
+        if (mTraceFirstBuffer && (stream_type == CAMERA_STREAM_OUTPUT)) {
             {
                 char traceLog[48];
                 snprintf(traceLog, sizeof(traceLog), "Stream %d: first full buffer\n", mId);
@@ -279,6 +286,12 @@
                   __FUNCTION__, mId, strerror(-res), res);
             return res;
         }
+        // If this is a JPEG output, and image dump mask is set, save image to
+        // disk.
+        if (getFormat() == HAL_PIXEL_FORMAT_BLOB && getDataSpace() == HAL_DATASPACE_V0_JFIF &&
+                mImageDumpMask) {
+            dumpImageToDisk(timestamp, anwBuffer, anwReleaseFence);
+        }
 
         res = queueBufferToConsumer(currentConsumer, anwBuffer, anwReleaseFence, surface_ids);
         if (shouldLogError(res, state)) {
@@ -290,7 +303,7 @@
 
     // Once a valid buffer has been returned to the queue, can no longer
     // dequeue all buffers for preallocation.
-    if (buffer.status != CAMERA3_BUFFER_STATUS_ERROR) {
+    if (buffer.status != CAMERA_BUFFER_STATUS_ERROR) {
         mStreamUnpreparable = true;
     }
 
@@ -411,7 +424,7 @@
     if (mMaxSize == 0) {
         // For buffers of known size
         res = native_window_set_buffers_dimensions(mConsumer.get(),
-                camera3_stream::width, camera3_stream::height);
+                camera_stream::width, camera_stream::height);
     } else {
         // For buffers with bounded size
         res = native_window_set_buffers_dimensions(mConsumer.get(),
@@ -420,23 +433,23 @@
     if (res != OK) {
         ALOGE("%s: Unable to configure stream buffer dimensions"
                 " %d x %d (maxSize %zu) for stream %d",
-                __FUNCTION__, camera3_stream::width, camera3_stream::height,
+                __FUNCTION__, camera_stream::width, camera_stream::height,
                 mMaxSize, mId);
         return res;
     }
     res = native_window_set_buffers_format(mConsumer.get(),
-            camera3_stream::format);
+            camera_stream::format);
     if (res != OK) {
         ALOGE("%s: Unable to configure stream buffer format %#x for stream %d",
-                __FUNCTION__, camera3_stream::format, mId);
+                __FUNCTION__, camera_stream::format, mId);
         return res;
     }
 
     res = native_window_set_buffers_data_space(mConsumer.get(),
-            camera3_stream::data_space);
+            camera_stream::data_space);
     if (res != OK) {
         ALOGE("%s: Unable to configure stream dataspace %#x for stream %d",
-                __FUNCTION__, camera3_stream::data_space, mId);
+                __FUNCTION__, camera_stream::data_space, mId);
         return res;
     }
 
@@ -451,14 +464,14 @@
     }
 
     ALOGV("%s: Consumer wants %d buffers, HAL wants %d", __FUNCTION__,
-            maxConsumerBuffers, camera3_stream::max_buffers);
-    if (camera3_stream::max_buffers == 0) {
+            maxConsumerBuffers, camera_stream::max_buffers);
+    if (camera_stream::max_buffers == 0) {
         ALOGE("%s: Camera HAL requested max_buffer count: %d, requires at least 1",
-                __FUNCTION__, camera3_stream::max_buffers);
+                __FUNCTION__, camera_stream::max_buffers);
         return INVALID_OPERATION;
     }
 
-    mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers;
+    mTotalBufferCount = maxConsumerBuffers + camera_stream::max_buffers;
     mHandoutTotalBufferCount = 0;
     mFrameCount = 0;
     mLastTimestamp = 0;
@@ -750,7 +763,7 @@
     uint64_t u = 0;
 
     res = native_window_get_consumer_usage(static_cast<ANativeWindow*>(surface.get()), &u);
-    applyZSLUsageQuirk(camera3_stream::format, &u);
+    applyZSLUsageQuirk(camera_stream::format, &u);
     *usage = u;
     return res;
 }
@@ -957,6 +970,49 @@
     return (usage & GRALLOC_USAGE_HW_TEXTURE) != 0;
 }
 
+void Camera3OutputStream::dumpImageToDisk(nsecs_t timestamp,
+        ANativeWindowBuffer* anwBuffer, int fence) {
+    // Deriver output file name
+    std::string fileExtension = "jpg";
+    char imageFileName[64];
+    time_t now = time(0);
+    tm *localTime = localtime(&now);
+    snprintf(imageFileName, sizeof(imageFileName), "IMG_%4d%02d%02d_%02d%02d%02d_%" PRId64 ".%s",
+            1900 + localTime->tm_year, localTime->tm_mon, localTime->tm_mday,
+            localTime->tm_hour, localTime->tm_min, localTime->tm_sec,
+            timestamp, fileExtension.c_str());
+
+    // Lock the image for CPU read
+    sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(anwBuffer);
+    void* mapped = nullptr;
+    base::unique_fd fenceFd(dup(fence));
+    status_t res = graphicBuffer->lockAsync(GraphicBuffer::USAGE_SW_READ_OFTEN, &mapped,
+            fenceFd.get());
+    if (res != OK) {
+        ALOGE("%s: Failed to lock the buffer: %s (%d)", __FUNCTION__, strerror(-res), res);
+        return;
+    }
+
+    // Figure out actual file size
+    auto actualJpegSize = android::camera2::JpegProcessor::findJpegSize((uint8_t*)mapped, mMaxSize);
+    if (actualJpegSize == 0) {
+        actualJpegSize = mMaxSize;
+    }
+
+    // Output image data to file
+    std::string filePath = "/data/misc/cameraserver/";
+    filePath += imageFileName;
+    std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
+    if (!imageFile.is_open()) {
+        ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
+        graphicBuffer->unlock();
+        return;
+    }
+    imageFile.write((const char*)mapped, actualJpegSize);
+
+    graphicBuffer->unlock();
+}
+
 }; // namespace camera3
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index b4e49f9..f504171 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -81,7 +81,7 @@
      */
     Camera3OutputStream(int id, sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
-            android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+            android_dataspace dataSpace, camera_stream_rotation_t rotation,
             nsecs_t timestampOffset, const String8& physicalCameraId,
             int setId = CAMERA3_STREAM_SET_ID_INVALID);
 
@@ -93,7 +93,7 @@
      */
     Camera3OutputStream(int id, sp<Surface> consumer,
             uint32_t width, uint32_t height, size_t maxSize, int format,
-            android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+            android_dataspace dataSpace, camera_stream_rotation_t rotation,
             nsecs_t timestampOffset, const String8& physicalCameraId,
             int setId = CAMERA3_STREAM_SET_ID_INVALID);
 
@@ -104,7 +104,7 @@
      */
     Camera3OutputStream(int id, uint32_t width, uint32_t height, int format,
             uint64_t consumerUsage, android_dataspace dataSpace,
-            camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
+            camera_stream_rotation_t rotation, nsecs_t timestampOffset,
             const String8& physicalCameraId,
             int setId = CAMERA3_STREAM_SET_ID_INVALID);
 
@@ -210,10 +210,12 @@
      */
     static void applyZSLUsageQuirk(int format, uint64_t *consumerUsage /*inout*/);
 
+    void setImageDumpMask(int mask) { mImageDumpMask = mask; }
+
   protected:
-    Camera3OutputStream(int id, camera3_stream_type_t type,
+    Camera3OutputStream(int id, camera_stream_type_t type,
             uint32_t width, uint32_t height, int format,
-            android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+            android_dataspace dataSpace, camera_stream_rotation_t rotation,
             const String8& physicalCameraId,
             uint64_t consumerUsage = 0, nsecs_t timestampOffset = 0,
             int setId = CAMERA3_STREAM_SET_ID_INVALID);
@@ -222,7 +224,7 @@
      * Note that we release the lock briefly in this function
      */
     virtual status_t returnBufferCheckedLocked(
-            const camera3_stream_buffer &buffer,
+            const camera_stream_buffer &buffer,
             nsecs_t timestamp,
             bool output,
             const std::vector<size_t>& surface_ids,
@@ -293,11 +295,11 @@
     /**
      * Internal Camera3Stream interface
      */
-    virtual status_t getBufferLocked(camera3_stream_buffer *buffer,
+    virtual status_t getBufferLocked(camera_stream_buffer *buffer,
             const std::vector<size_t>& surface_ids);
 
     virtual status_t returnBufferLocked(
-            const camera3_stream_buffer &buffer,
+            const camera_stream_buffer &buffer,
             nsecs_t timestamp, const std::vector<size_t>& surface_ids);
 
     virtual status_t queueBufferToConsumer(sp<ANativeWindow>& consumer,
@@ -325,9 +327,14 @@
     // STATE_ABANDONED
     static bool shouldLogError(status_t res, StreamState state);
 
+    // Dump images to disk before returning to consumer
+    void dumpImageToDisk(nsecs_t timestamp, ANativeWindowBuffer* anwBuffer, int fence);
+
     static const int32_t kDequeueLatencyBinSize = 5; // in ms
     CameraLatencyHistogram mDequeueBufferLatency;
 
+    int mImageDumpMask = 0;
+
 }; // class Camera3OutputStream
 
 } // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index f88b062..384c2c6 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -484,7 +484,7 @@
     states.inflightIntf.checkInflightMapLengthLocked();
 }
 
-void processCaptureResult(CaptureOutputStates& states, const camera3_capture_result *result) {
+void processCaptureResult(CaptureOutputStates& states, const camera_capture_result *result) {
     ATRACE_CALL();
 
     status_t res;
@@ -688,7 +688,7 @@
     using hardware::camera::device::V3_2::BufferStatus;
     std::unique_ptr<ResultMetadataQueue>& fmq = states.fmq;
     BufferRecordsInterface& bufferRecords = states.bufferRecordsIntf;
-    camera3_capture_result r;
+    camera_capture_result r;
     status_t res;
     r.frame_number = result.frameNumber;
 
@@ -727,7 +727,7 @@
     r.physcam_ids = physCamIds.data();
     r.physcam_metadata = phyCamMetadatas.data();
 
-    std::vector<camera3_stream_buffer_t> outputBuffers(result.outputBuffers.size());
+    std::vector<camera_stream_buffer_t> outputBuffers(result.outputBuffers.size());
     std::vector<buffer_handle_t> outputBufferHandles(result.outputBuffers.size());
     for (size_t i = 0; i < result.outputBuffers.size(); i++) {
         auto& bDst = outputBuffers[i];
@@ -788,7 +788,7 @@
     r.num_output_buffers = outputBuffers.size();
     r.output_buffers = outputBuffers.data();
 
-    camera3_stream_buffer_t inputBuffer;
+    camera_stream_buffer_t inputBuffer;
     if (result.inputBuffer.streamId == -1) {
         r.input_buffer = nullptr;
     } else {
@@ -829,7 +829,7 @@
 void returnOutputBuffers(
         bool useHalBufManager,
         sp<NotificationListener> listener,
-        const camera3_stream_buffer_t *outputBuffers, size_t numBuffers,
+        const camera_stream_buffer_t *outputBuffers, size_t numBuffers,
         nsecs_t timestamp, bool requested, nsecs_t requestTimeNs,
         SessionStatsBuilder& sessionStatsBuilder, bool timestampIncreasing,
         const SurfaceMap& outputSurfaces,
@@ -842,7 +842,7 @@
         int streamId = stream->getId();
 
         // Call notify(ERROR_BUFFER) if necessary.
-        if (outputBuffers[i].status == CAMERA3_BUFFER_STATUS_ERROR &&
+        if (outputBuffers[i].status == CAMERA_BUFFER_STATUS_ERROR &&
                 errorBufStrategy == ERROR_BUF_RETURN_NOTIFY) {
             if (listener != nullptr) {
                 CaptureResultExtras extras = inResultExtras;
@@ -872,7 +872,7 @@
 
         // Do not return the buffer if the buffer status is error, and the error
         // buffer strategy is CACHE.
-        if (outputBuffers[i].status != CAMERA3_BUFFER_STATUS_ERROR ||
+        if (outputBuffers[i].status != CAMERA_BUFFER_STATUS_ERROR ||
                 errorBufStrategy != ERROR_BUF_CACHE) {
             if (it != outputSurfaces.end()) {
                 res = stream->returnBuffer(
@@ -894,7 +894,7 @@
             ALOGE("Can't return buffer to its stream: %s (%d)", strerror(-res), res);
             dropped = true;
         } else {
-            if (outputBuffers[i].status == CAMERA3_BUFFER_STATUS_ERROR || timestamp == 0) {
+            if (outputBuffers[i].status == CAMERA_BUFFER_STATUS_ERROR || timestamp == 0) {
                 dropped = true;
             }
         }
@@ -907,10 +907,10 @@
         // Long processing consumers can cause returnBuffer timeout for shared stream
         // If that happens, cancel the buffer and send a buffer error to client
         if (it != outputSurfaces.end() && res == TIMED_OUT &&
-                outputBuffers[i].status == CAMERA3_BUFFER_STATUS_OK) {
+                outputBuffers[i].status == CAMERA_BUFFER_STATUS_OK) {
             // cancel the buffer
-            camera3_stream_buffer_t sb = outputBuffers[i];
-            sb.status = CAMERA3_BUFFER_STATUS_ERROR;
+            camera_stream_buffer_t sb = outputBuffers[i];
+            sb.status = CAMERA_BUFFER_STATUS_ERROR;
             stream->returnBuffer(sb, /*timestamp*/0,
                     timestampIncreasing, std::vector<size_t> (),
                     inResultExtras.frameNumber);
@@ -942,7 +942,7 @@
     for (auto iter = request.pendingOutputBuffers.begin();
             iter != request.pendingOutputBuffers.end(); ) {
         if (request.errorBufStrategy != ERROR_BUF_CACHE ||
-                iter->status != CAMERA3_BUFFER_STATUS_ERROR) {
+                iter->status != CAMERA_BUFFER_STATUS_ERROR) {
             iter = request.pendingOutputBuffers.erase(iter);
         } else {
             iter++;
@@ -950,7 +950,7 @@
     }
 }
 
-void notifyShutter(CaptureOutputStates& states, const camera3_shutter_msg_t &msg) {
+void notifyShutter(CaptureOutputStates& states, const camera_shutter_msg_t &msg) {
     ATRACE_CALL();
     ssize_t idx;
 
@@ -1028,26 +1028,26 @@
     }
 }
 
-void notifyError(CaptureOutputStates& states, const camera3_error_msg_t &msg) {
+void notifyError(CaptureOutputStates& states, const camera_error_msg_t &msg) {
     ATRACE_CALL();
     // Map camera HAL error codes to ICameraDeviceCallback error codes
     // Index into this with the HAL error code
-    static const int32_t halErrorMap[CAMERA3_MSG_NUM_ERRORS] = {
+    static const int32_t halErrorMap[CAMERA_MSG_NUM_ERRORS] = {
         // 0 = Unused error code
         hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR,
-        // 1 = CAMERA3_MSG_ERROR_DEVICE
+        // 1 = CAMERA_MSG_ERROR_DEVICE
         hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
-        // 2 = CAMERA3_MSG_ERROR_REQUEST
+        // 2 = CAMERA_MSG_ERROR_REQUEST
         hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
-        // 3 = CAMERA3_MSG_ERROR_RESULT
+        // 3 = CAMERA_MSG_ERROR_RESULT
         hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT,
-        // 4 = CAMERA3_MSG_ERROR_BUFFER
+        // 4 = CAMERA_MSG_ERROR_BUFFER
         hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER
     };
 
     int32_t errorCode =
             ((msg.error_code >= 0) &&
-                    (msg.error_code < CAMERA3_MSG_NUM_ERRORS)) ?
+                    (msg.error_code < CAMERA_MSG_NUM_ERRORS)) ?
             halErrorMap[msg.error_code] :
             hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR;
 
@@ -1136,13 +1136,13 @@
     }
 }
 
-void notify(CaptureOutputStates& states, const camera3_notify_msg *msg) {
+void notify(CaptureOutputStates& states, const camera_notify_msg *msg) {
     switch (msg->type) {
-        case CAMERA3_MSG_ERROR: {
+        case CAMERA_MSG_ERROR: {
             notifyError(states, msg->message.error);
             break;
         }
-        case CAMERA3_MSG_SHUTTER: {
+        case CAMERA_MSG_SHUTTER: {
             notifyShutter(states, msg->message.shutter);
             break;
         }
@@ -1158,10 +1158,10 @@
     using android::hardware::camera::device::V3_2::ErrorCode;
 
     ATRACE_CALL();
-    camera3_notify_msg m;
+    camera_notify_msg m;
     switch (msg.type) {
         case MsgType::ERROR:
-            m.type = CAMERA3_MSG_ERROR;
+            m.type = CAMERA_MSG_ERROR;
             m.message.error.frame_number = msg.msg.error.frameNumber;
             if (msg.msg.error.errorStreamId >= 0) {
                 sp<Camera3StreamInterface> stream =
@@ -1177,21 +1177,21 @@
             }
             switch (msg.msg.error.errorCode) {
                 case ErrorCode::ERROR_DEVICE:
-                    m.message.error.error_code = CAMERA3_MSG_ERROR_DEVICE;
+                    m.message.error.error_code = CAMERA_MSG_ERROR_DEVICE;
                     break;
                 case ErrorCode::ERROR_REQUEST:
-                    m.message.error.error_code = CAMERA3_MSG_ERROR_REQUEST;
+                    m.message.error.error_code = CAMERA_MSG_ERROR_REQUEST;
                     break;
                 case ErrorCode::ERROR_RESULT:
-                    m.message.error.error_code = CAMERA3_MSG_ERROR_RESULT;
+                    m.message.error.error_code = CAMERA_MSG_ERROR_RESULT;
                     break;
                 case ErrorCode::ERROR_BUFFER:
-                    m.message.error.error_code = CAMERA3_MSG_ERROR_BUFFER;
+                    m.message.error.error_code = CAMERA_MSG_ERROR_BUFFER;
                     break;
             }
             break;
         case MsgType::SHUTTER:
-            m.type = CAMERA3_MSG_SHUTTER;
+            m.type = CAMERA_MSG_SHUTTER;
             m.message.shutter.frame_number = msg.msg.shutter.frameNumber;
             m.message.shutter.timestamp = msg.msg.shutter.timestamp;
             break;
@@ -1292,11 +1292,11 @@
 
         hardware::hidl_vec<StreamBuffer> tmpRetBuffers(numBuffersRequested);
         bool currentReqSucceeds = true;
-        std::vector<camera3_stream_buffer_t> streamBuffers(numBuffersRequested);
+        std::vector<camera_stream_buffer_t> streamBuffers(numBuffersRequested);
         size_t numAllocatedBuffers = 0;
         size_t numPushedInflightBuffers = 0;
         for (size_t b = 0; b < numBuffersRequested; b++) {
-            camera3_stream_buffer_t& sb = streamBuffers[b];
+            camera_stream_buffer_t& sb = streamBuffers[b];
             // Since this method can run concurrently with request thread
             // We need to update the wait duration everytime we call getbuffer
             nsecs_t waitDuration =  states.reqBufferIntf.getWaitDuration();
@@ -1367,9 +1367,9 @@
                 }
             }
             for (size_t b = 0; b < numAllocatedBuffers; b++) {
-                camera3_stream_buffer_t& sb = streamBuffers[b];
+                camera_stream_buffer_t& sb = streamBuffers[b];
                 sb.acquire_fence = -1;
-                sb.status = CAMERA3_BUFFER_STATUS_ERROR;
+                sb.status = CAMERA_BUFFER_STATUS_ERROR;
             }
             returnOutputBuffers(states.useHalBufManager, /*listener*/nullptr,
                     streamBuffers.data(), numAllocatedBuffers, 0, /*requested*/false,
@@ -1407,9 +1407,9 @@
             continue;
         }
 
-        camera3_stream_buffer_t streamBuffer;
+        camera_stream_buffer_t streamBuffer;
         streamBuffer.buffer = buffer;
-        streamBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+        streamBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
         streamBuffer.acquire_fence = -1;
         streamBuffer.release_fence = -1;
 
@@ -1504,19 +1504,19 @@
         int32_t frameNumber = std::get<1>(tuple);
         buffer_handle_t* buffer = std::get<2>(tuple);
 
-        camera3_stream_buffer_t streamBuffer;
+        camera_stream_buffer_t streamBuffer;
         streamBuffer.buffer = buffer;
-        streamBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+        streamBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
         streamBuffer.acquire_fence = -1;
         streamBuffer.release_fence = -1;
 
         for (auto& stream : streams) {
             if (streamId == stream->getId()) {
                 // Return buffer to deleted stream
-                camera3_stream* halStream = stream->asHalStream();
+                camera_stream* halStream = stream->asHalStream();
                 streamBuffer.stream = halStream;
                 switch (halStream->stream_type) {
-                    case CAMERA3_STREAM_OUTPUT:
+                    case CAMERA_STREAM_OUTPUT:
                         res = stream->returnBuffer(streamBuffer, /*timestamp*/ 0,
                                 /*timestampIncreasing*/true,
                                 std::vector<size_t> (), frameNumber);
@@ -1526,7 +1526,7 @@
                                   frameNumber, streamId, strerror(-res), res);
                         }
                         break;
-                    case CAMERA3_STREAM_INPUT:
+                    case CAMERA_STREAM_INPUT:
                         res = stream->returnInputBuffer(streamBuffer);
                         if (res != OK) {
                             ALOGE("%s: Can't return input buffer for frame %d to"
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.h b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
index 45c8a43..772fe6e 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
@@ -42,6 +42,63 @@
 
 namespace camera3 {
 
+    typedef struct camera_stream_configuration {
+        uint32_t num_streams;
+        camera_stream_t **streams;
+        uint32_t operation_mode;
+    } camera_stream_configuration_t;
+
+    typedef struct camera_capture_request {
+        uint32_t frame_number;
+        const camera_metadata_t *settings;
+        camera_stream_buffer_t *input_buffer;
+        uint32_t num_output_buffers;
+        const camera_stream_buffer_t *output_buffers;
+        uint32_t num_physcam_settings;
+        const char **physcam_id;
+        const camera_metadata_t **physcam_settings;
+    } camera_capture_request_t;
+
+    typedef struct camera_capture_result {
+        uint32_t frame_number;
+        const camera_metadata_t *result;
+        uint32_t num_output_buffers;
+        const camera_stream_buffer_t *output_buffers;
+        const camera_stream_buffer_t *input_buffer;
+        uint32_t partial_result;
+        uint32_t num_physcam_metadata;
+        const char **physcam_ids;
+        const camera_metadata_t **physcam_metadata;
+    } camera_capture_result_t;
+
+    typedef struct camera_shutter_msg {
+        uint32_t frame_number;
+        uint64_t timestamp;
+    } camera_shutter_msg_t;
+
+    typedef struct camera_error_msg {
+        uint32_t frame_number;
+        camera_stream_t *error_stream;
+        int error_code;
+    } camera_error_msg_t;
+
+    typedef enum camera_error_msg_code {
+        CAMERA_MSG_ERROR_DEVICE = 1,
+        CAMERA_MSG_ERROR_REQUEST = 2,
+        CAMERA_MSG_ERROR_RESULT = 3,
+        CAMERA_MSG_ERROR_BUFFER = 4,
+        CAMERA_MSG_NUM_ERRORS
+    } camera_error_msg_code_t;
+
+    typedef struct camera_notify_msg {
+        int type;
+
+        union {
+            camera_error_msg_t error;
+            camera_shutter_msg_t shutter;
+        } message;
+    } camera_notify_msg_t;
+
     /**
      * Helper methods shared between Camera3Device/Camera3OfflineSession for HAL callbacks
      */
@@ -51,7 +108,7 @@
     void returnOutputBuffers(
             bool useHalBufManager,
             sp<NotificationListener> listener, // Only needed when outputSurfaces is not empty
-            const camera3_stream_buffer_t *outputBuffers,
+            const camera_stream_buffer_t *outputBuffers,
             size_t numBuffers, nsecs_t timestamp, bool requested, nsecs_t requestTimeNs,
             SessionStatsBuilder& sessionStatsBuilder, bool timestampIncreasing = true,
             // The following arguments are only meant for surface sharing use case
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index 86b45cb..8aa5f1a 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -30,10 +30,10 @@
         const std::vector<sp<Surface>>& surfaces,
         uint32_t width, uint32_t height, int format,
         uint64_t consumerUsage, android_dataspace dataSpace,
-        camera3_stream_rotation_t rotation,
+        camera_stream_rotation_t rotation,
         nsecs_t timestampOffset, const String8& physicalCameraId,
         int setId, bool useHalBufManager) :
-        Camera3OutputStream(id, CAMERA3_STREAM_OUTPUT, width, height,
+        Camera3OutputStream(id, CAMERA_STREAM_OUTPUT, width, height,
                             format, dataSpace, rotation, physicalCameraId,
                             consumerUsage, timestampOffset, setId),
         mUseHalBufManager(useHalBufManager) {
@@ -65,7 +65,7 @@
         }
     }
 
-    res = mStreamSplitter->connect(initialSurfaces, usage, mUsage, camera3_stream::max_buffers,
+    res = mStreamSplitter->connect(initialSurfaces, usage, mUsage, camera_stream::max_buffers,
             getWidth(), getHeight(), getFormat(), &mConsumer);
     if (res != OK) {
         ALOGE("%s: Failed to connect to stream splitter: %s(%d)",
@@ -157,7 +157,7 @@
     return ret;
 }
 
-status_t Camera3SharedOutputStream::getBufferLocked(camera3_stream_buffer *buffer,
+status_t Camera3SharedOutputStream::getBufferLocked(camera_stream_buffer *buffer,
         const std::vector<size_t>& surfaceIds) {
     ANativeWindowBuffer* anb;
     int fenceFd = -1;
@@ -180,7 +180,7 @@
      * in which case we reassign it to acquire_fence
      */
     handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
-                        /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/true);
+                        /*releaseFence*/-1, CAMERA_BUFFER_STATUS_OK, /*output*/true);
 
     return OK;
 }
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index e645e05..a61316c 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -36,7 +36,7 @@
     Camera3SharedOutputStream(int id, const std::vector<sp<Surface>>& surfaces,
             uint32_t width, uint32_t height, int format,
             uint64_t consumerUsage, android_dataspace dataSpace,
-            camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
+            camera_stream_rotation_t rotation, nsecs_t timestampOffset,
             const String8& physicalCameraId,
             int setId = CAMERA3_STREAM_SET_ID_INVALID,
             bool useHalBufManager = false);
@@ -116,7 +116,7 @@
     /**
      * Internal Camera3Stream interface
      */
-    virtual status_t getBufferLocked(camera3_stream_buffer *buffer,
+    virtual status_t getBufferLocked(camera_stream_buffer *buffer,
             const std::vector<size_t>& surface_ids);
 
     virtual status_t queueBufferToConsumer(sp<ANativeWindow>& consumer,
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 9a8f6fe..8d72b4c 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -37,20 +37,20 @@
     }
 }
 
-Camera3Stream* Camera3Stream::cast(camera3_stream *stream) {
+Camera3Stream* Camera3Stream::cast(camera_stream *stream) {
     return static_cast<Camera3Stream*>(stream);
 }
 
-const Camera3Stream* Camera3Stream::cast(const camera3_stream *stream) {
+const Camera3Stream* Camera3Stream::cast(const camera_stream *stream) {
     return static_cast<const Camera3Stream*>(stream);
 }
 
 Camera3Stream::Camera3Stream(int id,
-        camera3_stream_type type,
+        camera_stream_type type,
         uint32_t width, uint32_t height, size_t maxSize, int format,
-        android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+        android_dataspace dataSpace, camera_stream_rotation_t rotation,
         const String8& physicalCameraId, int setId) :
-    camera3_stream(),
+    camera_stream(),
     mId(id),
     mSetId(setId),
     mName(String8::format("Camera3Stream[%d]", id)),
@@ -75,15 +75,14 @@
     mPhysicalCameraId(physicalCameraId),
     mLastTimestamp(0) {
 
-    camera3_stream::stream_type = type;
-    camera3_stream::width = width;
-    camera3_stream::height = height;
-    camera3_stream::format = format;
-    camera3_stream::data_space = dataSpace;
-    camera3_stream::rotation = rotation;
-    camera3_stream::max_buffers = 0;
-    camera3_stream::priv = NULL;
-    camera3_stream::physical_camera_id = mPhysicalCameraId.string();
+    camera_stream::stream_type = type;
+    camera_stream::width = width;
+    camera_stream::height = height;
+    camera_stream::format = format;
+    camera_stream::data_space = dataSpace;
+    camera_stream::rotation = rotation;
+    camera_stream::max_buffers = 0;
+    camera_stream::physical_camera_id = mPhysicalCameraId.string();
 
     if ((format == HAL_PIXEL_FORMAT_BLOB || format == HAL_PIXEL_FORMAT_RAW_OPAQUE) &&
             maxSize == 0) {
@@ -101,19 +100,19 @@
 }
 
 uint32_t Camera3Stream::getWidth() const {
-    return camera3_stream::width;
+    return camera_stream::width;
 }
 
 uint32_t Camera3Stream::getHeight() const {
-    return camera3_stream::height;
+    return camera_stream::height;
 }
 
 int Camera3Stream::getFormat() const {
-    return camera3_stream::format;
+    return camera_stream::format;
 }
 
 android_dataspace Camera3Stream::getDataSpace() const {
-    return camera3_stream::data_space;
+    return camera_stream::data_space;
 }
 
 uint64_t Camera3Stream::getUsage() const {
@@ -153,7 +152,7 @@
 }
 
 int Camera3Stream::getMaxHalBuffers() const {
-    return camera3_stream::max_buffers;
+    return camera_stream::max_buffers;
 }
 
 void Camera3Stream::setOfflineProcessingSupport(bool support) {
@@ -233,7 +232,7 @@
     return res;
 }
 
-camera3_stream* Camera3Stream::startConfiguration() {
+camera_stream* Camera3Stream::startConfiguration() {
     ATRACE_CALL();
     Mutex::Autolock l(mLock);
     status_t res;
@@ -264,9 +263,9 @@
     }
 
     mOldUsage = mUsage;
-    mOldMaxBuffers = camera3_stream::max_buffers;
-    mOldFormat = camera3_stream::format;
-    mOldDataSpace = camera3_stream::data_space;
+    mOldMaxBuffers = camera_stream::max_buffers;
+    mOldFormat = camera_stream::format;
+    mOldDataSpace = camera_stream::data_space;
 
     res = getEndpointUsage(&mUsage);
     if (res != OK) {
@@ -339,12 +338,12 @@
     }
 
     // Check if the stream configuration is unchanged, and skip reallocation if
-    // so. As documented in hardware/camera3.h:configure_streams().
+    // so.
     if (mState == STATE_IN_RECONFIG &&
             mOldUsage == mUsage &&
-            mOldMaxBuffers == camera3_stream::max_buffers &&
-            mOldDataSpace == camera3_stream::data_space &&
-            mOldFormat == camera3_stream::format) {
+            mOldMaxBuffers == camera_stream::max_buffers &&
+            mOldDataSpace == camera_stream::data_space &&
+            mOldFormat == camera_stream::format) {
         mState = STATE_CONFIGURED;
         return OK;
     }
@@ -403,7 +402,7 @@
     }
 
     mUsage = mOldUsage;
-    camera3_stream::max_buffers = mOldMaxBuffers;
+    camera_stream::max_buffers = mOldMaxBuffers;
 
     mState = ((mState == STATE_IN_RECONFIG) || (mState == STATE_IN_IDLE)) ? STATE_CONFIGURED :
             STATE_CONSTRUCTED;
@@ -463,7 +462,7 @@
 
     mLastMaxCount = bufferCount;
 
-    mPreparedBuffers.insertAt(camera3_stream_buffer_t(), /*index*/0, bufferCount);
+    mPreparedBuffers.insertAt(camera_stream_buffer_t(), /*index*/0, bufferCount);
     mPreparedBufferIdx = 0;
 
     mState = STATE_PREPARING;
@@ -538,7 +537,7 @@
     // they weren't filled.
     for (size_t i = 0; i < mPreparedBufferIdx; i++) {
         mPreparedBuffers.editItemAt(i).release_fence = -1;
-        mPreparedBuffers.editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
+        mPreparedBuffers.editItemAt(i).status = CAMERA_BUFFER_STATUS_ERROR;
         returnBufferLocked(mPreparedBuffers[i], 0);
     }
     mPreparedBuffers.clear();
@@ -604,7 +603,7 @@
     return OK;
 }
 
-status_t Camera3Stream::getBuffer(camera3_stream_buffer *buffer,
+status_t Camera3Stream::getBuffer(camera_stream_buffer *buffer,
         nsecs_t waitBufferTimeout,
         const std::vector<size_t>& surface_ids) {
     ATRACE_HFR_CALL();
@@ -623,9 +622,9 @@
     }
 
     // Wait for new buffer returned back if we are running into the limit.
-    if (getHandoutOutputBufferCountLocked() == camera3_stream::max_buffers) {
+    if (getHandoutOutputBufferCountLocked() == camera_stream::max_buffers) {
         ALOGV("%s: Already dequeued max output buffers (%d), wait for next returned one.",
-                        __FUNCTION__, camera3_stream::max_buffers);
+                        __FUNCTION__, camera_stream::max_buffers);
         nsecs_t waitStart = systemTime(SYSTEM_TIME_MONOTONIC);
         if (waitBufferTimeout < kWaitForBufferDuration) {
             waitBufferTimeout = kWaitForBufferDuration;
@@ -637,7 +636,7 @@
             if (res == TIMED_OUT) {
                 ALOGE("%s: wait for output buffer return timed out after %lldms (max_buffers %d)",
                         __FUNCTION__, waitBufferTimeout / 1000000LL,
-                        camera3_stream::max_buffers);
+                        camera_stream::max_buffers);
             }
             return res;
         }
@@ -655,7 +654,7 @@
     return res;
 }
 
-bool Camera3Stream::isOutstandingBuffer(const camera3_stream_buffer &buffer) const{
+bool Camera3Stream::isOutstandingBuffer(const camera_stream_buffer &buffer) const{
     if (buffer.buffer == nullptr) {
         return false;
     }
@@ -670,7 +669,7 @@
     return false;
 }
 
-void Camera3Stream::removeOutstandingBuffer(const camera3_stream_buffer &buffer) {
+void Camera3Stream::removeOutstandingBuffer(const camera_stream_buffer &buffer) {
     if (buffer.buffer == nullptr) {
         return;
     }
@@ -685,7 +684,7 @@
     }
 }
 
-status_t Camera3Stream::returnBuffer(const camera3_stream_buffer &buffer,
+status_t Camera3Stream::returnBuffer(const camera_stream_buffer &buffer,
         nsecs_t timestamp, bool timestampIncreasing,
          const std::vector<size_t>& surface_ids, uint64_t frameNumber) {
     ATRACE_HFR_CALL();
@@ -700,11 +699,11 @@
     removeOutstandingBuffer(buffer);
 
     // Buffer status may be changed, so make a copy of the stream_buffer struct.
-    camera3_stream_buffer b = buffer;
+    camera_stream_buffer b = buffer;
     if (timestampIncreasing && timestamp != 0 && timestamp <= mLastTimestamp) {
         ALOGE("%s: Stream %d: timestamp %" PRId64 " is not increasing. Prev timestamp %" PRId64,
                 __FUNCTION__, mId, timestamp, mLastTimestamp);
-        b.status = CAMERA3_BUFFER_STATUS_ERROR;
+        b.status = CAMERA_BUFFER_STATUS_ERROR;
     }
     mLastTimestamp = timestamp;
 
@@ -728,7 +727,7 @@
     return res;
 }
 
-status_t Camera3Stream::getInputBuffer(camera3_stream_buffer *buffer, bool respectHalLimit) {
+status_t Camera3Stream::getInputBuffer(camera_stream_buffer *buffer, bool respectHalLimit) {
     ATRACE_CALL();
     Mutex::Autolock l(mLock);
     status_t res = OK;
@@ -741,9 +740,9 @@
     }
 
     // Wait for new buffer returned back if we are running into the limit.
-    if (getHandoutInputBufferCountLocked() == camera3_stream::max_buffers && respectHalLimit) {
+    if (getHandoutInputBufferCountLocked() == camera_stream::max_buffers && respectHalLimit) {
         ALOGV("%s: Already dequeued max input buffers (%d), wait for next returned one.",
-                __FUNCTION__, camera3_stream::max_buffers);
+                __FUNCTION__, camera_stream::max_buffers);
         res = mInputBufferReturnedSignal.waitRelative(mLock, kWaitForBufferDuration);
         if (res != OK) {
             if (res == TIMED_OUT) {
@@ -766,7 +765,7 @@
     return res;
 }
 
-status_t Camera3Stream::returnInputBuffer(const camera3_stream_buffer &buffer) {
+status_t Camera3Stream::returnInputBuffer(const camera_stream_buffer &buffer) {
     ATRACE_CALL();
     Mutex::Autolock l(mLock);
 
@@ -808,7 +807,7 @@
 }
 
 void Camera3Stream::fireBufferListenersLocked(
-        const camera3_stream_buffer& buffer, bool acquired, bool output, nsecs_t timestamp,
+        const camera_stream_buffer& buffer, bool acquired, bool output, nsecs_t timestamp,
         uint64_t frameNumber) {
     List<wp<Camera3StreamBufferListener> >::iterator it, end;
 
@@ -817,7 +816,7 @@
     Camera3StreamBufferListener::BufferInfo info =
         Camera3StreamBufferListener::BufferInfo();
     info.mOutput = output;
-    info.mError = (buffer.status == CAMERA3_BUFFER_STATUS_ERROR);
+    info.mError = (buffer.status == CAMERA_BUFFER_STATUS_ERROR);
     info.mFrameNumber = frameNumber;
     info.mTimestamp = timestamp;
     info.mStreamId = getId();
@@ -887,22 +886,22 @@
             "      Latency histogram for wait on max_buffers");
 }
 
-status_t Camera3Stream::getBufferLocked(camera3_stream_buffer *,
+status_t Camera3Stream::getBufferLocked(camera_stream_buffer *,
         const std::vector<size_t>&) {
     ALOGE("%s: This type of stream does not support output", __FUNCTION__);
     return INVALID_OPERATION;
 }
-status_t Camera3Stream::returnBufferLocked(const camera3_stream_buffer &,
+status_t Camera3Stream::returnBufferLocked(const camera_stream_buffer &,
                                            nsecs_t, const std::vector<size_t>&) {
     ALOGE("%s: This type of stream does not support output", __FUNCTION__);
     return INVALID_OPERATION;
 }
-status_t Camera3Stream::getInputBufferLocked(camera3_stream_buffer *) {
+status_t Camera3Stream::getInputBufferLocked(camera_stream_buffer *) {
     ALOGE("%s: This type of stream does not support input", __FUNCTION__);
     return INVALID_OPERATION;
 }
 status_t Camera3Stream::returnInputBufferLocked(
-        const camera3_stream_buffer &) {
+        const camera_stream_buffer &) {
     ALOGE("%s: This type of stream does not support input", __FUNCTION__);
     return INVALID_OPERATION;
 }
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 3654f89..47dc252 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -23,8 +23,6 @@
 #include <utils/String16.h>
 #include <utils/List.h>
 
-#include "hardware/camera3.h"
-
 #include "utils/LatencyHistogram.h"
 #include "Camera3StreamBufferListener.h"
 #include "Camera3StreamInterface.h"
@@ -50,7 +48,7 @@
  *    with the HAL.
  *
  *  STATE_IN_CONFIG: Configuration has started, but not yet concluded. During this
- *    time, the usage, max_buffers, and priv fields of camera3_stream returned by
+ *    time, the usage, max_buffers, and priv fields of camera_stream returned by
  *    startConfiguration() may be modified.
  *
  *  STATE_IN_RE_CONFIG: Configuration has started, and the stream has been
@@ -130,15 +128,15 @@
  *
  */
 class Camera3Stream :
-        protected camera3_stream,
+        protected camera_stream,
         public virtual Camera3StreamInterface,
         public virtual RefBase {
   public:
 
     virtual ~Camera3Stream();
 
-    static Camera3Stream*       cast(camera3_stream *stream);
-    static const Camera3Stream* cast(const camera3_stream *stream);
+    static Camera3Stream*       cast(camera_stream *stream);
+    static const Camera3Stream* cast(const camera_stream *stream);
 
     /**
      * Get the stream's ID
@@ -171,7 +169,7 @@
     void              setOfflineProcessingSupport(bool) override;
     bool              getOfflineProcessingSupport() const override;
 
-    camera3_stream*   asHalStream() override {
+    camera_stream*   asHalStream() override {
         return this;
     }
 
@@ -180,14 +178,12 @@
      * information to be passed into the HAL device's configure_streams call.
      *
      * Until finishConfiguration() is called, no other methods on the stream may be
-     * called. The usage and max_buffers fields of camera3_stream may be modified
+     * called. The usage and max_buffers fields of camera_stream may be modified
      * between start/finishConfiguration, but may not be changed after that.
-     * The priv field of camera3_stream may be modified at any time after
-     * startConfiguration.
      *
      * Returns NULL in case of error starting configuration.
      */
-    camera3_stream*  startConfiguration();
+    camera_stream*  startConfiguration();
 
     /**
      * Check if the stream is mid-configuration (start has been called, but not
@@ -308,7 +304,7 @@
     status_t       tearDown();
 
     /**
-     * Fill in the camera3_stream_buffer with the next valid buffer for this
+     * Fill in the camera_stream_buffer with the next valid buffer for this
      * stream, to hand over to the HAL.
      *
      * Multiple surfaces could share the same HAL stream, but a request may
@@ -321,7 +317,7 @@
      * buffers.
      *
      */
-    status_t         getBuffer(camera3_stream_buffer *buffer,
+    status_t         getBuffer(camera_stream_buffer *buffer,
             nsecs_t waitBufferTimeout,
             const std::vector<size_t>& surface_ids = std::vector<size_t>());
 
@@ -336,13 +332,13 @@
      * This method may only be called for buffers provided by getBuffer().
      * For bidirectional streams, this method applies to the output-side buffers
      */
-    status_t         returnBuffer(const camera3_stream_buffer &buffer,
+    status_t         returnBuffer(const camera_stream_buffer &buffer,
             nsecs_t timestamp, bool timestampIncreasing,
             const std::vector<size_t>& surface_ids = std::vector<size_t>(),
             uint64_t frameNumber = 0);
 
     /**
-     * Fill in the camera3_stream_buffer with the next valid buffer for this
+     * Fill in the camera_stream_buffer with the next valid buffer for this
      * stream, to hand over to the HAL.
      *
      * This method may only be called once finishConfiguration has been called.
@@ -352,7 +348,7 @@
      * Normally this call will block until the handed out buffer count is less than the stream
      * max buffer count; if respectHalLimit is set to false, this is ignored.
      */
-    status_t         getInputBuffer(camera3_stream_buffer *buffer, bool respectHalLimit = true);
+    status_t         getInputBuffer(camera_stream_buffer *buffer, bool respectHalLimit = true);
 
     /**
      * Return a buffer to the stream after use by the HAL.
@@ -360,7 +356,7 @@
      * This method may only be called for buffers provided by getBuffer().
      * For bidirectional streams, this method applies to the input-side buffers
      */
-    status_t         returnInputBuffer(const camera3_stream_buffer &buffer);
+    status_t         returnInputBuffer(const camera_stream_buffer &buffer);
 
     // get the buffer producer of the input buffer queue.
     // only apply to input streams.
@@ -477,9 +473,9 @@
 
     mutable Mutex mLock;
 
-    Camera3Stream(int id, camera3_stream_type type,
+    Camera3Stream(int id, camera_stream_type type,
             uint32_t width, uint32_t height, size_t maxSize, int format,
-            android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+            android_dataspace dataSpace, camera_stream_rotation_t rotation,
             const String8& physicalCameraId, int setId);
 
     wp<Camera3StreamBufferFreedListener> mBufferFreedListener;
@@ -490,18 +486,18 @@
 
     // getBuffer / returnBuffer implementations
 
-    // Since camera3_stream_buffer includes a raw pointer to the stream,
-    // cast to camera3_stream*, implementations must increment the
+    // Since camera_stream_buffer includes a raw pointer to the stream,
+    // cast to camera_stream*, implementations must increment the
     // refcount of the stream manually in getBufferLocked, and decrement it in
     // returnBufferLocked.
-    virtual status_t getBufferLocked(camera3_stream_buffer *buffer,
+    virtual status_t getBufferLocked(camera_stream_buffer *buffer,
             const std::vector<size_t>& surface_ids = std::vector<size_t>());
-    virtual status_t returnBufferLocked(const camera3_stream_buffer &buffer,
+    virtual status_t returnBufferLocked(const camera_stream_buffer &buffer,
             nsecs_t timestamp,
             const std::vector<size_t>& surface_ids = std::vector<size_t>());
-    virtual status_t getInputBufferLocked(camera3_stream_buffer *buffer);
+    virtual status_t getInputBufferLocked(camera_stream_buffer *buffer);
     virtual status_t returnInputBufferLocked(
-            const camera3_stream_buffer &buffer);
+            const camera_stream_buffer &buffer);
     virtual bool     hasOutstandingBuffersLocked() const = 0;
     // Get the buffer producer of the input buffer queue. Only apply to input streams.
     virtual status_t getInputBufferProducerLocked(sp<IGraphicBufferProducer> *producer);
@@ -530,7 +526,7 @@
     virtual status_t getEndpointUsage(uint64_t *usage) const = 0;
 
     // Return whether the buffer is in the list of outstanding buffers.
-    bool isOutstandingBuffer(const camera3_stream_buffer& buffer) const;
+    bool isOutstandingBuffer(const camera_stream_buffer& buffer) const;
 
     // Tracking for idle state
     wp<StatusTracker> mStatusTracker;
@@ -554,14 +550,14 @@
     Condition mInputBufferReturnedSignal;
     static const nsecs_t kWaitForBufferDuration = 3000000000LL; // 3000 ms
 
-    void fireBufferListenersLocked(const camera3_stream_buffer& buffer,
+    void fireBufferListenersLocked(const camera_stream_buffer& buffer,
             bool acquired, bool output, nsecs_t timestamp = 0, uint64_t frameNumber = 0);
     List<wp<Camera3StreamBufferListener> > mBufferListenerList;
 
     status_t        cancelPrepareLocked();
 
     // Remove the buffer from the list of outstanding buffers.
-    void removeOutstandingBuffer(const camera3_stream_buffer& buffer);
+    void removeOutstandingBuffer(const camera_stream_buffer& buffer);
 
     // Tracking for PREPARING state
 
@@ -571,7 +567,7 @@
     bool mPrepared;
     bool mPrepareBlockRequest;
 
-    Vector<camera3_stream_buffer_t> mPreparedBuffers;
+    Vector<camera_stream_buffer_t> mPreparedBuffers;
     size_t mPreparedBufferIdx;
 
     // Number of buffers allocated on last prepare call.
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index a053262..b48636e 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -23,13 +23,55 @@
 #include "Camera3StreamBufferListener.h"
 #include "Camera3StreamBufferFreedListener.h"
 
-struct camera3_stream;
-struct camera3_stream_buffer;
-
 namespace android {
 
 namespace camera3 {
 
+typedef enum camera_buffer_status {
+    CAMERA_BUFFER_STATUS_OK = 0,
+    CAMERA_BUFFER_STATUS_ERROR = 1
+} camera_buffer_status_t;
+
+typedef enum camera_stream_type {
+    CAMERA_STREAM_OUTPUT = 0,
+    CAMERA_STREAM_INPUT = 1,
+    CAMERA_NUM_STREAM_TYPES
+} camera_stream_type_t;
+
+typedef enum camera_stream_rotation {
+    /* No rotation */
+    CAMERA_STREAM_ROTATION_0 = 0,
+
+    /* Rotate by 90 degree counterclockwise */
+    CAMERA_STREAM_ROTATION_90 = 1,
+
+    /* Rotate by 180 degree counterclockwise */
+    CAMERA_STREAM_ROTATION_180 = 2,
+
+    /* Rotate by 270 degree counterclockwise */
+    CAMERA_STREAM_ROTATION_270 = 3
+} camera_stream_rotation_t;
+
+typedef struct camera_stream {
+    camera_stream_type_t stream_type;
+    uint32_t width;
+    uint32_t height;
+    int format;
+    uint32_t usage;
+    uint32_t max_buffers;
+    android_dataspace_t data_space;
+    camera_stream_rotation_t rotation;
+    const char* physical_camera_id;
+} camera_stream_t;
+
+typedef struct camera_stream_buffer {
+    camera_stream_t *stream;
+    buffer_handle_t *buffer;
+    camera_buffer_status_t status;
+    int acquire_fence;
+    int release_fence;
+} camera_stream_buffer_t;
+
 enum {
     /**
      * This stream set ID indicates that the set ID is invalid, and this stream doesn't intend to
@@ -109,23 +151,23 @@
     virtual bool getOfflineProcessingSupport() const = 0;
 
     /**
-     * Get a HAL3 handle for the stream, without starting stream configuration.
+     * Get a handle for the stream, without starting stream configuration.
      */
-    virtual camera3_stream* asHalStream() = 0;
+    virtual camera_stream* asHalStream() = 0;
 
     /**
      * Start the stream configuration process. Returns a handle to the stream's
-     * information to be passed into the HAL device's configure_streams call.
+     * information to be passed into the device's configure_streams call.
      *
      * Until finishConfiguration() is called, no other methods on the stream may
-     * be called. The usage and max_buffers fields of camera3_stream may be
+     * be called. The usage and max_buffers fields of camera_stream may be
      * modified between start/finishConfiguration, but may not be changed after
-     * that. The priv field of camera3_stream may be modified at any time after
+     * that. The priv field of camera_stream may be modified at any time after
      * startConfiguration.
      *
      * Returns NULL in case of error starting configuration.
      */
-    virtual camera3_stream* startConfiguration() = 0;
+    virtual camera_stream* startConfiguration() = 0;
 
     /**
      * Check if the stream is mid-configuration (start has been called, but not
@@ -241,7 +283,7 @@
     virtual status_t tearDown() = 0;
 
     /**
-     * Fill in the camera3_stream_buffer with the next valid buffer for this
+     * Fill in the camera_stream_buffer with the next valid buffer for this
      * stream, to hand over to the HAL.
      *
      * Multiple surfaces could share the same HAL stream, but a request may
@@ -255,7 +297,7 @@
      * buffers.
      *
      */
-    virtual status_t getBuffer(camera3_stream_buffer *buffer,
+    virtual status_t getBuffer(camera_stream_buffer *buffer,
             nsecs_t waitBufferTimeout,
             const std::vector<size_t>& surface_ids = std::vector<size_t>()) = 0;
 
@@ -271,13 +313,13 @@
      * This method may only be called for buffers provided by getBuffer().
      * For bidirectional streams, this method applies to the output-side buffers
      */
-    virtual status_t returnBuffer(const camera3_stream_buffer &buffer,
+    virtual status_t returnBuffer(const camera_stream_buffer &buffer,
             nsecs_t timestamp, bool timestampIncreasing = true,
             const std::vector<size_t>& surface_ids = std::vector<size_t>(),
             uint64_t frameNumber = 0) = 0;
 
     /**
-     * Fill in the camera3_stream_buffer with the next valid buffer for this
+     * Fill in the camera_stream_buffer with the next valid buffer for this
      * stream, to hand over to the HAL.
      *
      * This method may only be called once finishConfiguration has been called.
@@ -287,7 +329,7 @@
      * Normally this call will block until the handed out buffer count is less than the stream
      * max buffer count; if respectHalLimit is set to false, this is ignored.
      */
-    virtual status_t getInputBuffer(camera3_stream_buffer *buffer, bool respectHalLimit = true) = 0;
+    virtual status_t getInputBuffer(camera_stream_buffer *buffer, bool respectHalLimit = true) = 0;
 
     /**
      * Return a buffer to the stream after use by the HAL.
@@ -295,7 +337,7 @@
      * This method may only be called for buffers provided by getBuffer().
      * For bidirectional streams, this method applies to the input-side buffers
      */
-    virtual status_t returnInputBuffer(const camera3_stream_buffer &buffer) = 0;
+    virtual status_t returnInputBuffer(const camera_stream_buffer &buffer) = 0;
 
     /**
      * Get the buffer producer of the input buffer queue.
diff --git a/services/camera/libcameraservice/device3/InFlightRequest.h b/services/camera/libcameraservice/device3/InFlightRequest.h
index c7b7475..e3aaf44 100644
--- a/services/camera/libcameraservice/device3/InFlightRequest.h
+++ b/services/camera/libcameraservice/device3/InFlightRequest.h
@@ -24,8 +24,6 @@
 #include <utils/String8.h>
 #include <utils/Timers.h>
 
-#include "hardware/camera3.h"
-
 #include "common/CameraDeviceBase.h"
 
 namespace android {
@@ -75,7 +73,7 @@
     // return from HAL but framework has not yet received the shutter
     // event. They will be returned to the streams when framework receives
     // the shutter event.
-    Vector<camera3_stream_buffer_t> pendingOutputBuffers;
+    Vector<camera_stream_buffer_t> pendingOutputBuffers;
 
     // Whether this inflight request's shutter and result callback are to be
     // called. The policy is that if the request is the last one in the constrained
diff --git a/services/camera/libcameraservice/device3/StatusTracker.h b/services/camera/libcameraservice/device3/StatusTracker.h
index 3741cce..069bff6 100644
--- a/services/camera/libcameraservice/device3/StatusTracker.h
+++ b/services/camera/libcameraservice/device3/StatusTracker.h
@@ -24,7 +24,6 @@
 #include <utils/Mutex.h>
 #include <utils/Thread.h>
 #include <utils/KeyedVector.h>
-#include <hardware/camera3.h>
 
 #include "common/CameraDeviceBase.h"
 
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
index 81d7bf9..1bc2081 100644
--- a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
@@ -168,6 +168,19 @@
     entry = request->find(ANDROID_CONTROL_ZOOM_RATIO);
     if (entry.count == 1 && entry.data.f[0] != 1.0f) {
         zoomRatioIs1 = false;
+
+        // If cropRegion is windowboxing, override it with activeArray
+        camera_metadata_entry_t cropRegionEntry = request->find(ANDROID_SCALER_CROP_REGION);
+        if (cropRegionEntry.count == 4) {
+            int cropWidth = cropRegionEntry.data.i32[2];
+            int cropHeight = cropRegionEntry.data.i32[3];
+            if (cropWidth < mArrayWidth && cropHeight < mArrayHeight) {
+                cropRegionEntry.data.i32[0] = 0;
+                cropRegionEntry.data.i32[1] = 0;
+                cropRegionEntry.data.i32[2] = mArrayWidth;
+                cropRegionEntry.data.i32[3] = mArrayHeight;
+            }
+        }
     }
 
     if (mHalSupportsZoomRatio && zoomRatioIs1) {
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index ba68a63..c28f427 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -261,7 +261,7 @@
 
 
 void SessionConfigurationUtils::mapStreamInfo(const OutputStreamInfo &streamInfo,
-            camera3_stream_rotation_t rotation, String8 physicalId,
+            camera3::camera_stream_rotation_t rotation, String8 physicalId,
             hardware::camera::device::V3_4::Stream *stream /*out*/) {
     if (stream == nullptr) {
         return;
@@ -373,7 +373,7 @@
     }
     *earlyExit = false;
     auto ret = Camera3Device::mapToStreamConfigurationMode(
-            static_cast<camera3_stream_configuration_mode_t> (operatingMode),
+            static_cast<camera_stream_configuration_mode_t> (operatingMode),
             /*out*/ &streamConfiguration.operationMode);
     if (ret != OK) {
         String8 msg = String8::format(
@@ -432,7 +432,7 @@
             if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
                 streamInfo.consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
             }
-            mapStreamInfo(streamInfo, CAMERA3_STREAM_ROTATION_0, physicalCameraId,
+            mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId,
                     &streamConfiguration.streams[streamIdx++]);
             isStreamInfoValid = true;
 
@@ -487,12 +487,12 @@
 
                     for (const auto& compositeStream : compositeStreams) {
                         mapStreamInfo(compositeStream,
-                                static_cast<camera3_stream_rotation_t> (it.getRotation()),
+                                static_cast<camera_stream_rotation_t> (it.getRotation()),
                                 physicalCameraId, &streamConfiguration.streams[streamIdx++]);
                     }
                 } else {
                     mapStreamInfo(streamInfo,
-                            static_cast<camera3_stream_rotation_t> (it.getRotation()),
+                            static_cast<camera_stream_rotation_t> (it.getRotation()),
                             physicalCameraId, &streamConfiguration.streams[streamIdx++]);
                 }
                 isStreamInfoValid = true;
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index 6ce2cd7..6ac7ab4 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -23,7 +23,6 @@
 #include <camera/camera2/SubmitInfo.h>
 #include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
 
-#include <hardware/camera3.h>
 #include <device3/Camera3StreamInterface.h>
 
 #include <stdint.h>
@@ -54,7 +53,7 @@
         const String8 &cameraId, const CameraMetadata &physicalCameraMetadata);
 
     static void mapStreamInfo(const camera3::OutputStreamInfo &streamInfo,
-            camera3_stream_rotation_t rotation, String8 physicalId,
+            camera3::camera_stream_rotation_t rotation, String8 physicalId,
             hardware::camera::device::V3_4::Stream *stream /*out*/);
 
     // Check that the physicalCameraId passed in is spported by the camera
diff --git a/services/mediacodec/seccomp_policy/mediacodec-x86.policy b/services/mediacodec/seccomp_policy/mediacodec-x86.policy
index a9d32d6..4bcc077 100644
--- a/services/mediacodec/seccomp_policy/mediacodec-x86.policy
+++ b/services/mediacodec/seccomp_policy/mediacodec-x86.policy
@@ -27,6 +27,7 @@
 mmap: 1
 fstat64: 1
 fstat: 1
+stat: 1
 stat64: 1
 statfs64: 1
 madvise: 1
diff --git a/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy b/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy
index a9d32d6..4bcc077 100644
--- a/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy
+++ b/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy
@@ -27,6 +27,7 @@
 mmap: 1
 fstat64: 1
 fstat: 1
+stat: 1
 stat64: 1
 statfs64: 1
 madvise: 1
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy b/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy
index eb71e28..9bafe7b 100644
--- a/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy
@@ -27,6 +27,7 @@
 mmap: 1
 fstat64: 1
 fstat: 1
+stat: 1
 stat64: 1
 statfs64: 1
 madvise: 1
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy b/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy
index e72d4db..b0ed040 100644
--- a/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy
@@ -27,6 +27,7 @@
 mmap: 1
 fstat64: 1
 fstat: 1
+stat: 1
 stat64: 1
 statfs64: 1
 madvise: 1
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
new file mode 100644
index 0000000..df4c867
--- /dev/null
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_fuzz {
+    name: "mediametrics_service_fuzzer",
+
+    srcs: [
+        "mediametrics_service_fuzzer.cpp",
+    ],
+
+    static_libs: [
+        "libmediametrics",
+        "libmediametricsservice",
+        "libplatformprotos",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "liblog",
+        "libmedia_helper",
+        "libmediautils",
+        "libmemunreachable",
+        "libprotobuf-cpp-lite",
+        "libstagefright",
+        "libstatslog",
+        "libutils",
+    ],
+
+    include_dirs: [
+        "frameworks/av/services/mediametrics",
+        "system/media/audio_utils/include",
+    ],
+
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 155276,
+    },
+}
diff --git a/services/mediametrics/fuzzer/README.md b/services/mediametrics/fuzzer/README.md
new file mode 100644
index 0000000..a13830e
--- /dev/null
+++ b/services/mediametrics/fuzzer/README.md
@@ -0,0 +1,54 @@
+# Fuzzer for libmediametricsservice
+
+## Plugin Design Considerations
+The fuzzer plugin for libmediametricsservice is designed based on the
+understanding of the service and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+Media Metrics Service contains the following modules:
+1. Media Metrics Item Manipulation (module name: `Item`)
+2. Media Metrics Time Machine Storage (module name: `TimeMachineStorage`)
+3. Media Metrics Transaction Log (module name: `TransactionLog`)
+4. Media Metrics Analytics Action (module name: `AnalyticsAction`)
+5. Media Metrics Audio Analytics (module name: `AudioAnalytics`)
+6. Media Metrics Timed Action (module name: `TimedAction`)
+
+| Module| Valid Input Values| Configured Value|
+|------------- |-------------| ----- |
+| `Item` | Key: `std::string`. Values: `INT32_MIN` to `INT32_MAX`, `INT64_MIN` to `INT64_MAX`, `std::string`, `double`, `pair<INT32_MIN to INT32_MAX, INT32_MIN to INT32_MAX>` | Value obtained from FuzzedDataProvider |
+| `TimeMachineStorage`   | Key: `std::string`. Values: `INT32_MIN` to `INT32_MAX`, `INT64_MIN` to `INT64_MAX`, `std::string`, `double`, `pair<INT32_MIN to INT32_MAX, INT32_MIN to INT32_MAX>` | Value obtained from FuzzedDataProvider |
+| `TranscationLog`   | `mediametrics::Item` | `mediametrics::Item` created by obtaining values from FuzzedDataProvider|
+| `AnalyticsAction`   | URL: `std::string` ending with .event, Value: `std::string`, action: A function | URL and Values obtained from FuzzedDataProvider, a placeholder function was passed as action|
+| `AudioAnalytics`   | `mediametrics::Item` | `mediametrics::Item` created by obtaining values from FuzzedDataProvider|
+| `TimedAction`   | time: `std::chrono::seconds`, function: `std::function` | `std::chrono::seconds` : value obtained from FuzzedDataProvider, `std::function`: a placeholder function was used. |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+## Build
+
+This describes steps to build mediametrics_service_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) mediametrics_service_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some files to that folder
+Push this directory to device.
+
+To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mediametrics_service_fuzzer/mediametrics_service_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp
new file mode 100644
index 0000000..0cb2594
--- /dev/null
+++ b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp
@@ -0,0 +1,372 @@
+/******************************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <fuzzer/FuzzedDataProvider.h>
+#include <media/MediaMetricsItem.h>
+#include <stdio.h>
+#include <string.h>
+#include <utils/Log.h>
+#include <algorithm>
+
+#include "AudioTypes.h"
+#include "MediaMetricsService.h"
+#include "StringUtils.h"
+
+using namespace android;
+
+// low water mark
+constexpr size_t kLogItemsLowWater = 1;
+// high water mark
+constexpr size_t kLogItemsHighWater = 2;
+
+class MediaMetricsServiceFuzzer {
+   public:
+    void invokeStartsWith(const uint8_t *data, size_t size);
+    void invokeInstantiate(const uint8_t *data, size_t size);
+    void invokePackageInstallerCheck(const uint8_t *data, size_t size);
+    void invokeItemManipulation(const uint8_t *data, size_t size);
+    void invokeItemExpansion(const uint8_t *data, size_t size);
+    void invokeTimeMachineStorage(const uint8_t *data, size_t size);
+    void invokeTransactionLog(const uint8_t *data, size_t size);
+    void invokeAnalyticsAction(const uint8_t *data, size_t size);
+    void invokeAudioAnalytics(const uint8_t *data, size_t size);
+    void invokeTimedAction(const uint8_t *data, size_t size);
+    void process(const uint8_t *data, size_t size);
+};
+
+void MediaMetricsServiceFuzzer::invokeStartsWith(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+    while (fdp.remaining_bytes()) {
+        android::mediametrics::startsWith(fdp.ConsumeRandomLengthString(),
+                                          fdp.ConsumeRandomLengthString());
+    }
+}
+
+void MediaMetricsServiceFuzzer::invokeInstantiate(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+    sp mediaMetricsService = new MediaMetricsService();
+
+    while (fdp.remaining_bytes()) {
+        std::unique_ptr<mediametrics::Item> random_key(
+            mediametrics::Item::create(fdp.ConsumeRandomLengthString()));
+        mediaMetricsService->submit(random_key.get());
+        random_key->setInt32(fdp.ConsumeRandomLengthString().c_str(),
+                             fdp.ConsumeIntegral<int32_t>());
+        mediaMetricsService->submit(random_key.get());
+
+        std::unique_ptr<mediametrics::Item> audiotrack_key(
+            mediametrics::Item::create("audiotrack"));
+        mediaMetricsService->submit(audiotrack_key.get());
+        audiotrack_key->addInt32(fdp.ConsumeRandomLengthString().c_str(),
+                                 fdp.ConsumeIntegral<int32_t>());
+        mediaMetricsService->submit(audiotrack_key.get());
+    }
+}
+
+void MediaMetricsServiceFuzzer::invokePackageInstallerCheck(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+    while (fdp.remaining_bytes()) {
+        MediaMetricsService::useUidForPackage(fdp.ConsumeRandomLengthString().c_str(),
+                                              fdp.ConsumeRandomLengthString().c_str());
+    }
+}
+
+void MediaMetricsServiceFuzzer::invokeItemManipulation(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+    mediametrics::Item item(fdp.ConsumeRandomLengthString().c_str());
+    while (fdp.remaining_bytes()) {
+        const uint8_t action = fdp.ConsumeIntegralInRange<uint8_t>(0, 16);
+        const std::string key = fdp.ConsumeRandomLengthString();
+        if (fdp.remaining_bytes() < 1 || key.length() < 1) {
+            break;
+        }
+        switch (action) {
+            case 0: {
+                item.setInt32(key.c_str(), fdp.ConsumeIntegral<int32_t>());
+                break;
+            }
+            case 1: {
+                item.addInt32(key.c_str(), fdp.ConsumeIntegral<int32_t>());
+                break;
+            }
+            case 2: {
+                int32_t i32 = 0;
+                item.getInt32(key.c_str(), &i32);
+                break;
+            }
+            case 3: {
+                item.setInt64(key.c_str(), fdp.ConsumeIntegral<int64_t>());
+                break;
+            }
+            case 4: {
+                item.addInt64(key.c_str(), fdp.ConsumeIntegral<int64_t>());
+                break;
+            }
+            case 5: {
+                int64_t i64 = 0;
+                item.getInt64(key.c_str(), &i64);
+                break;
+            }
+            case 6: {
+                item.setDouble(key.c_str(), fdp.ConsumeFloatingPoint<double>());
+                break;
+            }
+            case 7: {
+                item.addDouble(key.c_str(), fdp.ConsumeFloatingPoint<double>());
+                break;
+            }
+            case 8: {
+                double d = 0;
+                item.getDouble(key.c_str(), &d);
+                break;
+            }
+            case 9: {
+                item.setCString(key.c_str(), fdp.ConsumeRandomLengthString().c_str());
+                break;
+            }
+            case 10: {
+                char *s = nullptr;
+                item.getCString(key.c_str(), &s);
+                if (s) free(s);
+                break;
+            }
+            case 11: {
+                std::string s;
+                item.getString(key.c_str(), &s);
+                break;
+            }
+            case 12: {
+                item.setRate(key.c_str(), fdp.ConsumeIntegral<int64_t>(),
+                             fdp.ConsumeIntegral<int64_t>());
+                break;
+            }
+            case 13: {
+                int64_t b = 0, h = 0;
+                double d = 0;
+                item.getRate(key.c_str(), &b, &h, &d);
+                break;
+            }
+            case 14: {
+                (void)item.filter(key.c_str());
+                break;
+            }
+            case 15: {
+                const char *arr[1] = {""};
+                arr[0] = const_cast<char *>(key.c_str());
+                (void)item.filterNot(1, arr);
+                break;
+            }
+            case 16: {
+                (void)item.toString().c_str();
+                break;
+            }
+        }
+    }
+
+    Parcel p;
+    mediametrics::Item item2;
+
+    (void)item.writeToParcel(&p);
+    p.setDataPosition(0);  // rewind for reading
+    (void)item2.readFromParcel(p);
+
+    char *byteData = nullptr;
+    size_t length = 0;
+    (void)item.writeToByteString(&byteData, &length);
+    (void)item2.readFromByteString(byteData, length);
+    if (byteData) {
+        free(byteData);
+    }
+
+    sp mediaMetricsService = new MediaMetricsService();
+    mediaMetricsService->submit(&item2);
+}
+
+void MediaMetricsServiceFuzzer::invokeItemExpansion(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+    mediametrics::LogItem<1> item("FuzzItem");
+    item.setPid(fdp.ConsumeIntegral<int16_t>()).setUid(fdp.ConsumeIntegral<int16_t>());
+
+    while (fdp.remaining_bytes()) {
+        int32_t i = fdp.ConsumeIntegral<int32_t>();
+        item.set(std::to_string(i).c_str(), (int32_t)i);
+    }
+    item.updateHeader();
+
+    mediametrics::Item item2;
+    (void)item2.readFromByteString(item.getBuffer(), item.getLength());
+
+    sp mediaMetricsService = new MediaMetricsService();
+    mediaMetricsService->submit(&item2);
+}
+
+void MediaMetricsServiceFuzzer::invokeTimeMachineStorage(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+    auto item = std::make_shared<mediametrics::Item>("FuzzKey");
+    int32_t i32 = fdp.ConsumeIntegral<int32_t>();
+    int64_t i64 = fdp.ConsumeIntegral<int64_t>();
+    double d = fdp.ConsumeFloatingPoint<double>();
+    std::string str = fdp.ConsumeRandomLengthString();
+    std::pair<int64_t, int64_t> pair(fdp.ConsumeIntegral<int64_t>(),
+                                     fdp.ConsumeIntegral<int64_t>());
+    (*item).set("i32", i32).set("i64", i64).set("double", d).set("string", str).set("rate", pair);
+
+    android::mediametrics::TimeMachine timeMachine;
+    timeMachine.put(item, true);
+
+    timeMachine.get("Key", "i32", &i32, -1);
+
+    timeMachine.get("Key", "i64", &i64, -1);
+
+    timeMachine.get("Key", "double", &d, -1);
+
+    timeMachine.get("Key", "string", &str, -1);
+
+    timeMachine.get("Key.i32", &i32, -1);
+
+    timeMachine.get("Key.i64", &i64, -1);
+
+    timeMachine.get("Key.double", &d, -1);
+
+    str.clear();
+    timeMachine.get("Key.string", &str, -1);
+}
+
+void MediaMetricsServiceFuzzer::invokeTransactionLog(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+    auto item = std::make_shared<mediametrics::Item>("Key1");
+    (*item)
+        .set("one", fdp.ConsumeIntegral<int32_t>())
+        .set("two", fdp.ConsumeIntegral<int32_t>())
+        .setTimestamp(fdp.ConsumeIntegral<int32_t>());
+
+    android::mediametrics::TransactionLog transactionLog(
+        kLogItemsLowWater, kLogItemsHighWater);  // keep at most 2 items
+    transactionLog.size();
+
+    transactionLog.put(item);
+    transactionLog.size();
+
+    auto item2 = std::make_shared<mediametrics::Item>("Key2");
+    (*item2)
+        .set("three", fdp.ConsumeIntegral<int32_t>())
+        .set("[Key1]three", fdp.ConsumeIntegral<int32_t>())
+        .setTimestamp(fdp.ConsumeIntegral<int32_t>());
+
+    transactionLog.put(item2);
+    transactionLog.size();
+
+    auto item3 = std::make_shared<mediametrics::Item>("Key3");
+    (*item3)
+        .set("six", fdp.ConsumeIntegral<int32_t>())
+        .set("[Key1]four", fdp.ConsumeIntegral<int32_t>())  // affects Key1
+        .set("[Key1]five", fdp.ConsumeIntegral<int32_t>())  // affects key1
+        .setTimestamp(fdp.ConsumeIntegral<int32_t>());
+
+    transactionLog.put(item3);
+    transactionLog.size();
+}
+
+void MediaMetricsServiceFuzzer::invokeAnalyticsAction(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+    mediametrics::AnalyticsActions analyticsActions;
+    bool action = false;
+
+    while (fdp.remaining_bytes()) {
+        analyticsActions.addAction(
+            (fdp.ConsumeRandomLengthString() + std::string(".event")).c_str(),
+            fdp.ConsumeRandomLengthString(),
+            std::make_shared<mediametrics::AnalyticsActions::Function>(
+                [&](const std::shared_ptr<const android::mediametrics::Item> &) {
+                    action = true;
+                }));
+    }
+
+    FuzzedDataProvider fdp2 = FuzzedDataProvider(data, size);
+
+    while (fdp2.remaining_bytes()) {
+        // make a test item
+        auto item = std::make_shared<mediametrics::Item>(fdp2.ConsumeRandomLengthString().c_str());
+        (*item).set("event", fdp2.ConsumeRandomLengthString().c_str());
+
+        // get the actions and execute them
+        auto actions = analyticsActions.getActionsForItem(item);
+        for (const auto &action : actions) {
+            action->operator()(item);
+        }
+    }
+}
+
+void MediaMetricsServiceFuzzer::invokeAudioAnalytics(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+    android::mediametrics::AudioAnalytics audioAnalytics;
+
+    while (fdp.remaining_bytes()) {
+        auto item = std::make_shared<mediametrics::Item>(fdp.ConsumeRandomLengthString().c_str());
+        int32_t transactionUid = fdp.ConsumeIntegral<int32_t>();  // arbitrary
+        (*item)
+            .set(fdp.ConsumeRandomLengthString().c_str(), fdp.ConsumeIntegral<int32_t>())
+            .set(fdp.ConsumeRandomLengthString().c_str(), fdp.ConsumeIntegral<int32_t>())
+            .set(AMEDIAMETRICS_PROP_ALLOWUID, transactionUid)
+            .setUid(transactionUid)
+            .setTimestamp(fdp.ConsumeIntegral<int32_t>());
+        audioAnalytics.submit(item, fdp.ConsumeBool());
+    }
+
+    audioAnalytics.dump(1000);
+}
+
+void MediaMetricsServiceFuzzer::invokeTimedAction(const uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+    android::mediametrics::TimedAction timedAction;
+    std::atomic_int value = 0;
+
+    while (fdp.remaining_bytes()) {
+        timedAction.postIn(std::chrono::seconds(fdp.ConsumeIntegral<int32_t>()),
+                           [&value] { ++value; });
+        timedAction.size();
+    }
+}
+
+void MediaMetricsServiceFuzzer::process(const uint8_t *data, size_t size) {
+    invokeStartsWith(data, size);
+    invokeInstantiate(data, size);
+    invokePackageInstallerCheck(data, size);
+    invokeItemManipulation(data, size);
+    invokeItemExpansion(data, size);
+    invokeTimeMachineStorage(data, size);
+    invokeTransactionLog(data, size);
+    invokeAnalyticsAction(data, size);
+    invokeAudioAnalytics(data, size);
+    invokeTimedAction(data, size);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    if (size < 1) {
+        return 0;
+    }
+    MediaMetricsServiceFuzzer mediaMetricsServiceFuzzer;
+    mediaMetricsServiceFuzzer.process(data, size);
+    return 0;
+}
diff --git a/services/mediametrics/statsd_extractor.cpp b/services/mediametrics/statsd_extractor.cpp
index 16814d9..4180e0c 100644
--- a/services/mediametrics/statsd_extractor.cpp
+++ b/services/mediametrics/statsd_extractor.cpp
@@ -71,6 +71,22 @@
         metrics_proto.set_tracks(ntrk);
     }
 
+    // android.media.mediaextractor.entry       string
+    std::string entry_point_string;
+    if (item->getString("android.media.mediaextractor.entry", &entry_point_string)) {
+      stats::mediametrics::ExtractorData::EntryPoint entry_point;
+      if (entry_point_string == "sdk") {
+        entry_point = stats::mediametrics::ExtractorData_EntryPoint_SDK;
+      } else if (entry_point_string == "ndk-with-jvm") {
+        entry_point = stats::mediametrics::ExtractorData_EntryPoint_NDK_WITH_JVM;
+      } else if (entry_point_string == "ndk-no-jvm") {
+        entry_point = stats::mediametrics::ExtractorData_EntryPoint_NDK_NO_JVM;
+      } else {
+        entry_point = stats::mediametrics::ExtractorData_EntryPoint_OTHER;
+      }
+      metrics_proto.set_entry_point(entry_point);
+    }
+
     std::string serialized;
     if (!metrics_proto.SerializeToString(&serialized)) {
         ALOGE("Failed to serialize extractor metrics");
diff --git a/services/mediaresourcemanager/Android.bp b/services/mediaresourcemanager/Android.bp
index cdf5a4e..83a139b 100644
--- a/services/mediaresourcemanager/Android.bp
+++ b/services/mediaresourcemanager/Android.bp
@@ -35,11 +35,27 @@
 
 aidl_interface {
     name: "resourceobserver_aidl_interface",
-    unstable: true,
     local_include_dir: "aidl",
     srcs: [
         ":resourceobserver_aidl",
     ],
+    backend: {
+        java: {
+            enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+        ndk: {
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.media",
+                "test_com.android.media",
+            ],
+            min_sdk_version: "29",
+            enabled: true,
+        },
+    },
 }
 
 cc_library {
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 32ac583..289cffd 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -22,6 +22,7 @@
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 #include <binder/IMediaResourceMonitor.h>
+#include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <cutils/sched_policy.h>
 #include <dirent.h>
@@ -96,7 +97,7 @@
 
     service->overridePid(mPid, -1);
     // thiz is freed in the call below, so it must be last call referring thiz
-    service->removeResource(mPid, mClientId, false);
+    service->removeResource(mPid, mClientId, false /*checkValid*/);
 }
 
 class OverrideProcessInfoDeathNotifier : public DeathNotifier {
@@ -422,8 +423,12 @@
 
     Mutex::Autolock lock(mLock);
     if (!mProcessInfo->isValidPid(pid)) {
-        ALOGE("Rejected addResource call with invalid pid.");
-        return Status::fromServiceSpecificError(BAD_VALUE);
+        pid_t callingPid = IPCThreadState::self()->getCallingPid();
+        uid_t callingUid = IPCThreadState::self()->getCallingUid();
+        ALOGW("%s called with untrusted pid %d, using calling pid %d, uid %d", __FUNCTION__,
+                pid, callingPid, callingUid);
+        pid = callingPid;
+        uid = callingUid;
     }
     ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
     ResourceInfo& info = getResourceInfoForEdit(uid, clientId, client, infos);
@@ -477,8 +482,10 @@
 
     Mutex::Autolock lock(mLock);
     if (!mProcessInfo->isValidPid(pid)) {
-        ALOGE("Rejected removeResource call with invalid pid.");
-        return Status::fromServiceSpecificError(BAD_VALUE);
+        pid_t callingPid = IPCThreadState::self()->getCallingPid();
+        ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
+                pid, callingPid);
+        pid = callingPid;
     }
     ssize_t index = mMap.indexOfKey(pid);
     if (index < 0) {
@@ -531,7 +538,7 @@
 }
 
 Status ResourceManagerService::removeClient(int32_t pid, int64_t clientId) {
-    removeResource(pid, clientId, true);
+    removeResource(pid, clientId, true /*checkValid*/);
     return Status::ok();
 }
 
@@ -543,8 +550,10 @@
 
     Mutex::Autolock lock(mLock);
     if (checkValid && !mProcessInfo->isValidPid(pid)) {
-        ALOGE("Rejected removeResource call with invalid pid.");
-        return Status::fromServiceSpecificError(BAD_VALUE);
+        pid_t callingPid = IPCThreadState::self()->getCallingPid();
+        ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
+                pid, callingPid);
+        pid = callingPid;
     }
     ssize_t index = mMap.indexOfKey(pid);
     if (index < 0) {
@@ -599,8 +608,10 @@
     {
         Mutex::Autolock lock(mLock);
         if (!mProcessInfo->isValidPid(callingPid)) {
-            ALOGE("Rejected reclaimResource call with invalid callingPid.");
-            return Status::fromServiceSpecificError(BAD_VALUE);
+            pid_t actualCallingPid = IPCThreadState::self()->getCallingPid();
+            ALOGW("%s called with untrusted pid %d, using actual calling pid %d", __FUNCTION__,
+                    callingPid, actualCallingPid);
+            callingPid = actualCallingPid;
         }
         const MediaResourceParcel *secureCodec = NULL;
         const MediaResourceParcel *nonSecureCodec = NULL;
@@ -836,8 +847,10 @@
 
     Mutex::Autolock lock(mLock);
     if (!mProcessInfo->isValidPid(pid)) {
-        ALOGE("Rejected markClientForPendingRemoval call with invalid pid.");
-        return Status::fromServiceSpecificError(BAD_VALUE);
+        pid_t callingPid = IPCThreadState::self()->getCallingPid();
+        ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
+                pid, callingPid);
+        pid = callingPid;
     }
     ssize_t index = mMap.indexOfKey(pid);
     if (index < 0) {
@@ -866,8 +879,10 @@
     {
         Mutex::Autolock lock(mLock);
         if (!mProcessInfo->isValidPid(pid)) {
-            ALOGE("Rejected reclaimResourcesFromClientsPendingRemoval call with invalid pid.");
-            return Status::fromServiceSpecificError(BAD_VALUE);
+            pid_t callingPid = IPCThreadState::self()->getCallingPid();
+            ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
+                    pid, callingPid);
+            pid = callingPid;
         }
 
         for (MediaResource::Type type : {MediaResource::Type::kSecureCodec,
diff --git a/services/mediaresourcemanager/ResourceObserverService.cpp b/services/mediaresourcemanager/ResourceObserverService.cpp
index 44fe72d..9cc6fe4 100644
--- a/services/mediaresourcemanager/ResourceObserverService.cpp
+++ b/services/mediaresourcemanager/ResourceObserverService.cpp
@@ -27,14 +27,6 @@
 
 #include "ResourceObserverService.h"
 
-namespace aidl {
-namespace android {
-namespace media {
-bool operator<(const MediaObservableFilter& lhs, const MediaObservableFilter &rhs) {
-    return lhs.type < rhs.type || (lhs.type == rhs.type && lhs.eventFilter < rhs.eventFilter);
-}
-}}} // namespace ::aidl::android::media
-
 namespace android {
 
 using ::aidl::android::media::MediaResourceParcel;
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/IResourceObserver.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/IResourceObserver.aidl
new file mode 100644
index 0000000..402704b
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/IResourceObserver.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+interface IResourceObserver {
+  oneway void onStatusChanged(android.media.MediaObservableEvent event, int uid, int pid, in android.media.MediaObservableParcel[] observables);
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/IResourceObserverService.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/IResourceObserverService.aidl
new file mode 100644
index 0000000..a0ef761
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/IResourceObserverService.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+interface IResourceObserverService {
+  void registerObserver(android.media.IResourceObserver observer, in android.media.MediaObservableFilter[] filters);
+  void unregisterObserver(android.media.IResourceObserver observer);
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableEvent.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableEvent.aidl
new file mode 100644
index 0000000..fd60bea
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableEvent.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+@Backing(type="long")
+enum MediaObservableEvent {
+  kBusy = 1,
+  kIdle = 2,
+  kAll = -1,
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableFilter.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableFilter.aidl
new file mode 100644
index 0000000..4045ae0
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableFilter.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+parcelable MediaObservableFilter {
+  android.media.MediaObservableType type;
+  android.media.MediaObservableEvent eventFilter;
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableParcel.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableParcel.aidl
new file mode 100644
index 0000000..ff5a8e8
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableParcel.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+parcelable MediaObservableParcel {
+  android.media.MediaObservableType type;
+  long value = 0;
+}
diff --git a/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableType.aidl b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableType.aidl
new file mode 100644
index 0000000..ebb8d8e
--- /dev/null
+++ b/services/mediaresourcemanager/aidl_api/resourceobserver_aidl_interface/current/android/media/MediaObservableType.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media;
+/* @hide */
+@Backing(type="int")
+enum MediaObservableType {
+  kInvalid = 0,
+  kVideoSecureCodec = 1000,
+  kVideoNonSecureCodec = 1001,
+}
diff --git a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
index 4cf5f0a..8e29312 100644
--- a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
+++ b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
@@ -23,15 +23,6 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/ProcessInfoInterface.h>
 
-namespace aidl {
-namespace android {
-namespace media {
-bool operator== (const MediaResourceParcel& lhs, const MediaResourceParcel& rhs) {
-    return lhs.type == rhs.type && lhs.subType == rhs.subType &&
-            lhs.id == rhs.id && lhs.value == rhs.value;
-}
-}}}
-
 namespace android {
 
 using Status = ::ndk::ScopedAStatus;
diff --git a/services/mediaresourcemanager/test/ResourceObserverService_test.cpp b/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
index 4c26246..e3d3e78 100644
--- a/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
@@ -25,14 +25,6 @@
 #include "ResourceObserverService.h"
 #include "ResourceManagerServiceTestUtils.h"
 
-namespace aidl {
-namespace android {
-namespace media {
-bool operator==(const MediaObservableParcel& lhs, const MediaObservableParcel& rhs) {
-    return lhs.type == rhs.type && lhs.value == rhs.value;
-}
-}}} // namespace ::aidl::android::media
-
 namespace android {
 
 using ::aidl::android::media::BnResourceObserver;
diff --git a/services/mediatranscoding/Android.bp b/services/mediatranscoding/Android.bp
index 3d6821b..48c2584 100644
--- a/services/mediatranscoding/Android.bp
+++ b/services/mediatranscoding/Android.bp
@@ -7,8 +7,14 @@
         "SimulatedTranscoder.cpp",
     ],
 
+    min_sdk_version: "29",
+    apex_available: [
+        "com.android.media",
+        "test_com.android.media",
+    ],
+
     shared_libs: [
-        "libandroid",
+        "libandroid#31",
         "libbase",
         "libbinder_ndk",
         "libcutils",
@@ -48,12 +54,16 @@
         "libmediatranscodingservice",
     ],
 
+    min_sdk_version: "29",
+    apex_available: [
+        "com.android.media",
+        "test_com.android.media",
+    ],
+
     static_libs: [
         "mediatranscoding_aidl_interface-ndk_platform",
     ],
 
-    init_rc: ["mediatranscoding.rc"],
-
     cflags: [
         "-Werror",
         "-Wall",
diff --git a/services/mediatranscoding/mediatranscoding.rc b/services/mediatranscoding/mediatranscoding.rc
deleted file mode 100644
index 5bfef59..0000000
--- a/services/mediatranscoding/mediatranscoding.rc
+++ /dev/null
@@ -1,6 +0,0 @@
-service media.transcoding /system/bin/mediatranscoding
-    class main
-    user media
-    group media
-    ioprio rt 4
-    task_profiles ProcessCapacityHigh HighPerformance
diff --git a/services/oboeservice/Android.bp b/services/oboeservice/Android.bp
index 80f17f4..9da4867 100644
--- a/services/oboeservice/Android.bp
+++ b/services/oboeservice/Android.bp
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-cc_library_shared {
+cc_library {
 
     name: "libaaudioservice",
 
diff --git a/services/tuner/Android.bp b/services/tuner/Android.bp
index 65d8d41..5327289 100644
--- a/services/tuner/Android.bp
+++ b/services/tuner/Android.bp
@@ -40,6 +40,21 @@
     srcs: [
         ":tv_tuner_aidl",
     ],
+    imports: [
+        "android.hardware.common.fmq",
+    ],
+
+    backend: {
+        java: {
+            enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+        ndk: {
+            enabled: true,
+        },
+    },
 }
 
 cc_library {
@@ -52,8 +67,10 @@
 
     shared_libs: [
         "android.hardware.tv.tuner@1.0",
-        "libbinder",
+        "libbase",
         "libbinder_ndk",
+        "libcutils",
+        "libfmq",
         "libhidlbase",
         "liblog",
         "libmedia",
@@ -61,7 +78,13 @@
         "tv_tuner_aidl_interface-ndk_platform",
     ],
 
-    include_dirs: ["frameworks/av/include"],
+    static_libs: [
+        "android.hardware.common.fmq-unstable-ndk_platform",
+    ],
+
+    include_dirs: [
+      "frameworks/av/include"
+    ],
 
     cflags: [
         "-Werror",
@@ -83,6 +106,7 @@
         "android.hardware.tv.tuner@1.0",
         "libbase",
         "libbinder",
+        "libfmq",
         "liblog",
         "libtunerservice",
         "libutils",
diff --git a/services/tuner/TunerService.cpp b/services/tuner/TunerService.cpp
index 2b3de17..56cb34c 100644
--- a/services/tuner/TunerService.cpp
+++ b/services/tuner/TunerService.cpp
@@ -32,14 +32,17 @@
 using ::aidl::android::media::tv::tuner::TunerFrontendIsdbsCapabilities;
 using ::aidl::android::media::tv::tuner::TunerFrontendIsdbtCapabilities;
 using ::android::hardware::hidl_vec;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
 using ::android::hardware::tv::tuner::V1_0::FrontendId;
 using ::android::hardware::tv::tuner::V1_0::FrontendType;
 using ::android::hardware::tv::tuner::V1_0::Result;
 
 namespace android {
 
-sp<ITuner> TunerService::mTuner;
-
 TunerService::TunerService() {}
 TunerService::~TunerService() {}
 
@@ -47,17 +50,160 @@
     std::shared_ptr<TunerService> service =
             ::ndk::SharedRefBase::make<TunerService>();
     AServiceManager_addService(service->asBinder().get(), getServiceName());
+}
+
+template <typename HidlPayload, typename AidlPayload, typename AidlFlavor>
+bool TunerService::unsafeHidlToAidlMQDescriptor(
+        const hardware::MQDescriptor<HidlPayload, FlavorTypeToValue<AidlFlavor>::value>& hidlDesc,
+        MQDescriptor<AidlPayload, AidlFlavor>* aidlDesc) {
+    // TODO: use the builtin coversion method when it's merged.
+    ALOGD("unsafeHidlToAidlMQDescriptor");
+    static_assert(sizeof(HidlPayload) == sizeof(AidlPayload), "Payload types are incompatible");
+    static_assert(
+            has_typedef_fixed_size<AidlPayload>::value == true ||
+            std::is_fundamental<AidlPayload>::value ||
+            std::is_enum<AidlPayload>::value,
+            "Only fundamental types, enums, and AIDL parcelables annotated with @FixedSize "
+            "and built for the NDK backend are supported as AIDL payload types.");
+    aidlDesc->fileDescriptor = ndk::ScopedFileDescriptor(dup(hidlDesc.handle()->data[0]));
+    for (const auto& grantor : hidlDesc.grantors()) {
+        if (static_cast<int32_t>(grantor.offset) < 0 || static_cast<int64_t>(grantor.extent) < 0) {
+            ALOGD("Unsafe static_cast of grantor fields. offset=%d, extend=%ld",
+                    static_cast<int32_t>(grantor.offset), static_cast<long>(grantor.extent));
+            logError(
+                    "Unsafe static_cast of grantor fields. Either the hardware::MQDescriptor is "
+                    "invalid, or the MessageQueue is too large to be described by AIDL.");
+            return false;
+        }
+        aidlDesc->grantors.push_back(
+                GrantorDescriptor {
+                        .offset = static_cast<int32_t>(grantor.offset),
+                        .extent = static_cast<int64_t>(grantor.extent)
+                });
+    }
+    if (static_cast<int32_t>(hidlDesc.getQuantum()) < 0 ||
+            static_cast<int32_t>(hidlDesc.getFlags()) < 0) {
+        ALOGD("Unsafe static_cast of quantum or flags. Quantum=%d, flags=%d",
+                static_cast<int32_t>(hidlDesc.getQuantum()),
+                static_cast<int32_t>(hidlDesc.getFlags()));
+        logError(
+                "Unsafe static_cast of quantum or flags. Either the hardware::MQDescriptor is "
+                "invalid, or the MessageQueue is too large to be described by AIDL.");
+        return false;
+    }
+    aidlDesc->quantum = static_cast<int32_t>(hidlDesc.getQuantum());
+    aidlDesc->flags = static_cast<int32_t>(hidlDesc.getFlags());
+    return true;
+}
+
+bool TunerService::getITuner() {
+    ALOGD("getITuner");
+    if (mTuner != nullptr) {
+        return true;
+    }
     mTuner = ITuner::getService();
     if (mTuner == nullptr) {
-        ALOGE("Failed to get ITuner service.");
+        ALOGE("Failed to get ITuner service");
+        return false;
     }
+    return true;
+}
+
+Result TunerService::openDemux() {
+    ALOGD("openDemux");
+    if (!getITuner()) {
+        return Result::NOT_INITIALIZED;
+    }
+    if (mDemux != nullptr) {
+        return Result::SUCCESS;
+    }
+    Result res;
+    uint32_t id;
+    sp<IDemux> demuxSp;
+    mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
+        demuxSp = demux;
+        id = demuxId;
+        res = r;
+        ALOGD("open demux, id = %d", demuxId);
+    });
+    if (res == Result::SUCCESS) {
+        mDemux = demuxSp;
+    } else {
+        ALOGD("open demux failed, res = %d", res);
+    }
+    return res;
+}
+
+Result TunerService::openFilter() {
+    ALOGD("openFilter");
+    if (!getITuner()) {
+        return Result::NOT_INITIALIZED;
+    }
+    DemuxFilterMainType mainType = DemuxFilterMainType::TS;
+    DemuxFilterType filterType {
+        .mainType = mainType,
+    };
+    filterType.subType.tsFilterType(DemuxTsFilterType::VIDEO);
+
+    sp<FilterCallback> callback = new FilterCallback();
+    Result res;
+    mDemux->openFilter(filterType, 16000000, callback,
+            [&](Result r, const sp<IFilter>& filter) {
+                mFilter = filter;
+                res = r;
+            });
+    if (res != Result::SUCCESS || mFilter == NULL) {
+        ALOGD("Failed to open filter, type = %d", filterType.mainType);
+        return res;
+    }
+
+    return Result::SUCCESS;
+}
+
+Result TunerService::configFilter() {
+    ALOGD("configFilter");
+    if (mFilter == NULL) {
+        ALOGD("Failed to configure filter: filter not found");
+        return Result::NOT_INITIALIZED;
+    }
+    DemuxFilterSettings filterSettings;
+    DemuxTsFilterSettings tsFilterSettings {
+        .tpid = 256,
+    };
+    DemuxFilterAvSettings filterAvSettings {
+        .isPassthrough = false,
+    };
+    tsFilterSettings.filterSettings.av(filterAvSettings);
+    filterSettings.ts(tsFilterSettings);
+    Result res = mFilter->configure(filterSettings);
+
+    if (res != Result::SUCCESS) {
+        ALOGD("config filter failed, res = %d", res);
+        return res;
+    }
+
+    Result getQueueDescResult = Result::UNKNOWN_ERROR;
+    mFilter->getQueueDesc(
+            [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
+                mFilterMQDesc = desc;
+                getQueueDescResult = r;
+                ALOGD("getFilterQueueDesc");
+            });
+    if (getQueueDescResult == Result::SUCCESS) {
+        unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(
+                mFilterMQDesc,  &mAidlMQDesc);
+        mAidlMq = new (std::nothrow) AidlMessageQueue(mAidlMQDesc);
+        EventFlag::createEventFlag(mAidlMq->getEventFlagWord(), &mEventFlag);
+    } else {
+        ALOGD("get MQDesc failed, res = %d", getQueueDescResult);
+    }
+    return getQueueDescResult;
 }
 
 Status TunerService::getFrontendIds(std::vector<int32_t>* ids, int32_t* /* _aidl_return */) {
-    if (mTuner == nullptr) {
-        ALOGE("ITuner service is not init.");
+    if (!getITuner()) {
         return ::ndk::ScopedAStatus::fromServiceSpecificError(
-                static_cast<int32_t>(Result::UNAVAILABLE));
+                static_cast<int32_t>(Result::NOT_INITIALIZED));
     }
     hidl_vec<FrontendId> feIds;
     Result res;
@@ -221,4 +367,24 @@
     info.caps = caps;
     return info;
 }
+
+Status TunerService::getFmqSyncReadWrite(
+        MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) {
+    ALOGD("getFmqSyncReadWrite");
+    // TODO: put the following methods AIDL, and should be called from clients.
+    openDemux();
+    openFilter();
+    configFilter();
+    mFilter->start();
+    if (mqDesc == nullptr) {
+        ALOGD("getFmqSyncReadWrite null MQDescriptor.");
+        *_aidl_return = false;
+    } else {
+        ALOGD("getFmqSyncReadWrite true");
+        *_aidl_return = true;
+        *mqDesc = std::move(mAidlMQDesc);
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
 } // namespace android
diff --git a/services/tuner/TunerService.h b/services/tuner/TunerService.h
index 36ccd3e..26591ab 100644
--- a/services/tuner/TunerService.h
+++ b/services/tuner/TunerService.h
@@ -20,17 +20,59 @@
 #include <aidl/android/media/tv/tuner/BnTunerService.h>
 #include <aidl/android/media/tv/tuner/TunerServiceFrontendInfo.h>
 #include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <fmq/AidlMessageQueue.h>
+#include <fmq/EventFlag.h>
+#include <fmq/MessageQueue.h>
 
-using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::hardware::common::fmq::GrantorDescriptor;
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
 using ::aidl::android::media::tv::tuner::BnTunerService;
 using ::aidl::android::media::tv::tuner::ITunerFrontend;
 using ::aidl::android::media::tv::tuner::TunerServiceFrontendInfo;
+
+using ::android::hardware::details::logError;
+using ::android::hardware::EventFlag;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using ::android::hardware::tv::tuner::V1_0::FrontendId;
 using ::android::hardware::tv::tuner::V1_0::FrontendInfo;
+using ::android::hardware::tv::tuner::V1_0::IDemux;
+using ::android::hardware::tv::tuner::V1_0::IFilter;
+using ::android::hardware::tv::tuner::V1_0::IFilterCallback;
 using ::android::hardware::tv::tuner::V1_0::ITuner;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+using Status = ::ndk::ScopedAStatus;
 
 namespace android {
 
+
+struct FilterCallback : public IFilterCallback {
+    ~FilterCallback() {}
+    Return<void> onFilterEvent(const DemuxFilterEvent&) {
+        return Void();
+    }
+    Return<void> onFilterStatus(const DemuxFilterStatus) {
+        return Void();
+    }
+};
+
 class TunerService : public BnTunerService {
+    typedef AidlMessageQueue<int8_t, SynchronizedReadWrite> AidlMessageQueue;
+    typedef MessageQueue<uint8_t, kSynchronizedReadWrite> HidlMessageQueue;
+    typedef MQDescriptor<int8_t, SynchronizedReadWrite> AidlMQDesc;
 
 public:
     static char const *getServiceName() { return "media.tuner"; }
@@ -46,10 +88,27 @@
     Status getFrontendInfo(int32_t frontendHandle, TunerServiceFrontendInfo* _aidl_return) override;
     Status openFrontend(
             int32_t frontendHandle, std::shared_ptr<ITunerFrontend>* _aidl_return) override;
+    Status getFmqSyncReadWrite(
+            MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) override;
 
 private:
-    static sp<ITuner> mTuner;
+    template <typename HidlPayload, typename AidlPayload, typename AidlFlavor>
+    bool unsafeHidlToAidlMQDescriptor(
+            const hardware::MQDescriptor<HidlPayload, FlavorTypeToValue<AidlFlavor>::value>& hidl,
+            MQDescriptor<AidlPayload, AidlFlavor>* aidl);
 
+    bool getITuner();
+    Result openFilter();
+    Result openDemux();
+    Result configFilter();
+
+    sp<ITuner> mTuner;
+    sp<IDemux> mDemux;
+    sp<IFilter> mFilter;
+    AidlMessageQueue* mAidlMq;
+    MQDescriptorSync<uint8_t> mFilterMQDesc;
+    AidlMQDesc mAidlMQDesc;
+    EventFlag* mEventFlag;
     TunerServiceFrontendInfo convertToAidlFrontendInfo(int feId, FrontendInfo halInfo);
 };
 
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
index 5a0b47d..5c1bce7 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
@@ -16,6 +16,9 @@
 
 package android.media.tv.tuner;
 
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+import android.hardware.common.fmq.UnsynchronizedWrite;
 import android.media.tv.tuner.ITunerFrontend;
 import android.media.tv.tuner.TunerServiceFrontendInfo;
 
@@ -24,6 +27,7 @@
  *
  * {@hide}
  */
+//@VintfStability
 interface ITunerService {
 
     /**
@@ -48,4 +52,11 @@
      * @return the aidl interface of the frontend.
      */
     ITunerFrontend openFrontend(in int frontendHandle);
+
+    /*
+     * Gets synchronized fast message queue.
+     *
+     * @return true if succeeds, false otherwise.
+     */
+    boolean getFmqSyncReadWrite(out MQDescriptor<byte, SynchronizedReadWrite> mqDesc);
 }