Merge "VT: Rx side of CVO implementation to CCodec."
diff --git a/camera/CameraSessionStats.cpp b/camera/CameraSessionStats.cpp
index 818b4d0..28e037f 100644
--- a/camera/CameraSessionStats.cpp
+++ b/camera/CameraSessionStats.cpp
@@ -94,6 +94,24 @@
         return err;
     }
 
+    int histogramType = HISTOGRAM_TYPE_UNKNOWN;
+    if ((err = parcel->readInt32(&histogramType)) != OK) {
+        ALOGE("%s: Failed to read histogram type from parcel", __FUNCTION__);
+        return err;
+    }
+
+    std::vector<float> histogramBins;
+    if ((err = parcel->readFloatVector(&histogramBins)) != OK) {
+        ALOGE("%s: Failed to read histogram bins from parcel", __FUNCTION__);
+        return err;
+    }
+
+    std::vector<int64_t> histogramCounts;
+    if ((err = parcel->readInt64Vector(&histogramCounts)) != OK) {
+        ALOGE("%s: Failed to read histogram counts from parcel", __FUNCTION__);
+        return err;
+    }
+
     mWidth = width;
     mHeight = height;
     mFormat = format;
@@ -104,6 +122,9 @@
     mStartLatencyMs = startLatencyMs;
     mMaxHalBuffers = maxHalBuffers;
     mMaxAppBuffers = maxAppBuffers;
+    mHistogramType = histogramType;
+    mHistogramBins = std::move(histogramBins);
+    mHistogramCounts = std::move(histogramCounts);
 
     return OK;
 }
@@ -166,6 +187,21 @@
         return err;
     }
 
+    if ((err = parcel->writeInt32(mHistogramType)) != OK) {
+        ALOGE("%s: Failed to write histogram type", __FUNCTION__);
+        return err;
+    }
+
+    if ((err = parcel->writeFloatVector(mHistogramBins)) != OK) {
+        ALOGE("%s: Failed to write histogram bins!", __FUNCTION__);
+        return err;
+    }
+
+    if ((err = parcel->writeInt64Vector(mHistogramCounts)) != OK) {
+        ALOGE("%s: Failed to write histogram counts!", __FUNCTION__);
+        return err;
+    }
+
     return OK;
 }
 
diff --git a/camera/include/camera/CameraSessionStats.h b/camera/include/camera/CameraSessionStats.h
index 27a756f..c398aca 100644
--- a/camera/include/camera/CameraSessionStats.h
+++ b/camera/include/camera/CameraSessionStats.h
@@ -27,6 +27,11 @@
  */
 class CameraStreamStats : public android::Parcelable {
 public:
+    enum HistogramType {
+        HISTOGRAM_TYPE_UNKNOWN = 0,
+        HISTOGRAM_TYPE_CAPTURE_LATENCY = 1,
+    };
+
     int mWidth;
     int mHeight;
     int mFormat;
@@ -45,15 +50,26 @@
     int mMaxHalBuffers;
     int mMaxAppBuffers;
 
+    // Histogram type. So far only capture latency histogram is supported.
+    int mHistogramType;
+    // The bounary values separating adjacent histogram bins.
+    // A vector of {h1, h2, h3} represents bins of [0, h1), [h1, h2), [h2, h3),
+    // and [h3, infinity)
+    std::vector<float> mHistogramBins;
+    // The counts for all histogram bins.
+    // size(mHistogramBins) + 1 = size(mHistogramCounts)
+    std::vector<int64_t> mHistogramCounts;
+
     CameraStreamStats() :
             mWidth(0), mHeight(0), mFormat(0), mDataSpace(0), mUsage(0),
             mRequestCount(0), mErrorCount(0), mStartLatencyMs(0),
-            mMaxHalBuffers(0), mMaxAppBuffers(0) {}
+            mMaxHalBuffers(0), mMaxAppBuffers(0), mHistogramType(HISTOGRAM_TYPE_UNKNOWN) {}
     CameraStreamStats(int width, int height, int format, int dataSpace, int64_t usage,
             int maxHalBuffers, int maxAppBuffers)
             : mWidth(width), mHeight(height), mFormat(format), mDataSpace(dataSpace),
               mUsage(usage), mRequestCount(0), mErrorCount(0), mStartLatencyMs(0),
-              mMaxHalBuffers(maxHalBuffers), mMaxAppBuffers(maxAppBuffers) {}
+              mMaxHalBuffers(maxHalBuffers), mMaxAppBuffers(maxAppBuffers),
+              mHistogramType(HISTOGRAM_TYPE_UNKNOWN) {}
 
     virtual status_t readFromParcel(const android::Parcel* parcel) override;
     virtual status_t writeToParcel(android::Parcel* parcel) const override;
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 55a32ae..b49ec75 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -51,6 +51,7 @@
         "android.hardware.drm@1.1",
         "android.hardware.drm@1.2",
         "android.hardware.drm@1.3",
+        "android.hardware.drm@1.4",
         "libhidlallocatorutils",
         "libhidlbase",
     ],
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index f218041..295c459 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -387,6 +387,7 @@
     mPlugin.clear();
     mPluginV1_1.clear();
     mPluginV1_2.clear();
+    mPluginV1_4.clear();
 }
 
 std::vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
@@ -622,6 +623,7 @@
                 mPlugin = plugin;
                 mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
                 mPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mPlugin);
+                mPluginV1_4 = drm::V1_4::IDrmPlugin::castFrom(mPlugin);
                 break;
             }
         }
@@ -642,6 +644,7 @@
             mPlugin.clear();
             mPluginV1_1.clear();
             mPluginV1_2.clear();
+            mPluginV1_4.clear();
         }
     }
 
@@ -1564,4 +1567,22 @@
     }
 }
 
+bool DrmHal::requiresSecureDecoder(const char *mime) const {
+    Mutex::Autolock autoLock(mLock);
+    if (mPluginV1_4 == NULL) {
+        return false;
+    }
+    return mPluginV1_4->requiresSecureDecoderDefault(hidl_string(mime));
+}
+
+bool DrmHal::requiresSecureDecoder(const char *mime,
+        DrmPlugin::SecurityLevel securityLevel) const {
+    Mutex::Autolock autoLock(mLock);
+    if (mPluginV1_4 == NULL) {
+        return false;
+    }
+    auto hLevel = toHidlSecurityLevel(securityLevel);
+    return mPluginV1_4->requiresSecureDecoder(hidl_string(mime), hLevel);
+}
+
 }  // namespace android
diff --git a/drm/libmediadrm/fuzzer/Android.bp b/drm/libmediadrm/fuzzer/Android.bp
index 6f2d054..5e389b4 100644
--- a/drm/libmediadrm/fuzzer/Android.bp
+++ b/drm/libmediadrm/fuzzer/Android.bp
@@ -47,6 +47,7 @@
         "android.hardware.drm@1.1",
         "android.hardware.drm@1.2",
         "android.hardware.drm@1.3",
+        "android.hardware.drm@1.4",
         "libhidlallocatorutils",
         "libhidlbase",
     ],
diff --git a/drm/libmediadrm/include/mediadrm/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
index 3b4639b..4705de0 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHal.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -25,7 +25,9 @@
 #include <android/hardware/drm/1.2/IDrmFactory.h>
 #include <android/hardware/drm/1.2/IDrmPlugin.h>
 #include <android/hardware/drm/1.2/IDrmPluginListener.h>
+#include <android/hardware/drm/1.4/IDrmPlugin.h>
 
+#include <media/drm/DrmAPI.h>
 #include <mediadrm/DrmMetrics.h>
 #include <mediadrm/DrmSessionManager.h>
 #include <mediadrm/IDrm.h>
@@ -176,6 +178,12 @@
 
     virtual status_t setListener(const sp<IDrmClient>& listener);
 
+    virtual bool requiresSecureDecoder(const char *mime) const;
+
+    virtual bool requiresSecureDecoder(
+            const char *mime,
+            DrmPlugin::SecurityLevel securityLevel) const;
+
     // Methods of IDrmPluginListener
     Return<void> sendEvent(EventType eventType,
             const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data);
@@ -202,6 +210,7 @@
     sp<IDrmPlugin> mPlugin;
     sp<drm::V1_1::IDrmPlugin> mPluginV1_1;
     sp<drm::V1_2::IDrmPlugin> mPluginV1_2;
+    sp<drm::V1_4::IDrmPlugin> mPluginV1_4;
     String8 mAppPackageName;
 
     // Mutable to allow modification within GetPropertyByteArray.
diff --git a/drm/libmediadrm/include/mediadrm/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
index 0177c24..c117cec 100644
--- a/drm/libmediadrm/include/mediadrm/IDrm.h
+++ b/drm/libmediadrm/include/mediadrm/IDrm.h
@@ -145,6 +145,13 @@
 
     virtual status_t setListener(const sp<IDrmClient>& listener) = 0;
 
+    virtual bool requiresSecureDecoder(
+            const char *mime) const = 0;
+
+    virtual bool requiresSecureDecoder(
+            const char *mime,
+            DrmPlugin::SecurityLevel securityLevel) const = 0;
+
 protected:
     IDrm() {}
 
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/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/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 6b0e363..9f8bc68 100644
--- a/media/codec2/components/avc/Android.bp
+++ b/media/codec2/components/avc/Android.bp
@@ -3,7 +3,8 @@
     defaults: [
         "libcodec2_soft-defaults",
         "libcodec2_soft_sanitize_signed-defaults",
-   ],
+        "libcodec2_soft_sanitize_cfi-defaults",
+    ],
 
     static_libs: ["libavcdec"],
 
@@ -20,7 +21,8 @@
     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 3712564..cfdb9e7 100644
--- a/media/codec2/components/base/Android.bp
+++ b/media/codec2/components/base/Android.bp
@@ -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,7 +91,17 @@
         misc_undefined: [
             "signed-integer-overflow",
         ],
+    },
+}
+
+cc_defaults {
+    name: "libcodec2_soft_sanitize_cfi-defaults",
+
+    sanitize: {
         cfi: true,
+        config: {
+            cfi_assembly_support: true,
+        },
     },
 }
 
@@ -131,4 +141,3 @@
 
     ldflags: ["-Wl,-Bsymbolic"],
 }
-
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/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/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/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 2858212..1be0cfc 100644
--- a/media/codec2/components/hevc/Android.bp
+++ b/media/codec2/components/hevc/Android.bp
@@ -3,6 +3,7 @@
     defaults: [
         "libcodec2_soft-defaults",
         "libcodec2_soft_sanitize_signed-defaults",
+        "libcodec2_soft_sanitize_cfi-defaults",
     ],
 
     srcs: ["C2SoftHevcDec.cpp"],
@@ -16,6 +17,7 @@
     defaults: [
         "libcodec2_soft-defaults",
         "libcodec2_soft_sanitize_signed-defaults",
+        "libcodec2_soft_sanitize_cfi-defaults",
     ],
 
     srcs: ["C2SoftHevcEnc.cpp"],
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/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/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/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/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/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/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/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 4889d78..9b7e2de 100644
--- a/media/codec2/components/xaac/Android.bp
+++ b/media/codec2/components/xaac/Android.bp
@@ -3,6 +3,7 @@
     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/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/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index a9c72fb..c697b80 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1316,54 +1316,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(
@@ -1412,28 +1388,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() == nullptr
-                    || 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 8356a59..1ef21aa 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/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 19414a0..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>
@@ -580,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) {
@@ -613,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/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/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/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 81394cb..aa740a7 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -61,7 +61,7 @@
     header_libs: ["libaudioclient_headers"],
 }
 
-cc_library_shared {
+cc_library {
     name: "libaudioclient",
 
     aidl: {
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index 0522099..c2f7229 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -85,7 +85,7 @@
     mDeviceType = (audio_devices_t) parcel->readInt32();
     mDeviceAddress = parcel->readString8();
     mCbFlags = (uint32_t)parcel->readInt32();
-    mAllowPrivilegedPlaybackCapture = parcel->readBool();
+    mAllowPrivilegedMediaPlaybackCapture = parcel->readBool();
     mVoiceCommunicationCaptureAllowed = parcel->readBool();
     size_t size = (size_t)parcel->readInt32();
     if (size > MAX_CRITERIA_PER_MIX) {
@@ -110,7 +110,7 @@
     parcel->writeInt32(mDeviceType);
     parcel->writeString8(mDeviceAddress);
     parcel->writeInt32(mCbFlags);
-    parcel->writeBool(mAllowPrivilegedPlaybackCapture);
+    parcel->writeBool(mAllowPrivilegedMediaPlaybackCapture);
     parcel->writeBool(mVoiceCommunicationCaptureAllowed);
     size_t size = mCriteria.size();
     if (size > MAX_CRITERIA_PER_MIX) {
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index 00fe278..08b3da1 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -120,7 +120,7 @@
     String8         mDeviceAddress;
     uint32_t        mCbFlags; // flags indicating which callbacks to use, see kCbFlag*
     /** Ignore the AUDIO_FLAG_NO_MEDIA_PROJECTION */
-    bool            mAllowPrivilegedPlaybackCapture = false;
+    bool            mAllowPrivilegedMediaPlaybackCapture = false;
     /** Indicates if the caller can capture voice communication output */
     bool            mVoiceCommunicationCaptureAllowed = false;
 };
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/DeviceDescriptorBase.cpp b/media/libaudiofoundation/DeviceDescriptorBase.cpp
index a3e9589..5cfea81 100644
--- a/media/libaudiofoundation/DeviceDescriptorBase.cpp
+++ b/media/libaudiofoundation/DeviceDescriptorBase.cpp
@@ -122,9 +122,9 @@
             spaces, "", ::android::toString(mDeviceTypeAddr.mType).c_str()));
 
     dst->append(base::StringPrintf(
-            "%*s- supported encapsulation modes: %u", spaces, "", mEncapsulationModes));
+            "%*s- supported encapsulation modes: %u\n", spaces, "", mEncapsulationModes));
     dst->append(base::StringPrintf(
-            "%*s- supported encapsulation metadata types: %u",
+            "%*s- supported encapsulation metadata types: %u\n",
             spaces, "", mEncapsulationMetadataTypes));
 
     if (mDeviceTypeAddr.address().size() != 0) {
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/Android.bp b/media/libaudiohal/Android.bp
index 482f40e..d9a7804 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -31,6 +31,7 @@
     header_libs: [
         "libaudiohal_headers",
         "libbase_headers",
+        "libmediautils_headers",
     ]
 }
 
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 09a7c1c..3a1fce8 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -62,7 +62,9 @@
 }
 
 StreamHalHidl::~StreamHalHidl() {
-    mStream = nullptr;
+    // The last step is to flush all binder commands so that the deletion
+    // of IStreamIn / IStreamOut (mStream) is issued with less delay. See b/35394629.
+    hardware::IPCThreadState::self()->flushCommands();
 }
 
 status_t StreamHalHidl::getSampleRate(uint32_t *rate) {
@@ -286,7 +288,7 @@
     }
 
   private:
-    wp<StreamOutHalHidl> mStream;
+    const wp<StreamOutHalHidl> mStream;
 };
 
 }  // namespace
@@ -297,21 +299,19 @@
 
 StreamOutHalHidl::~StreamOutHalHidl() {
     if (mStream != 0) {
-        if (mCallback.unsafe_get()) {
+        if (mCallback.load().unsafe_get()) {
             processReturn("clearCallback", mStream->clearCallback());
         }
 #if MAJOR_VERSION >= 6
-        if (mEventCallback.unsafe_get() != nullptr) {
+        if (mEventCallback.load().unsafe_get() != nullptr) {
             processReturn("setEventCallback",
                     mStream->setEventCallback(nullptr));
         }
 #endif
         processReturn("close", mStream->close());
-        mStream.clear();
     }
-    mCallback.clear();
-    mEventCallback.clear();
-    hardware::IPCThreadState::self()->flushCommands();
+    mCallback = nullptr;
+    mEventCallback = nullptr;
     if (mEfGroup) {
         EventFlag::deleteEventFlag(&mEfGroup);
     }
@@ -364,7 +364,7 @@
 
     if (bytes == 0 && !mDataMQ) {
         // Can't determine the size for the MQ buffer. Wait for a non-empty write request.
-        ALOGW_IF(mCallback.unsafe_get(), "First call to async write with 0 bytes");
+        ALOGW_IF(mCallback.load().unsafe_get(), "First call to async write with 0 bytes");
         return OK;
     }
 
@@ -680,28 +680,28 @@
 #endif
 
 void StreamOutHalHidl::onWriteReady() {
-    sp<StreamOutHalInterfaceCallback> callback = mCallback.promote();
+    sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
     if (callback == 0) return;
     ALOGV("asyncCallback onWriteReady");
     callback->onWriteReady();
 }
 
 void StreamOutHalHidl::onDrainReady() {
-    sp<StreamOutHalInterfaceCallback> callback = mCallback.promote();
+    sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
     if (callback == 0) return;
     ALOGV("asyncCallback onDrainReady");
     callback->onDrainReady();
 }
 
 void StreamOutHalHidl::onError() {
-    sp<StreamOutHalInterfaceCallback> callback = mCallback.promote();
+    sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
     if (callback == 0) return;
     ALOGV("asyncCallback onError");
     callback->onError();
 }
 
 void StreamOutHalHidl::onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs) {
-    sp<StreamOutHalInterfaceEventCallback> callback = mEventCallback.promote();
+    sp<StreamOutHalInterfaceEventCallback> callback = mEventCallback.load().promote();
     if (callback == nullptr) return;
     ALOGV("asyncCodecFormatCallback %s", __func__);
     callback->onCodecFormatChanged(metadataBs);
@@ -715,8 +715,6 @@
 StreamInHalHidl::~StreamInHalHidl() {
     if (mStream != 0) {
         processReturn("close", mStream->close());
-        mStream.clear();
-        hardware::IPCThreadState::self()->flushCommands();
     }
     if (mEfGroup) {
         EventFlag::deleteEventFlag(&mEfGroup);
diff --git a/media/libaudiohal/impl/StreamHalHidl.h b/media/libaudiohal/impl/StreamHalHidl.h
index 88f8587..95855fe 100644
--- a/media/libaudiohal/impl/StreamHalHidl.h
+++ b/media/libaudiohal/impl/StreamHalHidl.h
@@ -25,6 +25,7 @@
 #include <fmq/EventFlag.h>
 #include <fmq/MessageQueue.h>
 #include <media/audiohal/StreamHalInterface.h>
+#include <mediautils/Synchronization.h>
 
 #include "ConversionHelperHidl.h"
 #include "StreamPowerLog.h"
@@ -100,8 +101,7 @@
     // Subclasses can not be constructed directly by clients.
     explicit StreamHalHidl(IStream *stream);
 
-    // The destructor automatically closes the stream.
-    virtual ~StreamHalHidl();
+    ~StreamHalHidl() override;
 
     status_t getCachedBufferSize(size_t *size);
 
@@ -112,7 +112,7 @@
 
   private:
     const int HAL_THREAD_PRIORITY_DEFAULT = -1;
-    IStream *mStream;
+    IStream * const mStream;
     int mHalThreadPriority;
     size_t mCachedBufferSize;
 };
@@ -184,9 +184,9 @@
     typedef MessageQueue<uint8_t, hardware::kSynchronizedReadWrite> DataMQ;
     typedef MessageQueue<WriteStatus, hardware::kSynchronizedReadWrite> StatusMQ;
 
-    wp<StreamOutHalInterfaceCallback> mCallback;
-    wp<StreamOutHalInterfaceEventCallback> mEventCallback;
-    sp<IStreamOut> mStream;
+    mediautils::atomic_wp<StreamOutHalInterfaceCallback> mCallback;
+    mediautils::atomic_wp<StreamOutHalInterfaceEventCallback> mEventCallback;
+    const sp<IStreamOut> mStream;
     std::unique_ptr<CommandMQ> mCommandMQ;
     std::unique_ptr<DataMQ> mDataMQ;
     std::unique_ptr<StatusMQ> mStatusMQ;
@@ -242,7 +242,7 @@
     typedef MessageQueue<uint8_t, hardware::kSynchronizedReadWrite> DataMQ;
     typedef MessageQueue<ReadStatus, hardware::kSynchronizedReadWrite> StatusMQ;
 
-    sp<IStreamIn> mStream;
+    const sp<IStreamIn> mStream;
     std::unique_ptr<CommandMQ> mCommandMQ;
     std::unique_ptr<DataMQ> mDataMQ;
     std::unique_ptr<StatusMQ> mStatusMQ;
diff --git a/media/libeffects/lvm/lib/Android.bp b/media/libeffects/lvm/lib/Android.bp
index 34cad1f..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",
@@ -166,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",
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
index 4a72834..e8541fd 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
@@ -167,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/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 7bcb7d7..7046a94 100644
--- a/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
@@ -21,31 +21,6 @@
 #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) {
     memmove(dst, src, n * sizeof(LVM_FLOAT));
     return;
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/Reverb/src/LVREV_ApplyNewSettings.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
index be846eb..a744339 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
@@ -148,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
@@ -171,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;
 
             /*
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
index f542a2b..61b3732 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
@@ -63,45 +63,13 @@
     LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->HPTaps, 2);
     LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->LPTaps, 2);
 #endif
-    if ((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays == LVREV_DELAYLINES_4) {
+    for (size_t i = 0; i < pLVREV_Private->InstanceParams.NumDelays; i++) {
 #ifdef BIQUAD_OPT
-        for (int i = 0; i < LVREV_DELAYLINES_4; i++) {
-            pLVREV_Private->revLPFBiquad[i]->clear();
-        }
+        pLVREV_Private->revLPFBiquad[i]->clear();
 #else
-        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, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[i], 2);
 #endif
-
-        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) {
-#ifdef BIQUAD_OPT
-        for (int i = 0; i < LVREV_DELAYLINES_2; i++) {
-            pLVREV_Private->revLPFBiquad[i]->clear();
-        }
-#else
-        LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
-        LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-#endif
-
-        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) {
-#ifdef BIQUAD_OPT
-        pLVREV_Private->revLPFBiquad[0]->clear();
-#else
-        LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-#endif
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
+        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 6ed0605..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) {
@@ -139,61 +139,18 @@
     pLVREV_Private->pFastData =
             (LVREV_FastData_st*)InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
 #endif
-    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);
+    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
@@ -303,14 +260,10 @@
         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(
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
index e8b2019..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) {
@@ -142,20 +141,8 @@
 #ifndef BIQUAD_OPT
         InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
 #endif
-        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));
+        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);
@@ -179,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 e52a1ca..c62ad1e 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
@@ -110,14 +110,15 @@
 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
 
@@ -150,28 +151,28 @@
     LVREV_FastData_st* pFastData; /* Fast data memory base address */
     LVREV_FastCoef_st* pFastCoef; /* Fast coefficient memory base address */
 #endif
-    LVM_FLOAT* pScratchDelayLine[4]; /* Delay line scratch memory */
+    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_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.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_Private.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
index a150e90..605a204 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
@@ -113,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 */
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.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/build_and_run_all_unit_tests.sh b/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
index e96263c..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
@@ -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 627af21..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
@@ -59,7 +59,7 @@
         do
             for fs in ${fs_arr[*]}
             do
-                for chMask in {0..22}
+                for chMask in {0..38}
                 do
                     adb shell $testdir/reverb_test \
                         --input $testdir/sinesweepraw.raw \
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 b7704ff..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);
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/TranscodingClientManager.cpp b/media/libmediatranscoding/TranscodingClientManager.cpp
index c0cc862..09afb1f 100644
--- a/media/libmediatranscoding/TranscodingClientManager.cpp
+++ b/media/libmediatranscoding/TranscodingClientManager.cpp
@@ -302,11 +302,13 @@
     }
 
     int32_t result;
-    if (APermissionManager_checkPermission("android.permission.WRITE_MEDIA_STORAGE", pid, uid,
-                                           &result) == PERMISSION_MANAGER_STATUS_OK &&
-        result == PERMISSION_MANAGER_PERMISSION_GRANTED) {
-        mTrustedUids.insert(uid);
-        return true;
+    if (__builtin_available(android 31, *)) {
+        if (APermissionManager_checkPermission("android.permission.WRITE_MEDIA_STORAGE", pid, uid,
+                                               &result) == PERMISSION_MANAGER_STATUS_OK &&
+            result == PERMISSION_MANAGER_PERMISSION_GRANTED) {
+            mTrustedUids.insert(uid);
+            return true;
+        }
     }
 
     return false;
diff --git a/media/libmediatranscoding/TranscodingUidPolicy.cpp b/media/libmediatranscoding/TranscodingUidPolicy.cpp
index a725387..b0fa545 100644
--- a/media/libmediatranscoding/TranscodingUidPolicy.cpp
+++ b/media/libmediatranscoding/TranscodingUidPolicy.cpp
@@ -48,8 +48,9 @@
 }
 
 void TranscodingUidPolicy::registerSelf() {
-    mUidObserver = AActivityManager_addUidImportanceListener(
-            &OnUidImportance, -1, (void*)this);
+    if (__builtin_available(android 31, *)) {
+        mUidObserver = AActivityManager_addUidImportanceListener(&OnUidImportance, -1, (void*)this);
+    }
 
     if (mUidObserver == nullptr) {
         ALOGE("Failed to register uid observer");
@@ -62,12 +63,16 @@
 }
 
 void TranscodingUidPolicy::unregisterSelf() {
-    AActivityManager_removeUidImportanceListener(mUidObserver);
-    mUidObserver = nullptr;
+    if (__builtin_available(android 31, *)) {
+        AActivityManager_removeUidImportanceListener(mUidObserver);
+        mUidObserver = nullptr;
 
-    Mutex::Autolock _l(mUidLock);
-    mRegistered = false;
-    ALOGI("Unregistered uid observer");
+        Mutex::Autolock _l(mUidLock);
+        mRegistered = false;
+        ALOGI("Unregistered uid observer");
+    } else {
+        ALOGE("Failed to unregister uid observer");
+    }
 }
 
 void TranscodingUidPolicy::setCallback(const std::shared_ptr<UidPolicyCallbackInterface>& cb) {
@@ -86,8 +91,10 @@
     }
 
     int32_t state = IMPORTANCE_UNKNOWN;
-    if (mRegistered && AActivityManager_isUidActive(uid)) {
-        state = AActivityManager_getUidImportance(uid);
+    if (__builtin_available(android 31, *)) {
+        if (mRegistered && AActivityManager_isUidActive(uid)) {
+            state = AActivityManager_getUidImportance(uid);
+        }
     }
 
     ALOGV("%s: inserting new uid: %u, procState %d", __FUNCTION__, uid, state);
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/Video_4K_HEVC_10Frames_Audio.mp4 b/media/libmediatranscoding/tests/assets/TranscodingTestAssets/Video_4K_HEVC_10Frames_Audio.mp4
new file mode 100644
index 0000000..b652dd9
--- /dev/null
+++ b/media/libmediatranscoding/tests/assets/TranscodingTestAssets/Video_4K_HEVC_10Frames_Audio.mp4
Binary files differ
diff --git a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
index 0695bdb..21d60ea 100644
--- a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
@@ -260,7 +260,12 @@
         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;
@@ -290,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;
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/tests/MediaTranscoderTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
index bfc1f3b..54d8b89 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
@@ -334,6 +334,17 @@
     testTranscodeVideo(srcPath, destPath, AMEDIA_MIMETYPE_VIDEO_AVC);
 }
 
+TEST_F(MediaTranscoderTests, TestVideoTranscode_4K) {
+#if defined(__i386__) || defined(__x86_64__)
+    LOG(WARNING) << "Skipping 4K test on x86 as SW encoder does not support 4K.";
+    return;
+#else
+    const char* srcPath = "/data/local/tmp/TranscodingTestAssets/Video_4K_HEVC_10Frames_Audio.mp4";
+    const char* destPath = "/data/local/tmp/MediaTranscoder_4K.MP4";
+    testTranscodeVideo(srcPath, destPath, AMEDIA_MIMETYPE_VIDEO_AVC);
+#endif
+}
+
 TEST_F(MediaTranscoderTests, TestPreserveBitrate) {
     const char* srcPath = "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
     const char* destPath = "/data/local/tmp/MediaTranscoder_PreserveBitrate.MP4";
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index cfdaebf..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() {
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/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..7ee3119 100644
--- a/media/libstagefright/codecs/avcdec/Android.bp
+++ b/media/libstagefright/codecs/avcdec/Android.bp
@@ -16,6 +16,9 @@
             "signed-integer-overflow",
         ],
         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..94f214d 100644
--- a/media/libstagefright/codecs/avcenc/Android.bp
+++ b/media/libstagefright/codecs/avcenc/Android.bp
@@ -10,6 +10,9 @@
             "signed-integer-overflow",
         ],
         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/Android.bp b/media/libstagefright/codecs/hevcdec/Android.bp
index ec436ce..ffad18c 100644
--- a/media/libstagefright/codecs/hevcdec/Android.bp
+++ b/media/libstagefright/codecs/hevcdec/Android.bp
@@ -17,6 +17,9 @@
             "signed-integer-overflow",
         ],
         cfi: true,
+        config: {
+            cfi_assembly_support: true,
+        },
     },
 
     // We need this because the current asm generates the following link error:
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..2706665 100644
--- a/media/libstagefright/codecs/xaacdec/Android.bp
+++ b/media/libstagefright/codecs/xaacdec/Android.bp
@@ -14,6 +14,9 @@
         // integer_overflow: true,
         misc_undefined: [ "signed-integer-overflow", "unsigned-integer-overflow", ],
         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/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/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/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
index a0b66a7..cccb63a 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -25,6 +25,7 @@
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/avc_utils.h>
 #include <media/stagefright/foundation/hexdump.h>
 
 #include <stdint.h>
@@ -39,7 +40,9 @@
       mNextExpectedSeqNo(0),
       mAccessUnitDamaged(false),
       mFirstIFrameProvided(false),
-      mLastIFrameProvidedAtMs(0) {
+      mLastIFrameProvidedAtMs(0),
+      mWidth(0),
+      mHeight(0) {
 }
 
 AAVCAssembler::~AAVCAssembler() {
@@ -115,6 +118,8 @@
     sp<ABuffer> buffer = *queue->begin();
     uint32_t rtpTime;
     CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+    buffer->meta()->setObject("source", source);
+
     int64_t startTime = source->mFirstSysTime / 1000;
     int64_t nowTime = ALooper::GetNowUs() / 1000;
     int64_t playedTime = nowTime - startTime;
@@ -224,6 +229,21 @@
     }
 }
 
+void AAVCAssembler::checkSpsUpdated(const sp<ABuffer> &buffer) {
+    const uint8_t *data = buffer->data();
+    unsigned nalType = data[0] & 0x1f;
+    if (nalType == 0x7) {
+        int32_t width = 0, height = 0;
+        FindAVCDimensions(buffer, &width, &height);
+        if (width != mWidth || height != mHeight) {
+            mFirstIFrameProvided = false;
+            mWidth = width;
+            mHeight = height;
+            ALOGD("found a new resolution (%u x %u)", mWidth, mHeight);
+        }
+    }
+}
+
 void AAVCAssembler::checkIFrameProvided(const sp<ABuffer> &buffer) {
     if (buffer->size() == 0) {
         return;
@@ -231,26 +251,50 @@
     const uint8_t *data = buffer->data();
     unsigned nalType = data[0] & 0x1f;
     if (nalType == 0x5) {
-        mFirstIFrameProvided = true;
         mLastIFrameProvidedAtMs = ALooper::GetNowUs() / 1000;
+        if (!mFirstIFrameProvided) {
+            mFirstIFrameProvided = true;
 
-        uint32_t rtpTime;
-        CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
-        ALOGD("got First I-frame to be decoded. rtpTime=%u, size=%zu", rtpTime, buffer->size());
+            uint32_t rtpTime;
+            CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+            ALOGD("got First I-frame to be decoded. rtpTime=%d, size=%zu", rtpTime, buffer->size());
+        }
     }
 }
 
+bool AAVCAssembler::dropFramesUntilIframe(const sp<ABuffer> &buffer) {
+    const uint8_t *data = buffer->data();
+    unsigned nalType = data[0] & 0x1f;
+    if (!mFirstIFrameProvided && nalType < 0x5) {
+        return true;
+    }
+
+    return false;
+}
+
 void AAVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) {
     ALOGV("addSingleNALUnit of size %zu", buffer->size());
 #if !LOG_NDEBUG
     hexdump(buffer->data(), buffer->size());
 #endif
 
+    checkSpsUpdated(buffer);
     checkIFrameProvided(buffer);
 
     uint32_t rtpTime;
     CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
 
+    if (dropFramesUntilIframe(buffer)) {
+        sp<ARTPSource> source = nullptr;
+        buffer->meta()->findObject("source", (sp<android::RefBase>*)&source);
+        if (source != nullptr) {
+            ALOGD("Issued FIR to get the I-frame");
+            source->onIssueFIRByAssembler();
+        }
+        ALOGV("Dropping P-frame till I-frame provided. rtpTime %u", rtpTime);
+        return;
+    }
+
     if (!mNALUnits.empty() && rtpTime != mAccessUnitRTPTime) {
         submitAccessUnit();
     }
@@ -431,6 +475,7 @@
 
     size_t offset = 1;
     int32_t cvo = -1;
+    sp<ARTPSource> source = nullptr;
     List<sp<ABuffer> >::iterator it = queue->begin();
     for (size_t i = 0; i < totalCount; ++i) {
         const sp<ABuffer> &buffer = *it;
@@ -442,6 +487,7 @@
 
         memcpy(unit->data() + offset, buffer->data() + 2, buffer->size() - 2);
 
+        buffer->meta()->findObject("source", (sp<android::RefBase>*)&source);
         buffer->meta()->findInt32("cvo", &cvo);
         offset += buffer->size() - 2;
 
@@ -453,6 +499,9 @@
     if (cvo >= 0) {
         unit->meta()->setInt32("cvo", cvo);
     }
+    if (source != nullptr) {
+        unit->meta()->setObject("source", source);
+    }
 
     addSingleNALUnit(unit);
 
diff --git a/media/libstagefright/rtsp/AAVCAssembler.h b/media/libstagefright/rtsp/AAVCAssembler.h
index 913a868..79fc7c2 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.h
+++ b/media/libstagefright/rtsp/AAVCAssembler.h
@@ -48,10 +48,14 @@
     bool mAccessUnitDamaged;
     bool mFirstIFrameProvided;
     uint64_t mLastIFrameProvidedAtMs;
+    int32_t mWidth;
+    int32_t mHeight;
     List<sp<ABuffer> > mNALUnits;
 
     int32_t addNack(const sp<ARTPSource> &source);
+    void checkSpsUpdated(const sp<ABuffer> &buffer);
     void checkIFrameProvided(const sp<ABuffer> &buffer);
+    bool dropFramesUntilIframe(const sp<ABuffer> &buffer);
     AssemblyStatus addNALUnit(const sp<ARTPSource> &source);
     void addSingleNALUnit(const sp<ABuffer> &buffer);
     AssemblyStatus addFragmentedNALUnit(List<sp<ABuffer> > *queue);
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 6303fc4..c611f6f 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -226,7 +226,7 @@
         // Send it if last FIR is not sent within a sec.
         send = true;
     } else if (mIssueFIRRequests && (usecsSinceLastFIR > 5000000)) {
-        // A FIR issued periodically reagardless packet loss.
+        // A FIR issued periodically regardless packet loss.
         // Send it if last FIR is not sent within 5 secs.
         send = true;
     }
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/mtp/IMtpDatabase.h b/media/mtp/IMtpDatabase.h
index 81fa60c..3b9bbb0 100644
--- a/media/mtp/IMtpDatabase.h
+++ b/media/mtp/IMtpDatabase.h
@@ -39,7 +39,7 @@
     // Called to report success or failure of the SendObject file transfer.
     virtual void                    endSendObject(MtpObjectHandle handle,
                                             bool succeeded) = 0;
-    
+
     // Called to rescan a file, such as after an edit.
     virtual void                    rescanFile(const char* path,
                                             MtpObjectHandle handle,
@@ -91,6 +91,8 @@
                                             int64_t& outFileLength,
                                             MtpObjectFormat& outFormat) = 0;
 
+    virtual int                     openFilePath(const char* path, bool transcode) = 0;
+
     virtual MtpResponseCode         beginDeleteObject(MtpObjectHandle handle) = 0;
     virtual void                    endDeleteObject(MtpObjectHandle handle, bool succeeded) = 0;
 
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 8677b90..a92848c 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -790,11 +790,30 @@
     auto start = std::chrono::steady_clock::now();
 
     const char* filePath = (const char *)pathBuf;
-    mtp_file_range  mfr;
-    mfr.fd = open(filePath, O_RDONLY);
-    if (mfr.fd < 0) {
-        return MTP_RESPONSE_GENERAL_ERROR;
+    mtp_file_range mfr;
+    struct stat sstat;
+    uint64_t finalsize;
+    bool transcode = android::base::GetBoolProperty("sys.fuse.transcode_mtp", true);
+    ALOGD("Mtp transcode = %d", transcode);
+    mfr.fd = mDatabase->openFilePath(filePath, transcode);
+    // Doing this here because we want to update fileLength only for this case and leave the
+    // regular path as unchanged as possible.
+    if (mfr.fd >= 0) {
+        fstat(mfr.fd, &sstat);
+        finalsize = sstat.st_size;
+        fileLength = finalsize;
+    } else {
+        ALOGW("Mtp open via IMtpDatabase failed for %s. Falling back to the original",
+                filePath);
+
+        mfr.fd = open(filePath, O_RDONLY);
+        if (mfr.fd < 0) {
+            return MTP_RESPONSE_GENERAL_ERROR;
+        }
+        fstat(mfr.fd, &sstat);
+        finalsize = sstat.st_size;
     }
+
     mfr.offset = 0;
     mfr.length = fileLength;
     mfr.command = mRequest.getOperationCode();
@@ -815,9 +834,6 @@
 
     auto end = std::chrono::steady_clock::now();
     std::chrono::duration<double> diff = end - start;
-    struct stat sstat;
-    fstat(mfr.fd, &sstat);
-    uint64_t finalsize = sstat.st_size;
     ALOGV("Sent a file over MTP. Time: %f s, Size: %" PRIu64 ", Rate: %f bytes/s",
             diff.count(), finalsize, ((double) finalsize) / diff.count());
     closeObjFd(mfr.fd, filePath);
diff --git a/media/mtp/tests/MtpFuzzer/MtpMockDatabase.cpp b/media/mtp/tests/MtpFuzzer/MtpMockDatabase.cpp
index 5d95aa2..8aafe33 100644
--- a/media/mtp/tests/MtpFuzzer/MtpMockDatabase.cpp
+++ b/media/mtp/tests/MtpFuzzer/MtpMockDatabase.cpp
@@ -252,6 +252,11 @@
     return MTP_RESPONSE_OK;
 }
 
+int MtpMockDatabase::openFilePath(const char* path, bool transcode) {
+    ALOGD("MockDatabase %s: filePath=%s transcode=%d\n", __func__, path, transcode);
+    return 0;
+}
+
 MtpResponseCode MtpMockDatabase::beginDeleteObject(MtpObjectHandle handle) {
     ALOGD("MockDatabase %s: ohandle=%u\n", __func__, handle);
     return MTP_RESPONSE_OK;
diff --git a/media/mtp/tests/MtpFuzzer/MtpMockDatabase.h b/media/mtp/tests/MtpFuzzer/MtpMockDatabase.h
index 876719e..e9e6a64 100644
--- a/media/mtp/tests/MtpFuzzer/MtpMockDatabase.h
+++ b/media/mtp/tests/MtpFuzzer/MtpMockDatabase.h
@@ -90,6 +90,8 @@
     MtpResponseCode getObjectFilePath(MtpObjectHandle handle, MtpStringBuffer& outFilePath,
                                       int64_t& outFileLength, MtpObjectFormat& outFormat);
 
+    int openFilePath(const char* path, bool transcode);
+
     MtpResponseCode beginDeleteObject(MtpObjectHandle handle);
     void endDeleteObject(MtpObjectHandle handle, bool succeeded);
 
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/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 237b66e..2b389fe 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -167,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/utils/Android.bp b/media/utils/Android.bp
index e3f1e44..952fe37 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -60,3 +60,10 @@
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
 }
+
+cc_library_headers {
+    name: "libmediautils_headers",
+    vendor_available: true,  // required for platform/hardware/interfaces
+
+    export_include_dirs: ["include"],
+}
diff --git a/media/utils/include/mediautils/Synchronization.h b/media/utils/include/mediautils/Synchronization.h
new file mode 100644
index 0000000..aef4967
--- /dev/null
+++ b/media/utils/include/mediautils/Synchronization.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <mutex>
+#include <utils/RefBase.h>
+
+namespace android::mediautils {
+
+/**
+ * The LockItem class introduces a simple template which mimics atomic<T>
+ * for non-trivially copyable types.  For trivially copyable types,
+ * the LockItem will statically assert that an atomic<T> should be used instead.
+ *
+ * The default lock mutex is std::mutex which is suitable for all but rare cases
+ * e.g. recursive constructors that might be found in tree construction,
+ * setters that might recurse onto the same object.
+ */
+
+template <typename T, typename L = std::mutex, int FLAGS = 0>
+class LockItem {
+protected:
+    mutable L mLock;
+    mutable T mT;
+
+public:
+    enum {
+        // Best practices for smart pointers and complex containers is to move to a temp
+        // and invoke destructor outside of lock.  This reduces time under lock and in
+        // some cases eliminates deadlock.
+        FLAG_DTOR_OUT_OF_LOCK = 1,
+    };
+
+    // Check type, suggest std::atomic if possible.
+    static_assert(!std::is_trivially_copyable_v<T>,
+            "type is trivially copyable, please use std::atomic instead");
+
+    // Allow implicit conversions as expected for some types, e.g. sp -> wp.
+    template <typename... Args>
+    LockItem(Args&&... args) : mT(std::forward<Args>(args)...) {
+    }
+
+    // NOT copy or move / assignable or constructible.
+
+    // Do not enable this because it may lead to confusion because it returns
+    // a copy-value not a reference.
+    // operator T() const { return load(); }
+
+    // any conversion done under lock.
+    template <typename U>
+    void operator=(U&& u) {
+        store(std::forward<U>(u));
+    }
+
+    // returns a copy-value not a reference.
+    T load() const {
+        std::lock_guard lock(mLock);
+        return mT;
+    }
+
+    // any conversion done under lock.
+    template <typename U>
+    void store(U&& u) {
+        if constexpr ((FLAGS & FLAG_DTOR_OUT_OF_LOCK) != 0) {
+             std::unique_lock lock(mLock);
+             T temp = std::move(mT);
+             mT = std::forward<U>(u);
+             lock.unlock();
+        } else {
+            std::lock_guard lock(mLock);
+            mT = std::forward<U>(u);
+        }
+    }
+};
+
+/**
+ * atomic_wp<> and atomic_sp<> are used for concurrent access to Android
+ * sp<> and wp<> smart pointers, including their modifiers.  We
+ * return a copy of the smart pointer with load().
+ *
+ * Historical: The importance of an atomic<std::shared_ptr<T>> class is described
+ * by Herb Sutter in the following ISO document https://isocpp.org/files/papers/N4162.pdf
+ * and is part of C++20.  Lock free versions of atomic smart pointers are available
+ * publicly but usually require specialized smart pointer structs.
+ * See also https://en.cppreference.com/w/cpp/memory/shared_ptr/atomic
+ * and https://en.cppreference.com/w/cpp/memory/shared_ptr/atomic2
+ *
+ * We offer lock based atomic_wp<> and atomic_sp<> objects here. This is useful to
+ * copy the Android smart pointer to a different variable for subsequent local access,
+ * where the change of the original object after copy is acceptable.
+ *
+ * Note: Instead of atomics, it is often preferrable to create an explicit visible lock to
+ * ensure complete transaction consistency.  For example, one might want to ensure
+ * that the method called from the smart pointer is also done under lock.
+ * This may not be possible for callbacks due to inverted lock ordering.
+ */
+
+template <typename T>
+using atomic_wp = LockItem<::android::wp<T>>;
+
+template <typename T>
+using atomic_sp = LockItem<
+        ::android::sp<T>, std::mutex, LockItem<::android::sp<T>>::FLAG_DTOR_OUT_OF_LOCK>;
+
+/**
+ * Defers a function to run in the RAII destructor.
+ * A C++ implementation of Go _defer_ https://golangr.com/defer/.
+ */
+class Defer {
+public:
+    template <typename U>
+    explicit Defer(U &&f) : mThunk(std::forward<U>(f)) {}
+    ~Defer() { mThunk(); }
+
+private:
+    const std::function<void()> mThunk;
+};
+
+} // namespace android::mediautils
+
diff --git a/media/utils/tests/Android.bp b/media/utils/tests/Android.bp
new file mode 100644
index 0000000..bb413c3
--- /dev/null
+++ b/media/utils/tests/Android.bp
@@ -0,0 +1,19 @@
+cc_test {
+    name: "media_synchronization_tests",
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libmediautils",
+        "libutils",
+    ],
+
+    srcs: [
+        "media_synchronization_tests.cpp",
+    ],
+}
diff --git a/media/utils/tests/media_synchronization_tests.cpp b/media/utils/tests/media_synchronization_tests.cpp
new file mode 100644
index 0000000..169768e
--- /dev/null
+++ b/media/utils/tests/media_synchronization_tests.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "media_synchronization_tests"
+
+#include <mediautils/Synchronization.h>
+
+#include <gtest/gtest.h>
+#include <utils/Log.h>
+
+using namespace android;
+using namespace android::mediautils;
+
+// Simple Test Class
+template <typename T>
+class MyObject : public RefBase {
+    T value_;
+  public:
+    MyObject(const T& value) : value_(value) {}
+    MyObject(const MyObject<T>& mo) : value_(mo.get()) {}
+    T get() const { return value_; }
+    void set(const T& value) { value_ = value; }
+};
+
+TEST(media_synchronization_tests, atomic_wp) {
+  sp<MyObject<int>> refobj = new MyObject<int>(20);
+  atomic_wp<MyObject<int>> wpobj = refobj;
+
+  // we can promote.
+  ASSERT_EQ(20, wpobj.load().promote()->get());
+
+  // same underlying object for sp and atomic_wp.
+  ASSERT_EQ(refobj.get(), wpobj.load().promote().get());
+
+  // behavior is consistent with same underlying object.
+  wpobj.load().promote()->set(10);
+  ASSERT_EQ(10, refobj->get());
+  refobj->set(5);
+  ASSERT_EQ(5, wpobj.load().promote()->get());
+
+  // we can clear our weak ptr.
+  wpobj = nullptr;
+  ASSERT_EQ(nullptr, wpobj.load().promote());
+
+  // didn't affect our original obj.
+  ASSERT_NE(nullptr, refobj.get());
+}
+
+TEST(media_synchronization_tests, atomic_sp) {
+  sp<MyObject<int>> refobj = new MyObject<int>(20);
+  atomic_sp<MyObject<int>> spobj = refobj;
+
+  // same underlying object for sp and atomic_sp.
+  ASSERT_EQ(refobj.get(), spobj.load().get());
+
+  // behavior is consistent with same underlying object.
+  ASSERT_EQ(20, spobj.load()->get());
+  spobj.load()->set(10);
+  ASSERT_EQ(10, refobj->get());
+  refobj->set(5);
+  ASSERT_EQ(5, spobj.load()->get());
+
+  // we can clear spobj.
+  spobj = nullptr;
+  ASSERT_EQ(nullptr, spobj.load().get());
+
+  // didn't affect our original obj.
+  ASSERT_NE(nullptr, refobj.get());
+}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index a6f0953..b8257d3 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -128,9 +128,6 @@
 // we define a minimum time during which a global effect is considered enabled.
 static const nsecs_t kMinGlobalEffectEnabletimeNs = seconds(7200);
 
-Mutex gLock;
-wp<AudioFlinger> gAudioFlinger;
-
 // Keep a strong reference to media.log service around forever.
 // The service is within our parent process so it can never die in a way that we could observe.
 // These two variables are const after initialization.
@@ -268,7 +265,7 @@
 
     mMode = AUDIO_MODE_NORMAL;
 
-    gAudioFlinger = this;
+    gAudioFlinger = this;  // we are already refcounted, store into atomic pointer.
 
     mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
     mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
@@ -325,11 +322,9 @@
                                              sp<MmapStreamInterface>& interface,
                                              audio_port_handle_t *handle)
 {
-    sp<AudioFlinger> af;
-    {
-        Mutex::Autolock _l(gLock);
-        af = gAudioFlinger.promote();
-    }
+    // TODO: Use ServiceManager to get IAudioFlinger instead of by atomic pointer.
+    // This allows moving oboeservice (AAudio) to a separate process in the future.
+    sp<AudioFlinger> af = AudioFlinger::gAudioFlinger.load();  // either nullptr or singleton AF.
     status_t ret = NO_INIT;
     if (af != 0) {
         ret = af->openMmapStream(
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 1c6f57c..1d530a4 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -73,6 +73,7 @@
 #include <media/ExtendedAudioBufferProvider.h>
 #include <media/VolumeShaper.h>
 #include <mediautils/ServiceUtilities.h>
+#include <mediautils/Synchronization.h>
 
 #include <audio_utils/clock.h>
 #include <audio_utils/FdToString.h>
@@ -305,6 +306,24 @@
     Mutex               mUnregisteredWritersLock;
 
 public:
+    // Life cycle of gAudioFlinger and AudioFlinger:
+    //
+    // AudioFlinger is created once and survives until audioserver crashes
+    // irrespective of sp<> and wp<> as it is refcounted by ServiceManager and we
+    // don't issue a ServiceManager::tryUnregisterService().
+    //
+    // gAudioFlinger is an atomic pointer set on AudioFlinger::onFirstRef().
+    // After this is set, it is safe to obtain a wp<> or sp<> from it as the
+    // underlying object does not go away.
+    //
+    // Note: For most inner classes, it is acceptable to hold a reference to the outer
+    // AudioFlinger instance as creation requires AudioFlinger to exist in the first place.
+    //
+    // An atomic here ensures underlying writes have completed before setting
+    // the pointer. Access by memory_order_seq_cst.
+    //
+
+    static inline std::atomic<AudioFlinger *> gAudioFlinger = nullptr;
 
     class SyncEvent;
 
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 3ab7737..56d32a6 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -2785,11 +2785,7 @@
         const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
         sp<EffectHalInterface> *effect) {
     status_t status = NO_INIT;
-    sp<AudioFlinger> af = mAudioFlinger.promote();
-    if (af == nullptr) {
-        return status;
-    }
-    sp<EffectsFactoryHalInterface> effectsFactory = af->getEffectsFactory();
+    sp<EffectsFactoryHalInterface> effectsFactory = mAudioFlinger.getEffectsFactory();
     if (effectsFactory != 0) {
         status = effectsFactory->createEffect(pEffectUuid, sessionId, io(), deviceId, effect);
     }
@@ -2798,25 +2794,19 @@
 
 bool AudioFlinger::EffectChain::EffectCallback::updateOrphanEffectChains(
         const sp<AudioFlinger::EffectBase>& effect) {
-    sp<AudioFlinger> af = mAudioFlinger.promote();
-    if (af == nullptr) {
-        return false;
-    }
     // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
-    return af->updateOrphanEffectChains(effect->asEffectModule());
+    return mAudioFlinger.updateOrphanEffectChains(effect->asEffectModule());
 }
 
 status_t AudioFlinger::EffectChain::EffectCallback::allocateHalBuffer(
         size_t size, sp<EffectBufferHalInterface>* buffer) {
-    sp<AudioFlinger> af = mAudioFlinger.promote();
-    LOG_ALWAYS_FATAL_IF(af == nullptr, "allocateHalBuffer() could not retrieved audio flinger");
-    return af->mEffectsFactoryHal->allocateBuffer(size, buffer);
+    return mAudioFlinger.mEffectsFactoryHal->allocateBuffer(size, buffer);
 }
 
 status_t AudioFlinger::EffectChain::EffectCallback::addEffectToHal(
         sp<EffectHalInterface> effect) {
     status_t result = NO_INIT;
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return result;
     }
@@ -2832,7 +2822,7 @@
 status_t AudioFlinger::EffectChain::EffectCallback::removeEffectFromHal(
         sp<EffectHalInterface> effect) {
     status_t result = NO_INIT;
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return result;
     }
@@ -2846,7 +2836,7 @@
 }
 
 audio_io_handle_t AudioFlinger::EffectChain::EffectCallback::io() const {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_IO_HANDLE_NONE;
     }
@@ -2854,7 +2844,7 @@
 }
 
 bool AudioFlinger::EffectChain::EffectCallback::isOutput() const {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return true;
     }
@@ -2862,7 +2852,7 @@
 }
 
 bool AudioFlinger::EffectChain::EffectCallback::isOffload() const {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return false;
     }
@@ -2870,7 +2860,7 @@
 }
 
 bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrDirect() const {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return false;
     }
@@ -2878,7 +2868,7 @@
 }
 
 bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrMmap() const {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return false;
     }
@@ -2886,7 +2876,7 @@
 }
 
 uint32_t AudioFlinger::EffectChain::EffectCallback::sampleRate() const {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
@@ -2894,7 +2884,7 @@
 }
 
 audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::channelMask() const {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
@@ -2902,7 +2892,7 @@
 }
 
 uint32_t AudioFlinger::EffectChain::EffectCallback::channelCount() const {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
@@ -2910,7 +2900,7 @@
 }
 
 audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::hapticChannelMask() const {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
@@ -2918,7 +2908,7 @@
 }
 
 size_t AudioFlinger::EffectChain::EffectCallback::frameCount() const {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
@@ -2926,7 +2916,7 @@
 }
 
 uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
@@ -2934,7 +2924,7 @@
 }
 
 void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
@@ -2943,13 +2933,13 @@
 
 void AudioFlinger::EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
         const sp<EffectBase>& effect, bool enabled, bool threadLocked) {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
     t->checkSuspendOnEffectEnabled(enabled, effect->sessionId(), threadLocked);
 
-    sp<EffectChain> c = mChain.promote();
+    sp<EffectChain> c = chain().promote();
     if (c == nullptr) {
         return;
     }
@@ -2958,7 +2948,7 @@
 }
 
 void AudioFlinger::EffectChain::EffectCallback::onEffectEnable(const sp<EffectBase>& effect) {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
@@ -2969,7 +2959,7 @@
 void AudioFlinger::EffectChain::EffectCallback::onEffectDisable(const sp<EffectBase>& effect) {
     checkSuspendOnEffectEnabled(effect, false, false /*threadLocked*/);
 
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
@@ -2978,7 +2968,7 @@
 
 bool AudioFlinger::EffectChain::EffectCallback::disconnectEffectHandle(EffectHandle *handle,
                                                       bool unpinIfLast) {
-    sp<ThreadBase> t = mThread.promote();
+    sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return false;
     }
@@ -2987,7 +2977,7 @@
 }
 
 void AudioFlinger::EffectChain::EffectCallback::resetVolume() {
-    sp<EffectChain> c = mChain.promote();
+    sp<EffectChain> c = chain().promote();
     if (c == nullptr) {
         return;
     }
@@ -2996,7 +2986,7 @@
 }
 
 uint32_t AudioFlinger::EffectChain::EffectCallback::strategy() const {
-    sp<EffectChain> c = mChain.promote();
+    sp<EffectChain> c = chain().promote();
     if (c == nullptr) {
         return PRODUCT_STRATEGY_NONE;
     }
@@ -3004,7 +2994,7 @@
 }
 
 int32_t AudioFlinger::EffectChain::EffectCallback::activeTrackCnt() const {
-    sp<EffectChain> c = mChain.promote();
+    sp<EffectChain> c = chain().promote();
     if (c == nullptr) {
         return 0;
     }
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 03bdc60..139c049 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
@@ -512,14 +512,21 @@
 
 private:
 
+    // For transaction consistency, please consider holding the EffectChain lock before
+    // calling the EffectChain::EffectCallback methods, excepting
+    // createEffectHal and allocateHalBuffer.
+    //
+    // This prevents migration of the EffectChain to another PlaybackThread
+    // for the purposes of the EffectCallback.
     class EffectCallback :  public EffectCallbackInterface {
     public:
         // Note: ctors taking a weak pointer to their owner must not promote it
         // during construction (but may keep a reference for later promotion).
         EffectCallback(const wp<EffectChain>& owner,
                        const wp<ThreadBase>& thread)
-            : mChain(owner) {
-            setThread(thread);
+            : mChain(owner)
+            , mThread(thread)
+            , mAudioFlinger(*gAudioFlinger) {
         }
 
         status_t createEffectHal(const effect_uuid_t *pEffectUuid,
@@ -556,18 +563,16 @@
 
         wp<EffectChain> chain() const override { return mChain; }
 
-        wp<ThreadBase> thread() { return mThread; }
+        wp<ThreadBase> thread() const { return mThread.load(); }
 
         void setThread(const wp<ThreadBase>& thread) {
             mThread = thread;
-            sp<ThreadBase> p = thread.promote();
-            mAudioFlinger = p ? p->mAudioFlinger : nullptr;
         }
 
     private:
-        wp<EffectChain> mChain;
-        wp<ThreadBase> mThread;
-        wp<AudioFlinger> mAudioFlinger;
+        const wp<EffectChain> mChain;
+        mediautils::atomic_wp<ThreadBase> mThread;
+        AudioFlinger &mAudioFlinger;  // implementation detail: outer instance always exists.
     };
 
     friend class AudioFlinger;  // for mThread, mEffects
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 9d5a0a0..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,
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 5153dce..1f9b535 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -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);
@@ -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.
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 7c712e3..3d338ea 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -265,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;
@@ -273,7 +275,9 @@
 
 private:
     void refreshTypes();
+    void refreshAudioProfiles();
     DeviceTypeSet mDeviceTypes;
+    AudioProfileVector mSupportedProfiles;
 };
 
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 621c630..a5cd534 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -143,6 +143,8 @@
         return false;
     }
 
+    bool containsSingleDeviceSupportingEncodedFormats(const sp<DeviceDescriptor>& device) const;
+
     void clearSupportedDevices() { mSupportedDevices.clear(); }
     void addSupportedDevice(const sp<DeviceDescriptor> &device)
     {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index c4d7340..b872709 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -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()) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index fc1d0e2..c024a85 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -208,24 +208,25 @@
         // Loopback render mixes are created from a public API and thus restricted
         // to non sensible audio that have not opted out.
         if (is_mix_loopback_render(mix->mRouteFlags)) {
-            auto hasFlag = [](auto flags, auto flag) { return (flags & flag) == flag; };
-            if (hasFlag(attributes.flags, AUDIO_FLAG_NO_SYSTEM_CAPTURE)) {
-                return MixMatchStatus::NO_MATCH;
-            }
-            if (!mix->mAllowPrivilegedPlaybackCapture &&
-                hasFlag(attributes.flags, AUDIO_FLAG_NO_MEDIA_PROJECTION)) {
-                return MixMatchStatus::NO_MATCH;
-            }
-            if (attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION &&
-                !mix->mVoiceCommunicationCaptureAllowed) {
-                return MixMatchStatus::NO_MATCH;
-            }
             if (!(attributes.usage == AUDIO_USAGE_UNKNOWN ||
                   attributes.usage == AUDIO_USAGE_MEDIA ||
                   attributes.usage == AUDIO_USAGE_GAME ||
                   attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION)) {
                 return MixMatchStatus::NO_MATCH;
             }
+            auto hasFlag = [](auto flags, auto flag) { return (flags & flag) == flag; };
+            if (hasFlag(attributes.flags, AUDIO_FLAG_NO_SYSTEM_CAPTURE)) {
+                return MixMatchStatus::NO_MATCH;
+            }
+
+            if (attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION) {
+                if (!mix->mVoiceCommunicationCaptureAllowed) {
+                    return MixMatchStatus::NO_MATCH;
+                }
+            } else if (!mix->mAllowPrivilegedMediaPlaybackCapture &&
+                hasFlag(attributes.flags, AUDIO_FLAG_NO_MEDIA_PROJECTION)) {
+                return MixMatchStatus::NO_MATCH;
+            }
         }
 
         int userId = (int) multiuser_get_user_id(uid);
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 30b739c..6c31b79 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -217,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++) {
@@ -238,6 +250,7 @@
     }
     if (added) {
         refreshTypes();
+        refreshAudioProfiles();
     }
 }
 
@@ -250,6 +263,7 @@
         ret = SortedVector::add(item);
         if (ret >= 0) {
             refreshTypes();
+            refreshAudioProfiles();
         }
     } else {
         ALOGW("DeviceVector::add device %08x already in", item->type());
@@ -268,6 +282,7 @@
         ret = SortedVector::removeAt(ret);
         if (ret >= 0) {
             refreshTypes();
+            refreshAudioProfiles();
         }
     }
     return ret;
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/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index f15ed4b..65bae77 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -246,6 +246,7 @@
                     if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) ||
                             (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
                                 (desc->mDirectOpenCount == 0))) {
+                        clearAudioSourcesForOutput(output);
                         closeOutput(output);
                     }
                 }
@@ -265,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)) {
@@ -280,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) {
@@ -359,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);
         }
@@ -444,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) &&
@@ -538,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());
@@ -590,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
@@ -654,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);
@@ -721,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();
@@ -1932,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);
 
@@ -1945,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);
@@ -1960,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);
@@ -1969,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,
@@ -3495,7 +3547,9 @@
                                             offloadInfo.channel_mask,
                                             AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD,
                                             true /* directOnly */);
-    ALOGV("%s: profile %sfound", __func__, profile != 0 ? "" : "NOT ");
+    ALOGV("%s: profile %sfound%s", __func__, profile != nullptr ? "" : "NOT ",
+            (profile != nullptr && (profile->getFlags() & AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD) != 0)
+            ? ", supports gapless" : "");
     if (profile == nullptr) {
         return AUDIO_OFFLOAD_NOT_SUPPORTED;
     }
@@ -3821,6 +3875,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
@@ -3836,49 +3925,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;
@@ -3969,8 +4034,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.
@@ -4236,15 +4302,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;
@@ -4254,7 +4324,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) {
@@ -4551,13 +4621,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) {
@@ -4566,7 +4644,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(
@@ -4657,6 +4737,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*/);
@@ -4678,17 +4761,11 @@
         }
     }
 
-    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");
 
-    mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
-            mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
-
     updateDevicesAndOutputs();
     return status;
 }
@@ -4794,7 +4871,7 @@
                     setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
                 }
             }
-            if (mPrimaryOutput == 0 &&
+            if (mPrimaryOutput == nullptr &&
                     outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
                 mPrimaryOutput = outputDesc;
             }
@@ -4871,6 +4948,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();
 }
@@ -4964,82 +5045,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);
@@ -5048,6 +5055,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);
                 }
 
@@ -5072,7 +5081,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",
@@ -5085,11 +5094,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);
+                    }
                 }
             }
         }
@@ -5372,6 +5400,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);
@@ -5468,7 +5519,7 @@
                                 newDevices.types());
             }
             sp<SourceClientDescriptor> source = getSourceForAttributesOnOutput(srcOut, attr);
-            if (source != 0){
+            if (source != nullptr && !isCallRxAudioSource(source)) {
                 connectAudioSource(source);
             }
         }
@@ -5491,6 +5542,7 @@
     for (const auto &strategy : mEngine->getOrderedProductStrategies()) {
         auto attributes = mEngine->getAllAttributesForProductStrategy(strategy).front();
         checkOutputForAttributes(attributes);
+        checkAudioSourceForAttributes(attributes);
     }
 }
 
@@ -6462,9 +6514,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);
         }
     }
 
@@ -6478,10 +6531,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;
             }
         }
@@ -6704,4 +6761,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 4e745bd..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,
@@ -556,6 +556,15 @@
          */
         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.
          */
@@ -571,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;
 
@@ -740,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);
 
@@ -786,7 +806,6 @@
         SoundTriggerSessionCollection mSoundTriggerSessions;
 
         sp<AudioPatch> mCallTxPatch;
-        sp<AudioPatch> mCallRxPatch;
 
         HwAudioOutputCollection mHwOutputs;
         SourceClientCollection mAudioSources;
@@ -825,6 +844,10 @@
         // 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);
 
@@ -981,6 +1004,12 @@
                 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/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 10bf707..66f9fbd 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1241,7 +1241,7 @@
             return mix.mVoiceCommunicationCaptureAllowed; });
 
     bool needCaptureMediaOutput = std::any_of(mixes.begin(), mixes.end(), [](auto& mix) {
-            return mix.mAllowPrivilegedPlaybackCapture; });
+            return mix.mAllowPrivilegedMediaPlaybackCapture; });
 
     const uid_t callingUid = IPCThreadState::self()->getCallingUid();
     const pid_t callingPid = IPCThreadState::self()->getCallingPid();
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index a898dff..80022c8 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -529,6 +529,11 @@
 
     for (size_t i =0; i < mAudioRecordClients.size(); i++) {
         sp<AudioRecordClient> current = mAudioRecordClients[i];
+        if (!isVirtualSource(current->attributes.source)
+                && isUserSensorPrivacyEnabledForUid(current->uid)) {
+            setAppState_l(current->portId, APP_STATE_IDLE);
+            continue;
+        }
         if (!current->active) {
             continue;
         }
@@ -978,6 +983,16 @@
     return NO_INIT;
 }
 
+bool AudioPolicyService::isUserSensorPrivacyEnabledForUid(uid_t uid) {
+    userid_t userId = multiuser_get_user_id(uid);
+    if (mMicrophoneSensorPrivacyPolicies.find(userId) == mMicrophoneSensorPrivacyPolicies.end()) {
+        sp<SensorPrivacyPolicy> userPolicy = new SensorPrivacyPolicy(this);
+        userPolicy->registerSelfForMicrophoneOnly(userId);
+        mMicrophoneSensorPrivacyPolicies[userId] = userPolicy;
+    }
+    return mMicrophoneSensorPrivacyPolicies[userId]->isSensorPrivacyEnabled();
+}
+
 status_t AudioPolicyService::printHelp(int out) {
     return dprintf(out, "Audio policy service commands:\n"
         "  get-uid-state <PACKAGE> [--user USER_ID] gets the uid state\n"
@@ -1211,6 +1226,14 @@
     spm.addSensorPrivacyListener(this);
 }
 
+void AudioPolicyService::SensorPrivacyPolicy::registerSelfForMicrophoneOnly(int userId) {
+    SensorPrivacyManager spm;
+    mSensorPrivacyEnabled = spm.isIndividualSensorPrivacyEnabled(userId,
+            SensorPrivacyManager::INDIVIDUAL_SENSOR_MICROPHONE);
+    spm.addIndividualSensorPrivacyListener(userId,
+            SensorPrivacyManager::INDIVIDUAL_SENSOR_MICROPHONE, this);
+}
+
 void AudioPolicyService::SensorPrivacyPolicy::unregisterSelf() {
     SensorPrivacyManager spm;
     spm.removeSensorPrivacyListener(this);
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index db84d54..2cb8759 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -304,6 +304,8 @@
 
     virtual status_t setRttEnabled(bool enabled);
 
+    virtual bool isUserSensorPrivacyEnabledForUid(uid_t uid);
+
             bool isCallScreenModeSupported() override;
 
             void doOnNewAudioModulesAvailable();
@@ -466,6 +468,7 @@
                     : mService(service) {}
 
             void registerSelf();
+            void registerSelfForMicrophoneOnly(int userId);
             void unregisterSelf();
 
             bool isSensorPrivacyEnabled();
@@ -939,6 +942,8 @@
     MediaPackageManager mPackageManager; // To check allowPlaybackCapture
 
     CaptureStateNotifier mCaptureStateNotifier;
+
+    std::map<userid_t, sp<SensorPrivacyPolicy>> mMicrophoneSensorPrivacyPolicies;
 };
 
 } // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 92c8e30..e80404b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2161,6 +2161,14 @@
                 streamStats[i].mRequestCount = stats->second.mRequestedFrameCount;
                 streamStats[i].mErrorCount = stats->second.mDroppedFrameCount;
                 streamStats[i].mStartLatencyMs = stats->second.mStartLatencyMs;
+                streamStats[i].mHistogramType =
+                        hardware::CameraStreamStats::HISTOGRAM_TYPE_CAPTURE_LATENCY;
+                streamStats[i].mHistogramBins.assign(
+                        stats->second.mCaptureLatencyBins.begin(),
+                        stats->second.mCaptureLatencyBins.end());
+                streamStats[i].mHistogramCounts.assign(
+                        stats->second.mCaptureLatencyHistogram.begin(),
+                        stats->second.mCaptureLatencyHistogram.end());
             }
         }
         listener->notifyIdle(requestCount, resultErrorCount, deviceError, streamStats);
diff --git a/services/camera/libcameraservice/utils/SessionStatsBuilder.cpp b/services/camera/libcameraservice/utils/SessionStatsBuilder.cpp
index 83965c4..7a7707c 100644
--- a/services/camera/libcameraservice/utils/SessionStatsBuilder.cpp
+++ b/services/camera/libcameraservice/utils/SessionStatsBuilder.cpp
@@ -18,12 +18,21 @@
 #define ATRACE_TAG ATRACE_TAG_CAMERA
 //#define LOG_NDEBUG 0
 
+#include <numeric>
+
+#include <inttypes.h>
 #include <utils/Log.h>
 
 #include "SessionStatsBuilder.h"
 
 namespace android {
 
+// Bins for capture latency: [0, 100], [100, 200], [200, 300], ...
+// [1300, 2100], [2100, inf].
+// Capture latency is in the unit of millisecond.
+const std::array<int32_t, StreamStats::LATENCY_BIN_COUNT-1> StreamStats::mCaptureLatencyBins {
+        { 100, 200, 300, 400, 500, 700, 900, 1300, 2100 } };
+
 status_t SessionStatsBuilder::addStream(int id) {
     std::lock_guard<std::mutex> l(mLock);
     StreamStats stats;
@@ -52,10 +61,14 @@
     mCounterStopped = false;
     mDeviceError = false;
     for (auto& streamStats : mStatsMap) {
-        streamStats.second.mRequestedFrameCount = 0;
-        streamStats.second.mDroppedFrameCount = 0;
-        streamStats.second.mCounterStopped = false;
-        streamStats.second.mStartLatencyMs = 0;
+        StreamStats& streamStat = streamStats.second;
+        streamStat.mRequestedFrameCount = 0;
+        streamStat.mDroppedFrameCount = 0;
+        streamStat.mCounterStopped = false;
+        streamStat.mStartLatencyMs = 0;
+
+        std::fill(streamStat.mCaptureLatencyHistogram.begin(),
+                streamStat.mCaptureLatencyHistogram.end(), 0);
     }
 }
 
@@ -66,23 +79,28 @@
 
 void SessionStatsBuilder::stopCounter(int id) {
     std::lock_guard<std::mutex> l(mLock);
-    mStatsMap[id].mCounterStopped = true;
+    StreamStats& streamStat = mStatsMap[id];
+    streamStat.mCounterStopped = true;
 }
 
 void SessionStatsBuilder::incCounter(int id, bool dropped, int32_t captureLatencyMs) {
     std::lock_guard<std::mutex> l(mLock);
+
     auto it = mStatsMap.find(id);
-    if (it != mStatsMap.end()) {
-         if (!it->second.mCounterStopped) {
-             it->second.mRequestedFrameCount++;
-             if (dropped) {
-                 it->second.mDroppedFrameCount++;
-             } else if (it->second.mRequestedFrameCount == 1) {
-                 // The capture latency for the first request.
-                 it->second.mStartLatencyMs = captureLatencyMs;
-             }
-         }
+    if (it == mStatsMap.end()) return;
+
+    StreamStats& streamStat = it->second;
+    if (streamStat.mCounterStopped) return;
+
+    streamStat.mRequestedFrameCount++;
+    if (dropped) {
+        streamStat.mDroppedFrameCount++;
+    } else if (streamStat.mRequestedFrameCount - streamStat.mDroppedFrameCount == 1) {
+        // The capture latency for the first request.
+        streamStat.mStartLatencyMs = captureLatencyMs;
     }
+
+    streamStat.updateLatencyHistogram(captureLatencyMs);
 }
 
 void SessionStatsBuilder::stopCounter() {
@@ -95,10 +113,10 @@
 
 void SessionStatsBuilder::incResultCounter(bool dropped) {
     std::lock_guard<std::mutex> l(mLock);
-    if (!mCounterStopped) {
-        mRequestCount ++;
-        if (dropped) mErrorResultCount++;
-    }
+    if (mCounterStopped) return;
+
+    mRequestCount++;
+    if (dropped) mErrorResultCount++;
 }
 
 void SessionStatsBuilder::onDeviceError() {
@@ -106,4 +124,18 @@
     mDeviceError = true;
 }
 
+void StreamStats::updateLatencyHistogram(int32_t latencyMs) {
+    size_t i;
+    for (i = 0; i < mCaptureLatencyBins.size(); i++) {
+        if (latencyMs < mCaptureLatencyBins[i]) {
+            mCaptureLatencyHistogram[i] ++;
+            break;
+        }
+    }
+
+    if (i == mCaptureLatencyBins.size()) {
+        mCaptureLatencyHistogram[i]++;
+    }
+}
+
 }; // namespace android
diff --git a/services/camera/libcameraservice/utils/SessionStatsBuilder.h b/services/camera/libcameraservice/utils/SessionStatsBuilder.h
index 7943637..c23abb6 100644
--- a/services/camera/libcameraservice/utils/SessionStatsBuilder.h
+++ b/services/camera/libcameraservice/utils/SessionStatsBuilder.h
@@ -19,22 +19,38 @@
 
 #include <utils/Errors.h>
 
-#include <mutex>
+#include <array>
 #include <map>
+#include <mutex>
 
 namespace android {
 
 // Helper class to build stream stats
 struct StreamStats {
+    // Fields for buffer drop
     int64_t mRequestedFrameCount;
     int64_t mDroppedFrameCount;
     bool mCounterStopped;
+
+    // Fields for stream startup latency
     int32_t mStartLatencyMs;
 
+    // Fields for capture latency measurement
+    const static int LATENCY_BIN_COUNT = 10;
+    // Boundary values separating between adjacent bins, excluding 0 and
+    // infinity.
+    const static std::array<int32_t, LATENCY_BIN_COUNT-1> mCaptureLatencyBins;
+    // Counter values for all histogram bins. One more entry than mCaptureLatencyBins.
+    std::array<int64_t, LATENCY_BIN_COUNT> mCaptureLatencyHistogram;
+
     StreamStats() : mRequestedFrameCount(0),
                      mDroppedFrameCount(0),
                      mCounterStopped(false),
-                     mStartLatencyMs(0) {}
+                     mStartLatencyMs(0),
+                     mCaptureLatencyHistogram{}
+                  {}
+
+    void updateLatencyHistogram(int32_t latencyMs);
 };
 
 // Helper class to build session stats
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/mediaextractor/main_extractorservice.cpp b/services/mediaextractor/main_extractorservice.cpp
index b7b51a6..10b8135 100644
--- a/services/mediaextractor/main_extractorservice.cpp
+++ b/services/mediaextractor/main_extractorservice.cpp
@@ -15,6 +15,9 @@
 ** limitations under the License.
 */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "main_extractorservice"
+
 #include <fcntl.h>
 #include <sys/prctl.h>
 #include <sys/wait.h>
@@ -26,6 +29,7 @@
 
 #include <android-base/logging.h>
 #include <android-base/properties.h>
+#include <utils/Log.h>
 #include <utils/misc.h>
 
 // from LOCAL_C_INCLUDES
@@ -41,10 +45,16 @@
 
 int main(int argc __unused, char** argv)
 {
+
+#if __has_feature(hwaddress_sanitizer)
+    ALOGI("disable media.extractor memory limits (hwasan enabled)");
+#else
+    ALOGI("enable media.extractor memory limits");
     limitProcessMemory(
         "ro.media.maxmem", /* property that defines limit */
         SIZE_MAX, /* upper limit in bytes */
         20 /* upper limit as percentage of physical RAM */);
+#endif
 
     signal(SIGPIPE, SIG_IGN);
 
diff --git a/services/mediatranscoding/MediaTranscodingService.cpp b/services/mediatranscoding/MediaTranscodingService.cpp
index 64def5e..74477a8 100644
--- a/services/mediatranscoding/MediaTranscodingService.cpp
+++ b/services/mediatranscoding/MediaTranscodingService.cpp
@@ -62,16 +62,18 @@
 
     uid_t callingUid = AIBinder_getCallingUid();
     pid_t callingPid = AIBinder_getCallingPid();
-    int32_t permissionResult;
-    if (APermissionManager_checkPermission("android.permission.DUMP", callingPid, callingUid,
-                                           &permissionResult) != PERMISSION_MANAGER_STATUS_OK ||
-        permissionResult != PERMISSION_MANAGER_PERMISSION_GRANTED) {
-        result.format(
-                "Permission Denial: "
-                "can't dump MediaTranscodingService from pid=%d, uid=%d\n",
-                AIBinder_getCallingPid(), AIBinder_getCallingUid());
-        write(fd, result.string(), result.size());
-        return PERMISSION_DENIED;
+    if (__builtin_available(android 31, *)) {
+        int32_t permissionResult;
+        if (APermissionManager_checkPermission("android.permission.DUMP", callingPid, callingUid,
+                                               &permissionResult) != PERMISSION_MANAGER_STATUS_OK ||
+            permissionResult != PERMISSION_MANAGER_PERMISSION_GRANTED) {
+            result.format(
+                    "Permission Denial: "
+                    "can't dump MediaTranscodingService from pid=%d, uid=%d\n",
+                    AIBinder_getCallingPid(), AIBinder_getCallingUid());
+            write(fd, result.string(), result.size());
+            return PERMISSION_DENIED;
+        }
     }
 
     const size_t SIZE = 256;
diff --git a/services/tuner/Android.bp b/services/tuner/Android.bp
index 5327289..1379090 100644
--- a/services/tuner/Android.bp
+++ b/services/tuner/Android.bp
@@ -1,34 +1,16 @@
 filegroup {
     name: "tv_tuner_aidl",
     srcs: [
-        "aidl/android/media/tv/tuner/ITunerFrontend.aidl",
-        "aidl/android/media/tv/tuner/ITunerFrontendCallback.aidl",
-        "aidl/android/media/tv/tuner/ITunerService.aidl",
-        "aidl/android/media/tv/tuner/TunerAtsc3PlpInfo.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendAnalogCapabilities.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendAtscCapabilities.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendAtsc3Capabilities.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendCableCapabilities.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendCapabilities.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendDvbsCapabilities.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendDvbtCapabilities.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendIsdbsCapabilities.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendIsdbs3Capabilities.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendIsdbtCapabilities.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendAnalogSettings.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendAtsc3PlpSettings.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendAtsc3Settings.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendAtscSettings.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendCableSettings.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendDvbsCodeRate.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendDvbsSettings.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendDvbtSettings.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendIsdbs3Settings.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendIsdbsSettings.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendIsdbtSettings.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendSettings.aidl",
-        "aidl/android/media/tv/tuner/TunerFrontendStatus.aidl",
-        "aidl/android/media/tv/tuner/TunerServiceFrontendInfo.aidl",
+        "aidl/android/media/tv/tuner/*.aidl",
+    ],
+    path: "aidl",
+}
+
+filegroup {
+    name: "tv_tuner_frontend_info",
+    srcs: [
+        "aidl/android/media/tv/tuner/TunerFrontendInfo.aidl",
+        "aidl/android/media/tv/tuner/TunerFrontend*Capabilities.aidl",
     ],
     path: "aidl",
 }
@@ -57,16 +39,37 @@
     },
 }
 
+aidl_interface {
+    name: "tv_tuner_frontend_info_aidl_interface",
+    unstable: true,
+    local_include_dir: "aidl",
+    srcs: [
+        ":tv_tuner_frontend_info",
+    ],
+
+    backend: {
+        java: {
+            enabled: true,
+        },
+        cpp: {
+            enabled: true,
+        },
+        ndk: {
+            enabled: true,
+        },
+    },
+}
+
 cc_library {
     name: "libtunerservice",
 
     srcs: [
-        "TunerService.cpp",
-        "TunerFrontend.cpp"
+        "Tuner*.cpp"
     ],
 
     shared_libs: [
         "android.hardware.tv.tuner@1.0",
+        "android.hardware.tv.tuner@1.1",
         "libbase",
         "libbinder_ndk",
         "libcutils",
diff --git a/services/tuner/TunerFrontend.cpp b/services/tuner/TunerFrontend.cpp
index ba4553b..e92489d 100644
--- a/services/tuner/TunerFrontend.cpp
+++ b/services/tuner/TunerFrontend.cpp
@@ -17,10 +17,9 @@
 #define LOG_TAG "TunerFrontend"
 
 #include "TunerFrontend.h"
-#include "TunerService.h"
 
-using ::aidl::android::media::tv::tuner::TunerAtsc3PlpInfo;
 using ::aidl::android::media::tv::tuner::TunerFrontendAtsc3PlpSettings;
+using ::aidl::android::media::tv::tuner::TunerFrontendScanAtsc3PlpInfo;
 using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard;
 using ::android::hardware::tv::tuner::V1_0::FrontendAnalogType;
 using ::android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
@@ -69,29 +68,23 @@
 using ::android::hardware::tv::tuner::V1_0::FrontendScanType;
 using ::android::hardware::tv::tuner::V1_0::FrontendSettings;;
 using ::android::hardware::tv::tuner::V1_0::Result;
+using ::android::hardware::tv::tuner::V1_1::FrontendModulation;
 
 namespace android {
 
-TunerFrontend::TunerFrontend(sp<ITuner> tuner, int frontendHandle) {
-    mTuner = tuner;
-    mId = TunerService::getResourceIdFromHandle(frontendHandle);
-
-    if (mTuner != NULL) {
-        Result status;
-        mTuner->openFrontendById(mId, [&](Result result, const sp<IFrontend>& frontend) {
-            mFrontend = frontend;
-            status = result;
-        });
-        if (status != Result::SUCCESS) {
-            mFrontend = NULL;
-        }
-    }
+TunerFrontend::TunerFrontend(sp<IFrontend> frontend, int id) {
+    mFrontend = frontend;
+    mFrontend_1_1 = ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend);
+    mId = id;
 }
 
-TunerFrontend::~TunerFrontend() {}
+TunerFrontend::~TunerFrontend() {
+    mFrontend = NULL;
+    mId = -1;
+}
 
 Status TunerFrontend::setCallback(
-        const std::shared_ptr<ITunerFrontendCallback>& tunerFrontendCallback) {
+        const shared_ptr<ITunerFrontendCallback>& tunerFrontendCallback) {
     if (mFrontend == NULL) {
         ALOGE("IFrontend is not initialized");
         return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
@@ -124,6 +117,7 @@
         return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
     }
 
+    // TODO: extend TunerFrontendSettings to use 1.1 types
     FrontendSettings frontendSettings;
     switch (settings.getTag()) {
         case TunerFrontendSettings::analog:
@@ -307,8 +301,13 @@
     return Status::ok();
 }
 
-Status TunerFrontend::getStatus(const std::vector<int32_t>& /*statusTypes*/,
-		std::vector<TunerFrontendStatus>* /*_aidl_return*/) {
+Status TunerFrontend::getStatus(const vector<int32_t>& /*statusTypes*/,
+        vector<TunerFrontendStatus>* /*_aidl_return*/) {
+    return Status::ok();
+}
+
+Status TunerFrontend::getFrontendId(int* _aidl_return) {
+    *_aidl_return = mId;
     return Status::ok();
 }
 
@@ -323,59 +322,56 @@
 Return<void> TunerFrontend::FrontendCallback::onScanMessage(
         FrontendScanMessageType type, const FrontendScanMessage& message) {
     ALOGD("FrontendCallback::onScanMessage, type=%d", type);
+    TunerFrontendScanMessage scanMessage;
     switch(type) {
         case FrontendScanMessageType::LOCKED: {
-            if (message.isLocked()) {
-                mTunerFrontendCallback->onLocked();
-            }
+            scanMessage.set<TunerFrontendScanMessage::isLocked>(message.isLocked());
             break;
         }
         case FrontendScanMessageType::END: {
-            if (message.isEnd()) {
-                mTunerFrontendCallback->onScanStopped();
-            }
+            scanMessage.set<TunerFrontendScanMessage::isEnd>(message.isEnd());
             break;
         }
         case FrontendScanMessageType::PROGRESS_PERCENT: {
-            mTunerFrontendCallback->onProgress((int)message.progressPercent());
+            scanMessage.set<TunerFrontendScanMessage::progressPercent>(message.progressPercent());
             break;
         }
         case FrontendScanMessageType::FREQUENCY: {
             auto f = message.frequencies();
-            std::vector<int32_t> frequencies(std::begin(f), std::end(f));
-            mTunerFrontendCallback->onFrequenciesReport(frequencies);
+            vector<int> frequencies(begin(f), end(f));
+            scanMessage.set<TunerFrontendScanMessage::frequencies>(frequencies);
             break;
         }
         case FrontendScanMessageType::SYMBOL_RATE: {
             auto s = message.symbolRates();
-            std::vector<int32_t> symbolRates(std::begin(s), std::end(s));
-            mTunerFrontendCallback->onSymbolRates(symbolRates);
+            vector<int> symbolRates(begin(s), end(s));
+            scanMessage.set<TunerFrontendScanMessage::symbolRates>(symbolRates);
             break;
         }
         case FrontendScanMessageType::HIERARCHY: {
-            mTunerFrontendCallback->onHierarchy((int)message.hierarchy());
+            scanMessage.set<TunerFrontendScanMessage::hierarchy>((int)message.hierarchy());
             break;
         }
         case FrontendScanMessageType::ANALOG_TYPE: {
-            mTunerFrontendCallback->onSignalType((int)message.analogType());
+            scanMessage.set<TunerFrontendScanMessage::analogType>((int)message.analogType());
             break;
         }
         case FrontendScanMessageType::PLP_IDS: {
             auto p = message.plpIds();
-            std::vector<int32_t> plpIds(std::begin(p), std::end(p));
-            mTunerFrontendCallback->onPlpIds(plpIds);
+            vector<uint8_t> plpIds(begin(p), end(p));
+            scanMessage.set<TunerFrontendScanMessage::plpIds>(plpIds);
             break;
         }
         case FrontendScanMessageType::GROUP_IDS: {
             auto g = message.groupIds();
-            std::vector<int32_t> groupIds(std::begin(g), std::end(g));
-            mTunerFrontendCallback->onGroupIds(groupIds);
+            vector<uint8_t> groupIds(begin(g), end(g));
+            scanMessage.set<TunerFrontendScanMessage::groupIds>(groupIds);
             break;
         }
         case FrontendScanMessageType::INPUT_STREAM_IDS: {
             auto i = message.inputStreamIds();
-            std::vector<int32_t> streamIds(std::begin(i), std::end(i));
-            mTunerFrontendCallback->onInputStreamIds(streamIds);
+            vector<char16_t> streamIds(begin(i), end(i));
+            scanMessage.set<TunerFrontendScanMessage::inputStreamIds>(streamIds);
             break;
         }
         case FrontendScanMessageType::STANDARD: {
@@ -383,41 +379,85 @@
             int standard;
             if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sStd) {
                 standard = (int) std.sStd();
-                mTunerFrontendCallback->onDvbsStandard(standard);
             } else if (std.getDiscriminator() ==
                     FrontendScanMessage::Standard::hidl_discriminator::tStd) {
                 standard = (int) std.tStd();
-                mTunerFrontendCallback->onDvbsStandard(standard);
             } else if (std.getDiscriminator() ==
                     FrontendScanMessage::Standard::hidl_discriminator::sifStd) {
                 standard = (int) std.sifStd();
-                mTunerFrontendCallback->onAnalogSifStandard(standard);
             }
+            scanMessage.set<TunerFrontendScanMessage::std>(standard);
             break;
         }
         case FrontendScanMessageType::ATSC3_PLP_INFO: {
-            std::vector<FrontendScanAtsc3PlpInfo> plpInfos = message.atsc3PlpInfos();
-            std::vector<TunerAtsc3PlpInfo> tunerPlpInfos;
+            vector<FrontendScanAtsc3PlpInfo> plpInfos = message.atsc3PlpInfos();
+            vector<TunerFrontendScanAtsc3PlpInfo> tunerPlpInfos;
             for (int i = 0; i < plpInfos.size(); i++) {
                 auto info = plpInfos[i];
                 int plpId = (int) info.plpId;
                 bool lls = (bool) info.bLlsFlag;
-                TunerAtsc3PlpInfo plpInfo{
+                TunerFrontendScanAtsc3PlpInfo plpInfo{
                     .plpId = plpId,
                     .llsFlag = lls,
                 };
                 tunerPlpInfos.push_back(plpInfo);
             }
-            mTunerFrontendCallback->onAtsc3PlpInfos(tunerPlpInfos);
+            scanMessage.set<TunerFrontendScanMessage::atsc3PlpInfos>(tunerPlpInfos);
             break;
         }
         default:
             break;
     }
+    mTunerFrontendCallback->onScanMessage((int)type, scanMessage);
     return Void();
 }
 
-////////////////////////////////////////////////////////////////////////////////
+Return<void> TunerFrontend::FrontendCallback::onScanMessageExt1_1(
+        FrontendScanMessageTypeExt1_1 type, const FrontendScanMessageExt1_1& message) {
+    ALOGD("onScanMessageExt1_1::onScanMessage, type=%d", type);
+    TunerFrontendScanMessage scanMessage;
+    switch(type) {
+        case FrontendScanMessageTypeExt1_1::MODULATION: {
+            FrontendModulation m = message.modulation();
+            int modulation;
+            if (m.getDiscriminator() == FrontendModulation::hidl_discriminator::dvbc) {
+                modulation = (int) m.dvbc();
+            } else if (m.getDiscriminator() == FrontendModulation::hidl_discriminator::dvbt) {
+                modulation = (int) m.dvbt();
+            } else if (m.getDiscriminator() == FrontendModulation::hidl_discriminator::dvbs) {
+                modulation = (int) m.dvbs();
+            } else if (m.getDiscriminator() == FrontendModulation::hidl_discriminator::isdbs) {
+                modulation = (int) m.isdbs();
+            } else if (m.getDiscriminator() == FrontendModulation::hidl_discriminator::isdbs3) {
+                modulation = (int) m.isdbs3();
+            } else if (m.getDiscriminator() == FrontendModulation::hidl_discriminator::isdbt) {
+                modulation = (int) m.isdbt();
+            } else if (m.getDiscriminator() == FrontendModulation::hidl_discriminator::atsc) {
+                modulation = (int) m.atsc();
+            } else if (m.getDiscriminator() == FrontendModulation::hidl_discriminator::atsc3) {
+                modulation = (int) m.atsc3();
+            } else if (m.getDiscriminator() == FrontendModulation::hidl_discriminator::dtmb) {
+                modulation = (int) m.dtmb();
+            }
+            scanMessage.set<TunerFrontendScanMessage::modulation>(modulation);
+            break;
+        }
+        case FrontendScanMessageTypeExt1_1::DVBC_ANNEX: {
+            scanMessage.set<TunerFrontendScanMessage::annex>((int)message.annex());
+            break;
+        }
+        case FrontendScanMessageTypeExt1_1::HIGH_PRIORITY: {
+            scanMessage.set<TunerFrontendScanMessage::isHighPriority>(message.isHighPriority());
+            break;
+        }
+        default:
+            break;
+    }
+    mTunerFrontendCallback->onScanMessage((int)type, scanMessage);
+    return Void();
+}
+
+/////////////// TunerFrontend Helper Methods ///////////////////////
 
 hidl_vec<FrontendAtsc3PlpSettings> TunerFrontend::getAtsc3PlpSettings(
         const TunerFrontendAtsc3Settings& settings) {
diff --git a/services/tuner/TunerFrontend.h b/services/tuner/TunerFrontend.h
index c7d3ddd..99cdcdf 100644
--- a/services/tuner/TunerFrontend.h
+++ b/services/tuner/TunerFrontend.h
@@ -19,6 +19,8 @@
 
 #include <aidl/android/media/tv/tuner/BnTunerFrontend.h>
 #include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.1/IFrontend.h>
+#include <android/hardware/tv/tuner/1.1/IFrontendCallback.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <utils/Log.h>
 
@@ -27,6 +29,7 @@
 using ::aidl::android::media::tv::tuner::ITunerFrontendCallback;
 using ::aidl::android::media::tv::tuner::TunerFrontendAtsc3Settings;
 using ::aidl::android::media::tv::tuner::TunerFrontendDvbsCodeRate;
+using ::aidl::android::media::tv::tuner::TunerFrontendScanMessage;
 using ::aidl::android::media::tv::tuner::TunerFrontendSettings;
 using ::aidl::android::media::tv::tuner::TunerFrontendStatus;
 using ::android::hardware::Return;
@@ -39,19 +42,21 @@
 using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
 using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
 using ::android::hardware::tv::tuner::V1_0::IFrontend;
-using ::android::hardware::tv::tuner::V1_0::IFrontendCallback;
-using ::android::hardware::tv::tuner::V1_0::ITuner;
+using ::android::hardware::tv::tuner::V1_1::IFrontendCallback;
+using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageTypeExt1_1;
 
+using namespace std;
 
 namespace android {
 
 class TunerFrontend : public BnTunerFrontend {
 
 public:
-    TunerFrontend(sp<ITuner> tuner, int frontendHandle);
+    TunerFrontend(sp<IFrontend> frontend, int id);
     virtual ~TunerFrontend();
     Status setCallback(
-            const std::shared_ptr<ITunerFrontendCallback>& tunerFrontendCallback) override;
+            const shared_ptr<ITunerFrontendCallback>& tunerFrontendCallback) override;
     Status tune(const TunerFrontendSettings& settings) override;
     Status stopTune() override;
     Status scan(const TunerFrontendSettings& settings, int frontendScanType) override;
@@ -59,27 +64,31 @@
     Status setLnb(int lnbHandle) override;
     Status setLna(bool bEnable) override;
     Status close() override;
-    Status getStatus(const std::vector<int32_t>& statusTypes,
-            std::vector<TunerFrontendStatus>* _aidl_return) override;
+    Status getStatus(const vector<int32_t>& statusTypes,
+            vector<TunerFrontendStatus>* _aidl_return) override;
+    Status getFrontendId(int* _aidl_return) override;
 
     struct FrontendCallback : public IFrontendCallback {
-        FrontendCallback(const std::shared_ptr<ITunerFrontendCallback> tunerFrontendCallback)
+        FrontendCallback(const shared_ptr<ITunerFrontendCallback> tunerFrontendCallback)
                 : mTunerFrontendCallback(tunerFrontendCallback) {};
 
         virtual Return<void> onEvent(FrontendEventType frontendEventType);
         virtual Return<void> onScanMessage(
                 FrontendScanMessageType type, const FrontendScanMessage& message);
+        virtual Return<void> onScanMessageExt1_1(
+                FrontendScanMessageTypeExt1_1 type, const FrontendScanMessageExt1_1& message);
 
-        std::shared_ptr<ITunerFrontendCallback> mTunerFrontendCallback;
+        shared_ptr<ITunerFrontendCallback> mTunerFrontendCallback;
     };
 
 private:
     hidl_vec<FrontendAtsc3PlpSettings> getAtsc3PlpSettings(
             const TunerFrontendAtsc3Settings& settings);
     FrontendDvbsCodeRate getDvbsCodeRate(const TunerFrontendDvbsCodeRate& codeRate);
+
     int mId;
-    sp<ITuner> mTuner;
     sp<IFrontend> mFrontend;
+    sp<::android::hardware::tv::tuner::V1_1::IFrontend> mFrontend_1_1;
 };
 
 } // namespace android
diff --git a/services/tuner/TunerLnb.cpp b/services/tuner/TunerLnb.cpp
new file mode 100644
index 0000000..0bfa3fd
--- /dev/null
+++ b/services/tuner/TunerLnb.cpp
@@ -0,0 +1,120 @@
+/**
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "TunerLnb"
+
+#include "TunerLnb.h"
+
+using ::android::hardware::tv::tuner::V1_0::LnbPosition;
+using ::android::hardware::tv::tuner::V1_0::LnbTone;
+using ::android::hardware::tv::tuner::V1_0::LnbVoltage;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+namespace android {
+
+TunerLnb::TunerLnb(sp<ILnb> lnb, int id) {
+    mLnb = lnb;
+    mId = id;
+}
+
+TunerLnb::~TunerLnb() {
+    mLnb = NULL;
+    mId = -1;
+}
+
+Status TunerLnb::setCallback(
+        const shared_ptr<ITunerLnbCallback>& tunerLnbCallback) {
+    if (mLnb == NULL) {
+        ALOGE("ILnb is not initialized");
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+    }
+
+    if (tunerLnbCallback == NULL) {
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_ARGUMENT));
+    }
+
+    sp<ILnbCallback> lnbCallback = new LnbCallback(tunerLnbCallback);
+    Result status = mLnb->setCallback(lnbCallback);
+    return Status::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+Status TunerLnb::setVoltage(int voltage) {
+    if (mLnb == NULL) {
+        ALOGE("ILnb is not initialized");
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+    }
+
+    Result status = mLnb->setVoltage(static_cast<LnbVoltage>(voltage));
+    return Status::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+Status TunerLnb::setTone(int tone) {
+    if (mLnb == NULL) {
+        ALOGE("ILnb is not initialized");
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+    }
+
+    Result status = mLnb->setTone(static_cast<LnbTone>(tone));
+    return Status::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+Status TunerLnb::setSatellitePosition(int position) {
+    if (mLnb == NULL) {
+        ALOGE("ILnb is not initialized");
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+    }
+
+    Result status = mLnb->setSatellitePosition(static_cast<LnbPosition>(position));
+    return Status::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+Status TunerLnb::sendDiseqcMessage(const vector<uint8_t>& diseqcMessage) {
+    if (mLnb == NULL) {
+        ALOGE("ILnb is not initialized");
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+    }
+
+    Result status = mLnb->sendDiseqcMessage(diseqcMessage);
+    return Status::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+Status TunerLnb::close() {
+    if (mLnb == NULL) {
+        ALOGE("ILnb is not initialized");
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+    }
+
+    Result status = mLnb->close();
+    return Status::fromServiceSpecificError(static_cast<int32_t>(status));
+}
+
+/////////////// ILnbCallback ///////////////////////
+
+Return<void> TunerLnb::LnbCallback::onEvent(const LnbEventType lnbEventType) {
+    if (mTunerLnbCallback != NULL) {
+        mTunerLnbCallback->onEvent((int)lnbEventType);
+    }
+    return Void();
+}
+
+Return<void> TunerLnb::LnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
+    if (mTunerLnbCallback != NULL && diseqcMessage != NULL) {
+        vector<uint8_t> msg(begin(diseqcMessage), end(diseqcMessage));
+        mTunerLnbCallback->onDiseqcMessage(msg);
+    }
+    return Void();
+}
+}  // namespace android
diff --git a/services/tuner/TunerLnb.h b/services/tuner/TunerLnb.h
new file mode 100644
index 0000000..e80b97e
--- /dev/null
+++ b/services/tuner/TunerLnb.h
@@ -0,0 +1,69 @@
+/**
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MEDIA_TUNERFLNB_H
+#define ANDROID_MEDIA_TUNERFLNB_H
+
+#include <aidl/android/media/tv/tuner/BnTunerLnb.h>
+#include <android/hardware/tv/tuner/1.0/ILnb.h>
+#include <android/hardware/tv/tuner/1.0/ILnbCallback.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <utils/Log.h>
+
+using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::media::tv::tuner::BnTunerLnb;
+using ::aidl::android::media::tv::tuner::ITunerLnbCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::tv::tuner::V1_0::ILnb;
+using ::android::hardware::tv::tuner::V1_0::ILnbCallback;
+using ::android::hardware::tv::tuner::V1_0::LnbEventType;
+
+using namespace std;
+
+namespace android {
+
+class TunerLnb : public BnTunerLnb {
+
+public:
+    TunerLnb(sp<ILnb> lnb, int id);
+    virtual ~TunerLnb();
+    Status setCallback(const shared_ptr<ITunerLnbCallback>& tunerLnbCallback) override;
+    Status setVoltage(int voltage) override;
+    Status setTone(int tone) override;
+    Status setSatellitePosition(int position) override;
+    Status sendDiseqcMessage(const vector<uint8_t>& diseqcMessage) override;
+    Status close() override;
+
+    struct LnbCallback : public ILnbCallback {
+        LnbCallback(const shared_ptr<ITunerLnbCallback> tunerLnbCallback)
+                : mTunerLnbCallback(tunerLnbCallback) {};
+
+        virtual Return<void> onEvent(const LnbEventType lnbEventType);
+        virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage);
+
+        shared_ptr<ITunerLnbCallback> mTunerLnbCallback;
+    };
+
+private:
+    int mId;
+    sp<ILnb> mLnb;
+};
+
+} // namespace android
+
+#endif // ANDROID_MEDIA_TUNERFLNB_H
diff --git a/services/tuner/TunerService.cpp b/services/tuner/TunerService.cpp
index 56cb34c..ef3d1f2 100644
--- a/services/tuner/TunerService.cpp
+++ b/services/tuner/TunerService.cpp
@@ -18,8 +18,9 @@
 
 #include <android/binder_manager.h>
 #include <utils/Log.h>
-#include "TunerFrontend.h"
 #include "TunerService.h"
+#include "TunerFrontend.h"
+#include "TunerLnb.h"
 
 using ::aidl::android::media::tv::tuner::TunerFrontendAnalogCapabilities;
 using ::aidl::android::media::tv::tuner::TunerFrontendAtsc3Capabilities;
@@ -39,6 +40,9 @@
 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::IFrontend;
+using ::android::hardware::tv::tuner::V1_0::ILnb;
+using ::android::hardware::tv::tuner::V1_0::LnbId;
 using ::android::hardware::tv::tuner::V1_0::Result;
 
 namespace android {
@@ -47,7 +51,7 @@
 TunerService::~TunerService() {}
 
 void TunerService::instantiate() {
-    std::shared_ptr<TunerService> service =
+    shared_ptr<TunerService> service =
             ::ndk::SharedRefBase::make<TunerService>();
     AServiceManager_addService(service->asBinder().get(), getServiceName());
 }
@@ -61,8 +65,8 @@
     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,
+            is_fundamental<AidlPayload>::value ||
+            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]));
@@ -192,7 +196,7 @@
     if (getQueueDescResult == Result::SUCCESS) {
         unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(
                 mFilterMQDesc,  &mAidlMQDesc);
-        mAidlMq = new (std::nothrow) AidlMessageQueue(mAidlMQDesc);
+        mAidlMq = new (nothrow) AidlMessageQueue(mAidlMQDesc);
         EventFlag::createEventFlag(mAidlMq->getEventFlagWord(), &mEventFlag);
     } else {
         ALOGD("get MQDesc failed, res = %d", getQueueDescResult);
@@ -200,9 +204,9 @@
     return getQueueDescResult;
 }
 
-Status TunerService::getFrontendIds(std::vector<int32_t>* ids, int32_t* /* _aidl_return */) {
+Status TunerService::getFrontendIds(vector<int32_t>* ids, int32_t* /* _aidl_return */) {
     if (!getITuner()) {
-        return ::ndk::ScopedAStatus::fromServiceSpecificError(
+        return Status::fromServiceSpecificError(
                 static_cast<int32_t>(Result::NOT_INITIALIZED));
     }
     hidl_vec<FrontendId> feIds;
@@ -212,16 +216,16 @@
         res = r;
     });
     if (res != Result::SUCCESS) {
-        return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+        return Status::fromServiceSpecificError(static_cast<int32_t>(res));
     }
     ids->resize(feIds.size());
-    std::copy(feIds.begin(), feIds.end(), ids->begin());
+    copy(feIds.begin(), feIds.end(), ids->begin());
 
     return Status::ok();
 }
 
 Status TunerService::getFrontendInfo(
-        int32_t frontendHandle, TunerServiceFrontendInfo* _aidl_return) {
+        int32_t frontendHandle, TunerFrontendInfo* _aidl_return) {
     if (mTuner == nullptr) {
         ALOGE("ITuner service is not init.");
         return ::ndk::ScopedAStatus::fromServiceSpecificError(
@@ -230,7 +234,7 @@
 
     Result res;
     FrontendInfo info;
-    int feId = getResourceIdFromHandle(frontendHandle);
+    int feId = getResourceIdFromHandle(frontendHandle, FRONTEND);
     mTuner->getFrontendInfo(feId, [&](Result r, const FrontendInfo& feInfo) {
         info = feInfo;
         res = r;
@@ -239,26 +243,96 @@
         return Status::fromServiceSpecificError(static_cast<int32_t>(res));
     }
 
-    TunerServiceFrontendInfo tunerInfo = convertToAidlFrontendInfo(feId, info);
+    TunerFrontendInfo tunerInfo = convertToAidlFrontendInfo(info);
     *_aidl_return = tunerInfo;
     return Status::ok();
 }
 
 Status TunerService::openFrontend(
-        int32_t frontendHandle, std::shared_ptr<ITunerFrontend>* _aidl_return) {
+        int32_t frontendHandle, shared_ptr<ITunerFrontend>* _aidl_return) {
     if (mTuner == nullptr) {
         ALOGE("ITuner service is not init.");
-        return ::ndk::ScopedAStatus::fromServiceSpecificError(
-                static_cast<int32_t>(Result::UNAVAILABLE));
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
     }
 
-    *_aidl_return = ::ndk::SharedRefBase::make<TunerFrontend>(mTuner, frontendHandle);
+    Result status;
+    sp<IFrontend> frontend;
+    int id = getResourceIdFromHandle(frontendHandle, FRONTEND);
+    mTuner->openFrontendById(id, [&](Result result, const sp<IFrontend>& fe) {
+        frontend = fe;
+        status = result;
+    });
+    if (status != Result::SUCCESS) {
+        return Status::fromServiceSpecificError(static_cast<int32_t>(status));
+    }
+    *_aidl_return = ::ndk::SharedRefBase::make<TunerFrontend>(frontend, id);
     return Status::ok();
 }
 
-TunerServiceFrontendInfo TunerService::convertToAidlFrontendInfo(int feId, FrontendInfo halInfo) {
-    TunerServiceFrontendInfo info{
-        .id = feId,
+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 = move(mAidlMQDesc);
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+Status TunerService::openLnb(int lnbHandle, shared_ptr<ITunerLnb>* _aidl_return) {
+    if (mTuner == nullptr) {
+        ALOGE("ITuner service is not init.");
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+    }
+
+    Result status;
+    sp<ILnb> lnb;
+    int id = getResourceIdFromHandle(lnbHandle, LNB);
+    mTuner->openLnbById(id, [&](Result result, const sp<ILnb>& lnbSp){
+        lnb = lnbSp;
+        status = result;
+    });
+    if (status != Result::SUCCESS) {
+        return Status::fromServiceSpecificError(static_cast<int32_t>(status));
+    }
+
+    *_aidl_return = ::ndk::SharedRefBase::make<TunerLnb>(lnb, id);
+    return Status::ok();
+}
+
+Status TunerService::openLnbByName(const string& lnbName, shared_ptr<ITunerLnb>* _aidl_return) {
+    if (mTuner == nullptr) {
+        ALOGE("ITuner service is not init.");
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+    }
+
+    int lnbId;
+    Result status;
+    sp<ILnb> lnb;
+    mTuner->openLnbByName(lnbName, [&](Result r, LnbId id, const sp<ILnb>& lnbSp) {
+        status = r;
+        lnb = lnbSp;
+        lnbId = (int)id;
+    });
+    if (status != Result::SUCCESS) {
+        return Status::fromServiceSpecificError(static_cast<int32_t>(status));
+    }
+
+    *_aidl_return = ::ndk::SharedRefBase::make<TunerLnb>(lnb, lnbId);
+    return Status::ok();
+}
+
+TunerFrontendInfo TunerService::convertToAidlFrontendInfo(FrontendInfo halInfo) {
+    TunerFrontendInfo info{
         .type = (int)halInfo.type,
         .minFrequency = (int)halInfo.minFrequency,
         .maxFrequency = (int)halInfo.maxFrequency,
@@ -367,24 +441,4 @@
     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 26591ab..82b6fcd 100644
--- a/services/tuner/TunerService.h
+++ b/services/tuner/TunerService.h
@@ -18,7 +18,6 @@
 #define ANDROID_MEDIA_TUNERSERVICE_H
 
 #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>
@@ -29,7 +28,8 @@
 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 ::aidl::android::media::tv::tuner::ITunerLnb;
+using ::aidl::android::media::tv::tuner::TunerFrontendInfo;
 
 using ::android::hardware::details::logError;
 using ::android::hardware::EventFlag;
@@ -56,8 +56,16 @@
 
 using Status = ::ndk::ScopedAStatus;
 
+using namespace std;
+
 namespace android {
 
+typedef enum {
+    FRONTEND,
+    LNB,
+    DEMUX,
+    DESCRAMBLER,
+} TunerResourceType;
 
 struct FilterCallback : public IFilterCallback {
     ~FilterCallback() {}
@@ -80,16 +88,19 @@
     TunerService();
     virtual ~TunerService();
 
-    static int getResourceIdFromHandle(int resourceHandle) {
+    // TODO: create a map between resource id and handles.
+    static int getResourceIdFromHandle(int resourceHandle, int /*type*/) {
         return (resourceHandle & 0x00ff0000) >> 16;
     }
 
-    Status getFrontendIds(std::vector<int32_t>* ids, int32_t* _aidl_return) override;
-    Status getFrontendInfo(int32_t frontendHandle, TunerServiceFrontendInfo* _aidl_return) override;
+    Status getFrontendIds(vector<int32_t>* ids, int32_t* _aidl_return) override;
+    Status getFrontendInfo(int32_t frontendHandle, TunerFrontendInfo* _aidl_return) override;
     Status openFrontend(
-            int32_t frontendHandle, std::shared_ptr<ITunerFrontend>* _aidl_return) override;
+            int32_t frontendHandle, shared_ptr<ITunerFrontend>* _aidl_return) override;
     Status getFmqSyncReadWrite(
             MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) override;
+    Status openLnb(int lnbHandle, shared_ptr<ITunerLnb>* _aidl_return) override;
+    Status openLnbByName(const string& lnbName, shared_ptr<ITunerLnb>* _aidl_return) override;
 
 private:
     template <typename HidlPayload, typename AidlPayload, typename AidlFlavor>
@@ -109,7 +120,7 @@
     MQDescriptorSync<uint8_t> mFilterMQDesc;
     AidlMQDesc mAidlMQDesc;
     EventFlag* mEventFlag;
-    TunerServiceFrontendInfo convertToAidlFrontendInfo(int feId, FrontendInfo halInfo);
+    TunerFrontendInfo convertToAidlFrontendInfo(FrontendInfo halInfo);
 };
 
 } // namespace android
diff --git a/services/tuner/TunerTimeFilter.cpp b/services/tuner/TunerTimeFilter.cpp
new file mode 100644
index 0000000..dce76d2
--- /dev/null
+++ b/services/tuner/TunerTimeFilter.cpp
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "TunerTimeFilter"
+
+#include "TunerTimeFilter.h"
+
+namespace android {
+
+TunerTimeFilter::TunerTimeFilter(sp<ITimeFilter> timeFilter) {
+    mTimeFilter = timeFilter;
+}
+
+TunerTimeFilter::~TunerTimeFilter() {
+    mTimeFilter = NULL;
+}
+
+Status TunerTimeFilter::setTimeStamp(int64_t /*timeStamp*/) {
+    return Status::ok();
+}
+
+Status TunerTimeFilter::clearTimeStamp() {
+    return Status::ok();
+}
+
+Status TunerTimeFilter::getSourceTime(int64_t* /*_aidl_return*/) {
+    return Status::ok();
+}
+
+Status TunerTimeFilter::getTimeStamp(int64_t* /*_aidl_return*/) {
+    return Status::ok();
+}
+
+Status TunerTimeFilter::close() {
+    return Status::ok();
+}
+}  // namespace android
diff --git a/services/tuner/TunerTimeFilter.h b/services/tuner/TunerTimeFilter.h
new file mode 100644
index 0000000..50b8f54
--- /dev/null
+++ b/services/tuner/TunerTimeFilter.h
@@ -0,0 +1,53 @@
+/**
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MEDIA_TUNERFTIMEFILTER_H
+#define ANDROID_MEDIA_TUNERFTIMEFILTER_H
+
+#include <aidl/android/media/tv/tuner/BnTunerTimeFilter.h>
+#include <android/hardware/tv/tuner/1.0/ITimeFilter.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <utils/Log.h>
+
+using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::media::tv::tuner::BnTunerTimeFilter;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::tv::tuner::V1_0::ITimeFilter;
+
+using namespace std;
+
+namespace android {
+
+class TunerTimeFilter : public BnTunerTimeFilter {
+
+public:
+    TunerTimeFilter(sp<ITimeFilter> timeFilter);
+    virtual ~TunerTimeFilter();
+    Status setTimeStamp(int64_t timeStamp) override;
+    Status clearTimeStamp() override;
+    Status getSourceTime(int64_t* _aidl_return) override;
+    Status getTimeStamp(int64_t* _aidl_return) override;
+    Status close() override;
+
+private:
+    sp<ITimeFilter> mTimeFilter;
+};
+
+} // namespace android
+
+#endif // ANDROID_MEDIA_TUNERFTIMEFILTER_H
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerFrontend.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerFrontend.aidl
index 08d20a9..bfc3e30 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerFrontend.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerFrontend.aidl
@@ -19,10 +19,9 @@
 import android.media.tv.tuner.ITunerFrontendCallback;
 import android.media.tv.tuner.TunerFrontendSettings;
 import android.media.tv.tuner.TunerFrontendStatus;
-import android.media.tv.tuner.TunerServiceFrontendInfo;
 
 /**
- * Tuner Frontend interface handles tuner related operations.
+ * Tuner Frontend interface handles frontend related operations.
  *
  * {@hide}
  */
@@ -82,4 +81,9 @@
      * Gets the statuses of the frontend.
      */
     TunerFrontendStatus[] getStatus(in int[] statusTypes);
+
+    /**
+     * Gets the id of the frontend.
+     */
+    int getFrontendId();
 }
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerFrontendCallback.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerFrontendCallback.aidl
index ae62c15..c92f5ee 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerFrontendCallback.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerFrontendCallback.aidl
@@ -16,7 +16,7 @@
 
 package android.media.tv.tuner;
 
-import android.media.tv.tuner.TunerAtsc3PlpInfo;
+import android.media.tv.tuner.TunerFrontendScanMessage;
 
 /**
  * TunerFrontendCallback interface handles tuner frontend related callbacks.
@@ -24,73 +24,13 @@
  * {@hide}
  */
 interface ITunerFrontendCallback {
-    /**
+        /**
      * Notify the client that a new event happened on the frontend.
      */
     void onEvent(in int frontendEventType);
 
     /**
-     * notify locked message to client from the ongoing scan.
+     * notify the client of scan messages.
      */
-    void onLocked();
-
-    /**
-     * notify scan stopped message to client from the ongoing scan.
-     */
-    void onScanStopped();
-
-    /**
-     * notify progress message to client from the ongoing scan.
-     */
-    void onProgress(in int percent);
-
-    /**
-     * notify Frequencies message to client from the ongoing scan.
-     */
-    void onFrequenciesReport(in int[] frequency);
-
-    /**
-     * notify SymbolRates message to client from the ongoing scan.
-     */
-    void onSymbolRates(in int[] rates);
-
-    /**
-     * notify Hierarchy message to client from the ongoing scan.
-     */
-    void onHierarchy(in int hierarchy);
-
-    /**
-     * notify SignalType message to client from the ongoing scan.
-     */
-    void onSignalType(in int signalType);
-
-    /**
-     * notify PlpIds message to client from the ongoing scan.
-     */
-    void onPlpIds(in int[] plpIds);
-
-    /**
-     * notify GroupIds message to client from the ongoing scan.
-     */
-    void onGroupIds(in int[] groupIds);
-
-    /**
-     * notify InputStreamIds message to client from the ongoing scan.
-     */
-    void onInputStreamIds(in int[] inputStreamIds);
-
-    /**
-     * notify DvbsStandard message to client from the ongoing scan.
-     */
-    void onDvbsStandard(in int dvbsStandandard);
-
-    /**
-     * notify AnalogSifStandard message to client from the ongoing scan.
-     */
-    void onAnalogSifStandard(in int sifStandandard);
-
-    /**
-     * notify Atsc3PlpInfos message to client from the ongoing scan.
-     */
-    void onAtsc3PlpInfos(in TunerAtsc3PlpInfo[] atsc3PlpInfos);
+    void onScanMessage(in int messageType, in TunerFrontendScanMessage message);
 }
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerLnb.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerLnb.aidl
new file mode 100644
index 0000000..d62145e
--- /dev/null
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerLnb.aidl
@@ -0,0 +1,56 @@
+/**
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner;
+
+import android.media.tv.tuner.ITunerLnbCallback;
+
+/**
+ * Tuner Lnb interface handles Lnb related operations.
+ *
+ * {@hide}
+ */
+interface ITunerLnb {
+    /**
+     * Set the lnb callback.
+     */
+    void setCallback(in ITunerLnbCallback tunerLnbCallback);
+
+    /**
+     * Set the lnb's power voltage.
+     */
+    void setVoltage(in int voltage);
+
+    /**
+     * Set the lnb's tone mode.
+     */
+    void setTone(in int tone);
+
+    /**
+     * Select the lnb's position.
+     */
+    void setSatellitePosition(in int position);
+
+    /**
+     * Sends DiSEqC (Digital Satellite Equipment Control) message.
+     */
+    void sendDiseqcMessage(in byte[] diseqcMessage);
+
+    /**
+     * Releases the LNB instance.
+     */
+    void close();
+}
diff --git a/services/tuner/aidl/android/media/tv/tuner/TunerAtsc3PlpInfo.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerLnbCallback.aidl
similarity index 62%
copy from services/tuner/aidl/android/media/tv/tuner/TunerAtsc3PlpInfo.aidl
copy to services/tuner/aidl/android/media/tv/tuner/ITunerLnbCallback.aidl
index a0648a5..117352f 100644
--- a/services/tuner/aidl/android/media/tv/tuner/TunerAtsc3PlpInfo.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerLnbCallback.aidl
@@ -1,5 +1,5 @@
 /**
- * Copyright 2020, The Android Open Source Project
+ * Copyright 2021, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,12 +17,18 @@
 package android.media.tv.tuner;
 
 /**
- * Atsc3 Frontend Physical Layer Pipe Info.
+ * TuneLnbCallback interface handles tuner lnb related callbacks.
  *
  * {@hide}
  */
-parcelable TunerAtsc3PlpInfo {
-    int plpId;
+interface ITunerLnbCallback {
+    /**
+     * Notify the client that a new event happened on the Lnb.
+     */
+    void onEvent(in int lnbEventType);
 
-    boolean llsFlag;
+    /**
+     * notify the client of new DiSEqC message.
+     */
+    void onDiseqcMessage(in byte[] diseqcMessage);
 }
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
index 5c1bce7..5b60685 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
@@ -20,7 +20,8 @@
 import android.hardware.common.fmq.SynchronizedReadWrite;
 import android.hardware.common.fmq.UnsynchronizedWrite;
 import android.media.tv.tuner.ITunerFrontend;
-import android.media.tv.tuner.TunerServiceFrontendInfo;
+import android.media.tv.tuner.ITunerLnb;
+import android.media.tv.tuner.TunerFrontendInfo;
 
 /**
  * TunerService interface handles tuner related operations.
@@ -43,7 +44,7 @@
      * @param frontendHandle the handle of the frontend granted by TRM.
      * @return the information of the frontend.
      */
-    TunerServiceFrontendInfo getFrontendInfo(in int frontendHandle);
+    TunerFrontendInfo getFrontendInfo(in int frontendHandle);
 
     /**
      * Open a Tuner Frontend interface.
@@ -59,4 +60,21 @@
      * @return true if succeeds, false otherwise.
      */
     boolean getFmqSyncReadWrite(out MQDescriptor<byte, SynchronizedReadWrite> mqDesc);
+
+    /**
+     * Open a new interface of ITunerLnb given a lnbHandle.
+     *
+     * @param lnbHandle the handle of the LNB granted by TRM.
+     * @return a newly created ITunerLnb interface.
+     */
+    ITunerLnb openLnb(in int lnbHandle);
+
+    /**
+     * Open a new interface of ITunerLnb given a LNB name.
+     *
+     * @param lnbName the name for an external LNB to be opened.
+     * @return a newly created ITunerLnb interface.
+     */
+    ITunerLnb openLnbByName(in String lnbName);
+
 }
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerTimeFilter.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerTimeFilter.aidl
new file mode 100644
index 0000000..f84b9bf
--- /dev/null
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerTimeFilter.aidl
@@ -0,0 +1,49 @@
+/**
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner;
+
+/**
+ * Tuner Time Filter interface handles time filter related operations.
+ *
+ * {@hide}
+ */
+interface ITunerTimeFilter {
+    /**
+     * Set time stamp for time based filter.
+     */
+    void setTimeStamp(in long timeStamp);
+
+    /**
+     * Clear the time stamp in the time filter.
+     */
+    void clearTimeStamp();
+
+    /**
+     * Get the time from the beginning of current data source.
+     */
+    long getSourceTime();
+
+    /**
+     * Get the current time in the time filter.
+     */
+    long getTimeStamp();
+
+    /**
+     * Close the Time Filter instance.
+     */
+    void close();
+}
diff --git a/services/tuner/aidl/android/media/tv/tuner/TunerServiceFrontendInfo.aidl b/services/tuner/aidl/android/media/tv/tuner/TunerFrontendInfo.aidl
similarity index 89%
rename from services/tuner/aidl/android/media/tv/tuner/TunerServiceFrontendInfo.aidl
rename to services/tuner/aidl/android/media/tv/tuner/TunerFrontendInfo.aidl
index ddcbcdc..4bccd56 100644
--- a/services/tuner/aidl/android/media/tv/tuner/TunerServiceFrontendInfo.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/TunerFrontendInfo.aidl
@@ -21,13 +21,16 @@
 /**
  * FrontendInfo interface that carries tuner frontend information.
  *
+ * <p>This is used to update the TunerResourceManager and pass Frontend
+ * information from HAL to the client side.
+ *
  * {@hide}
  */
-parcelable TunerServiceFrontendInfo {
+parcelable TunerFrontendInfo {
     /**
-     * Frontend Id
+     * Frontend Handle
      */
-    int id;
+    int handle;
 
     /**
      * Frontend Type
diff --git a/services/tuner/aidl/android/media/tv/tuner/TunerAtsc3PlpInfo.aidl b/services/tuner/aidl/android/media/tv/tuner/TunerFrontendScanAtsc3PlpInfo.aidl
similarity index 94%
rename from services/tuner/aidl/android/media/tv/tuner/TunerAtsc3PlpInfo.aidl
rename to services/tuner/aidl/android/media/tv/tuner/TunerFrontendScanAtsc3PlpInfo.aidl
index a0648a5..ca4a9af 100644
--- a/services/tuner/aidl/android/media/tv/tuner/TunerAtsc3PlpInfo.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/TunerFrontendScanAtsc3PlpInfo.aidl
@@ -21,7 +21,7 @@
  *
  * {@hide}
  */
-parcelable TunerAtsc3PlpInfo {
+parcelable TunerFrontendScanAtsc3PlpInfo {
     int plpId;
 
     boolean llsFlag;
diff --git a/services/tuner/aidl/android/media/tv/tuner/TunerFrontendScanMessage.aidl b/services/tuner/aidl/android/media/tv/tuner/TunerFrontendScanMessage.aidl
new file mode 100644
index 0000000..9921ca1
--- /dev/null
+++ b/services/tuner/aidl/android/media/tv/tuner/TunerFrontendScanMessage.aidl
@@ -0,0 +1,56 @@
+/**
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner;
+
+import android.media.tv.tuner.TunerFrontendScanAtsc3PlpInfo;
+
+/**
+ * Tuner Frontend Scan Message interface.
+ *
+ * {@hide}
+ */
+union TunerFrontendScanMessage {
+    boolean isLocked;
+
+    boolean isEnd;
+
+    byte progressPercent;
+
+    int[] frequencies;
+
+    int[] symbolRates;
+
+    int hierarchy;
+
+    int analogType;
+
+    byte[] plpIds;
+
+    byte[] groupIds;
+
+    char[] inputStreamIds;
+
+    int std;
+
+    TunerFrontendScanAtsc3PlpInfo[] atsc3PlpInfos;
+
+    int modulation;
+
+    int annex;
+
+    boolean isHighPriority;
+}