Merge "cameraserver: fix deadlock scenario in torchModeStatusChanged callback."
diff --git a/camera/OWNERS b/camera/OWNERS
index a4ab616..385c163 100644
--- a/camera/OWNERS
+++ b/camera/OWNERS
@@ -1,8 +1,7 @@
-
 # Bug component: 41727
+etalvala@google.com
 arakesh@google.com
 epeev@google.com
-etalvala@google.com
 jchowdhary@google.com
 shuzhenwang@google.com
 ruchamk@google.com
diff --git a/camera/aidl/android/hardware/ICameraServiceProxy.aidl b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
index bbb0289..3d78aef 100644
--- a/camera/aidl/android/hardware/ICameraServiceProxy.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
@@ -37,8 +37,11 @@
     oneway void notifyCameraState(in CameraSessionStats cameraSessionStats);
 
     /**
-     * Reports whether the top activity needs a rotate and crop override.
+     * Returns the necessary rotate and crop override for the top activity which
+     * will be one of ({@link android.hardware.camera2.CameraMetadata#SCALER_ROTATE_AND_CROP_NONE},
+     * {@link android.hardware.camera2.CameraMetadata#SCALER_ROTATE_AND_CROP_90},
+     * {@link android.hardware.camera2.CameraMetadata#SCALER_ROTATE_AND_CROP_180},
+     * {@link android.hardware.camera2.CameraMetadata#SCALER_ROTATE_AND_CROP_270}).
      */
-    boolean isRotateAndCropOverrideNeeded(String packageName, int sensorOrientation,
-            int lensFacing);
+    int getRotateAndCropOverride(String packageName, int lensFacing);
 }
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index c353b2d..abc63ac 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -2144,6 +2144,50 @@
      */
     ACAMERA_FLASH_INFO_AVAILABLE =                              // byte (acamera_metadata_enum_android_flash_info_available_t)
             ACAMERA_FLASH_INFO_START,
+    /**
+     * <p>Maximum flashlight brightness level.</p>
+     *
+     * <p>Type: int32</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+     * </ul></p>
+     *
+     * <p>If this value is greater than 1, then the device supports controlling the
+     * flashlight brightness level via
+     * {android.hardware.camera2.CameraManager#setTorchStrengthLevel}.
+     * If this value is equal to 1, flashlight brightness control is not supported.
+     * This value will be -1 if the flash unit is not available.</p>
+     */
+    ACAMERA_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL =                 // int32
+            ACAMERA_FLASH_INFO_START + 2,
+    /**
+     * <p>Default flashlight brightness level to be set via
+     * {android.hardware.camera2.CameraManager#setTorchStrengthLevel}.</p>
+     *
+     * <p>Type: int32</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+     * </ul></p>
+     *
+     * <p>If flash unit is available this will be greater than or equal to 1 and less
+     * or equal to <code>ACAMERA_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL</code>.
+     * If flash unit is not available this will be set to -1.</p>
+     * <p>Setting flashlight brightness above the default level
+     * (i.e.<code>ACAMERA_FLASH_INFO_STRENGTH_DEFAULT_LEVEL</code>) may make the device more
+     * likely to reach thermal throttling conditions and slow down, or drain the
+     * battery quicker than normal. To minimize such issues, it is recommended to
+     * start the flashlight at this default brightness until a user explicitly requests
+     * a brighter level.</p>
+     *
+     * @see ACAMERA_FLASH_INFO_STRENGTH_DEFAULT_LEVEL
+     * @see ACAMERA_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL
+     */
+    ACAMERA_FLASH_INFO_STRENGTH_DEFAULT_LEVEL =                 // int32
+            ACAMERA_FLASH_INFO_START + 3,
     ACAMERA_FLASH_INFO_END,
 
     /**
@@ -4585,7 +4629,7 @@
      * Clients are advised to not cache or store the orientation value of such logical sensors.
      * In case repeated queries to CameraCharacteristics are not preferred, then clients can
      * also access the entire mapping from device state to sensor orientation in
-     * <a href="https://developer.android.com/reference/android/hardware/camera2/params/DeviceStateOrientationMap.html">DeviceStateOrientationMap</a>.
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/params/DeviceStateSensorOrientationMap.html">DeviceStateSensorOrientationMap</a>.
      * Do note that a dynamically changing sensor orientation value in camera characteristics
      * will not be the best way to establish the orientation per frame. Clients that want to
      * know the sensor orientation of a particular captured frame should query the
diff --git a/cmds/screenrecord/Android.bp b/cmds/screenrecord/Android.bp
index 359a835..d0b3ce0 100644
--- a/cmds/screenrecord/Android.bp
+++ b/cmds/screenrecord/Android.bp
@@ -55,12 +55,6 @@
         "libGLESv2",
     ],
 
-    include_dirs: [
-        "frameworks/av/media/libstagefright",
-        "frameworks/av/media/libstagefright/include",
-        "frameworks/native/include/media/openmax",
-    ],
-
     cflags: [
         "-Werror",
         "-Wall",
diff --git a/media/audioserver/Android.bp b/media/audioserver/Android.bp
index e4fc4de..0b44700 100644
--- a/media/audioserver/Android.bp
+++ b/media/audioserver/Android.bp
@@ -25,6 +25,7 @@
     ],
 
     shared_libs: [
+        "packagemanager_aidl-cpp",
         "libaaudioservice",
         "libaudioclient",
         "libaudioflinger",
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index e8287f9..cc4517d 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -511,7 +511,7 @@
 status_t C2SoftAvcDec::initDecoder() {
     if (OK != createDecoder()) return UNKNOWN_ERROR;
     mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
-    mStride = ALIGN32(mWidth);
+    mStride = ALIGN128(mWidth);
     mSignalledError = false;
     resetPlugin();
     (void) setNumCores();
@@ -777,20 +777,20 @@
         return C2_CORRUPTED;
     }
     if (mOutBlock &&
-            (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
+            (mOutBlock->width() != ALIGN128(mWidth) || mOutBlock->height() != mHeight)) {
         mOutBlock.reset();
     }
     if (!mOutBlock) {
         uint32_t format = HAL_PIXEL_FORMAT_YV12;
         C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
         c2_status_t err =
-            pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
+            pool->fetchGraphicBlock(ALIGN128(mWidth), mHeight, format, usage, &mOutBlock);
         if (err != C2_OK) {
             ALOGE("fetchGraphicBlock for Output failed with status %d", err);
             return err;
         }
         ALOGV("provided (%dx%d) required (%dx%d)",
-              mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
+              mOutBlock->width(), mOutBlock->height(), ALIGN128(mWidth), mHeight);
     }
 
     return C2_OK;
@@ -928,7 +928,7 @@
         if (0 < ps_decode_op->u4_pic_wd && 0 < ps_decode_op->u4_pic_ht) {
             if (mHeaderDecoded == false) {
                 mHeaderDecoded = true;
-                mStride = ALIGN32(ps_decode_op->u4_pic_wd);
+                mStride = ALIGN128(ps_decode_op->u4_pic_wd);
                 setParams(mStride, IVD_DECODE_FRAME);
             }
             if (ps_decode_op->u4_pic_wd != mWidth || ps_decode_op->u4_pic_ht != mHeight) {
diff --git a/media/codec2/components/avc/C2SoftAvcDec.h b/media/codec2/components/avc/C2SoftAvcDec.h
index 5c07d29..59d5184 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.h
+++ b/media/codec2/components/avc/C2SoftAvcDec.h
@@ -38,7 +38,7 @@
 #define ivdext_ctl_set_num_cores_op_t   ih264d_ctl_set_num_cores_op_t
 #define ivdext_ctl_get_vui_params_ip_t  ih264d_ctl_get_vui_params_ip_t
 #define ivdext_ctl_get_vui_params_op_t  ih264d_ctl_get_vui_params_op_t
-#define ALIGN32(x)                      ((((x) + 31) >> 5) << 5)
+#define ALIGN128(x)                     ((((x) + 127) >> 7) << 7)
 #define MAX_NUM_CORES                   4
 #define IVDEXT_CMD_CTL_SET_NUM_CORES    \
         (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index f857e87..7bd3358 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -20,6 +20,7 @@
 
 #include <C2Debug.h>
 #include <C2PlatformSupport.h>
+#include <Codec2Mapper.h>
 #include <SimpleC2Interface.h>
 #include <log/log.h>
 #include <media/stagefright/foundation/AUtils.h>
@@ -156,6 +157,42 @@
             .withSetter(DefaultColorAspectsSetter)
             .build());
 
+      addParameter(
+              DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
+              .withDefault(new C2StreamColorAspectsInfo::input(
+                      0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
+                      C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+              .withFields({
+                  C2F(mCodedColorAspects, range).inRange(
+                              C2Color::RANGE_UNSPECIFIED,     C2Color::RANGE_OTHER),
+                  C2F(mCodedColorAspects, primaries).inRange(
+                              C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+                  C2F(mCodedColorAspects, transfer).inRange(
+                              C2Color::TRANSFER_UNSPECIFIED,  C2Color::TRANSFER_OTHER),
+                  C2F(mCodedColorAspects, matrix).inRange(
+                              C2Color::MATRIX_UNSPECIFIED,    C2Color::MATRIX_OTHER)
+              })
+              .withSetter(CodedColorAspectsSetter)
+              .build());
+
+      addParameter(
+              DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
+              .withDefault(new C2StreamColorAspectsInfo::output(
+                      0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
+                      C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+              .withFields({
+                  C2F(mColorAspects, range).inRange(
+                              C2Color::RANGE_UNSPECIFIED,     C2Color::RANGE_OTHER),
+                  C2F(mColorAspects, primaries).inRange(
+                              C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+                  C2F(mColorAspects, transfer).inRange(
+                              C2Color::TRANSFER_UNSPECIFIED,  C2Color::TRANSFER_OTHER),
+                  C2F(mColorAspects, matrix).inRange(
+                              C2Color::MATRIX_UNSPECIFIED,    C2Color::MATRIX_OTHER)
+              })
+              .withSetter(ColorAspectsSetter, mDefaultColorAspects, mCodedColorAspects)
+              .build());
+
     // TODO: support more formats?
     addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
                      .withConstValue(new C2StreamPixelFormatInfo::output(
@@ -218,6 +255,37 @@
     return C2R::Ok();
   }
 
+  static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) {
+    (void)mayBlock;
+    if (me.v.range > C2Color::RANGE_OTHER) {
+      me.set().range = C2Color::RANGE_OTHER;
+    }
+    if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
+      me.set().primaries = C2Color::PRIMARIES_OTHER;
+    }
+    if (me.v.transfer > C2Color::TRANSFER_OTHER) {
+      me.set().transfer = C2Color::TRANSFER_OTHER;
+    }
+    if (me.v.matrix > C2Color::MATRIX_OTHER) {
+      me.set().matrix = C2Color::MATRIX_OTHER;
+    }
+    return C2R::Ok();
+  }
+
+  static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
+                                const C2P<C2StreamColorAspectsTuning::output> &def,
+                                const C2P<C2StreamColorAspectsInfo::input> &coded) {
+    (void)mayBlock;
+    // take default values for all unspecified fields, and coded values for specified ones
+    me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range;
+    me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED
+        ? def.v.primaries : coded.v.primaries;
+    me.set().transfer = coded.v.transfer == TRANSFER_UNSPECIFIED
+        ? def.v.transfer : coded.v.transfer;
+    me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix : coded.v.matrix;
+    return C2R::Ok();
+  }
+
   static C2R ProfileLevelSetter(
       bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
       const C2P<C2StreamPictureSizeInfo::output> &size) {
@@ -232,6 +300,10 @@
     return mDefaultColorAspects;
   }
 
+  std::shared_ptr<C2StreamColorAspectsInfo::output> getColorAspects_l() {
+      return mColorAspects;
+  }
+
   static C2R Hdr10PlusInfoInputSetter(bool mayBlock,
                                       C2P<C2StreamHdr10PlusInfo::input> &me) {
     (void)mayBlock;
@@ -254,6 +326,8 @@
   std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
   std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
   std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
+  std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects;
+  std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
   std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput;
   std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput;
 };
@@ -371,6 +445,10 @@
                                const std::shared_ptr<C2GraphicBlock> &block) {
   std::shared_ptr<C2Buffer> buffer =
       createGraphicBuffer(block, C2Rect(mWidth, mHeight));
+  {
+      IntfImpl::Lock lock = mIntf->lock();
+      buffer->setInfo(mIntf->getColorAspects_l());
+  }
   auto fillWork = [buffer, index](const std::unique_ptr<C2Work> &work) {
     uint32_t flags = 0;
     if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
@@ -609,6 +687,38 @@
   }
 }
 
+void C2SoftGav1Dec::getVuiParams(const libgav1::DecoderBuffer *buffer) {
+    VuiColorAspects vuiColorAspects;
+    vuiColorAspects.primaries = buffer->color_primary;
+    vuiColorAspects.transfer = buffer->transfer_characteristics;
+    vuiColorAspects.coeffs = buffer->matrix_coefficients;
+    vuiColorAspects.fullRange = buffer->color_range;
+
+    // convert vui aspects to C2 values if changed
+    if (!(vuiColorAspects == mBitstreamColorAspects)) {
+        mBitstreamColorAspects = vuiColorAspects;
+        ColorAspects sfAspects;
+        C2StreamColorAspectsInfo::input codedAspects = { 0u };
+        ColorUtils::convertIsoColorAspectsToCodecAspects(
+                vuiColorAspects.primaries, vuiColorAspects.transfer, vuiColorAspects.coeffs,
+                vuiColorAspects.fullRange, sfAspects);
+        if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) {
+            codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED;
+        }
+        if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) {
+            codedAspects.range = C2Color::RANGE_UNSPECIFIED;
+        }
+        if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) {
+            codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED;
+        }
+        if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) {
+            codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED;
+        }
+        std::vector<std::unique_ptr<C2SettingResult>> failures;
+        mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures);
+    }
+}
+
 bool C2SoftGav1Dec::outputBuffer(const std::shared_ptr<C2BlockPool> &pool,
                                  const std::unique_ptr<C2Work> &work) {
   if (!(work && pool)) return false;
@@ -651,6 +761,7 @@
     }
   }
 
+  getVuiParams(buffer);
   if (!(buffer->image_format == libgav1::kImageFormatYuv420 ||
         buffer->image_format == libgav1::kImageFormatMonochrome400)) {
     ALOGE("image_format %d not supported", buffer->image_format);
@@ -666,12 +777,12 @@
   uint32_t format = HAL_PIXEL_FORMAT_YV12;
   if (buffer->bitdepth == 10) {
     IntfImpl::Lock lock = mIntf->lock();
-    std::shared_ptr<C2StreamColorAspectsTuning::output> defaultColorAspects =
-        mIntf->getDefaultColorAspects_l();
+    std::shared_ptr<C2StreamColorAspectsInfo::output> codedColorAspects =
+        mIntf->getColorAspects_l();
 
-    if (defaultColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
-        defaultColorAspects->matrix == C2Color::MATRIX_BT2020 &&
-        defaultColorAspects->transfer == C2Color::TRANSFER_ST2084) {
+    if (codedColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
+        codedColorAspects->matrix == C2Color::MATRIX_BT2020 &&
+        codedColorAspects->transfer == C2Color::TRANSFER_ST2084) {
       if (buffer->image_format != libgav1::kImageFormatYuv420) {
         ALOGE("Only YUV420 output is supported when targeting RGBA_1010102");
         mSignalledError = true;
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h
index 555adc9..134fa0d 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.h
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.h
@@ -17,7 +17,10 @@
 #ifndef ANDROID_C2_SOFT_GAV1_DEC_H_
 #define ANDROID_C2_SOFT_GAV1_DEC_H_
 
+#include <media/stagefright/foundation/ColorUtils.h>
+
 #include <SimpleC2Component.h>
+#include <C2Config.h>
 #include "libgav1/src/gav1/decoder.h"
 #include "libgav1/src/gav1/decoder_settings.h"
 
@@ -56,10 +59,32 @@
   bool mSignalledOutputEos;
   bool mSignalledError;
 
+  // Color aspects. These are ISO values and are meant to detect changes in aspects to avoid
+  // converting them to C2 values for each frame
+  struct VuiColorAspects {
+      uint8_t primaries;
+      uint8_t transfer;
+      uint8_t coeffs;
+      uint8_t fullRange;
+
+      // default color aspects
+      VuiColorAspects()
+          : primaries(C2Color::PRIMARIES_UNSPECIFIED),
+            transfer(C2Color::TRANSFER_UNSPECIFIED),
+            coeffs(C2Color::MATRIX_UNSPECIFIED),
+            fullRange(C2Color::RANGE_UNSPECIFIED) { }
+
+      bool operator==(const VuiColorAspects &o) {
+          return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs
+                  && fullRange == o.fullRange;
+      }
+  } mBitstreamColorAspects;
+
   struct timeval mTimeStart;  // Time at the start of decode()
   struct timeval mTimeEnd;    // Time at the end of decode()
 
   bool initDecoder();
+  void getVuiParams(const libgav1::DecoderBuffer *buffer);
   void destroyDecoder();
   void finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
                   const std::shared_ptr<C2GraphicBlock>& block);
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index 6bcf3a2..5f5b2ef 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -502,7 +502,7 @@
 status_t C2SoftHevcDec::initDecoder() {
     if (OK != createDecoder()) return UNKNOWN_ERROR;
     mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
-    mStride = ALIGN32(mWidth);
+    mStride = ALIGN128(mWidth);
     mSignalledError = false;
     resetPlugin();
     (void) setNumCores();
@@ -768,20 +768,20 @@
         return C2_CORRUPTED;
     }
     if (mOutBlock &&
-            (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
+            (mOutBlock->width() != ALIGN128(mWidth) || mOutBlock->height() != mHeight)) {
         mOutBlock.reset();
     }
     if (!mOutBlock) {
         uint32_t format = HAL_PIXEL_FORMAT_YV12;
         C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
         c2_status_t err =
-            pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
+            pool->fetchGraphicBlock(ALIGN128(mWidth), mHeight, format, usage, &mOutBlock);
         if (err != C2_OK) {
             ALOGE("fetchGraphicBlock for Output failed with status %d", err);
             return err;
         }
         ALOGV("provided (%dx%d) required (%dx%d)",
-              mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
+              mOutBlock->width(), mOutBlock->height(), ALIGN128(mWidth), mHeight);
     }
 
     return C2_OK;
@@ -917,7 +917,7 @@
         if (0 < ps_decode_op->u4_pic_wd && 0 < ps_decode_op->u4_pic_ht) {
             if (mHeaderDecoded == false) {
                 mHeaderDecoded = true;
-                setParams(ALIGN32(ps_decode_op->u4_pic_wd), IVD_DECODE_FRAME);
+                setParams(ALIGN128(ps_decode_op->u4_pic_wd), IVD_DECODE_FRAME);
             }
             if (ps_decode_op->u4_pic_wd != mWidth ||  ps_decode_op->u4_pic_ht != mHeight) {
                 mWidth = ps_decode_op->u4_pic_wd;
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.h b/media/codec2/components/hevc/C2SoftHevcDec.h
index b9b0a48..b9296e9 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.h
+++ b/media/codec2/components/hevc/C2SoftHevcDec.h
@@ -36,7 +36,7 @@
 #define ivdext_ctl_set_num_cores_op_t   ihevcd_cxa_ctl_set_num_cores_op_t
 #define ivdext_ctl_get_vui_params_ip_t  ihevcd_cxa_ctl_get_vui_params_ip_t
 #define ivdext_ctl_get_vui_params_op_t  ihevcd_cxa_ctl_get_vui_params_op_t
-#define ALIGN32(x)                      ((((x) + 31) >> 5) << 5)
+#define ALIGN128(x)                     ((((x) + 127) >> 7) << 7)
 #define MAX_NUM_CORES                   4
 #define IVDEXT_CMD_CTL_SET_NUM_CORES    \
         (IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index b1cf388..5f9b30b 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -572,7 +572,7 @@
     if (OK != createDecoder()) return UNKNOWN_ERROR;
 
     mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
-    mStride = ALIGN32(mWidth);
+    mStride = ALIGN128(mWidth);
     mSignalledError = false;
     resetPlugin();
     (void) setNumCores();
@@ -845,20 +845,20 @@
         return C2_CORRUPTED;
     }
     if (mOutBlock &&
-            (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
+            (mOutBlock->width() != ALIGN128(mWidth) || mOutBlock->height() != mHeight)) {
         mOutBlock.reset();
     }
     if (!mOutBlock) {
         uint32_t format = HAL_PIXEL_FORMAT_YV12;
         C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
         c2_status_t err =
-            pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
+            pool->fetchGraphicBlock(ALIGN128(mWidth), mHeight, format, usage, &mOutBlock);
         if (err != C2_OK) {
             ALOGE("fetchGraphicBlock for Output failed with status %d", err);
             return err;
         }
         ALOGV("provided (%dx%d) required (%dx%d)",
-              mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
+              mOutBlock->width(), mOutBlock->height(), ALIGN128(mWidth), mHeight);
     }
 
     return C2_OK;
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
index fd66304a..8a29c14 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
@@ -37,7 +37,7 @@
 #define ivdext_ctl_set_num_cores_op_t   impeg2d_ctl_set_num_cores_op_t
 #define ivdext_ctl_get_seq_info_ip_t    impeg2d_ctl_get_seq_info_ip_t
 #define ivdext_ctl_get_seq_info_op_t    impeg2d_ctl_get_seq_info_op_t
-#define ALIGN32(x)                      ((((x) + 31) >> 5) << 5)
+#define ALIGN128(x)                     ((((x) + 127) >> 7) << 7)
 #define MAX_NUM_CORES                   4
 #define IVDEXT_CMD_CTL_SET_NUM_CORES    \
         (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp
index 169de0c..01995fd 100644
--- a/media/codec2/vndk/platform/C2BqBuffer.cpp
+++ b/media/codec2/vndk/platform/C2BqBuffer.cpp
@@ -16,6 +16,7 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "C2BqBuffer"
+#include <android/hardware_buffer.h>
 #include <utils/Log.h>
 
 #include <ui/BufferQueueDefs.h>
@@ -171,6 +172,91 @@
     return stamp;
 }
 
+// Do not rely on AHardwareBuffer module for GraphicBuffer handling since AHardwareBuffer
+// module is linked to framework which could have a different implementation of GraphicBuffer
+// than mainline/vndk implementation.(See b/203347494.)
+//
+// b2h/h2b between HardwareBuffer and GraphicBuffer cannot be used. (b2h/h2b depend on
+// AHardwareBuffer module for the conversion between HardwareBuffer and GraphicBuffer.)
+// hgbp_ prefixed methods are added to be used instead of b2h/h2b.
+//
+// TODO: Remove dependency with existing AHwB module. Also clean up conversions.(conversions here
+// and h2b/b2h coversions)
+const GraphicBuffer* hgbp_AHBuffer_to_GraphicBuffer(const AHardwareBuffer* buffer) {
+    return GraphicBuffer::fromAHardwareBuffer(buffer);
+}
+
+int hgbp_createFromHandle(const AHardwareBuffer_Desc* desc,
+                                     const native_handle_t* handle,
+                                     sp<GraphicBuffer> *outBuffer) {
+
+    if (!desc || !handle || !outBuffer) return ::android::BAD_VALUE;
+    if (desc->rfu0 != 0 || desc->rfu1 != 0) return ::android::BAD_VALUE;
+    if (desc->format == AHARDWAREBUFFER_FORMAT_BLOB && desc->height != 1)
+        return ::android::BAD_VALUE;
+
+    const int format = uint32_t(desc->format);
+    const uint64_t usage = uint64_t(desc->usage);
+    sp<GraphicBuffer> gbuffer(new GraphicBuffer(handle,
+                                                GraphicBuffer::HandleWrapMethod::CLONE_HANDLE,
+                                                desc->width, desc->height,
+                                                format, desc->layers, usage, desc->stride));
+    status_t err = gbuffer->initCheck();
+    if (err != 0 || gbuffer->handle == 0) return err;
+
+    *outBuffer = gbuffer;
+
+    return ::android::NO_ERROR;
+}
+
+void hgbp_describe(const AHardwareBuffer* buffer,
+        AHardwareBuffer_Desc* outDesc) {
+    if (!buffer || !outDesc) return;
+
+    const GraphicBuffer* gbuffer = hgbp_AHBuffer_to_GraphicBuffer(buffer);
+
+    outDesc->width = gbuffer->getWidth();
+    outDesc->height = gbuffer->getHeight();
+    outDesc->layers = gbuffer->getLayerCount();
+    outDesc->format = uint32_t(gbuffer->getPixelFormat());
+    outDesc->usage = uint64_t(gbuffer->getUsage());
+    outDesc->stride = gbuffer->getStride();
+    outDesc->rfu0 = 0;
+    outDesc->rfu1 = 0;
+}
+
+
+bool hgbp_h2b(HBuffer const& from, sp<GraphicBuffer>* to) {
+    AHardwareBuffer_Desc const* desc =
+            reinterpret_cast<AHardwareBuffer_Desc const*>(
+            from.description.data());
+    native_handle_t const* handle = from.nativeHandle;
+    if (hgbp_createFromHandle(desc, handle, to) != ::android::OK) {
+        return false;
+    }
+    return true;
+}
+
+bool hgbp_b2h(sp<GraphicBuffer> const& from, HBuffer* to,
+         uint32_t* toGenerationNumber) {
+    if (!from) {
+        return false;
+    }
+    AHardwareBuffer* hwBuffer = from->toAHardwareBuffer();
+    to->nativeHandle.setTo(
+          const_cast<native_handle_t*>(from->handle),
+          false);
+    hgbp_describe(
+            hwBuffer,
+            reinterpret_cast<AHardwareBuffer_Desc*>(to->description.data()));
+    if (toGenerationNumber) {
+        *toGenerationNumber = from->getGenerationNumber();
+    }
+    return true;
+}
+
+// End of hgbp methods for GraphicBuffer creation.
+
 bool getGenerationNumberAndUsage(const sp<HGraphicBufferProducer> &producer,
                                  uint32_t *generation, uint64_t *usage) {
     status_t status{};
@@ -211,7 +297,7 @@
                     HBuffer const& hBuffer,
                     uint32_t generationNumber){
                 if (h2b(hStatus, &status) &&
-                        h2b(hBuffer, &slotBuffer) &&
+                        hgbp_h2b(hBuffer, &slotBuffer) &&
                         slotBuffer) {
                     *generation = generationNumber;
                     *usage = slotBuffer->getUsage();
@@ -402,7 +488,7 @@
                             HBuffer const& hBuffer,
                             uint32_t generationNumber){
                         if (h2b(hStatus, &status) &&
-                                h2b(hBuffer, &slotBuffer) &&
+                                hgbp_h2b(hBuffer, &slotBuffer) &&
                                 slotBuffer) {
                             slotBuffer->setGenerationNumber(generationNumber);
                             outGeneration = generationNumber;
@@ -804,7 +890,7 @@
 
     HBuffer hBuffer{};
     uint32_t hGenerationNumber{};
-    if (!b2h(graphicBuffer, &hBuffer, &hGenerationNumber)) {
+    if (!hgbp_b2h(graphicBuffer, &hBuffer, &hGenerationNumber)) {
         ALOGD("I to O conversion failed");
         return -1;
     }
diff --git a/media/libaaudio/fuzzer/Android.bp b/media/libaaudio/fuzzer/Android.bp
new file mode 100644
index 0000000..b19376d
--- /dev/null
+++ b/media/libaaudio/fuzzer/Android.bp
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+cc_fuzz {
+    name: "libaaudio_fuzzer",
+    srcs: [
+        "libaaudio_fuzzer.cpp",
+    ],
+    header_libs: [
+        "libaaudio_headers",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libaudiomanager",
+        "libaudiopolicy",
+        "libaudioclient_aidl_conversion",
+    ],
+    static_libs: [
+        "android.media.audio.common.types-V1-cpp",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libaaudio",
+        "libjsoncpp",
+        "libbase_ndk",
+        "libcgrouprc",
+        "libaudioutils",
+        "libaudioclient",
+        "aaudio-aidl-cpp",
+        "libmedia_helper",
+        "libmediametrics",
+        "libprocessgroup",
+        "av-types-aidl-cpp",
+        "libaaudio_internal",
+        "libcgrouprc_format",
+        "audiopolicy-aidl-cpp",
+        "audioflinger-aidl-cpp",
+        "audiopolicy-types-aidl-cpp",
+        "audioclient-types-aidl-cpp",
+        "shared-file-region-aidl-cpp",
+        "framework-permission-aidl-cpp",
+        "mediametricsservice-aidl-cpp",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 155276,
+    },
+}
diff --git a/media/libaaudio/fuzzer/README.md b/media/libaaudio/fuzzer/README.md
new file mode 100644
index 0000000..4ba15c5
--- /dev/null
+++ b/media/libaaudio/fuzzer/README.md
@@ -0,0 +1,77 @@
+# Fuzzer for libaaudio
+
+## Plugin Design Considerations
+The fuzzer plugin for `libaaudio` are designed based on the understanding of the
+source code 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.
+
+Fuzzers assigns values to the following parameters to pass on to libaaudio:
+1. Device Id (parameter name: `deviceId`)
+2. Sampling Rate (parameter name: `sampleRate`)
+3. Number of channels (parameter name: `channelCount`)
+4. Audio Travel Direction (parameter name: `direction`)
+5. Audio Format (parameter name: `format`)
+6. Audio Sharing Mode (parameter name: `sharingMode`)
+7. Audio Usage (parameter name: `usage`)
+8. Audio Content type (parameter name: `contentType`)
+9. Audio Input Preset (parameter name: `inputPreset`)
+10. Audio Privacy Sensitivity (parameter name: `privacySensitive`)
+11. Buffer Capacity In Frames (parameter name: `frames`)
+12. Performance Mode (parameter name: `mode`)
+13. Allowed Capture Policy (parameter name: `allowedCapturePolicy`)
+14. Session Id (parameter name: `sessionId`)
+15. Frames per Data Callback (parameter name: `framesPerDataCallback`)
+16. MMap Policy (parameter name: `policy`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `deviceId` | Any value of type `int32_t`  | Value obtained from FuzzedDataProvider |
+| `sampleRate` | Any value of type `int32_t`  | Value obtained from FuzzedDataProvider |
+| `channelCount` |  Any value of type `int32_t` | Value obtained from FuzzedDataProvider |
+| `direction` | 0. `AAUDIO_DIRECTION_OUTPUT` 1. `AAUDIO_DIRECTION_INPUT` | Value obtained from FuzzedDataProvider |
+| `format` | 0. `AAUDIO_FORMAT_INVALID` 1. `AAUDIO_FORMAT_UNSPECIFIED` 2. `AAUDIO_FORMAT_PCM_I16` 3. `AAUDIO_FORMAT_PCM_FLOAT` | Value obtained from FuzzedDataProvider |
+| `sharingMode` | 0. `AAUDIO_SHARING_MODE_EXCLUSIVE` 1. `AAUDIO_SHARING_MODE_SHARED` | Value obtained from FuzzedDataProvider |
+| `usage` | 0. `AAUDIO_USAGE_MEDIA` 1. `AAUDIO_USAGE_VOICE_COMMUNICATION` 2. `AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING` 3. `AAUDIO_USAGE_ALARM` 4. `AAUDIO_USAGE_NOTIFICATION` 5. `AAUDIO_USAGE_NOTIFICATION_RINGTONE` 6. `AAUDIO_USAGE_NOTIFICATION_EVENT` 7. `AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY` 8. `AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE` 9. `AAUDIO_USAGE_ASSISTANCE_SONIFICATION` 10. `AAUDIO_USAGE_GAME` 11. `AAUDIO_USAGE_ASSISTANT` 12. `AAUDIO_SYSTEM_USAGE_EMERGENCY` 13. `AAUDIO_SYSTEM_USAGE_SAFETY` 14. `AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS` 15. `AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT` | Value obtained from FuzzedDataProvider |
+| `contentType` | 0. `AAUDIO_CONTENT_TYPE_SPEECH` 1. `AAUDIO_CONTENT_TYPE_MUSIC` 2. `AAUDIO_CONTENT_TYPE_MOVIE` 3. `AAUDIO_CONTENT_TYPE_SONIFICATION` | Value obtained from FuzzedDataProvider |
+| `inputPreset` | 0. `AAUDIO_INPUT_PRESET_GENERIC` 1. `AAUDIO_INPUT_PRESET_CAMCORDER` 2. `AAUDIO_INPUT_PRESET_VOICE_RECOGNITION` 3. `AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION` 4. `AAUDIO_INPUT_PRESET_UNPROCESSED` 5. `AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE` | Value obtained from FuzzedDataProvider |
+| `privacySensitive` | 0. `true` 1. `false` | Value obtained from FuzzedDataProvider |
+| `frames` | Any value of type `int32_t`  | Value obtained from FuzzedDataProvider |
+| `mode` | 0. `AAUDIO_PERFORMANCE_MODE_NONE` 1. `AAUDIO_PERFORMANCE_MODE_POWER_SAVING` 2. `AAUDIO_PERFORMANCE_MODE_LOW_LATENCY` | Value obtained from FuzzedDataProvider |
+| `allowedCapturePolicy` | 0. `AAUDIO_ALLOW_CAPTURE_BY_ALL` 1. `AAUDIO_ALLOW_CAPTURE_BY_SYSTEM` 2. `AAUDIO_ALLOW_CAPTURE_BY_NONE` | Value obtained from FuzzedDataProvider |
+| `sessionId` | 0. `AAUDIO_SESSION_ID_NONE` 1. `AAUDIO_SESSION_ID_ALLOCATE` | Value obtained from FuzzedDataProvider |
+| `framesPerDataCallback` | Any value of type `int32_t` | Value obtained from FuzzedDataProvider |
+| `policy` | 0. `AAUDIO_POLICY_NEVER` 1. `AAUDIO_POLICY_AUTO` 2. `AAUDIO_POLICY_ALWAYS` | Value obtained from FuzzedDataProvider |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feed the entire input data to the module.
+This ensures that the plugins tolerates any kind of input (empty, huge,
+malformed, etc) and doesn't `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build libaaudio_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) libaaudio_fuzzer
+```
+### Steps to run
+
+To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/libaaudio_fuzzer/libaaudio_fuzzer
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp b/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp
new file mode 100644
index 0000000..1167bb0
--- /dev/null
+++ b/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp
@@ -0,0 +1,289 @@
+/*
+ * 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.
+ *
+ */
+
+#include "aaudio/AAudio.h"
+#include "aaudio/AAudioTesting.h"
+#include <fuzzer/FuzzedDataProvider.h>
+
+constexpr int32_t kRandomStringLength = 256;
+
+constexpr int64_t kNanosPerMillisecond = 1000 * 1000;
+
+constexpr aaudio_direction_t kDirections[] = {
+    AAUDIO_DIRECTION_OUTPUT, AAUDIO_DIRECTION_INPUT, AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_performance_mode_t kPerformanceModes[] = {
+    AAUDIO_PERFORMANCE_MODE_NONE, AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
+    AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_format_t kFormats[] = {
+    AAUDIO_FORMAT_INVALID,        AAUDIO_FORMAT_UNSPECIFIED,
+    AAUDIO_FORMAT_PCM_I16,        AAUDIO_FORMAT_PCM_FLOAT,
+    AAUDIO_FORMAT_PCM_I24_PACKED, AAUDIO_FORMAT_PCM_I32};
+
+constexpr aaudio_sharing_mode_t kSharingModes[] = {
+    AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_SHARING_MODE_SHARED};
+
+constexpr int32_t kSampleRates[] = {AAUDIO_UNSPECIFIED,
+                                    8000,
+                                    11025,
+                                    16000,
+                                    22050,
+                                    32000,
+                                    44100,
+                                    48000,
+                                    88200,
+                                    96000};
+
+constexpr aaudio_usage_t kUsages[] = {
+    AAUDIO_USAGE_MEDIA,
+    AAUDIO_USAGE_VOICE_COMMUNICATION,
+    AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+    AAUDIO_USAGE_ALARM,
+    AAUDIO_USAGE_NOTIFICATION,
+    AAUDIO_USAGE_NOTIFICATION_RINGTONE,
+    AAUDIO_USAGE_NOTIFICATION_EVENT,
+    AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
+    AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+    AAUDIO_USAGE_ASSISTANCE_SONIFICATION,
+    AAUDIO_USAGE_GAME,
+    AAUDIO_USAGE_ASSISTANT,
+    AAUDIO_SYSTEM_USAGE_EMERGENCY,
+    AAUDIO_SYSTEM_USAGE_SAFETY,
+    AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS,
+    AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT,
+    AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_content_type_t kContentTypes[] = {
+    AAUDIO_CONTENT_TYPE_SPEECH, AAUDIO_CONTENT_TYPE_MUSIC,
+    AAUDIO_CONTENT_TYPE_MOVIE, AAUDIO_CONTENT_TYPE_SONIFICATION,
+    AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_input_preset_t kInputPresets[] = {
+    AAUDIO_INPUT_PRESET_GENERIC,
+    AAUDIO_INPUT_PRESET_CAMCORDER,
+    AAUDIO_INPUT_PRESET_VOICE_RECOGNITION,
+    AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION,
+    AAUDIO_INPUT_PRESET_UNPROCESSED,
+    AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE,
+    AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_allowed_capture_policy_t kAllowedCapturePolicies[] = {
+    AAUDIO_ALLOW_CAPTURE_BY_ALL, AAUDIO_ALLOW_CAPTURE_BY_SYSTEM,
+    AAUDIO_ALLOW_CAPTURE_BY_NONE, AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_session_id_t kSessionIds[] = {
+    AAUDIO_SESSION_ID_NONE, AAUDIO_SESSION_ID_ALLOCATE, AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_policy_t kPolicies[] = {
+    AAUDIO_POLICY_NEVER, AAUDIO_POLICY_AUTO, AAUDIO_POLICY_ALWAYS,
+    AAUDIO_UNSPECIFIED};
+
+class LibAaudioFuzzer {
+public:
+  ~LibAaudioFuzzer() { deInit(); }
+  bool init();
+  void process(const uint8_t *data, size_t size);
+  void deInit();
+
+private:
+  AAudioStreamBuilder *mAaudioBuilder = nullptr;
+  AAudioStream *mAaudioStream = nullptr;
+};
+
+bool LibAaudioFuzzer::init() {
+  aaudio_result_t result = AAudio_createStreamBuilder(&mAaudioBuilder);
+  if ((result != AAUDIO_OK) || (!mAaudioBuilder)) {
+    return false;
+  }
+  return true;
+}
+
+void LibAaudioFuzzer::process(const uint8_t *data, size_t size) {
+  FuzzedDataProvider fdp(data, size);
+  aaudio_performance_mode_t mode =
+      fdp.PickValueInArray({fdp.PickValueInArray(kPerformanceModes),
+                            fdp.ConsumeIntegral<int32_t>()});
+  AAudioStreamBuilder_setPerformanceMode(mAaudioBuilder, mode);
+
+  int32_t deviceId = fdp.PickValueInArray(
+      {AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
+  AAudioStreamBuilder_setDeviceId(mAaudioBuilder, deviceId);
+
+  std::string packageName = fdp.PickValueInArray<std::string>(
+      {"android.nativemedia.aaudio", "android.app.appops.cts",
+       fdp.ConsumeRandomLengthString(kRandomStringLength)});
+  AAudioStreamBuilder_setPackageName(mAaudioBuilder, packageName.c_str());
+
+  std::string attributionTag =
+      fdp.ConsumeRandomLengthString(kRandomStringLength);
+  AAudioStreamBuilder_setAttributionTag(mAaudioBuilder, attributionTag.c_str());
+
+  int32_t sampleRate = fdp.PickValueInArray(kSampleRates);
+  AAudioStreamBuilder_setSampleRate(mAaudioBuilder, sampleRate);
+
+  int32_t channelCount = fdp.PickValueInArray(
+      {AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
+  AAudioStreamBuilder_setChannelCount(mAaudioBuilder, channelCount);
+
+  aaudio_direction_t direction = fdp.PickValueInArray(
+      {fdp.PickValueInArray(kDirections), fdp.ConsumeIntegral<int32_t>()});
+  AAudioStreamBuilder_setDirection(mAaudioBuilder, direction);
+
+  aaudio_format_t format = fdp.PickValueInArray(
+      {fdp.PickValueInArray(kFormats), fdp.ConsumeIntegral<int32_t>()});
+  AAudioStreamBuilder_setFormat(mAaudioBuilder, format);
+
+  aaudio_sharing_mode_t sharingMode = fdp.PickValueInArray(
+      {fdp.PickValueInArray(kSharingModes), fdp.ConsumeIntegral<int32_t>()});
+  AAudioStreamBuilder_setSharingMode(mAaudioBuilder, sharingMode);
+
+  aaudio_usage_t usage = fdp.PickValueInArray(
+      {fdp.PickValueInArray(kUsages), fdp.ConsumeIntegral<int32_t>()});
+  AAudioStreamBuilder_setUsage(mAaudioBuilder, usage);
+
+  aaudio_content_type_t contentType = fdp.PickValueInArray(
+      {fdp.PickValueInArray(kContentTypes), fdp.ConsumeIntegral<int32_t>()});
+  AAudioStreamBuilder_setContentType(mAaudioBuilder, contentType);
+
+  aaudio_input_preset_t inputPreset = fdp.PickValueInArray(
+      {fdp.PickValueInArray(kInputPresets), fdp.ConsumeIntegral<int32_t>()});
+  AAudioStreamBuilder_setInputPreset(mAaudioBuilder, inputPreset);
+
+  bool privacySensitive = fdp.ConsumeBool();
+  AAudioStreamBuilder_setPrivacySensitive(mAaudioBuilder, privacySensitive);
+
+  int32_t frames = fdp.PickValueInArray(
+      {AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
+  AAudioStreamBuilder_setBufferCapacityInFrames(mAaudioBuilder, frames);
+
+  aaudio_allowed_capture_policy_t allowedCapturePolicy =
+      fdp.PickValueInArray({fdp.PickValueInArray(kAllowedCapturePolicies),
+                            fdp.ConsumeIntegral<int32_t>()});
+  AAudioStreamBuilder_setAllowedCapturePolicy(mAaudioBuilder,
+                                              allowedCapturePolicy);
+
+  aaudio_session_id_t sessionId = fdp.PickValueInArray(
+      {fdp.PickValueInArray(kSessionIds), fdp.ConsumeIntegral<int32_t>()});
+  AAudioStreamBuilder_setSessionId(mAaudioBuilder, sessionId);
+
+  AAudioStreamBuilder_setDataCallback(mAaudioBuilder, nullptr, nullptr);
+  AAudioStreamBuilder_setErrorCallback(mAaudioBuilder, nullptr, nullptr);
+
+  int32_t framesPerDataCallback = fdp.PickValueInArray(
+      {AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
+  AAudioStreamBuilder_setFramesPerDataCallback(mAaudioBuilder,
+                                               framesPerDataCallback);
+
+  aaudio_policy_t policy = fdp.PickValueInArray(
+      {fdp.PickValueInArray(kPolicies), fdp.ConsumeIntegral<int32_t>()});
+  AAudio_setMMapPolicy(policy);
+  (void)AAudio_getMMapPolicy();
+
+  aaudio_result_t result =
+      AAudioStreamBuilder_openStream(mAaudioBuilder, &mAaudioStream);
+  if ((result != AAUDIO_OK) || (!mAaudioStream)) {
+    return;
+  }
+
+  int32_t framesPerBurst = AAudioStream_getFramesPerBurst(mAaudioStream);
+  uint8_t numberOfBursts = fdp.ConsumeIntegral<uint8_t>();
+  int32_t maxInputFrames = numberOfBursts * framesPerBurst;
+  int32_t requestedBufferSize =
+      fdp.ConsumeIntegral<uint16_t>() * framesPerBurst;
+  AAudioStream_setBufferSizeInFrames(mAaudioStream, requestedBufferSize);
+
+  int64_t position = 0, nanoseconds = 0;
+  AAudioStream_getTimestamp(mAaudioStream, CLOCK_MONOTONIC, &position,
+                            &nanoseconds);
+
+  AAudioStream_requestStart(mAaudioStream);
+
+  aaudio_format_t actualFormat = AAudioStream_getFormat(mAaudioStream);
+  int32_t actualChannelCount = AAudioStream_getChannelCount(mAaudioStream);
+
+  int32_t count = fdp.ConsumeIntegral<int32_t>();
+  direction = AAudioStream_getDirection(mAaudioStream);
+  framesPerDataCallback = AAudioStream_getFramesPerDataCallback(mAaudioStream);
+
+  if (actualFormat == AAUDIO_FORMAT_PCM_I16) {
+    std::vector<int16_t> inputShortData(maxInputFrames * actualChannelCount,
+                                        0x0);
+    if (direction == AAUDIO_DIRECTION_INPUT) {
+      AAudioStream_read(mAaudioStream, inputShortData.data(),
+                        framesPerDataCallback, count * kNanosPerMillisecond);
+    } else if (direction == AAUDIO_DIRECTION_OUTPUT) {
+      AAudioStream_write(mAaudioStream, inputShortData.data(),
+                         framesPerDataCallback, count * kNanosPerMillisecond);
+    }
+  } else if (actualFormat == AAUDIO_FORMAT_PCM_FLOAT) {
+    std::vector<float> inputFloatData(maxInputFrames * actualChannelCount, 0x0);
+    if (direction == AAUDIO_DIRECTION_INPUT) {
+      AAudioStream_read(mAaudioStream, inputFloatData.data(),
+                        framesPerDataCallback, count * kNanosPerMillisecond);
+    } else if (direction == AAUDIO_DIRECTION_OUTPUT) {
+      AAudioStream_write(mAaudioStream, inputFloatData.data(),
+                         framesPerDataCallback, count * kNanosPerMillisecond);
+    }
+  }
+
+  aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
+  AAudioStream_waitForStateChange(mAaudioStream, AAUDIO_STREAM_STATE_UNKNOWN,
+                                  &state, count * kNanosPerMillisecond);
+  (void)AAudio_convertStreamStateToText(state);
+
+  (void)AAudioStream_getUsage(mAaudioStream);
+  (void)AAudioStream_getSampleRate(mAaudioStream);
+  (void)AAudioStream_getState(mAaudioStream);
+  (void)AAudioStream_getSamplesPerFrame(mAaudioStream);
+  (void)AAudioStream_getContentType(mAaudioStream);
+  (void)AAudioStream_getInputPreset(mAaudioStream);
+  (void)AAudioStream_isPrivacySensitive(mAaudioStream);
+  (void)AAudioStream_getAllowedCapturePolicy(mAaudioStream);
+  (void)AAudioStream_getPerformanceMode(mAaudioStream);
+  (void)AAudioStream_getDeviceId(mAaudioStream);
+  (void)AAudioStream_getSharingMode(mAaudioStream);
+  (void)AAudioStream_getSessionId(mAaudioStream);
+  (void)AAudioStream_getFramesRead(mAaudioStream);
+  (void)AAudioStream_getFramesWritten(mAaudioStream);
+  (void)AAudioStream_getXRunCount(mAaudioStream);
+  (void)AAudioStream_getBufferCapacityInFrames(mAaudioStream);
+  (void)AAudioStream_getBufferSizeInFrames(mAaudioStream);
+  (void)AAudioStream_isMMapUsed(mAaudioStream);
+
+  AAudioStream_requestPause(mAaudioStream);
+  AAudioStream_requestFlush(mAaudioStream);
+  AAudioStream_release(mAaudioStream);
+  AAudioStream_requestStop(mAaudioStream);
+}
+
+void LibAaudioFuzzer::deInit() {
+  if (mAaudioBuilder) {
+    AAudioStreamBuilder_delete(mAaudioBuilder);
+  }
+  if (mAaudioStream) {
+    AAudioStream_close(mAaudioStream);
+  }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  LibAaudioFuzzer libAaudioFuzzer;
+  if (libAaudioFuzzer.init()) {
+    libAaudioFuzzer.process(data, size);
+  }
+  return 0;
+}
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index b710e29..efa9941 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -20,7 +20,7 @@
  */
 
 /**
- * @file AAudio.h
+ * @file aaudio/AAudio.h
  */
 
 /**
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 5f63a69..fad861a 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -50,8 +50,12 @@
 using media::audio::common::AudioGain;
 using media::audio::common::AudioGainConfig;
 using media::audio::common::AudioGainMode;
+using media::audio::common::AudioInputFlags;
+using media::audio::common::AudioIoFlags;
 using media::audio::common::AudioMode;
 using media::audio::common::AudioOffloadInfo;
+using media::audio::common::AudioOutputFlags;
+using media::audio::common::AudioPortDeviceExt;
 using media::audio::common::AudioPortExt;
 using media::audio::common::AudioPortMixExt;
 using media::audio::common::AudioPortMixExtUseCase;
@@ -1281,129 +1285,129 @@
 }
 
 ConversionResult<audio_input_flags_t> aidl2legacy_AudioInputFlags_audio_input_flags_t(
-        media::AudioInputFlags aidl) {
+        AudioInputFlags aidl) {
     switch (aidl) {
-        case media::AudioInputFlags::FAST:
+        case AudioInputFlags::FAST:
             return AUDIO_INPUT_FLAG_FAST;
-        case media::AudioInputFlags::HW_HOTWORD:
+        case AudioInputFlags::HW_HOTWORD:
             return AUDIO_INPUT_FLAG_HW_HOTWORD;
-        case media::AudioInputFlags::RAW:
+        case AudioInputFlags::RAW:
             return AUDIO_INPUT_FLAG_RAW;
-        case media::AudioInputFlags::SYNC:
+        case AudioInputFlags::SYNC:
             return AUDIO_INPUT_FLAG_SYNC;
-        case media::AudioInputFlags::MMAP_NOIRQ:
+        case AudioInputFlags::MMAP_NOIRQ:
             return AUDIO_INPUT_FLAG_MMAP_NOIRQ;
-        case media::AudioInputFlags::VOIP_TX:
+        case AudioInputFlags::VOIP_TX:
             return AUDIO_INPUT_FLAG_VOIP_TX;
-        case media::AudioInputFlags::HW_AV_SYNC:
+        case AudioInputFlags::HW_AV_SYNC:
             return AUDIO_INPUT_FLAG_HW_AV_SYNC;
-        case media::AudioInputFlags::DIRECT:
+        case AudioInputFlags::DIRECT:
             return AUDIO_INPUT_FLAG_DIRECT;
     }
     return unexpected(BAD_VALUE);
 }
 
-ConversionResult<media::AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
+ConversionResult<AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
         audio_input_flags_t legacy) {
     switch (legacy) {
         case AUDIO_INPUT_FLAG_NONE:
             break; // shouldn't get here. must be listed  -Werror,-Wswitch
         case AUDIO_INPUT_FLAG_FAST:
-            return media::AudioInputFlags::FAST;
+            return AudioInputFlags::FAST;
         case AUDIO_INPUT_FLAG_HW_HOTWORD:
-            return media::AudioInputFlags::HW_HOTWORD;
+            return AudioInputFlags::HW_HOTWORD;
         case AUDIO_INPUT_FLAG_RAW:
-            return media::AudioInputFlags::RAW;
+            return AudioInputFlags::RAW;
         case AUDIO_INPUT_FLAG_SYNC:
-            return media::AudioInputFlags::SYNC;
+            return AudioInputFlags::SYNC;
         case AUDIO_INPUT_FLAG_MMAP_NOIRQ:
-            return media::AudioInputFlags::MMAP_NOIRQ;
+            return AudioInputFlags::MMAP_NOIRQ;
         case AUDIO_INPUT_FLAG_VOIP_TX:
-            return media::AudioInputFlags::VOIP_TX;
+            return AudioInputFlags::VOIP_TX;
         case AUDIO_INPUT_FLAG_HW_AV_SYNC:
-            return media::AudioInputFlags::HW_AV_SYNC;
+            return AudioInputFlags::HW_AV_SYNC;
         case AUDIO_INPUT_FLAG_DIRECT:
-            return media::AudioInputFlags::DIRECT;
+            return AudioInputFlags::DIRECT;
     }
     return unexpected(BAD_VALUE);
 }
 
 ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
-        media::AudioOutputFlags aidl) {
+        AudioOutputFlags aidl) {
     switch (aidl) {
-        case media::AudioOutputFlags::DIRECT:
+        case AudioOutputFlags::DIRECT:
             return AUDIO_OUTPUT_FLAG_DIRECT;
-        case media::AudioOutputFlags::PRIMARY:
+        case AudioOutputFlags::PRIMARY:
             return AUDIO_OUTPUT_FLAG_PRIMARY;
-        case media::AudioOutputFlags::FAST:
+        case AudioOutputFlags::FAST:
             return AUDIO_OUTPUT_FLAG_FAST;
-        case media::AudioOutputFlags::DEEP_BUFFER:
+        case AudioOutputFlags::DEEP_BUFFER:
             return AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
-        case media::AudioOutputFlags::COMPRESS_OFFLOAD:
+        case AudioOutputFlags::COMPRESS_OFFLOAD:
             return AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
-        case media::AudioOutputFlags::NON_BLOCKING:
+        case AudioOutputFlags::NON_BLOCKING:
             return AUDIO_OUTPUT_FLAG_NON_BLOCKING;
-        case media::AudioOutputFlags::HW_AV_SYNC:
+        case AudioOutputFlags::HW_AV_SYNC:
             return AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
-        case media::AudioOutputFlags::TTS:
+        case AudioOutputFlags::TTS:
             return AUDIO_OUTPUT_FLAG_TTS;
-        case media::AudioOutputFlags::RAW:
+        case AudioOutputFlags::RAW:
             return AUDIO_OUTPUT_FLAG_RAW;
-        case media::AudioOutputFlags::SYNC:
+        case AudioOutputFlags::SYNC:
             return AUDIO_OUTPUT_FLAG_SYNC;
-        case media::AudioOutputFlags::IEC958_NONAUDIO:
+        case AudioOutputFlags::IEC958_NONAUDIO:
             return AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
-        case media::AudioOutputFlags::DIRECT_PCM:
+        case AudioOutputFlags::DIRECT_PCM:
             return AUDIO_OUTPUT_FLAG_DIRECT_PCM;
-        case media::AudioOutputFlags::MMAP_NOIRQ:
+        case AudioOutputFlags::MMAP_NOIRQ:
             return AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
-        case media::AudioOutputFlags::VOIP_RX:
+        case AudioOutputFlags::VOIP_RX:
             return AUDIO_OUTPUT_FLAG_VOIP_RX;
-        case media::AudioOutputFlags::INCALL_MUSIC:
+        case AudioOutputFlags::INCALL_MUSIC:
             return AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
-        case media::AudioOutputFlags::GAPLESS_OFFLOAD:
+        case AudioOutputFlags::GAPLESS_OFFLOAD:
             return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
     }
     return unexpected(BAD_VALUE);
 }
 
-ConversionResult<media::AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
+ConversionResult<AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
         audio_output_flags_t legacy) {
     switch (legacy) {
         case AUDIO_OUTPUT_FLAG_NONE:
             break; // shouldn't get here. must be listed  -Werror,-Wswitch
         case AUDIO_OUTPUT_FLAG_DIRECT:
-            return media::AudioOutputFlags::DIRECT;
+            return AudioOutputFlags::DIRECT;
         case AUDIO_OUTPUT_FLAG_PRIMARY:
-            return media::AudioOutputFlags::PRIMARY;
+            return AudioOutputFlags::PRIMARY;
         case AUDIO_OUTPUT_FLAG_FAST:
-            return media::AudioOutputFlags::FAST;
+            return AudioOutputFlags::FAST;
         case AUDIO_OUTPUT_FLAG_DEEP_BUFFER:
-            return media::AudioOutputFlags::DEEP_BUFFER;
+            return AudioOutputFlags::DEEP_BUFFER;
         case AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD:
-            return media::AudioOutputFlags::COMPRESS_OFFLOAD;
+            return AudioOutputFlags::COMPRESS_OFFLOAD;
         case AUDIO_OUTPUT_FLAG_NON_BLOCKING:
-            return media::AudioOutputFlags::NON_BLOCKING;
+            return AudioOutputFlags::NON_BLOCKING;
         case AUDIO_OUTPUT_FLAG_HW_AV_SYNC:
-            return media::AudioOutputFlags::HW_AV_SYNC;
+            return AudioOutputFlags::HW_AV_SYNC;
         case AUDIO_OUTPUT_FLAG_TTS:
-            return media::AudioOutputFlags::TTS;
+            return AudioOutputFlags::TTS;
         case AUDIO_OUTPUT_FLAG_RAW:
-            return media::AudioOutputFlags::RAW;
+            return AudioOutputFlags::RAW;
         case AUDIO_OUTPUT_FLAG_SYNC:
-            return media::AudioOutputFlags::SYNC;
+            return AudioOutputFlags::SYNC;
         case AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO:
-            return media::AudioOutputFlags::IEC958_NONAUDIO;
+            return AudioOutputFlags::IEC958_NONAUDIO;
         case AUDIO_OUTPUT_FLAG_DIRECT_PCM:
-            return media::AudioOutputFlags::DIRECT_PCM;
+            return AudioOutputFlags::DIRECT_PCM;
         case AUDIO_OUTPUT_FLAG_MMAP_NOIRQ:
-            return media::AudioOutputFlags::MMAP_NOIRQ;
+            return AudioOutputFlags::MMAP_NOIRQ;
         case AUDIO_OUTPUT_FLAG_VOIP_RX:
-            return media::AudioOutputFlags::VOIP_RX;
+            return AudioOutputFlags::VOIP_RX;
         case AUDIO_OUTPUT_FLAG_INCALL_MUSIC:
-            return media::AudioOutputFlags::INCALL_MUSIC;
+            return AudioOutputFlags::INCALL_MUSIC;
         case AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD:
-            return media::AudioOutputFlags::GAPLESS_OFFLOAD;
+            return AudioOutputFlags::GAPLESS_OFFLOAD;
     }
     return unexpected(BAD_VALUE);
 }
@@ -1413,9 +1417,9 @@
     using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
 
     LegacyMask converted = VALUE_OR_RETURN(
-            (convertBitmask<LegacyMask, int32_t, audio_input_flags_t, media::AudioInputFlags>(
+            (convertBitmask<LegacyMask, int32_t, audio_input_flags_t, AudioInputFlags>(
                     aidl, aidl2legacy_AudioInputFlags_audio_input_flags_t,
-                    indexToEnum_index<media::AudioInputFlags>,
+                    indexToEnum_index<AudioInputFlags>,
                     enumToMask_bitmask<LegacyMask, audio_input_flags_t>)));
     return static_cast<audio_input_flags_t>(converted);
 }
@@ -1425,10 +1429,10 @@
     using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
 
     LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
-    return convertBitmask<int32_t, LegacyMask, media::AudioInputFlags, audio_input_flags_t>(
+    return convertBitmask<int32_t, LegacyMask, AudioInputFlags, audio_input_flags_t>(
             legacyMask, legacy2aidl_audio_input_flags_t_AudioInputFlags,
             indexToEnum_bitmask<audio_input_flags_t>,
-            enumToMask_index<int32_t, media::AudioInputFlags>);
+            enumToMask_index<int32_t, AudioInputFlags>);
 }
 
 ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
@@ -1436,9 +1440,9 @@
     return convertBitmask<audio_output_flags_t,
             int32_t,
             audio_output_flags_t,
-            media::AudioOutputFlags>(
+            AudioOutputFlags>(
             aidl, aidl2legacy_AudioOutputFlags_audio_output_flags_t,
-            indexToEnum_index<media::AudioOutputFlags>,
+            indexToEnum_index<AudioOutputFlags>,
             enumToMask_bitmask<audio_output_flags_t, audio_output_flags_t>);
 }
 
@@ -1447,14 +1451,14 @@
     using LegacyMask = std::underlying_type_t<audio_output_flags_t>;
 
     LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
-    return convertBitmask<int32_t, LegacyMask, media::AudioOutputFlags, audio_output_flags_t>(
+    return convertBitmask<int32_t, LegacyMask, AudioOutputFlags, audio_output_flags_t>(
             legacyMask, legacy2aidl_audio_output_flags_t_AudioOutputFlags,
             indexToEnum_bitmask<audio_output_flags_t>,
-            enumToMask_index<int32_t, media::AudioOutputFlags>);
+            enumToMask_index<int32_t, AudioOutputFlags>);
 }
 
 ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
-        const media::AudioIoFlags& aidl, media::AudioPortRole role, media::AudioPortType type) {
+        const AudioIoFlags& aidl, media::AudioPortRole role, media::AudioPortType type) {
     audio_io_flags legacy;
     Direction dir = VALUE_OR_RETURN(direction(role, type));
     switch (dir) {
@@ -1476,9 +1480,9 @@
     return legacy;
 }
 
-ConversionResult<media::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
+ConversionResult<AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
         const audio_io_flags& legacy, audio_port_role_t role, audio_port_type_t type) {
-    media::AudioIoFlags aidl;
+    AudioIoFlags aidl;
 
     Direction dir = VALUE_OR_RETURN(direction(role, type));
     switch (dir) {
@@ -1497,21 +1501,22 @@
 }
 
 ConversionResult<audio_port_config_device_ext>
-aidl2legacy_AudioDevice_audio_port_config_device_ext(
-        const AudioDevice& aidl, const media::AudioPortDeviceExtSys& aidlDeviceExt) {
+aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
+        const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlDeviceExt) {
     audio_port_config_device_ext legacy;
     legacy.hw_module = VALUE_OR_RETURN(
             aidl2legacy_int32_t_audio_module_handle_t(aidlDeviceExt.hwModule));
-    RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(aidl, &legacy.type, legacy.address));
+    RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+                    aidl.device, &legacy.type, legacy.address));
     return legacy;
 }
 
-status_t legacy2aidl_audio_port_config_device_ext_AudioDevice(
+status_t legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
         const audio_port_config_device_ext& legacy,
-        AudioDevice* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
+        AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
     aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
-    *aidl = VALUE_OR_RETURN_STATUS(
+    aidl->device = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
     return OK;
 }
@@ -1777,7 +1782,7 @@
             return legacy;
         case media::AudioPortType::DEVICE:
             legacy.device = VALUE_OR_RETURN(
-                    aidl2legacy_AudioDevice_audio_port_config_device_ext(
+                    aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
                             VALUE_OR_RETURN(UNION_GET(aidl, device)),
                             VALUE_OR_RETURN(UNION_GET(aidlSys, device))));
             return legacy;
@@ -1806,10 +1811,10 @@
             UNION_SET(*aidlSys, unspecified, false);
             return OK;
         case AUDIO_PORT_TYPE_DEVICE: {
-            AudioDevice device;
+            AudioPortDeviceExt device;
             media::AudioPortDeviceExtSys deviceSys;
             RETURN_STATUS_IF_ERROR(
-                    legacy2aidl_audio_port_config_device_ext_AudioDevice(
+                    legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
                             legacy.device, &device, &deviceSys));
             UNION_SET(*aidl, device, device);
             UNION_SET(*aidlSys, device, deviceSys);
@@ -1862,10 +1867,10 @@
                         aidl.hal.gain.value(), isInput));
         legacy.config_mask |= AUDIO_PORT_CONFIG_GAIN;
     }
-    if (aidl.sys.flags.has_value()) {
+    if (aidl.hal.flags.has_value()) {
         legacy.flags = VALUE_OR_RETURN(
                 aidl2legacy_AudioIoFlags_audio_io_flags(
-                        aidl.sys.flags.value(), aidl.sys.role, aidl.sys.type));
+                        aidl.hal.flags.value(), aidl.sys.role, aidl.sys.type));
         legacy.config_mask |= AUDIO_PORT_CONFIG_FLAGS;
     }
     legacy.ext = VALUE_OR_RETURN(
@@ -1900,7 +1905,7 @@
                 legacy2aidl_audio_gain_config_AudioGainConfig(legacy.gain, isInput));
     }
     if (legacy.config_mask & AUDIO_PORT_CONFIG_FLAGS) {
-        aidl.sys.flags = VALUE_OR_RETURN(
+        aidl.hal.flags = VALUE_OR_RETURN(
                 legacy2aidl_audio_io_flags_AudioIoFlags(legacy.flags, legacy.role, legacy.type));
     }
     RETURN_IF_ERROR(legacy2aidl_AudioPortExt(legacy.ext, legacy.type, legacy.role,
@@ -2581,12 +2586,13 @@
 }
 
 ConversionResult<audio_port_device_ext>
-aidl2legacy_AudioDevice_audio_port_device_ext(
-        const AudioDevice& aidl, const media::AudioPortDeviceExtSys& aidlSys) {
+aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
+        const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlSys) {
     audio_port_device_ext legacy;
     legacy.hw_module = VALUE_OR_RETURN(
             aidl2legacy_int32_t_audio_module_handle_t(aidlSys.hwModule));
-    RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(aidl, &legacy.type, legacy.address));
+    RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+                    aidl.device, &legacy.type, legacy.address));
     legacy.encapsulation_modes = VALUE_OR_RETURN(
             aidl2legacy_AudioEncapsulationMode_mask(aidlSys.encapsulationModes));
     legacy.encapsulation_metadata_types = VALUE_OR_RETURN(
@@ -2595,12 +2601,12 @@
     return legacy;
 }
 
-status_t legacy2aidl_audio_port_device_ext_AudioDevice(
+status_t legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
         const audio_port_device_ext& legacy,
-        AudioDevice* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
+        AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
     aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
-    *aidl = VALUE_OR_RETURN_STATUS(
+    aidl->device = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
     aidlDeviceExt->encapsulationModes = VALUE_OR_RETURN_STATUS(
             legacy2aidl_AudioEncapsulationMode_mask(legacy.encapsulation_modes));
@@ -2653,7 +2659,7 @@
             return legacy;
         case media::AudioPortType::DEVICE:
             legacy.device = VALUE_OR_RETURN(
-                    aidl2legacy_AudioDevice_audio_port_device_ext(
+                    aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
                             VALUE_OR_RETURN(UNION_GET(aidl, device)),
                             VALUE_OR_RETURN(UNION_GET(aidlSys, device))));
             return legacy;
@@ -2682,10 +2688,10 @@
             UNION_SET(*aidlSys, unspecified, false);
             return OK;
         case AUDIO_PORT_TYPE_DEVICE: {
-            AudioDevice device;
+            AudioPortDeviceExt device;
             media::AudioPortDeviceExtSys deviceSys;
             RETURN_STATUS_IF_ERROR(
-                    legacy2aidl_audio_port_device_ext_AudioDevice(
+                    legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
                             legacy.device, &device, &deviceSys));
             UNION_SET(*aidl, device, device);
             UNION_SET(*aidlSys, device, deviceSys);
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index f6446bb..d63a002 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -138,6 +138,7 @@
         "libshmemcompat",
         "libutils",
         "framework-permission-aidl-cpp",
+        "packagemanager_aidl-cpp",
     ],
     export_shared_lib_headers: [
         "audioflinger-aidl-cpp",
@@ -315,11 +316,8 @@
         "aidl/android/media/AudioDualMonoMode.aidl",
         "aidl/android/media/AudioFlag.aidl",
         "aidl/android/media/AudioGainSys.aidl",
-        "aidl/android/media/AudioInputFlags.aidl",
         "aidl/android/media/AudioIoConfigEvent.aidl",
         "aidl/android/media/AudioIoDescriptor.aidl",
-        "aidl/android/media/AudioIoFlags.aidl",
-        "aidl/android/media/AudioOutputFlags.aidl",
         "aidl/android/media/AudioPatch.aidl",
         "aidl/android/media/AudioPlaybackRate.aidl",
         "aidl/android/media/AudioPort.aidl",
diff --git a/media/libaudioclient/aidl/android/media/AudioGainSys.aidl b/media/libaudioclient/aidl/android/media/AudioGainSys.aidl
index 9ec8390..426f4ed 100644
--- a/media/libaudioclient/aidl/android/media/AudioGainSys.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioGainSys.aidl
@@ -24,5 +24,4 @@
 parcelable AudioGainSys {
     int index;
     boolean isInput;
-    boolean useForVolume;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioInputFlags.aidl b/media/libaudioclient/aidl/android/media/AudioInputFlags.aidl
deleted file mode 100644
index bfc0eb0..0000000
--- a/media/libaudioclient/aidl/android/media/AudioInputFlags.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-/**
- * {@hide}
- */
-@Backing(type="int")
-enum AudioInputFlags {
-    FAST       = 0,
-    HW_HOTWORD = 1,
-    RAW        = 2,
-    SYNC       = 3,
-    MMAP_NOIRQ = 4,
-    VOIP_TX    = 5,
-    HW_AV_SYNC = 6,
-    DIRECT     = 7,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioIoFlags.aidl b/media/libaudioclient/aidl/android/media/AudioIoFlags.aidl
deleted file mode 100644
index f9b25bf..0000000
--- a/media/libaudioclient/aidl/android/media/AudioIoFlags.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/**
- * {@hide}
- */
-union AudioIoFlags {
-    /** Bitmask indexed by AudioInputFlags. */
-    int input;
-    /** Bitmask indexed by AudioOutputFlags. */
-    int output;
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl b/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl
deleted file mode 100644
index cebd8f0..0000000
--- a/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-/**
- * {@hide}
- */
-@Backing(type="int")
-enum AudioOutputFlags {
-    DIRECT           = 0,
-    PRIMARY          = 1,
-    FAST             = 2,
-    DEEP_BUFFER      = 3,
-    COMPRESS_OFFLOAD = 4,
-    NON_BLOCKING     = 5,
-    HW_AV_SYNC       = 6,
-    TTS              = 7,
-    RAW              = 8,
-    SYNC             = 9,
-    IEC958_NONAUDIO  = 10,
-    DIRECT_PCM       = 11,
-    MMAP_NOIRQ       = 12,
-    VOIP_RX          = 13,
-    INCALL_MUSIC     = 14,
-    GAPLESS_OFFLOAD  = 15,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioPortConfigSys.aidl b/media/libaudioclient/aidl/android/media/AudioPortConfigSys.aidl
index 6a615cd..8692848 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortConfigSys.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortConfigSys.aidl
@@ -16,7 +16,6 @@
 
 package android.media;
 
-import android.media.AudioIoFlags;
 import android.media.AudioPortExtSys;
 import android.media.AudioPortRole;
 import android.media.AudioPortType;
@@ -29,7 +28,5 @@
     AudioPortRole role;
     /** Device, mix ... */
     AudioPortType type;
-    /** Flags: HW_AV_SYNC, DIRECT, ... Can be left unspecified. */
-    @nullable AudioIoFlags flags;
     AudioPortExtSys ext;
 }
diff --git a/media/libaudioclient/aidl/android/media/INativeSpatializerCallback.aidl b/media/libaudioclient/aidl/android/media/INativeSpatializerCallback.aidl
index 0e9634c..88b8108 100644
--- a/media/libaudioclient/aidl/android/media/INativeSpatializerCallback.aidl
+++ b/media/libaudioclient/aidl/android/media/INativeSpatializerCallback.aidl
@@ -31,4 +31,9 @@
      * (e.g. when the spatializer is enabled or disabled)
      */
     void onLevelChanged(SpatializationLevel level);
+
+    /** Called when the output stream the Spatializer is attached to changes.
+     * Indicates the IO Handle of the new output.
+     */
+    void onOutputChanged(int output);
 }
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 52ea91b..fda9efb 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -25,10 +25,8 @@
 #include <android/media/AudioClient.h>
 #include <android/media/AudioDualMonoMode.h>
 #include <android/media/AudioFlag.h>
-#include <android/media/AudioInputFlags.h>
 #include <android/media/AudioIoConfigEvent.h>
 #include <android/media/AudioIoDescriptor.h>
-#include <android/media/AudioOutputFlags.h>
 #include <android/media/AudioPlaybackRate.h>
 #include <android/media/AudioPort.h>
 #include <android/media/AudioPortConfig.h>
@@ -49,8 +47,10 @@
 #include <android/media/audio/common/AudioGain.h>
 #include <android/media/audio/common/AudioGainConfig.h>
 #include <android/media/audio/common/AudioGainMode.h>
+#include <android/media/audio/common/AudioInputFlags.h>
 #include <android/media/audio/common/AudioMode.h>
 #include <android/media/audio/common/AudioOffloadInfo.h>
+#include <android/media/audio/common/AudioOutputFlags.h>
 #include <android/media/audio/common/AudioPortExt.h>
 #include <android/media/audio/common/AudioPortMixExt.h>
 #include <android/media/audio/common/AudioProfile.h>
@@ -173,15 +173,15 @@
 ConversionResult<media::audio::common::AudioGainConfig>
 legacy2aidl_audio_gain_config_AudioGainConfig(const audio_gain_config& legacy, bool isInput);
 
-ConversionResult<audio_input_flags_t> aidl2legacy_AudioInputFlags_audio_input_flags_t(
-        media::AudioInputFlags aidl);
-ConversionResult<media::AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
-        audio_input_flags_t legacy);
+ConversionResult<audio_input_flags_t>
+aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
+ConversionResult<media::audio::common::AudioInputFlags>
+legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
 
-ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
-        media::AudioOutputFlags aidl);
-ConversionResult<media::AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
-        audio_output_flags_t legacy);
+ConversionResult<audio_output_flags_t>
+aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
+ConversionResult<media::audio::common::AudioOutputFlags>
+legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
 
 ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
         int32_t aidl);
@@ -194,17 +194,19 @@
         audio_output_flags_t legacy);
 
 ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
-        const media::AudioIoFlags& aidl, media::AudioPortRole role, media::AudioPortType type);
-ConversionResult<media::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
+        const media::audio::common::AudioIoFlags& aidl,
+        media::AudioPortRole role, media::AudioPortType type);
+ConversionResult<media::audio::common::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
         const audio_io_flags& legacy, audio_port_role_t role, audio_port_type_t type);
 
 ConversionResult<audio_port_config_device_ext>
-aidl2legacy_AudioDevice_audio_port_config_device_ext(
-        const media::audio::common::AudioDevice& aidl,
+aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
+        const media::audio::common::AudioPortDeviceExt& aidl,
         const media::AudioPortDeviceExtSys& aidlDeviceExt);
-status_t legacy2aidl_audio_port_config_device_ext_AudioDevice(
+status_t legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
         const audio_port_config_device_ext& legacy,
-        media::audio::common::AudioDevice* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt);
+        media::audio::common::AudioPortDeviceExt* aidl,
+        media::AudioPortDeviceExtSys* aidlDeviceExt);
 
 ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
         media::audio::common::AudioStreamType aidl);
@@ -344,12 +346,12 @@
 legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy);
 
 ConversionResult<audio_port_device_ext>
-aidl2legacy_AudioDevice_audio_port_device_ext(
-        const media::audio::common::AudioDevice& aidl,
+aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
+        const media::audio::common::AudioPortDeviceExt& aidl,
         const media::AudioPortDeviceExtSys& aidlDeviceExt);
-status_t legacy2aidl_audio_port_device_ext_AudioDevice(
+status_t legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
         const audio_port_device_ext& legacy,
-        media::audio::common::AudioDevice* aidl,
+        media::audio::common::AudioPortDeviceExt* aidl,
         media::AudioPortDeviceExtSys* aidlDeviceExt);
 
 ConversionResult<audio_port_mix_ext>
diff --git a/media/libaudiofoundation/AudioGain.cpp b/media/libaudiofoundation/AudioGain.cpp
index 1a8fbf0..47e0edb 100644
--- a/media/libaudiofoundation/AudioGain.cpp
+++ b/media/libaudiofoundation/AudioGain.cpp
@@ -122,20 +122,20 @@
 ConversionResult<AudioGain::Aidl> AudioGain::toParcelable() const {
     media::audio::common::AudioGain aidl = VALUE_OR_RETURN(
             legacy2aidl_audio_gain_AudioGain(mGain, mIsInput));
+    aidl.useForVolume = mUseForVolume;
     media::AudioGainSys aidlSys;
     aidlSys.index = VALUE_OR_RETURN(convertIntegral<int32_t>(mIndex));
     aidlSys.isInput = mIsInput;
-    aidlSys.useForVolume = mUseForVolume;
     return std::make_pair(aidl, aidlSys);
 }
 
 ConversionResult<sp<AudioGain>> AudioGain::fromParcelable(const AudioGain::Aidl& aidl) {
+    const media::audio::common::AudioGain& hal = aidl.first;
     const media::AudioGainSys& sys = aidl.second;
     auto index = VALUE_OR_RETURN(convertIntegral<int>(sys.index));
     sp<AudioGain> legacy = sp<AudioGain>::make(index, sys.isInput);
-    legacy->mGain = VALUE_OR_RETURN(
-            aidl2legacy_AudioGain_audio_gain(aidl.first, sys.isInput));
-    legacy->mUseForVolume = sys.useForVolume;
+    legacy->mGain = VALUE_OR_RETURN(aidl2legacy_AudioGain_audio_gain(hal, sys.isInput));
+    legacy->mUseForVolume = hal.useForVolume;
     return legacy;
 }
 
diff --git a/media/libaudiofoundation/AudioPort.cpp b/media/libaudiofoundation/AudioPort.cpp
index 099aff4..a00e00d 100644
--- a/media/libaudiofoundation/AudioPort.cpp
+++ b/media/libaudiofoundation/AudioPort.cpp
@@ -219,6 +219,14 @@
     auto aidlGains = VALUE_OR_RETURN_STATUS(legacy2aidl_AudioGains(mGains));
     parcelable->hal.gains = aidlGains.first;
     parcelable->sys.gains = aidlGains.second;
+    if (mType == AUDIO_PORT_TYPE_MIX) {
+        media::audio::common::AudioPortMixExt mixExt{};
+        mixExt.maxOpenStreamCount = maxOpenCount;
+        mixExt.maxActiveStreamCount = maxActiveCount;
+        mixExt.recommendedMuteDurationMs = recommendedMuteDurationMs;
+        parcelable->hal.ext = media::audio::common::AudioPortExt::make<
+                media::audio::common::AudioPortExt::mix>(mixExt);
+    }
     return OK;
 }
 
@@ -241,6 +249,13 @@
     mExtraAudioDescriptors = parcelable.hal.extraAudioDescriptors;
     mGains = VALUE_OR_RETURN_STATUS(
             aidl2legacy_AudioGains(std::make_pair(parcelable.hal.gains, parcelable.sys.gains)));
+    if (mType == AUDIO_PORT_TYPE_MIX) {
+        const media::audio::common::AudioPortMixExt& mixExt =
+                parcelable.hal.ext.get<media::audio::common::AudioPortExt::mix>();
+        maxOpenCount = mixExt.maxOpenStreamCount;
+        maxActiveCount = mixExt.maxActiveStreamCount;
+        recommendedMuteDurationMs = mixExt.recommendedMuteDurationMs;
+    }
     return OK;
 }
 
diff --git a/media/libaudiofoundation/DeviceDescriptorBase.cpp b/media/libaudiofoundation/DeviceDescriptorBase.cpp
index cf829b5..b383db4 100644
--- a/media/libaudiofoundation/DeviceDescriptorBase.cpp
+++ b/media/libaudiofoundation/DeviceDescriptorBase.cpp
@@ -30,16 +30,20 @@
 {
 }
 
-DeviceDescriptorBase::DeviceDescriptorBase(audio_devices_t type, const std::string& address) :
-        DeviceDescriptorBase(AudioDeviceTypeAddr(type, address))
+DeviceDescriptorBase::DeviceDescriptorBase(
+        audio_devices_t type, const std::string& address,
+        const FormatVector &encodedFormats) :
+        DeviceDescriptorBase(AudioDeviceTypeAddr(type, address), encodedFormats)
 {
 }
 
-DeviceDescriptorBase::DeviceDescriptorBase(const AudioDeviceTypeAddr &deviceTypeAddr) :
+DeviceDescriptorBase::DeviceDescriptorBase(
+        const AudioDeviceTypeAddr &deviceTypeAddr, const FormatVector &encodedFormats) :
         AudioPort("", AUDIO_PORT_TYPE_DEVICE,
                   audio_is_output_device(deviceTypeAddr.mType) ? AUDIO_PORT_ROLE_SINK :
                                          AUDIO_PORT_ROLE_SOURCE),
-        mDeviceTypeAddr(deviceTypeAddr)
+        mDeviceTypeAddr(deviceTypeAddr),
+        mEncodedFormats(encodedFormats)
 {
     if (mDeviceTypeAddr.address().empty() && audio_is_remote_submix_device(mDeviceTypeAddr.mType)) {
         mDeviceTypeAddr.setAddress("0");
@@ -148,12 +152,35 @@
     AudioPort::log("  ");
 }
 
+template<typename T>
+bool checkEqual(const T& f1, const T& f2)
+{
+    std::set<typename T::value_type> s1(f1.begin(), f1.end());
+    std::set<typename T::value_type> s2(f2.begin(), f2.end());
+    return s1 == s2;
+}
+
 bool DeviceDescriptorBase::equals(const sp<DeviceDescriptorBase> &other) const
 {
     return other != nullptr &&
            static_cast<const AudioPort*>(this)->equals(other) &&
            static_cast<const AudioPortConfig*>(this)->equals(other) &&
-           mDeviceTypeAddr.equals(other->mDeviceTypeAddr);
+           mDeviceTypeAddr.equals(other->mDeviceTypeAddr) &&
+           checkEqual(mEncodedFormats, other->mEncodedFormats);
+}
+
+bool DeviceDescriptorBase::supportsFormat(audio_format_t format)
+{
+    if (mEncodedFormats.empty()) {
+        return true;
+    }
+
+    for (const auto& devFormat : mEncodedFormats) {
+        if (devFormat == format) {
+            return true;
+        }
+    }
+    return false;
 }
 
 
@@ -169,9 +196,13 @@
     AudioPortConfig::writeToParcelable(&parcelable->hal.activeConfig, useInputChannelMask());
     parcelable->hal.id = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(mId));
 
-    media::audio::common::AudioDevice device = VALUE_OR_RETURN_STATUS(
+    media::audio::common::AudioPortDeviceExt deviceExt;
+    deviceExt.device = VALUE_OR_RETURN_STATUS(
             legacy2aidl_AudioDeviceTypeAddress(mDeviceTypeAddr));
-    UNION_SET(parcelable->hal.ext, device, device);
+    deviceExt.encodedFormats = VALUE_OR_RETURN_STATUS(
+            convertContainer<std::vector<media::audio::common::AudioFormatDescription>>(
+                    mEncodedFormats, legacy2aidl_audio_format_t_AudioFormatDescription));
+    UNION_SET(parcelable->hal.ext, device, deviceExt);
     media::AudioPortDeviceExtSys deviceSys;
     deviceSys.encapsulationModes = VALUE_OR_RETURN_STATUS(
             legacy2aidl_AudioEncapsulationMode_mask(mEncapsulationModes));
@@ -198,10 +229,13 @@
         return status;
     }
 
-    media::audio::common::AudioDevice device = VALUE_OR_RETURN_STATUS(
+    media::audio::common::AudioPortDeviceExt deviceExt = VALUE_OR_RETURN_STATUS(
             UNION_GET(parcelable.hal.ext, device));
     mDeviceTypeAddr = VALUE_OR_RETURN_STATUS(
-            aidl2legacy_AudioDeviceTypeAddress(device));
+            aidl2legacy_AudioDeviceTypeAddress(deviceExt.device));
+    mEncodedFormats = VALUE_OR_RETURN_STATUS(
+            convertContainer<FormatVector>(deviceExt.encodedFormats,
+                    aidl2legacy_AudioFormatDescription_audio_format_t));
     media::AudioPortDeviceExtSys deviceSys = VALUE_OR_RETURN_STATUS(
             UNION_GET(parcelable.sys.ext, device));
     mEncapsulationModes = VALUE_OR_RETURN_STATUS(
diff --git a/media/libaudiofoundation/include/media/AudioPort.h b/media/libaudiofoundation/include/media/AudioPort.h
index aa9b5f6..b5a17c9 100644
--- a/media/libaudiofoundation/include/media/AudioPort.h
+++ b/media/libaudiofoundation/include/media/AudioPort.h
@@ -106,6 +106,21 @@
     status_t readFromParcelable(const media::AudioPort& parcelable);
 
     AudioGains mGains; // gain controllers
+    // Maximum number of input or output streams that can be simultaneously
+    // opened for this profile. By convention 0 means no limit. To respect
+    // legacy behavior, initialized to 1 for output profiles and 0 for input
+    // profiles
+    // FIXME: IOProfile code used the same value for both cases.
+    uint32_t maxOpenCount = 1;
+    // Maximum number of input or output streams that can be simultaneously
+    // active for this profile. By convention 0 means no limit. To respect
+    // legacy behavior, initialized to 0 for output profiles and 1 for input
+    // profiles
+    // FIXME: IOProfile code used the same value for both cases.
+    uint32_t maxActiveCount = 1;
+    // Mute duration while changing device on this output profile.
+    uint32_t recommendedMuteDurationMs = 0;
+
 protected:
     std::string  mName;
     audio_port_type_t mType;
diff --git a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
index 140ce36..a4092eb 100644
--- a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
+++ b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
@@ -36,16 +36,21 @@
 public:
      // Note that empty name refers by convention to a generic device.
     explicit DeviceDescriptorBase(audio_devices_t type);
-    DeviceDescriptorBase(audio_devices_t type, const std::string& address);
-    explicit DeviceDescriptorBase(const AudioDeviceTypeAddr& deviceTypeAddr);
+    DeviceDescriptorBase(audio_devices_t type, const std::string& address,
+            const FormatVector &encodedFormats = FormatVector{});
+    DeviceDescriptorBase(const AudioDeviceTypeAddr& deviceTypeAddr,
+            const FormatVector &encodedFormats = FormatVector{});
 
-    virtual ~DeviceDescriptorBase() {}
+    virtual ~DeviceDescriptorBase() = default;
 
     audio_devices_t type() const { return mDeviceTypeAddr.mType; }
     const std::string& address() const { return mDeviceTypeAddr.address(); }
     void setAddress(const std::string &address);
     const AudioDeviceTypeAddr& getDeviceTypeAddr() const { return mDeviceTypeAddr; }
 
+    const FormatVector& encodedFormats() const { return mEncodedFormats; }
+    bool supportsFormat(audio_format_t format);
+
     // AudioPortConfig
     virtual sp<AudioPort> getAudioPort() const {
         return static_cast<AudioPort*>(const_cast<DeviceDescriptorBase*>(this));
@@ -82,6 +87,7 @@
 
 protected:
     AudioDeviceTypeAddr mDeviceTypeAddr;
+    FormatVector        mEncodedFormats;
     uint32_t mEncapsulationModes = 0;
     uint32_t mEncapsulationMetadataTypes = 0;
 private:
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index e68c002..e6fdb1d 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -108,15 +108,11 @@
 
     if (track->mHapticChannelCount > 0) {
         track->mAdjustInChannelCount = track->channelCount + track->mHapticChannelCount;
-        track->mAdjustOutChannelCount = track->channelCount + track->mMixerHapticChannelCount;
-        track->mAdjustNonDestructiveInChannelCount = track->mAdjustOutChannelCount;
-        track->mAdjustNonDestructiveOutChannelCount = track->channelCount;
+        track->mAdjustOutChannelCount = track->channelCount;
         track->mKeepContractedChannels = track->mHapticPlaybackEnabled;
     } else {
         track->mAdjustInChannelCount = 0;
         track->mAdjustOutChannelCount = 0;
-        track->mAdjustNonDestructiveInChannelCount = 0;
-        track->mAdjustNonDestructiveOutChannelCount = 0;
         track->mKeepContractedChannels = false;
     }
 
@@ -131,8 +127,7 @@
     // do it after downmix since track format may change!
     track->prepareForReformat();
 
-    track->prepareForAdjustChannelsNonDestructive(mFrameCount);
-    track->prepareForAdjustChannels();
+    track->prepareForAdjustChannels(mFrameCount);
 
     // Resampler channels may have changed.
     track->recreateResampler(mSampleRate);
@@ -193,6 +188,24 @@
         // mDownmixerBufferProvider reset below.
     }
 
+    // See if we should use our built-in non-effect downmixer.
+    if (mMixerInFormat == AUDIO_FORMAT_PCM_FLOAT
+            && mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO
+            && audio_channel_mask_get_representation(channelMask)
+                    == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
+        mDownmixerBufferProvider.reset(new ChannelMixBufferProvider(channelMask,
+                mMixerChannelMask, mMixerInFormat, kCopyBufferFrameCount));
+        if (static_cast<ChannelMixBufferProvider *>(mDownmixerBufferProvider.get())
+                ->isValid()) {
+            mDownmixRequiresFormat = mMixerInFormat;
+            reconfigureBufferProviders();
+            ALOGD("%s: Fallback using ChannelMix", __func__);
+            return NO_ERROR;
+        } else {
+            ALOGD("%s: ChannelMix not supported for channel mask %#x", __func__, channelMask);
+        }
+    }
+
     // Effect downmixer does not accept the channel conversion.  Let's use our remixer.
     mDownmixerBufferProvider.reset(new RemixBufferProvider(channelMask,
             mMixerChannelMask, mMixerInFormat, kCopyBufferFrameCount));
@@ -265,48 +278,20 @@
     }
 }
 
-status_t AudioMixer::Track::prepareForAdjustChannels()
+status_t AudioMixer::Track::prepareForAdjustChannels(size_t frames)
 {
     ALOGV("AudioMixer::prepareForAdjustChannels(%p) with inChannelCount: %u, outChannelCount: %u",
             this, mAdjustInChannelCount, mAdjustOutChannelCount);
     unprepareForAdjustChannels();
     if (mAdjustInChannelCount != mAdjustOutChannelCount) {
-        mAdjustChannelsBufferProvider.reset(new AdjustChannelsBufferProvider(
-                mFormat, mAdjustInChannelCount, mAdjustOutChannelCount, kCopyBufferFrameCount));
-        reconfigureBufferProviders();
-    }
-    return NO_ERROR;
-}
-
-void AudioMixer::Track::unprepareForAdjustChannelsNonDestructive()
-{
-    ALOGV("AUDIOMIXER::unprepareForAdjustChannelsNonDestructive");
-    if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
-        mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
-        reconfigureBufferProviders();
-    }
-}
-
-status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames)
-{
-    ALOGV("AudioMixer::prepareForAdjustChannelsNonDestructive(%p) with inChannelCount: %u, "
-          "outChannelCount: %u, keepContractedChannels: %d",
-            this, mAdjustNonDestructiveInChannelCount, mAdjustNonDestructiveOutChannelCount,
-            mKeepContractedChannels);
-    unprepareForAdjustChannelsNonDestructive();
-    if (mAdjustNonDestructiveInChannelCount != mAdjustNonDestructiveOutChannelCount) {
         uint8_t* buffer = mKeepContractedChannels
                 ? (uint8_t*)mainBuffer + frames * audio_bytes_per_frame(
                         mMixerChannelCount, mMixerFormat)
-                : NULL;
-        mContractChannelsNonDestructiveBufferProvider.reset(
-                new AdjustChannelsBufferProvider(
-                        mFormat,
-                        mAdjustNonDestructiveInChannelCount,
-                        mAdjustNonDestructiveOutChannelCount,
-                        frames,
-                        mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
-                        buffer));
+                : nullptr;
+        mAdjustChannelsBufferProvider.reset(new AdjustChannelsBufferProvider(
+                mFormat, mAdjustInChannelCount, mAdjustOutChannelCount, frames,
+                mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
+                buffer, mMixerHapticChannelCount));
         reconfigureBufferProviders();
     }
     return NO_ERROR;
@@ -314,9 +299,9 @@
 
 void AudioMixer::Track::clearContractedBuffer()
 {
-    if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
+    if (mAdjustChannelsBufferProvider.get() != nullptr) {
         static_cast<AdjustChannelsBufferProvider*>(
-                mContractChannelsNonDestructiveBufferProvider.get())->clearContractedFrames();
+                mAdjustChannelsBufferProvider.get())->clearContractedFrames();
     }
 }
 
@@ -328,10 +313,6 @@
         mAdjustChannelsBufferProvider->setBufferProvider(bufferProvider);
         bufferProvider = mAdjustChannelsBufferProvider.get();
     }
-    if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
-        mContractChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider);
-        bufferProvider = mContractChannelsNonDestructiveBufferProvider.get();
-    }
     if (mReformatBufferProvider.get() != nullptr) {
         mReformatBufferProvider->setBufferProvider(bufferProvider);
         bufferProvider = mReformatBufferProvider.get();
@@ -377,7 +358,7 @@
                 track->mainBuffer = valueBuf;
                 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
                 if (track->mKeepContractedChannels) {
-                    track->prepareForAdjustChannelsNonDestructive(mFrameCount);
+                    track->prepareForAdjustChannels(mFrameCount);
                 }
                 invalidate();
             }
@@ -405,7 +386,7 @@
                 track->mMixerFormat = format;
                 ALOGV("setParameter(TRACK, MIXER_FORMAT, %#x)", format);
                 if (track->mKeepContractedChannels) {
-                    track->prepareForAdjustChannelsNonDestructive(mFrameCount);
+                    track->prepareForAdjustChannels(mFrameCount);
                 }
             }
             } break;
@@ -424,8 +405,7 @@
             if (track->mHapticPlaybackEnabled != hapticPlaybackEnabled) {
                 track->mHapticPlaybackEnabled = hapticPlaybackEnabled;
                 track->mKeepContractedChannels = hapticPlaybackEnabled;
-                track->prepareForAdjustChannelsNonDestructive(mFrameCount);
-                track->prepareForAdjustChannels();
+                track->prepareForAdjustChannels(mFrameCount);
             }
             } break;
         case HAPTIC_INTENSITY: {
@@ -518,8 +498,6 @@
         track->mDownmixerBufferProvider->reset();
     } else if (track->mReformatBufferProvider.get() != nullptr) {
         track->mReformatBufferProvider->reset();
-    } else if (track->mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
-        track->mContractChannelsNonDestructiveBufferProvider->reset();
     } else if (track->mAdjustChannelsBufferProvider.get() != nullptr) {
         track->mAdjustChannelsBufferProvider->reset();
     }
@@ -563,9 +541,7 @@
     t->mMixerHapticChannelMask = AUDIO_CHANNEL_NONE;
     t->mMixerHapticChannelCount = 0;
     t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount;
-    t->mAdjustOutChannelCount = t->channelCount + t->mMixerHapticChannelCount;
-    t->mAdjustNonDestructiveInChannelCount = t->mAdjustOutChannelCount;
-    t->mAdjustNonDestructiveOutChannelCount = t->channelCount;
+    t->mAdjustOutChannelCount = t->channelCount;
     t->mKeepContractedChannels = false;
     // Check the downmixing (or upmixing) requirements.
     status_t status = t->prepareForDownmix();
@@ -576,8 +552,7 @@
     // prepareForDownmix() may change mDownmixRequiresFormat
     ALOGVV("mMixerFormat:%#x  mMixerInFormat:%#x\n", t->mMixerFormat, t->mMixerInFormat);
     t->prepareForReformat();
-    t->prepareForAdjustChannelsNonDestructive(mFrameCount);
-    t->prepareForAdjustChannels();
+    t->prepareForAdjustChannels(mFrameCount);
     return OK;
 }
 
diff --git a/media/libaudioprocessing/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
index 6d31c12..4658db8 100644
--- a/media/libaudioprocessing/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -364,6 +364,29 @@
             src, mInputChannels, mIdxAry, mSampleSize, frames);
 }
 
+ChannelMixBufferProvider::ChannelMixBufferProvider(audio_channel_mask_t inputChannelMask,
+        audio_channel_mask_t outputChannelMask, audio_format_t format,
+        size_t bufferFrameCount) :
+        CopyBufferProvider(
+                audio_bytes_per_sample(format)
+                    * audio_channel_count_from_out_mask(inputChannelMask),
+                audio_bytes_per_sample(format)
+                    * audio_channel_count_from_out_mask(outputChannelMask),
+                bufferFrameCount)
+{
+    ALOGV("ChannelMixBufferProvider(%p)(%#x, %#x, %#x)",
+            this, format, inputChannelMask, outputChannelMask);
+    if (outputChannelMask == AUDIO_CHANNEL_OUT_STEREO && format == AUDIO_FORMAT_PCM_FLOAT) {
+        mIsValid = mChannelMix.setInputChannelMask(inputChannelMask);
+    }
+}
+
+void ChannelMixBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
+{
+    mChannelMix.process(static_cast<const float *>(src), static_cast<float *>(dst),
+            frames, false /* accumulate */);
+}
+
 ReformatBufferProvider::ReformatBufferProvider(int32_t channelCount,
         audio_format_t inputFormat, audio_format_t outputFormat,
         size_t bufferFrameCount) :
@@ -630,7 +653,8 @@
 
 AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(
         audio_format_t format, size_t inChannelCount, size_t outChannelCount,
-        size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer) :
+        size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer,
+        size_t contractedOutChannelCount) :
         CopyBufferProvider(
                 audio_bytes_per_frame(inChannelCount, format),
                 audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
@@ -640,15 +664,22 @@
         mOutChannelCount(outChannelCount),
         mSampleSizeInBytes(audio_bytes_per_sample(format)),
         mFrameCount(frameCount),
-        mContractedChannelCount(inChannelCount - outChannelCount),
-        mContractedFormat(contractedFormat),
+        mContractedFormat(inChannelCount > outChannelCount
+                ? contractedFormat : AUDIO_FORMAT_INVALID),
+        mContractedInChannelCount(inChannelCount > outChannelCount
+                ? inChannelCount - outChannelCount : 0),
+        mContractedOutChannelCount(contractedOutChannelCount),
+        mContractedSampleSizeInBytes(audio_bytes_per_sample(contractedFormat)),
+        mContractedInputFrameSize(mContractedInChannelCount * mContractedSampleSizeInBytes),
         mContractedBuffer(contractedBuffer),
         mContractedWrittenFrames(0)
 {
-    ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p)", this, format,
-            inChannelCount, outChannelCount, frameCount, contractedFormat, contractedBuffer);
+    ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p, %zu)",
+          this, format, inChannelCount, outChannelCount, frameCount, contractedFormat,
+          contractedBuffer, contractedOutChannelCount);
     if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) {
-        mContractedFrameSize = audio_bytes_per_frame(mContractedChannelCount, mContractedFormat);
+        mContractedOutputFrameSize =
+                audio_bytes_per_frame(mContractedOutChannelCount, mContractedFormat);
     }
 }
 
@@ -667,25 +698,39 @@
 
 void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
 {
-    if (mInChannelCount > mOutChannelCount) {
-        // For case multi to mono, adjust_channels has special logic that will mix first two input
-        // channels into a single output channel. In that case, use adjust_channels_non_destructive
-        // to keep only one channel data even when contracting to mono.
-        adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount,
-                mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
-        if (mContractedFormat != AUDIO_FORMAT_INVALID
-            && mContractedBuffer != nullptr) {
-            const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
+    // For case multi to mono, adjust_channels has special logic that will mix first two input
+    // channels into a single output channel. In that case, use adjust_channels_non_destructive
+    // to keep only one channel data even when contracting to mono.
+    adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount,
+            mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
+    if (mContractedFormat != AUDIO_FORMAT_INVALID
+        && mContractedBuffer != nullptr) {
+        const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
+        uint8_t* oriBuf = (uint8_t*) dst + contractedIdx;
+        uint8_t* buf = (uint8_t*) mContractedBuffer
+                + mContractedWrittenFrames * mContractedOutputFrameSize;
+        if (mContractedInChannelCount > mContractedOutChannelCount) {
+            // Adjust the channels first as the contracted buffer may not have enough
+            // space for the data.
+            // Use adjust_channels_non_destructive to avoid mix first two channels into one single
+            // output channel when it is multi to mono.
+            adjust_channels_non_destructive(
+                    oriBuf, mContractedInChannelCount, oriBuf, mContractedOutChannelCount,
+                    mSampleSizeInBytes, frames * mContractedInChannelCount * mSampleSizeInBytes);
             memcpy_by_audio_format(
-                    (uint8_t*) mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
-                    mContractedFormat, (uint8_t*) dst + contractedIdx, mFormat,
-                    mContractedChannelCount * frames);
-            mContractedWrittenFrames += frames;
+                    buf, mContractedFormat, oriBuf, mFormat, mContractedOutChannelCount * frames);
+        } else {
+            // Copy the data first as the dst buffer may not have enough space for extra channel.
+            memcpy_by_audio_format(
+                buf, mContractedFormat, oriBuf, mFormat, mContractedInChannelCount * frames);
+            // Note that if the contracted data is from MONO to MULTICHANNEL, the first 2 channels
+            // will be duplicated with the original single input channel and all the other channels
+            // will be 0-filled.
+            adjust_channels(
+                    buf, mContractedInChannelCount, buf, mContractedOutChannelCount,
+                    mContractedSampleSizeInBytes, mContractedInputFrameSize * frames);
         }
-    } else {
-        // Prefer expanding data from the end of each audio frame.
-        adjust_channels(src, mInChannelCount, dst, mOutChannelCount,
-                mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
+        mContractedWrittenFrames += frames;
     }
 }
 
diff --git a/media/libaudioprocessing/include/media/AudioMixer.h b/media/libaudioprocessing/include/media/AudioMixer.h
index 5a9fa07..2993a60 100644
--- a/media/libaudioprocessing/include/media/AudioMixer.h
+++ b/media/libaudioprocessing/include/media/AudioMixer.h
@@ -80,7 +80,6 @@
             mPostDownmixReformatBufferProvider.reset(nullptr);
             mDownmixerBufferProvider.reset(nullptr);
             mReformatBufferProvider.reset(nullptr);
-            mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
             mAdjustChannelsBufferProvider.reset(nullptr);
         }
 
@@ -95,10 +94,8 @@
         void        unprepareForDownmix();
         status_t    prepareForReformat();
         void        unprepareForReformat();
-        status_t    prepareForAdjustChannels();
+        status_t    prepareForAdjustChannels(size_t frames);
         void        unprepareForAdjustChannels();
-        status_t    prepareForAdjustChannelsNonDestructive(size_t frames);
-        void        unprepareForAdjustChannelsNonDestructive();
         void        clearContractedBuffer();
         bool        setPlaybackRate(const AudioPlaybackRate &playbackRate);
         void        reconfigureBufferProviders();
@@ -114,24 +111,18 @@
          * 2) mAdjustChannelsBufferProvider: Expands or contracts sample data from one interleaved
          *    channel format to another. Expanded channels are filled with zeros and put at the end
          *    of each audio frame. Contracted channels are copied to the end of the buffer.
-         * 3) mContractChannelsNonDestructiveBufferProvider: Non-destructively contract sample data.
-         *    This is currently using at audio-haptic coupled playback to separate audio and haptic
-         *    data. Contracted channels could be written to given buffer.
-         * 4) mReformatBufferProvider: If not NULL, performs the audio reformat to
+         * 3) mReformatBufferProvider: If not NULL, performs the audio reformat to
          *    match either mMixerInFormat or mDownmixRequiresFormat, if the downmixer
          *    requires reformat. For example, it may convert floating point input to
          *    PCM_16_bit if that's required by the downmixer.
-         * 5) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match
+         * 4) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match
          *    the number of channels required by the mixer sink.
-         * 6) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from
+         * 5) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from
          *    the downmixer requirements to the mixer engine input requirements.
-         * 7) mTimestretchBufferProvider: Adds timestretching for playback rate
+         * 6) mTimestretchBufferProvider: Adds timestretching for playback rate
          */
         AudioBufferProvider* mInputBufferProvider;    // externally provided buffer provider.
-        // TODO: combine mAdjustChannelsBufferProvider and
-        // mContractChannelsNonDestructiveBufferProvider
         std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider;
-        std::unique_ptr<PassthruBufferProvider> mContractChannelsNonDestructiveBufferProvider;
         std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider;
         std::unique_ptr<PassthruBufferProvider> mDownmixerBufferProvider;
         std::unique_ptr<PassthruBufferProvider> mPostDownmixReformatBufferProvider;
@@ -153,8 +144,6 @@
         uint32_t             mMixerHapticChannelCount;
         uint32_t             mAdjustInChannelCount;
         uint32_t             mAdjustOutChannelCount;
-        uint32_t             mAdjustNonDestructiveInChannelCount;
-        uint32_t             mAdjustNonDestructiveOutChannelCount;
         bool                 mKeepContractedChannels;
     };
 
diff --git a/media/libaudioprocessing/include/media/BufferProviders.h b/media/libaudioprocessing/include/media/BufferProviders.h
index b038854..b3ab8a5 100644
--- a/media/libaudioprocessing/include/media/BufferProviders.h
+++ b/media/libaudioprocessing/include/media/BufferProviders.h
@@ -20,6 +20,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <audio_utils/ChannelMix.h>
 #include <media/AudioBufferProvider.h>
 #include <media/AudioResamplerPublic.h>
 #include <system/audio.h>
@@ -129,6 +130,23 @@
     static const int32_t SESSION_ID_INVALID_AND_IGNORED = -2;
 };
 
+// ChannelMixBufferProvider derives from CopyBufferProvider to perform an
+// downmix to the proper channel count and mask.
+class ChannelMixBufferProvider : public CopyBufferProvider {
+public:
+    ChannelMixBufferProvider(audio_channel_mask_t inputChannelMask,
+            audio_channel_mask_t outputChannelMask, audio_format_t format,
+            size_t bufferFrameCount);
+
+    void copyFrames(void *dst, const void *src, size_t frames) override;
+
+    bool isValid() const { return mIsValid; }
+
+protected:
+    audio_utils::channels::ChannelMix mChannelMix;
+    bool mIsValid = false;
+};
+
 // RemixBufferProvider derives from CopyBufferProvider to perform an
 // upmix or downmix to the proper channel count and mask.
 class RemixBufferProvider : public CopyBufferProvider {
@@ -223,17 +241,22 @@
 // Extra expanded channels are filled with zeros and put at the end of each audio frame.
 // Contracted channels are copied to the end of the output buffer(storage should be
 // allocated appropriately).
-// Contracted channels could be written to output buffer.
+// Contracted channels could be written to output buffer and got adjusted. When the contracted
+// channels are adjusted in the contracted buffer, the input channel count will be calculated
+// as `inChannelCount - outChannelCount`. The output channel count is provided by caller, which
+// is `contractedOutChannelCount`. Currently, adjusting contracted channels is used for audio
+// coupled haptic playback. If the device supports two haptic channels while apps only provide
+// single haptic channel, the second haptic channel will be duplicated with the first haptic
+// channel's data. If the device supports single haptic channels while apps provide two haptic
+// channels, the second channel will be contracted.
 class AdjustChannelsBufferProvider : public CopyBufferProvider {
 public:
-    AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
-            size_t outChannelCount, size_t frameCount) : AdjustChannelsBufferProvider(
-                    format, inChannelCount, outChannelCount,
-                    frameCount, AUDIO_FORMAT_INVALID, nullptr) { }
     // Contracted data is converted to contractedFormat and put into contractedBuffer.
     AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
-            size_t outChannelCount, size_t frameCount, audio_format_t contractedFormat,
-            void* contractedBuffer);
+            size_t outChannelCount, size_t frameCount,
+            audio_format_t contractedFormat = AUDIO_FORMAT_INVALID,
+            void* contractedBuffer = nullptr,
+            size_t contractedOutChannelCount = 0);
     //Overrides
     status_t getNextBuffer(Buffer* pBuffer) override;
     void copyFrames(void *dst, const void *src, size_t frames) override;
@@ -247,11 +270,14 @@
     const size_t         mOutChannelCount;
     const size_t         mSampleSizeInBytes;
     const size_t         mFrameCount;
-    const size_t         mContractedChannelCount;
     const audio_format_t mContractedFormat;
+    const size_t         mContractedInChannelCount;
+    const size_t         mContractedOutChannelCount;
+    const size_t         mContractedSampleSizeInBytes;
+    const size_t         mContractedInputFrameSize; // contracted input frame size
     void                *mContractedBuffer;
     size_t               mContractedWrittenFrames;
-    size_t               mContractedFrameSize;
+    size_t               mContractedOutputFrameSize; // contracted output frame size
 };
 // ----------------------------------------------------------------------------
 } // namespace android
diff --git a/media/libmedia/tests/codeclist/Android.bp b/media/libmedia/tests/codeclist/Android.bp
index 57af9a9..2ed3126 100644
--- a/media/libmedia/tests/codeclist/Android.bp
+++ b/media/libmedia/tests/codeclist/Android.bp
@@ -28,6 +28,22 @@
     test_suites: ["device-tests", "mts"],
     gtest: true,
 
+    // Support multilib variants (using different suffix per sub-architecture), which is needed on
+    // build targets with secondary architectures, as the MTS test suite packaging logic flattens
+    // all test artifacts into a single `testcases` directory.
+    compile_multilib: "both",
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+
+    // used within mainline MTS, but only to R, not to Q.
+    min_sdk_version: "30",
+
     srcs: [
         "CodecListTest.cpp",
     ],
@@ -35,13 +51,13 @@
     shared_libs: [
         "libbinder",
         "liblog",
-        "libmedia_codeclist",
+        "libmedia_codeclist", // available >= R
         "libstagefright",
         "libstagefright_foundation",
         "libstagefright_xmlparser",
         "libutils",
     ],
-    compile_multilib: "first",
+
     cflags: [
         "-Werror",
         "-Wall",
diff --git a/media/libmedia/tests/codeclist/AndroidTest.xml b/media/libmedia/tests/codeclist/AndroidTest.xml
new file mode 100644
index 0000000..eeaab8e
--- /dev/null
+++ b/media/libmedia/tests/codeclist/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test module config for CodecList unit tests">
+    <option name="test-suite-tag" value="CodecListTest" />
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="append-bitness" value="true" />
+        <option name="push" value="CodecListTest->/data/local/tmp/CodecListTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="CodecListTest" />
+    </test>
+
+
+</configuration>
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 37f8103..c416a51 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -83,7 +83,6 @@
     export_shared_lib_headers: [
         "libmedia",
         "framework-permission-aidl-cpp",
-        "packagemanager_aidl-cpp",
     ],
 
     include_dirs: [
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
new file mode 100644
index 0000000..d83d3c9
--- /dev/null
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_av_media_libmediaplayerservice_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: [
+        "frameworks_av_media_libmediaplayerservice_license",
+    ],
+}
+
+cc_defaults {
+    name: "libmediaplayerserviceFuzzer_defaults",
+    include_dirs: [
+        "frameworks/av/media/libmediaplayerservice",
+    ],
+    static_libs: [
+        "libmediaplayerservice",
+        "liblog",
+    ],
+    shared_libs: [
+        "framework-permission-aidl-cpp",
+        "libbinder",
+        "libcutils",
+        "libmedia",
+        "libstagefright",
+        "libutils",
+        "libstagefright_foundation",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 155276,
+    },
+}
+
+cc_fuzz {
+    name: "mediarecorder_fuzzer",
+    srcs: [
+        "mediarecorder_fuzzer.cpp",
+    ],
+    defaults: [
+        "libmediaplayerserviceFuzzer_defaults",
+    ],
+    static_libs: [
+        "libstagefright_rtsp",
+        "libbase",
+    ],
+    shared_libs: [
+        "av-types-aidl-cpp",
+        "media_permission-aidl-cpp",
+        "libaudioclient_aidl_conversion",
+        "libandroid_net",
+        "libcamera_client",
+        "libgui",
+        "libmediametrics",
+    ],
+}
+
+cc_fuzz {
+    name: "metadataretriever_fuzzer",
+    srcs: [
+        "metadataretriever_fuzzer.cpp",
+    ],
+    defaults: [
+        "libmediaplayerserviceFuzzer_defaults",
+    ],
+    static_libs: [
+        "libplayerservice_datasource",
+    ],
+    shared_libs: [
+        "libdatasource",
+        "libdrmframework",
+    ],
+}
+
+cc_fuzz {
+    name: "mediaplayer_fuzzer",
+    srcs: [
+        "mediaplayer_fuzzer.cpp",
+    ],
+    defaults: [
+        "libmediaplayerserviceFuzzer_defaults",
+    ],
+    static_libs: [
+        "libplayerservice_datasource",
+        "libstagefright_nuplayer",
+        "libstagefright_rtsp",
+        "libstagefright_timedtext",
+    ],
+    shared_libs: [
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.omx@1.0",
+        "av-types-aidl-cpp",
+        "libaudioclient_aidl_conversion",
+        "libbase",
+        "libactivitymanager_aidl",
+        "libandroid_net",
+        "libaudioclient",
+        "libcamera_client",
+        "libcodec2_client",
+        "libcrypto",
+        "libdatasource",
+        "libdrmframework",
+        "libgui",
+        "libhidlbase",
+        "liblog",
+        "libmedia_codeclist",
+        "libmedia_omx",
+        "libmediadrm",
+        "libmediametrics",
+        "libmediautils",
+        "libmemunreachable",
+        "libnetd_client",
+        "libpowermanager",
+        "libstagefright_httplive",
+    ],
+}
diff --git a/media/libmediaplayerservice/fuzzer/README.md b/media/libmediaplayerservice/fuzzer/README.md
new file mode 100644
index 0000000..a93c809
--- /dev/null
+++ b/media/libmediaplayerservice/fuzzer/README.md
@@ -0,0 +1,83 @@
+# Fuzzer for libmediaplayerservice
+## Table of contents
++ [StagefrightMediaRecorder](#StagefrightMediaRecorder)
++ [StagefrightMetadataRetriever](#StagefrightMetadataRetriever)
++ [MediaPlayer](#MediaPlayer)
+
+# <a name="StagefrightMediaRecorder"></a> Fuzzer for StagefrightMediaRecorder
+
+StagefrightMediaRecorder supports the following parameters:
+1. Output Formats (parameter name: `setOutputFormat`)
+2. Audio Encoders (parameter name: `setAudioEncoder`)
+3. Video Encoders (parameter name: `setVideoEncoder`)
+4. Audio Sources (parameter name: `setAudioSource`)
+5. Video Sources (parameter name: `setVideoSource`)
+6. Microphone Direction (parameter name: `setMicrophoneDirection`)
+
+You can find the possible values in the fuzzer's source code.
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) mediarecorder_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mediarecorder_fuzzer/mediarecorder_fuzzer
+```
+
+# <a name="StagefrightMetadataRetriever"></a> Fuzzer for StagefrightMetadataRetriever
+
+StagefrightMetadataRetriever supports the following data sources:
+1. Url (parameter name: `url`)
+2. File descriptor (parameter name: `fd`)
+3. DataSource (parameter name: `source`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `url` | Url of data source | Value obtained from FuzzedDataProvider |
+| `fd` | File descriptor value of input file | Value obtained from FuzzedDataProvider |
+| `source` | DataSource object | Data obtained from FuzzedDataProvider |
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) metadataretriever_fuzzer
+```
+2. To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/metadataretriever_fuzzer/metadataretriever_fuzzer
+```
+
+# <a name="MediaPlayer"></a> Fuzzer for MediaPlayer
+
+MediaPlayerService supports the following data sources:
+1. Url (parameter name: `url`)
+2. File descriptor (parameter name: `fd`)
+3. IStreamSource  (parameter name: `source`)
+4. IDataSource (parameter name: `source`)
+5. RTP Parameters  (parameter name: `rtpParams`)
+
+MediaPlayerService supports the following parameters:
+1. Audio sessions (parameter name: `audioSessionId`)
+2. Audio stretch modes (parameter name: `mStretchMode`)
+3. Audio fallback modes  (parameter name: `mFallbackMode`)
+4. Media parameter keys (parameter name: `key`)
+5. Audio Stream Types (parameter name: `streamType`)
+6. Media Event Types (parameter name: `msg`)
+7. Media Info Types (parameter name: `ext1`)
+
+You can find the possible values in the fuzzer's source code.
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) mediaplayer_fuzzer
+```
+2. To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mediaplayer_fuzzer/mediaplayer_fuzzer
+```
diff --git a/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp b/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp
new file mode 100644
index 0000000..7799f44
--- /dev/null
+++ b/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp
@@ -0,0 +1,368 @@
+/*
+ * 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.
+ *
+ */
+
+#include <MediaPlayerService.h>
+#include <camera/Camera.h>
+#include <datasource/FileSource.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+#include <media/IMediaCodecList.h>
+#include <media/IMediaHTTPService.h>
+#include <media/IMediaPlayer.h>
+#include <media/IMediaRecorder.h>
+#include <media/IRemoteDisplay.h>
+#include <media/IRemoteDisplayClient.h>
+#include <media/stagefright/RemoteDataSource.h>
+#include <media/stagefright/foundation/base64.h>
+#include <thread>
+#include "fuzzer/FuzzedDataProvider.h"
+
+constexpr int32_t kUuidSize = 16;
+constexpr int32_t kMaxSleepTimeInMs = 100;
+constexpr int32_t kMinSleepTimeInMs = 0;
+constexpr int32_t kPlayCountMin = 1;
+constexpr int32_t kPlayCountMax = 10;
+constexpr int32_t kMaxDimension = 8192;
+constexpr int32_t kMinDimension = 0;
+
+using namespace std;
+using namespace android;
+
+constexpr audio_session_t kSupportedAudioSessions[] = {
+    AUDIO_SESSION_DEVICE, AUDIO_SESSION_OUTPUT_STAGE, AUDIO_SESSION_OUTPUT_MIX};
+
+constexpr audio_timestretch_stretch_mode_t kAudioStretchModes[] = {
+    AUDIO_TIMESTRETCH_STRETCH_DEFAULT, AUDIO_TIMESTRETCH_STRETCH_VOICE};
+
+constexpr audio_timestretch_fallback_mode_t kAudioFallbackModes[] = {
+    AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT, AUDIO_TIMESTRETCH_FALLBACK_DEFAULT,
+    AUDIO_TIMESTRETCH_FALLBACK_MUTE, AUDIO_TIMESTRETCH_FALLBACK_FAIL};
+
+constexpr media_parameter_keys kMediaParamKeys[] = {
+    KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS, KEY_PARAMETER_AUDIO_CHANNEL_COUNT,
+    KEY_PARAMETER_PLAYBACK_RATE_PERMILLE, KEY_PARAMETER_AUDIO_ATTRIBUTES,
+    KEY_PARAMETER_RTP_ATTRIBUTES};
+
+constexpr audio_stream_type_t kAudioStreamTypes[] = {
+    AUDIO_STREAM_DEFAULT,      AUDIO_STREAM_VOICE_CALL,    AUDIO_STREAM_SYSTEM,
+    AUDIO_STREAM_RING,         AUDIO_STREAM_MUSIC,         AUDIO_STREAM_ALARM,
+    AUDIO_STREAM_NOTIFICATION, AUDIO_STREAM_BLUETOOTH_SCO, AUDIO_STREAM_ENFORCED_AUDIBLE,
+    AUDIO_STREAM_DTMF,         AUDIO_STREAM_TTS,           AUDIO_STREAM_ASSISTANT};
+
+constexpr media_event_type kMediaEventTypes[] = {MEDIA_NOP,
+                                                 MEDIA_PREPARED,
+                                                 MEDIA_PLAYBACK_COMPLETE,
+                                                 MEDIA_BUFFERING_UPDATE,
+                                                 MEDIA_SEEK_COMPLETE,
+                                                 MEDIA_SET_VIDEO_SIZE,
+                                                 MEDIA_STARTED,
+                                                 MEDIA_PAUSED,
+                                                 MEDIA_STOPPED,
+                                                 MEDIA_SKIPPED,
+                                                 MEDIA_NOTIFY_TIME,
+                                                 MEDIA_TIMED_TEXT,
+                                                 MEDIA_ERROR,
+                                                 MEDIA_INFO,
+                                                 MEDIA_SUBTITLE_DATA,
+                                                 MEDIA_META_DATA,
+                                                 MEDIA_DRM_INFO,
+                                                 MEDIA_TIME_DISCONTINUITY,
+                                                 MEDIA_IMS_RX_NOTICE,
+                                                 MEDIA_AUDIO_ROUTING_CHANGED};
+
+constexpr media_info_type kMediaInfoTypes[] = {
+    MEDIA_INFO_UNKNOWN,           MEDIA_INFO_STARTED_AS_NEXT,
+    MEDIA_INFO_RENDERING_START,   MEDIA_INFO_VIDEO_TRACK_LAGGING,
+    MEDIA_INFO_BUFFERING_START,   MEDIA_INFO_BUFFERING_END,
+    MEDIA_INFO_NETWORK_BANDWIDTH, MEDIA_INFO_BAD_INTERLEAVING,
+    MEDIA_INFO_NOT_SEEKABLE,      MEDIA_INFO_METADATA_UPDATE,
+    MEDIA_INFO_PLAY_AUDIO_ERROR,  MEDIA_INFO_PLAY_VIDEO_ERROR,
+    MEDIA_INFO_TIMED_TEXT_ERROR};
+
+const char *kUrlPrefix[] = {"data:", "http://", "https://", "rtsp://", "content://", "test://"};
+
+struct TestStreamSource : public IStreamSource {
+    void setListener(const sp<IStreamListener> & /*listener*/) override{};
+    void setBuffers(const Vector<sp<IMemory>> & /*buffers*/) override{};
+    void onBufferAvailable(size_t /*index*/) override{};
+    IBinder *onAsBinder() { return nullptr; };
+};
+
+class BinderDeathNotifier : public IBinder::DeathRecipient {
+   public:
+    void binderDied(const wp<IBinder> &) { abort(); }
+};
+
+class MediaPlayerServiceFuzzer {
+   public:
+    MediaPlayerServiceFuzzer(const uint8_t *data, size_t size)
+        : mFdp(data, size), mDataSourceFd(memfd_create("InputFile", MFD_ALLOW_SEALING)){};
+    ~MediaPlayerServiceFuzzer() { close(mDataSourceFd); };
+    void process(const uint8_t *data, size_t size);
+
+   private:
+    bool setDataSource(const uint8_t *data, size_t size);
+    void invokeMediaPlayer();
+    FuzzedDataProvider mFdp;
+    sp<IMediaPlayer> mMediaPlayer = nullptr;
+    sp<IMediaPlayerClient> mMediaPlayerClient = nullptr;
+    const int32_t mDataSourceFd;
+};
+
+bool MediaPlayerServiceFuzzer::setDataSource(const uint8_t *data, size_t size) {
+    status_t status = -1;
+    enum DataSourceType {http, fd, stream, file, socket, kMaxValue = socket};
+    switch (mFdp.ConsumeEnum<DataSourceType>()) {
+        case http: {
+            KeyedVector<String8, String8> headers;
+            headers.add(String8(mFdp.ConsumeRandomLengthString().c_str()),
+                        String8(mFdp.ConsumeRandomLengthString().c_str()));
+
+            uint32_t dataBlobSize = mFdp.ConsumeIntegralInRange<uint16_t>(0, size);
+            vector<uint8_t> uriSuffix = mFdp.ConsumeBytes<uint8_t>(dataBlobSize);
+
+            string uri(mFdp.PickValueInArray(kUrlPrefix));
+            uri += ";base64,";
+            AString out;
+            encodeBase64(uriSuffix.data(), uriSuffix.size(), &out);
+            uri += out.c_str();
+            status = mMediaPlayer->setDataSource(nullptr /*httpService*/, uri.c_str(), &headers);
+            break;
+        }
+        case fd: {
+            write(mDataSourceFd, data, size);
+
+            status = mMediaPlayer->setDataSource(mDataSourceFd, 0, size);
+            break;
+        }
+        case stream: {
+            sp<IStreamSource> streamSource = sp<TestStreamSource>::make();
+            status = mMediaPlayer->setDataSource(streamSource);
+            break;
+        }
+        case file: {
+            write(mDataSourceFd, data, size);
+
+            sp<DataSource> dataSource = new FileSource(dup(mDataSourceFd), 0, size);
+            sp<IDataSource> iDataSource = RemoteDataSource::wrap(dataSource);
+            if (!iDataSource) {
+                return false;
+            }
+            status = mMediaPlayer->setDataSource(iDataSource);
+            break;
+        }
+        case socket: {
+            String8 rtpParams = String8(mFdp.ConsumeRandomLengthString().c_str());
+            struct sockaddr_in endpoint;
+            endpoint.sin_family = mFdp.ConsumeIntegral<unsigned short>();
+            endpoint.sin_port = mFdp.ConsumeIntegral<uint16_t>();
+            mMediaPlayer->setRetransmitEndpoint(&endpoint);
+            status = mMediaPlayer->setDataSource(rtpParams);
+            break;
+        }
+    }
+
+    if (status != 0) {
+        return false;
+    }
+    return true;
+}
+
+void MediaPlayerServiceFuzzer::invokeMediaPlayer() {
+    sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
+    String8 name = String8(mFdp.ConsumeRandomLengthString().c_str());
+    uint32_t width = mFdp.ConsumeIntegralInRange<uint32_t>(kMinDimension, kMaxDimension);
+    uint32_t height = mFdp.ConsumeIntegralInRange<uint32_t>(kMinDimension, kMaxDimension);
+    uint32_t pixelFormat = mFdp.ConsumeIntegral<int32_t>();
+    uint32_t flags = mFdp.ConsumeIntegral<int32_t>();
+    sp<SurfaceControl> surfaceControl =
+        composerClient->createSurface(name, width, height, pixelFormat, flags);
+    if (surfaceControl) {
+        sp<Surface> surface = surfaceControl->getSurface();
+        mMediaPlayer->setVideoSurfaceTexture(surface->getIGraphicBufferProducer());
+    }
+
+    BufferingSettings buffering;
+    buffering.mInitialMarkMs = mFdp.ConsumeIntegral<int32_t>();
+    buffering.mResumePlaybackMarkMs = mFdp.ConsumeIntegral<int32_t>();
+    mMediaPlayer->setBufferingSettings(buffering);
+    mMediaPlayer->getBufferingSettings(&buffering);
+
+    mMediaPlayer->prepareAsync();
+    size_t playCount = mFdp.ConsumeIntegralInRange<size_t>(kPlayCountMin, kPlayCountMax);
+    for (size_t Idx = 0; Idx < playCount; ++Idx) {
+        mMediaPlayer->start();
+        this_thread::sleep_for(chrono::milliseconds(
+            mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs)));
+        mMediaPlayer->pause();
+        this_thread::sleep_for(chrono::milliseconds(
+            mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs)));
+        mMediaPlayer->stop();
+    }
+    bool state;
+    mMediaPlayer->isPlaying(&state);
+
+    AudioPlaybackRate rate;
+    rate.mSpeed = mFdp.ConsumeFloatingPoint<float>();
+    rate.mPitch = mFdp.ConsumeFloatingPoint<float>();
+    rate.mStretchMode = mFdp.PickValueInArray(kAudioStretchModes);
+    rate.mFallbackMode = mFdp.PickValueInArray(kAudioFallbackModes);
+    mMediaPlayer->setPlaybackSettings(rate);
+    mMediaPlayer->getPlaybackSettings(&rate);
+
+    AVSyncSettings *avSyncSettings = new AVSyncSettings();
+    float videoFpsHint = mFdp.ConsumeFloatingPoint<float>();
+    mMediaPlayer->setSyncSettings(*avSyncSettings, videoFpsHint);
+    mMediaPlayer->getSyncSettings(avSyncSettings, &videoFpsHint);
+    delete avSyncSettings;
+
+    mMediaPlayer->seekTo(mFdp.ConsumeIntegral<int32_t>());
+
+    int32_t msec;
+    mMediaPlayer->getCurrentPosition(&msec);
+    mMediaPlayer->getDuration(&msec);
+    mMediaPlayer->reset();
+
+    mMediaPlayer->notifyAt(mFdp.ConsumeIntegral<int64_t>());
+
+    mMediaPlayer->setAudioStreamType(mFdp.PickValueInArray(kAudioStreamTypes));
+    mMediaPlayer->setLooping(mFdp.ConsumeIntegral<int32_t>());
+    float left = mFdp.ConsumeFloatingPoint<float>();
+    float right = mFdp.ConsumeFloatingPoint<float>();
+    mMediaPlayer->setVolume(left, right);
+
+    Parcel request, reply;
+    request.writeInt32(mFdp.ConsumeIntegral<int32_t>());
+    request.setDataPosition(0);
+    mMediaPlayer->invoke(request, &reply);
+
+    Parcel filter;
+    filter.writeInt32(mFdp.ConsumeIntegral<int32_t>());
+    filter.setDataPosition(0);
+    mMediaPlayer->setMetadataFilter(filter);
+
+    bool updateOnly = mFdp.ConsumeBool();
+    bool applyFilter = mFdp.ConsumeBool();
+    mMediaPlayer->getMetadata(updateOnly, applyFilter, &reply);
+    mMediaPlayer->setAuxEffectSendLevel(mFdp.ConsumeFloatingPoint<float>());
+    mMediaPlayer->attachAuxEffect(mFdp.ConsumeIntegral<int32_t>());
+
+    int32_t key = mFdp.PickValueInArray(kMediaParamKeys);
+    request.writeInt32(mFdp.ConsumeIntegral<int32_t>());
+    request.setDataPosition(0);
+    mMediaPlayer->setParameter(key, request);
+    key = mFdp.PickValueInArray(kMediaParamKeys);
+    mMediaPlayer->getParameter(key, &reply);
+
+    struct sockaddr_in endpoint;
+    mMediaPlayer->getRetransmitEndpoint(&endpoint);
+
+    AttributionSourceState attributionSource;
+    attributionSource.packageName = mFdp.ConsumeRandomLengthString().c_str();
+    attributionSource.token = sp<BBinder>::make();
+    const sp<IMediaPlayerService> mpService(IMediaDeathNotifier::getMediaPlayerService());
+    sp<IMediaPlayer> mNextMediaPlayer = mpService->create(
+        mMediaPlayerClient, mFdp.PickValueInArray(kSupportedAudioSessions), attributionSource);
+    mMediaPlayer->setNextPlayer(mNextMediaPlayer);
+
+    const sp<media::VolumeShaper::Configuration> configuration =
+        sp<media::VolumeShaper::Configuration>::make();
+    const sp<media::VolumeShaper::Operation> operation = sp<media::VolumeShaper::Operation>::make();
+    mMediaPlayer->applyVolumeShaper(configuration, operation);
+
+    mMediaPlayer->getVolumeShaperState(mFdp.ConsumeIntegral<int32_t>());
+    uint8_t uuid[kUuidSize];
+    for (int32_t index = 0; index < kUuidSize; ++index) {
+        uuid[index] = mFdp.ConsumeIntegral<uint8_t>();
+    }
+    Vector<uint8_t> drmSessionId;
+    drmSessionId.push_back(mFdp.ConsumeIntegral<uint8_t>());
+    mMediaPlayer->prepareDrm(uuid, drmSessionId);
+    mMediaPlayer->releaseDrm();
+
+    audio_port_handle_t deviceId = mFdp.ConsumeIntegral<int32_t>();
+    mMediaPlayer->setOutputDevice(deviceId);
+    mMediaPlayer->getRoutedDeviceId(&deviceId);
+
+    mMediaPlayer->enableAudioDeviceCallback(mFdp.ConsumeBool());
+
+    sp<MediaPlayer> mediaPlayer = (MediaPlayer *)mMediaPlayer.get();
+
+    int32_t msg = mFdp.PickValueInArray(kMediaEventTypes);
+    int32_t ext1 = mFdp.PickValueInArray(kMediaInfoTypes);
+    int32_t ext2 = mFdp.ConsumeIntegral<int32_t>();
+    Parcel obj;
+    obj.writeInt32(mFdp.ConsumeIntegral<int32_t>());
+    obj.setDataPosition(0);
+    mediaPlayer->notify(msg, ext1, ext2, &obj);
+
+    int32_t mediaPlayerDumpFd = memfd_create("OutputDumpFile", MFD_ALLOW_SEALING);
+    Vector<String16> args;
+    args.push_back(String16(mFdp.ConsumeRandomLengthString().c_str()));
+    mediaPlayer->dump(mediaPlayerDumpFd, args);
+    close(mediaPlayerDumpFd);
+
+    mMediaPlayer->disconnect();
+}
+
+void MediaPlayerServiceFuzzer::process(const uint8_t *data, size_t size) {
+    MediaPlayerService::instantiate();
+
+    const sp<IMediaPlayerService> mpService(IMediaDeathNotifier::getMediaPlayerService());
+    if (!mpService) {
+        return;
+    }
+
+    sp<IMediaCodecList> mediaCodecList = mpService->getCodecList();
+
+    sp<IRemoteDisplayClient> remoteDisplayClient;
+    sp<IRemoteDisplay> remoteDisplay = mpService->listenForRemoteDisplay(
+        String16(mFdp.ConsumeRandomLengthString().c_str()) /*opPackageName*/, remoteDisplayClient,
+        String8(mFdp.ConsumeRandomLengthString().c_str()) /*iface*/);
+
+    mpService->addBatteryData(mFdp.ConsumeIntegral<uint32_t>());
+    Parcel reply;
+    mpService->pullBatteryData(&reply);
+
+    sp<MediaPlayerService> mediaPlayerService = (MediaPlayerService *)mpService.get();
+    AttributionSourceState attributionSource;
+    attributionSource.packageName = mFdp.ConsumeRandomLengthString().c_str();
+    attributionSource.token = sp<BBinder>::make();
+    mMediaPlayer = mediaPlayerService->create(
+        mMediaPlayerClient, mFdp.PickValueInArray(kSupportedAudioSessions), attributionSource);
+
+    int32_t mediaPlayerServiceDumpFd = memfd_create("OutputDumpFile", MFD_ALLOW_SEALING);
+    Vector<String16> args;
+    args.push_back(String16(mFdp.ConsumeRandomLengthString().c_str()));
+    mediaPlayerService->dump(mediaPlayerServiceDumpFd, args);
+    close(mediaPlayerServiceDumpFd);
+
+    if (!mMediaPlayer) {
+        return;
+    }
+
+    if (setDataSource(data, size)) {
+        invokeMediaPlayer();
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    MediaPlayerServiceFuzzer mpsFuzzer(data, size);
+    ProcessState::self()->startThreadPool();
+    mpsFuzzer.process(data, size);
+    return 0;
+};
diff --git a/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp b/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
new file mode 100644
index 0000000..b0040fe
--- /dev/null
+++ b/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
@@ -0,0 +1,312 @@
+/*
+ * 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.
+ *
+ */
+
+#include <media/stagefright/foundation/AString.h>
+#include "fuzzer/FuzzedDataProvider.h"
+
+#include <StagefrightRecorder.h>
+#include <camera/Camera.h>
+#include <camera/android/hardware/ICamera.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+#include <media/stagefright/PersistentSurface.h>
+#include <thread>
+
+using namespace std;
+using namespace android;
+using namespace android::hardware;
+
+constexpr video_source kSupportedVideoSources[] = {VIDEO_SOURCE_DEFAULT, VIDEO_SOURCE_CAMERA,
+                                                   VIDEO_SOURCE_SURFACE};
+
+constexpr audio_source_t kSupportedAudioSources[] = {
+    AUDIO_SOURCE_DEFAULT,           AUDIO_SOURCE_MIC,
+    AUDIO_SOURCE_VOICE_UPLINK,      AUDIO_SOURCE_VOICE_DOWNLINK,
+    AUDIO_SOURCE_VOICE_CALL,        AUDIO_SOURCE_CAMCORDER,
+    AUDIO_SOURCE_VOICE_RECOGNITION, AUDIO_SOURCE_VOICE_COMMUNICATION,
+    AUDIO_SOURCE_REMOTE_SUBMIX,     AUDIO_SOURCE_UNPROCESSED,
+    AUDIO_SOURCE_VOICE_PERFORMANCE, AUDIO_SOURCE_ECHO_REFERENCE,
+    AUDIO_SOURCE_FM_TUNER,          AUDIO_SOURCE_HOTWORD};
+
+constexpr audio_microphone_direction_t kSupportedMicrophoneDirections[] = {
+    MIC_DIRECTION_UNSPECIFIED, MIC_DIRECTION_FRONT, MIC_DIRECTION_BACK, MIC_DIRECTION_EXTERNAL};
+
+struct RecordingConfig {
+    output_format outputFormat;
+    audio_encoder audioEncoder;
+    video_encoder videoEncoder;
+};
+
+const struct RecordingConfig kRecordingConfigList[] = {
+    {OUTPUT_FORMAT_AMR_NB, AUDIO_ENCODER_AMR_NB, VIDEO_ENCODER_DEFAULT},
+    {OUTPUT_FORMAT_AMR_WB, AUDIO_ENCODER_AMR_WB, VIDEO_ENCODER_DEFAULT},
+    {OUTPUT_FORMAT_AAC_ADTS, AUDIO_ENCODER_AAC, VIDEO_ENCODER_DEFAULT},
+    {OUTPUT_FORMAT_AAC_ADTS, AUDIO_ENCODER_HE_AAC, VIDEO_ENCODER_DEFAULT},
+    {OUTPUT_FORMAT_AAC_ADTS, AUDIO_ENCODER_AAC_ELD, VIDEO_ENCODER_DEFAULT},
+    {OUTPUT_FORMAT_OGG, AUDIO_ENCODER_OPUS, VIDEO_ENCODER_DEFAULT},
+    {OUTPUT_FORMAT_RTP_AVP, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_DEFAULT},
+    {OUTPUT_FORMAT_MPEG2TS, AUDIO_ENCODER_AAC, VIDEO_ENCODER_H264},
+    {OUTPUT_FORMAT_WEBM, AUDIO_ENCODER_VORBIS, VIDEO_ENCODER_VP8},
+    {OUTPUT_FORMAT_THREE_GPP, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_MPEG_4_SP},
+    {OUTPUT_FORMAT_MPEG_4, AUDIO_ENCODER_AAC, VIDEO_ENCODER_H264},
+    {OUTPUT_FORMAT_MPEG_4, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_MPEG_4_SP},
+    {OUTPUT_FORMAT_MPEG_4, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_HEVC}};
+
+const string kParametersList[] = {"max-duration",
+                                  "max-filesize",
+                                  "interleave-duration-us",
+                                  "param-movie-time-scale",
+                                  "param-geotag-longitude",
+                                  "param-geotag-latitude",
+                                  "param-track-time-status",
+                                  "audio-param-sampling-rate",
+                                  "audio-param-encoding-bitrate",
+                                  "audio-param-number-of-channels",
+                                  "audio-param-time-scale",
+                                  "video-param-rotation-angle-degrees",
+                                  "video-param-encoding-bitrate",
+                                  "video-param-bitrate-mode",
+                                  "video-param-i-frames-interval",
+                                  "video-param-encoder-profile",
+                                  "video-param-encoder-level",
+                                  "video-param-camera-id",
+                                  "video-param-time-scale",
+                                  "param-use-64bit-offset",
+                                  "time-lapse-enable",
+                                  "time-lapse-fps",
+                                  "rtp-param-local-ip",
+                                  "rtp-param-local-port",
+                                  "rtp-param-remote-port",
+                                  "rtp-param-self-id",
+                                  "rtp-param-opponent-id",
+                                  "rtp-param-payload-type",
+                                  "rtp-param-ext-cvo-extmap",
+                                  "rtp-param-ext-cvo-degrees",
+                                  "video-param-request-i-frame",
+                                  "rtp-param-set-socket-dscp",
+                                  "rtp-param-set-socket-network"};
+
+constexpr int32_t kMaxSleepTimeInMs = 100;
+constexpr int32_t kMinSleepTimeInMs = 0;
+constexpr int32_t kMinVideoSize = 2;
+constexpr int32_t kMaxVideoSize = 8192;
+constexpr int32_t kNumRecordMin = 1;
+constexpr int32_t kNumRecordMax = 10;
+
+class TestAudioDeviceCallback : public AudioSystem::AudioDeviceCallback {
+   public:
+    virtual ~TestAudioDeviceCallback() = default;
+
+    void onAudioDeviceUpdate(audio_io_handle_t /*audioIo*/,
+                             audio_port_handle_t /*deviceId*/) override{};
+};
+
+class TestCamera : public ICamera {
+   public:
+    virtual ~TestCamera() = default;
+
+    binder::Status disconnect() override { return binder::Status::ok(); };
+    status_t connect(const sp<ICameraClient> & /*client*/) override { return 0; };
+    status_t lock() override { return 0; };
+    status_t unlock() override { return 0; };
+    status_t setPreviewTarget(const sp<IGraphicBufferProducer> & /*bufferProducer*/) override {
+        return 0;
+    };
+    void setPreviewCallbackFlag(int /*flag*/) override{};
+    status_t setPreviewCallbackTarget(
+        const sp<IGraphicBufferProducer> & /*callbackProducer*/) override {
+        return 0;
+    };
+    status_t startPreview() override { return 0; };
+    void stopPreview() override{};
+    bool previewEnabled() override { return true; };
+    status_t startRecording() override { return 0; };
+    void stopRecording() override{};
+    bool recordingEnabled() override { return true; };
+    void releaseRecordingFrame(const sp<IMemory> & /*mem*/) override{};
+    void releaseRecordingFrameHandle(native_handle_t * /*handle*/) override{};
+    void releaseRecordingFrameHandleBatch(const vector<native_handle_t *> & /*handles*/) override{};
+    status_t autoFocus() override { return 0; };
+    status_t cancelAutoFocus() override { return 0; };
+    status_t takePicture(int /*msgType*/) override { return 0; };
+    status_t setParameters(const String8 & /*params*/) override { return 0; };
+    String8 getParameters() const override { return String8(); };
+    status_t sendCommand(int32_t /*cmd*/, int32_t /*arg1*/, int32_t /*arg2*/) override {
+        return 0;
+    };
+    status_t setVideoBufferMode(int32_t /*videoBufferMode*/) override { return 0; };
+    status_t setVideoTarget(const sp<IGraphicBufferProducer> & /*bufferProducer*/) override {
+        return 0;
+    };
+    status_t setAudioRestriction(int32_t /*mode*/) override { return 0; };
+    int32_t getGlobalAudioRestriction() override { return 0; };
+    IBinder *onAsBinder() override { return reinterpret_cast<IBinder *>(this); };
+};
+
+class TestMediaRecorderClient : public IMediaRecorderClient {
+   public:
+    virtual ~TestMediaRecorderClient() = default;
+
+    void notify(int /*msg*/, int /*ext1*/, int /*ext2*/) override{};
+    IBinder *onAsBinder() override { return reinterpret_cast<IBinder *>(this); };
+};
+
+class MediaRecorderClientFuzzer {
+   public:
+    MediaRecorderClientFuzzer(const uint8_t *data, size_t size);
+    ~MediaRecorderClientFuzzer() { close(mMediaRecorderOutputFd); }
+    void process();
+
+   private:
+    void setConfig();
+    void getConfig();
+    void dumpInfo();
+
+    FuzzedDataProvider mFdp;
+    unique_ptr<MediaRecorderBase> mStfRecorder = nullptr;
+    SurfaceComposerClient mComposerClient;
+    sp<SurfaceControl> mSurfaceControl = nullptr;
+    sp<Surface> mSurface = nullptr;
+    const int32_t mMediaRecorderOutputFd;
+};
+
+void MediaRecorderClientFuzzer::getConfig() {
+    int32_t max;
+    mStfRecorder->getMaxAmplitude(&max);
+
+    int32_t deviceId = mFdp.ConsumeIntegral<int32_t>();
+    mStfRecorder->setInputDevice(deviceId);
+    mStfRecorder->getRoutedDeviceId(&deviceId);
+
+    vector<android::media::MicrophoneInfo> activeMicrophones{};
+    mStfRecorder->getActiveMicrophones(&activeMicrophones);
+
+    int32_t portId;
+    mStfRecorder->getPortId(&portId);
+
+    uint64_t bytes;
+    mStfRecorder->getRtpDataUsage(&bytes);
+
+    Parcel parcel;
+    mStfRecorder->getMetrics(&parcel);
+
+    sp<IGraphicBufferProducer> buffer = mStfRecorder->querySurfaceMediaSource();
+}
+
+void MediaRecorderClientFuzzer::dumpInfo() {
+    int32_t dumpFd = memfd_create("DumpFile", MFD_ALLOW_SEALING);
+    Vector<String16> args;
+    args.push_back(String16(mFdp.ConsumeRandomLengthString().c_str()));
+    mStfRecorder->dump(dumpFd, args);
+    close(dumpFd);
+}
+
+void MediaRecorderClientFuzzer::setConfig() {
+    mStfRecorder->setOutputFile(mMediaRecorderOutputFd);
+    mStfRecorder->setAudioSource(mFdp.PickValueInArray(kSupportedAudioSources));
+    mStfRecorder->setVideoSource(mFdp.PickValueInArray(kSupportedVideoSources));
+    mStfRecorder->setPreferredMicrophoneDirection(
+        mFdp.PickValueInArray(kSupportedMicrophoneDirections));
+    mStfRecorder->setPrivacySensitive(mFdp.ConsumeBool());
+    bool isPrivacySensitive;
+    mStfRecorder->isPrivacySensitive(&isPrivacySensitive);
+    mStfRecorder->setVideoSize(mFdp.ConsumeIntegralInRange<int32_t>(kMinVideoSize, kMaxVideoSize),
+                               mFdp.ConsumeIntegralInRange<int32_t>(kMinVideoSize, kMaxVideoSize));
+    mStfRecorder->setVideoFrameRate(mFdp.ConsumeIntegral<int32_t>());
+    mStfRecorder->enableAudioDeviceCallback(mFdp.ConsumeBool());
+    mStfRecorder->setPreferredMicrophoneFieldDimension(mFdp.ConsumeFloatingPoint<float>());
+    mStfRecorder->setClientName(String16(mFdp.ConsumeRandomLengthString().c_str()));
+
+    int32_t Idx = mFdp.ConsumeIntegralInRange<int32_t>(0, size(kRecordingConfigList) - 1);
+    mStfRecorder->setOutputFormat(kRecordingConfigList[Idx].outputFormat);
+    mStfRecorder->setAudioEncoder(kRecordingConfigList[Idx].audioEncoder);
+    mStfRecorder->setVideoEncoder(kRecordingConfigList[Idx].videoEncoder);
+
+    int32_t nextOutputFd = memfd_create("NextOutputFile", MFD_ALLOW_SEALING);
+    mStfRecorder->setNextOutputFile(nextOutputFd);
+    close(nextOutputFd);
+
+    for (Idx = 0; Idx < size(kParametersList); ++Idx) {
+        if (mFdp.ConsumeBool()) {
+            int32_t value = mFdp.ConsumeIntegral<int32_t>();
+            mStfRecorder->setParameters(
+                String8((kParametersList[Idx] + "=" + to_string(value)).c_str()));
+        }
+    }
+}
+
+MediaRecorderClientFuzzer::MediaRecorderClientFuzzer(const uint8_t *data, size_t size)
+    : mFdp(data, size), mMediaRecorderOutputFd(memfd_create("OutputFile", MFD_ALLOW_SEALING)) {
+    AttributionSourceState attributionSource;
+    attributionSource.packageName = mFdp.ConsumeRandomLengthString().c_str();
+    attributionSource.token = sp<BBinder>::make();
+    mStfRecorder = make_unique<StagefrightRecorder>(attributionSource);
+
+    mSurfaceControl = mComposerClient.createSurface(
+        String8(mFdp.ConsumeRandomLengthString().c_str()), mFdp.ConsumeIntegral<uint32_t>(),
+        mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<int32_t>(),
+        mFdp.ConsumeIntegral<int32_t>());
+    if (mSurfaceControl) {
+        mSurface = mSurfaceControl->getSurface();
+        mStfRecorder->setPreviewSurface(mSurface->getIGraphicBufferProducer());
+    }
+
+    sp<TestMediaRecorderClient> listener = sp<TestMediaRecorderClient>::make();
+    mStfRecorder->setListener(listener);
+
+    sp<TestCamera> testCamera = sp<TestCamera>::make();
+    sp<Camera> camera = Camera::create(testCamera);
+    mStfRecorder->setCamera(camera->remote(), camera->getRecordingProxy());
+
+    sp<PersistentSurface> persistentSurface = sp<PersistentSurface>::make();
+    mStfRecorder->setInputSurface(persistentSurface);
+
+    sp<TestAudioDeviceCallback> callback = sp<TestAudioDeviceCallback>::make();
+    mStfRecorder->setAudioDeviceCallback(callback);
+}
+
+void MediaRecorderClientFuzzer::process() {
+    setConfig();
+
+    mStfRecorder->init();
+    mStfRecorder->prepare();
+    size_t numRecord = mFdp.ConsumeIntegralInRange<size_t>(kNumRecordMin, kNumRecordMax);
+    for (size_t Idx = 0; Idx < numRecord; ++Idx) {
+        mStfRecorder->start();
+        this_thread::sleep_for(chrono::milliseconds(
+            mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs)));
+        mStfRecorder->pause();
+        this_thread::sleep_for(chrono::milliseconds(
+            mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs)));
+        mStfRecorder->resume();
+        this_thread::sleep_for(chrono::milliseconds(
+            mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs)));
+        mStfRecorder->stop();
+    }
+    dumpInfo();
+    getConfig();
+
+    mStfRecorder->close();
+    mStfRecorder->reset();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    MediaRecorderClientFuzzer mrcFuzzer(data, size);
+    mrcFuzzer.process();
+    return 0;
+}
diff --git a/media/libmediaplayerservice/fuzzer/metadataretriever_fuzzer.cpp b/media/libmediaplayerservice/fuzzer/metadataretriever_fuzzer.cpp
new file mode 100644
index 0000000..a7cb689
--- /dev/null
+++ b/media/libmediaplayerservice/fuzzer/metadataretriever_fuzzer.cpp
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ *
+ */
+
+#include <StagefrightMetadataRetriever.h>
+#include <binder/ProcessState.h>
+#include <datasource/FileSource.h>
+#include <media/IMediaHTTPService.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+#include <media/stagefright/foundation/base64.h>
+
+#include <fuzzer/FuzzedDataProvider.h>
+
+using namespace std;
+using namespace android;
+
+const char *kMimeTypes[] = {MEDIA_MIMETYPE_IMAGE_JPEG,         MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC,
+                            MEDIA_MIMETYPE_VIDEO_VP8,          MEDIA_MIMETYPE_VIDEO_VP9,
+                            MEDIA_MIMETYPE_VIDEO_AV1,          MEDIA_MIMETYPE_VIDEO_AVC,
+                            MEDIA_MIMETYPE_VIDEO_HEVC,         MEDIA_MIMETYPE_VIDEO_MPEG4,
+                            MEDIA_MIMETYPE_VIDEO_H263,         MEDIA_MIMETYPE_VIDEO_MPEG2,
+                            MEDIA_MIMETYPE_VIDEO_RAW,          MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
+                            MEDIA_MIMETYPE_VIDEO_SCRAMBLED,    MEDIA_MIMETYPE_VIDEO_DIVX,
+                            MEDIA_MIMETYPE_VIDEO_DIVX3,        MEDIA_MIMETYPE_VIDEO_XVID,
+                            MEDIA_MIMETYPE_VIDEO_MJPEG,        MEDIA_MIMETYPE_AUDIO_AMR_NB,
+                            MEDIA_MIMETYPE_AUDIO_AMR_WB,       MEDIA_MIMETYPE_AUDIO_MPEG,
+                            MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
+                            MEDIA_MIMETYPE_AUDIO_MIDI,         MEDIA_MIMETYPE_AUDIO_AAC,
+                            MEDIA_MIMETYPE_AUDIO_QCELP,        MEDIA_MIMETYPE_AUDIO_VORBIS,
+                            MEDIA_MIMETYPE_AUDIO_OPUS,         MEDIA_MIMETYPE_AUDIO_G711_ALAW,
+                            MEDIA_MIMETYPE_AUDIO_G711_MLAW,    MEDIA_MIMETYPE_AUDIO_RAW,
+                            MEDIA_MIMETYPE_AUDIO_FLAC,         MEDIA_MIMETYPE_AUDIO_AAC_ADTS,
+                            MEDIA_MIMETYPE_AUDIO_MSGSM,        MEDIA_MIMETYPE_AUDIO_AC3,
+                            MEDIA_MIMETYPE_AUDIO_EAC3,         MEDIA_MIMETYPE_AUDIO_EAC3_JOC,
+                            MEDIA_MIMETYPE_AUDIO_AC4,          MEDIA_MIMETYPE_AUDIO_SCRAMBLED,
+                            MEDIA_MIMETYPE_AUDIO_ALAC,         MEDIA_MIMETYPE_AUDIO_WMA,
+                            MEDIA_MIMETYPE_AUDIO_MS_ADPCM,     MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM,
+                            MEDIA_MIMETYPE_CONTAINER_MPEG4,    MEDIA_MIMETYPE_CONTAINER_WAV,
+                            MEDIA_MIMETYPE_CONTAINER_OGG,      MEDIA_MIMETYPE_CONTAINER_MATROSKA,
+                            MEDIA_MIMETYPE_CONTAINER_MPEG2TS,  MEDIA_MIMETYPE_CONTAINER_AVI,
+                            MEDIA_MIMETYPE_CONTAINER_MPEG2PS,  MEDIA_MIMETYPE_CONTAINER_HEIF,
+                            MEDIA_MIMETYPE_TEXT_3GPP,          MEDIA_MIMETYPE_TEXT_SUBRIP,
+                            MEDIA_MIMETYPE_TEXT_VTT,           MEDIA_MIMETYPE_TEXT_CEA_608,
+                            MEDIA_MIMETYPE_TEXT_CEA_708,       MEDIA_MIMETYPE_DATA_TIMED_ID3};
+
+class MetadataRetrieverFuzzer {
+   public:
+    MetadataRetrieverFuzzer(const uint8_t *data, size_t size)
+        : mFdp(data, size),
+          mMdRetriever(new StagefrightMetadataRetriever()),
+          mDataSourceFd(memfd_create("InputFile", MFD_ALLOW_SEALING)) {}
+    ~MetadataRetrieverFuzzer() { close(mDataSourceFd); }
+    bool setDataSource(const uint8_t *data, size_t size);
+    void getData();
+
+   private:
+    FuzzedDataProvider mFdp;
+    sp<StagefrightMetadataRetriever> mMdRetriever = nullptr;
+    const int32_t mDataSourceFd;
+};
+
+void MetadataRetrieverFuzzer::getData() {
+    int64_t timeUs = mFdp.ConsumeIntegral<int64_t>();
+    int32_t option = mFdp.ConsumeIntegral<int32_t>();
+    int32_t colorFormat = mFdp.ConsumeIntegral<int32_t>();
+    bool metaOnly = mFdp.ConsumeBool();
+    mMdRetriever->getFrameAtTime(timeUs, option, colorFormat, metaOnly);
+
+    int32_t index = mFdp.ConsumeIntegral<int32_t>();
+    colorFormat = mFdp.ConsumeIntegral<int32_t>();
+    metaOnly = mFdp.ConsumeBool();
+    bool thumbnail = mFdp.ConsumeBool();
+    mMdRetriever->getImageAtIndex(index, colorFormat, metaOnly, thumbnail);
+
+    index = mFdp.ConsumeIntegral<int32_t>();
+    colorFormat = mFdp.ConsumeIntegral<int32_t>();
+    int32_t left = mFdp.ConsumeIntegral<int32_t>();
+    int32_t top = mFdp.ConsumeIntegral<int32_t>();
+    int32_t right = mFdp.ConsumeIntegral<int32_t>();
+    int32_t bottom = mFdp.ConsumeIntegral<int32_t>();
+    mMdRetriever->getImageRectAtIndex(index, colorFormat, left, top, right, bottom);
+
+    index = mFdp.ConsumeIntegral<int32_t>();
+    colorFormat = mFdp.ConsumeIntegral<int32_t>();
+    metaOnly = mFdp.ConsumeBool();
+    mMdRetriever->getFrameAtIndex(index, colorFormat, metaOnly);
+
+    mMdRetriever->extractAlbumArt();
+
+    int32_t keyCode = mFdp.ConsumeIntegral<int32_t>();
+    mMdRetriever->extractMetadata(keyCode);
+}
+
+bool MetadataRetrieverFuzzer::setDataSource(const uint8_t *data, size_t size) {
+    status_t status = -1;
+
+    enum DataSourceChoice {FromHttp, FromFd, FromFileSource, kMaxValue = FromFileSource};
+    switch (mFdp.ConsumeEnum<DataSourceChoice>()) {
+        case FromHttp: {
+            KeyedVector<String8, String8> mHeaders;
+            mHeaders.add(String8(mFdp.ConsumeRandomLengthString().c_str()),
+                         String8(mFdp.ConsumeRandomLengthString().c_str()));
+
+            uint32_t dataBlobSize = mFdp.ConsumeIntegralInRange<uint16_t>(0, size);
+            vector<uint8_t> uriSuffix = mFdp.ConsumeBytes<uint8_t>(dataBlobSize);
+
+            string uri("data:");
+            uri += ";base64,";
+            AString out;
+            encodeBase64(uriSuffix.data(), uriSuffix.size(), &out);
+            uri += out.c_str();
+            status = mMdRetriever->setDataSource(nullptr /*httpService*/, uri.c_str(), &mHeaders);
+            break;
+        }
+        case FromFd: {
+            write(mDataSourceFd, data, size);
+
+            status = mMdRetriever->setDataSource(mDataSourceFd, 0, size);
+            break;
+        }
+        case FromFileSource: {
+            write(mDataSourceFd, data, size);
+
+            sp<DataSource> dataSource = new FileSource(dup(mDataSourceFd), 0, size);
+            status = mMdRetriever->setDataSource(dataSource, mFdp.PickValueInArray(kMimeTypes));
+            break;
+        }
+    }
+
+    if (status != 0) {
+        return false;
+    }
+    return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    MetadataRetrieverFuzzer mrtFuzzer(data, size);
+    ProcessState::self()->startThreadPool();
+    if (mrtFuzzer.setDataSource(data, size)) {
+        mrtFuzzer.getData();
+    }
+    return 0;
+}
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 1e9d4fe..e47e7ff 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -373,7 +373,6 @@
         "libmedia",
         "android.hidl.allocator@1.0",
         "framework-permission-aidl-cpp",
-        "packagemanager_aidl-cpp",
     ],
 
     export_include_dirs: [
diff --git a/media/libstagefright/colorconversion/Android.bp b/media/libstagefright/colorconversion/Android.bp
index 06cebd3..7ff9b10 100644
--- a/media/libstagefright/colorconversion/Android.bp
+++ b/media/libstagefright/colorconversion/Android.bp
@@ -25,10 +25,6 @@
         "SoftwareRenderer.cpp",
     ],
 
-    include_dirs: [
-        "frameworks/native/include/media/openmax",
-    ],
-
     shared_libs: [
         "libui",
         "libnativewindow",
@@ -37,6 +33,7 @@
     header_libs: [
         "libstagefright_headers",
         "libstagefright_foundation_headers",
+        "media_plugin_headers",
     ],
 
     static_libs: ["libyuv_static"],
diff --git a/media/libstagefright/filters/Android.bp b/media/libstagefright/filters/Android.bp
index acc9e87..b46a271 100644
--- a/media/libstagefright/filters/Android.bp
+++ b/media/libstagefright/filters/Android.bp
@@ -22,10 +22,6 @@
         "ZeroFilter.cpp",
     ],
 
-    include_dirs: [
-        "frameworks/native/include/media/openmax",
-    ],
-
     cflags: [
         "-Wno-multichar",
         "-Werror",
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index dd2c66f..5f86c22 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -33,18 +33,13 @@
     },
     host_supported: true,
     double_loadable: true,
-    include_dirs: [
-        "frameworks/av/include",
-        "frameworks/native/include",
-        "frameworks/native/libs/arect/include",
-        "frameworks/native/libs/nativebase/include",
-    ],
 
     local_include_dirs: [
         "include/media/stagefright/foundation",
     ],
 
     header_libs: [
+        "av-headers",
         // this is only needed for the vendor variant that removes libbinder, but vendor
         // target below does not allow adding header_libs.
         "libbinder_headers",
diff --git a/media/libstagefright/foundation/tests/AVCUtils/Android.bp b/media/libstagefright/foundation/tests/AVCUtils/Android.bp
index 594da56..ee7db21 100644
--- a/media/libstagefright/foundation/tests/AVCUtils/Android.bp
+++ b/media/libstagefright/foundation/tests/AVCUtils/Android.bp
@@ -43,10 +43,6 @@
         "libstagefright_foundation",
     ],
 
-    include_dirs: [
-        "frameworks/av/media/libstagefright/foundation",
-    ],
-
     cflags: [
         "-Werror",
         "-Wall",
diff --git a/media/libstagefright/foundation/tests/Android.bp b/media/libstagefright/foundation/tests/Android.bp
index e50742e..e72ce43 100644
--- a/media/libstagefright/foundation/tests/Android.bp
+++ b/media/libstagefright/foundation/tests/Android.bp
@@ -18,10 +18,6 @@
         "-Wall",
     ],
 
-    include_dirs: [
-        "frameworks/av/include",
-    ],
-
     shared_libs: [
         "liblog",
         "libstagefright_foundation",
diff --git a/media/libstagefright/tests/HEVC/Android.bp b/media/libstagefright/tests/HEVC/Android.bp
index 91bf385..7a0ba52 100644
--- a/media/libstagefright/tests/HEVC/Android.bp
+++ b/media/libstagefright/tests/HEVC/Android.bp
@@ -44,10 +44,6 @@
         "libstagefright_foundation",
     ],
 
-    include_dirs: [
-        "frameworks/av/media/libstagefright",
-    ],
-
     cflags: [
         "-Werror",
         "-Wall",
diff --git a/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp b/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
index 324a042..c43e1f8 100644
--- a/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
+++ b/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
@@ -21,7 +21,7 @@
 #include <fstream>
 
 #include <media/stagefright/foundation/ABitReader.h>
-#include "include/HevcUtils.h"
+#include <HevcUtils.h>
 
 #include "HEVCUtilsTestEnvironment.h"
 
diff --git a/media/libstagefright/tests/extractorFactory/Android.bp b/media/libstagefright/tests/extractorFactory/Android.bp
index 13d5b89..a067284 100644
--- a/media/libstagefright/tests/extractorFactory/Android.bp
+++ b/media/libstagefright/tests/extractorFactory/Android.bp
@@ -51,10 +51,6 @@
         "libstagefright_foundation",
     ],
 
-    include_dirs: [
-        "frameworks/av/media/libstagefright",
-    ],
-
     // TODO: (b/150181583)
     compile_multilib: "first",
 
diff --git a/media/libstagefright/tests/fuzzers/Android.bp b/media/libstagefright/tests/fuzzers/Android.bp
index ea17a4d..250ffb9 100644
--- a/media/libstagefright/tests/fuzzers/Android.bp
+++ b/media/libstagefright/tests/fuzzers/Android.bp
@@ -74,6 +74,7 @@
     srcs: [
         "FrameDecoderFuzzer.cpp",
     ],
+    corpus: ["corpus/*"],
     defaults: ["libstagefright_fuzzer_defaults"],
 }
 
diff --git a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
index c251479..b346718 100644
--- a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
+++ b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
@@ -46,12 +46,15 @@
     }
 
     while (fdp.remaining_bytes()) {
-        switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 3)) {
-            case 0:
-                decoder->init(/*frameTimeUs*/ fdp.ConsumeIntegral<int64_t>(),
-                              /*option*/ fdp.ConsumeIntegral<int>(),
-                              /*colorFormat*/ fdp.ConsumeIntegral<int>());
+        uint8_t switchCase = fdp.ConsumeIntegralInRange<uint8_t>(0, 3);
+        switch (switchCase) {
+            case 0: {
+                int64_t frameTimeUs = fdp.ConsumeIntegral<int64_t>();
+                int option = fdp.ConsumeIntegral<int>();
+                int colorFormat = fdp.ConsumeIntegral<int>();
+                decoder->init(frameTimeUs, option, colorFormat);
                 break;
+            }
             case 1:
                 decoder->extractFrame();
                 break;
diff --git a/media/libstagefright/tests/fuzzers/corpus/color_format_rgb_565.dat b/media/libstagefright/tests/fuzzers/corpus/color_format_rgb_565.dat
new file mode 100644
index 0000000..698e21d
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/corpus/color_format_rgb_565.dat
Binary files differ
diff --git a/media/libstagefright/tests/writer/Android.bp b/media/libstagefright/tests/writer/Android.bp
index 38d5ecc..49fb569 100644
--- a/media/libstagefright/tests/writer/Android.bp
+++ b/media/libstagefright/tests/writer/Android.bp
@@ -52,10 +52,6 @@
         "libogg",
     ],
 
-    include_dirs: [
-        "frameworks/av/media/libstagefright",
-    ],
-
     cflags: [
         "-Werror",
         "-Wall",
diff --git a/media/libstagefright/tests/writer/WriterTest.cpp b/media/libstagefright/tests/writer/WriterTest.cpp
index d170e7c..398c592 100644
--- a/media/libstagefright/tests/writer/WriterTest.cpp
+++ b/media/libstagefright/tests/writer/WriterTest.cpp
@@ -36,7 +36,7 @@
 #include <media/stagefright/MPEG2TSWriter.h>
 #include <media/stagefright/MPEG4Writer.h>
 #include <media/stagefright/OggWriter.h>
-#include <webm/WebmWriter.h>
+#include <WebmWriter.h>
 
 #include "WriterTestEnvironment.h"
 #include "WriterUtility.h"
diff --git a/media/libstagefright/webm/Android.bp b/media/libstagefright/webm/Android.bp
index 32a22ba..4209aea 100644
--- a/media/libstagefright/webm/Android.bp
+++ b/media/libstagefright/webm/Android.bp
@@ -33,7 +33,7 @@
         "WebmWriter.cpp",
     ],
 
-    include_dirs: ["frameworks/av/include"],
+    export_include_dirs: ["."],
 
     shared_libs: [
         "libdatasource",
@@ -44,6 +44,7 @@
     ],
 
     header_libs: [
+        "av-headers",
         "libmedia_headers",
         "media_ndk_headers",
     ],
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index 6e29ac8..88b822d 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -72,7 +72,6 @@
 
     export_shared_lib_headers: [
         "libpermission",
-        "packagemanager_aidl-cpp",
     ],
 
     include_dirs: [
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 9c7b863..9620d24 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -71,6 +71,7 @@
   switch (source) {
     case AUDIO_SOURCE_HOTWORD:
       return AppOpsManager::OP_RECORD_AUDIO_HOTWORD;
+    case AUDIO_SOURCE_ECHO_REFERENCE: // fallthrough
     case AUDIO_SOURCE_REMOTE_SUBMIX:
       return AppOpsManager::OP_RECORD_AUDIO_OUTPUT;
     case AUDIO_SOURCE_VOICE_DOWNLINK:
diff --git a/media/utils/fuzzers/Android.bp b/media/utils/fuzzers/Android.bp
index c1698dc..c4dc24f 100644
--- a/media/utils/fuzzers/Android.bp
+++ b/media/utils/fuzzers/Android.bp
@@ -18,6 +18,7 @@
         "libutils",
         "libbinder",
         "framework-permission-aidl-cpp",
+        "packagemanager_aidl-cpp",
     ],
 
     cflags: [
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index f401fff..763c070 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -101,7 +101,6 @@
 
     export_shared_lib_headers: [
         "libpermission",
-        "packagemanager_aidl-cpp",
     ],
 
     cflags: [
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index fc34d95..26bd92d 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -89,6 +89,7 @@
     // TODO: Add channel mask to NBAIO_Format.
     // We assume that the channel mask must be a valid positional channel mask.
     mSinkChannelMask = getChannelMaskFromCount(mSinkChannelCount);
+    mBalance.setChannelMask(mSinkChannelMask);
 
     unsigned i;
     for (i = 0; i < FastMixerState::sMaxFastTracks; ++i) {
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 58d05c6..b444fd7 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -43,7 +43,7 @@
     DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr, const std::string &tagName = "",
             const FormatVector &encodedFormats = FormatVector{});
 
-    virtual ~DeviceDescriptor() {}
+    virtual ~DeviceDescriptor() = default;
 
     virtual void addAudioProfile(const sp<AudioProfile> &profile) {
         addAudioProfileAndSort(mProfiles, profile);
@@ -51,8 +51,6 @@
 
     virtual const std::string getTagName() const { return mTagName; }
 
-    const FormatVector& encodedFormats() const { return mEncodedFormats; }
-
     audio_format_t getEncodedFormat() { return mCurrentEncodedFormat; }
 
     void setEncodedFormat(audio_format_t format) {
@@ -63,8 +61,6 @@
 
     bool hasCurrentEncodedFormat() const;
 
-    bool supportsFormat(audio_format_t format);
-
     void setDynamic() { mIsDynamic = true; }
     bool isDynamic() const { return mIsDynamic; }
 
@@ -106,7 +102,6 @@
     }
 
     std::string mTagName; // Unique human readable identifier for a device port found in conf file.
-    FormatVector        mEncodedFormats;
     audio_format_t      mCurrentEncodedFormat;
     bool                mIsDynamic = false;
     const std::string   mDeclaredAddress; // Original device address
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 81828ed..0e1548f 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -37,9 +37,7 @@
 public:
     IOProfile(const std::string &name, audio_port_role_t role)
         : AudioPort(name, AUDIO_PORT_TYPE_MIX, role),
-          maxOpenCount(1),
           curOpenCount(0),
-          maxActiveCount(1),
           curActiveCount(0) {}
 
     virtual ~IOProfile() = default;
@@ -194,21 +192,11 @@
         return false;
     }
 
-    // Maximum number of input or output streams that can be simultaneously opened for this profile.
-    // By convention 0 means no limit. To respect legacy behavior, initialized to 1 for output
-    // profiles and 0 for input profiles
-    uint32_t     maxOpenCount;
     // Number of streams currently opened for this profile.
     uint32_t     curOpenCount;
-    // Maximum number of input or output streams that can be simultaneously active for this profile.
-    // By convention 0 means no limit. To respect legacy behavior, initialized to 0 for output
-    // profiles and 1 for input profiles
-    uint32_t     maxActiveCount;
     // Number of streams currently active for this profile. This is not the number of active clients
     // (AudioTrack or AudioRecord) but the number of active HAL streams.
     uint32_t     curActiveCount;
-    // Mute duration while changing device on this output profile.
-    uint32_t     recommendedMuteDurationMs = 0;
 
 private:
     DeviceVector mSupportedDevices; // supported devices: this input/output can be routed from/to
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index c9c8ede..4a4ee12 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -54,7 +54,7 @@
 DeviceDescriptor::DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr,
                                    const std::string &tagName,
                                    const FormatVector &encodedFormats) :
-        DeviceDescriptorBase(deviceTypeAddr), mTagName(tagName), mEncodedFormats(encodedFormats),
+        DeviceDescriptorBase(deviceTypeAddr, encodedFormats), mTagName(tagName),
         mDeclaredAddress(DeviceDescriptorBase::address())
 {
     mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
@@ -109,20 +109,6 @@
     return (mCurrentEncodedFormat != AUDIO_FORMAT_DEFAULT);
 }
 
-bool DeviceDescriptor::supportsFormat(audio_format_t format)
-{
-    if (mEncodedFormats.empty()) {
-        return true;
-    }
-
-    for (const auto& devFormat : mEncodedFormats) {
-        if (devFormat == format) {
-            return true;
-        }
-    }
-    return false;
-}
-
 status_t DeviceDescriptor::applyAudioPortConfig(const struct audio_port_config *config,
                                                 audio_port_config *backupConfig)
 {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a46da41..6221c05 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -5457,7 +5457,8 @@
             if (!desc->isDuplicated()) {
                 // exact match on device
                 if (device_distinguishes_on_address(deviceType) && desc->supportsDevice(device)
-                        && desc->containsSingleDeviceSupportingEncodedFormats(device)) {
+                        && desc->containsSingleDeviceSupportingEncodedFormats(device)
+                        && !mAvailableOutputDevices.containsAtLeastOne(desc->supportedDevices())) {
                     outputs.add(mOutputs.keyAt(i));
                 } else if (!mAvailableOutputDevices.containsAtLeastOne(desc->supportedDevices())) {
                     ALOGV("checkOutputsForDevice(): disconnecting adding output %d",
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 502a8d0..0fdbe20 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -627,6 +627,9 @@
 
 status_t Spatializer::attachOutput(audio_io_handle_t output) {
     std::shared_ptr<SpatializerPoseController> poseController;
+    bool outputChanged = false;
+    sp<media::INativeSpatializerCallback> callback;
+
     {
         std::lock_guard lock(mLock);
         ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
@@ -654,6 +657,7 @@
                              std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
 
         mEngine->setEnabled(true);
+        outputChanged = mOutput != output;
         mOutput = output;
 
         if (mSupportsHeadTracking) {
@@ -668,26 +672,42 @@
             mPoseController->setDisplayOrientation(mDisplayOrientation);
             poseController = mPoseController;
         }
+        callback = mSpatializerCallback;
     }
     if (poseController != nullptr) {
         poseController->waitUntilCalculated();
     }
+
+    if (outputChanged && callback != nullptr) {
+        callback->onOutputChanged(output);
+    }
+
     return NO_ERROR;
 }
 
 audio_io_handle_t Spatializer::detachOutput() {
-    std::lock_guard lock(mLock);
-    ALOGV("%s mOutput %d", __func__, (int)mOutput);
     audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
-    if (mOutput == AUDIO_IO_HANDLE_NONE) {
-        return output;
+    sp<media::INativeSpatializerCallback> callback;
+
+    {
+        std::lock_guard lock(mLock);
+        ALOGV("%s mOutput %d", __func__, (int)mOutput);
+        if (mOutput == AUDIO_IO_HANDLE_NONE) {
+            return output;
+        }
+        // remove FX instance
+        mEngine->setEnabled(false);
+        mEngine.clear();
+        output = mOutput;
+        mOutput = AUDIO_IO_HANDLE_NONE;
+        mPoseController.reset();
+
+        callback = mSpatializerCallback;
     }
-    // remove FX instance
-    mEngine->setEnabled(false);
-    mEngine.clear();
-    output = mOutput;
-    mOutput = AUDIO_IO_HANDLE_NONE;
-    mPoseController.reset();
+
+    if (callback != nullptr) {
+        callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
+    }
     return output;
 }
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 6c6e938..425c50d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -137,6 +137,7 @@
 static constexpr int32_t kVendorClientState = ActivityManager::PROCESS_STATE_PERSISTENT_UI;
 
 const String8 CameraService::kOfflineDevice("offline-");
+const String16 CameraService::kWatchAllClientsFlag("all");
 
 // Set to keep track of logged service error events.
 static std::set<String8> sServiceErrorEventSet;
@@ -1795,7 +1796,8 @@
         LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
                 __FUNCTION__);
 
-        err = client->initialize(mCameraProviderManager, mMonitorTags);
+        String8 monitorTags = isClientWatched(client.get()) ? mMonitorTags : String8("");
+        err = client->initialize(mCameraProviderManager, monitorTags);
         if (err != OK) {
             ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__);
             // Errors could be from the HAL module open call or from AppOpsManager
@@ -1843,10 +1845,9 @@
         // Set rotate-and-crop override behavior
         if (mOverrideRotateAndCropMode != ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
             client->setRotateAndCropOverride(mOverrideRotateAndCropMode);
-        } else if ((effectiveApiLevel == API_2) &&
-                CameraServiceProxyWrapper::isRotateAndCropOverrideNeeded(clientPackageName,
-                        orientation, facing) ) {
-            client->setRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_90);
+        } else if (effectiveApiLevel == API_2) {
+            client->setRotateAndCropOverride(CameraServiceProxyWrapper::getRotateAndCropOverride(
+                    clientPackageName, facing));
         }
 
         // Set camera muting behavior
@@ -1962,7 +1963,8 @@
             return BAD_VALUE;
         }
 
-        auto err = offlineClient->initialize(mCameraProviderManager, mMonitorTags);
+        String8 monitorTags = isClientWatched(offlineClient.get()) ? mMonitorTags : String8("");
+        auto err = offlineClient->initialize(mCameraProviderManager, monitorTags);
         if (err != OK) {
             ALOGE("%s: Could not initialize offline client.", __FUNCTION__);
             return err;
@@ -2248,13 +2250,9 @@
         if (current != nullptr) {
             const auto basicClient = current->getValue();
             if (basicClient.get() != nullptr && basicClient->canCastToApiClient(API_2)) {
-                if (CameraServiceProxyWrapper::isRotateAndCropOverrideNeeded(
-                            basicClient->getPackageName(), basicClient->getCameraOrientation(),
-                            basicClient->getCameraFacing())) {
-                    basicClient->setRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_90);
-                } else {
-                    basicClient->setRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE);
-                }
+                basicClient->setRotateAndCropOverride(
+                        CameraServiceProxyWrapper::getRotateAndCropOverride(
+                            basicClient->getPackageName(), basicClient->getCameraFacing()));
             }
         }
     }
@@ -2632,6 +2630,7 @@
     for (auto& i : mActiveClientManager.getAll()) {
         auto clientSp = i->getValue();
         if (clientSp.get() == client) {
+            cacheClientTagDumpIfNeeded(client->mCameraIdStr, clientSp.get());
             mActiveClientManager.remove(i);
         }
     }
@@ -2708,7 +2707,11 @@
         return sp<BasicClient>{nullptr};
     }
 
-    return clientDescriptorPtr->getValue();
+    sp<BasicClient> client = clientDescriptorPtr->getValue();
+    if (client.get() != nullptr) {
+        cacheClientTagDumpIfNeeded(clientDescriptorPtr->getKey(), client.get());
+    }
+    return client;
 }
 
 void CameraService::doUserSwitch(const std::vector<int32_t>& newUserIds) {
@@ -3127,6 +3130,21 @@
     return OK;
 }
 
+status_t CameraService::BasicClient::startWatchingTags(const String8&, int) {
+    // Can't watch tags directly, must go through CameraService::startWatchingTags
+    return OK;
+}
+
+status_t CameraService::BasicClient::stopWatchingTags(int) {
+    // Can't watch tags directly, must go through CameraService::stopWatchingTags
+    return OK;
+}
+
+status_t CameraService::BasicClient::dumpWatchedEventsToVector(std::vector<std::string> &) {
+    // Can't watch tags directly, must go through CameraService::dumpWatchedEventsToVector
+    return OK;
+}
+
 String16 CameraService::BasicClient::getPackageName() const {
     return mClientPackageName;
 }
@@ -4148,7 +4166,7 @@
 
     // Dump camera traces if there were any
     dprintf(fd, "\n");
-    camera3::CameraTraces::dump(fd, args);
+    camera3::CameraTraces::dump(fd);
 
     // Process dump arguments, if any
     int n = args.size();
@@ -4242,6 +4260,30 @@
     dprintf(fd, "\n");
 }
 
+void CameraService::cacheClientTagDumpIfNeeded(const char *cameraId, BasicClient* client) {
+    Mutex::Autolock lock(mLogLock);
+    if (!isClientWatchedLocked(client)) { return; }
+
+    std::vector<std::string> dumpVector;
+    client->dumpWatchedEventsToVector(dumpVector);
+
+    if (dumpVector.empty()) { return; }
+
+    std::string dumpString;
+    size_t i = dumpVector.size();
+
+    // Store the string in reverse order (latest last)
+    while (i > 0) {
+         i--;
+         dumpString += cameraId;
+         dumpString += ":";
+         dumpString += dumpVector[i]; // implicitly ends with '\n'
+    }
+
+    const String16 &packageName = client->getPackageName();
+    mWatchedClientsDumpCache[packageName] = dumpString;
+}
+
 void CameraService::handleTorchClientBinderDied(const wp<IBinder> &who) {
     Mutex::Autolock al(mTorchClientMapMutex);
     for (size_t i = 0; i < mTorchClientMap.size(); i++) {
@@ -4546,9 +4588,11 @@
         return handleGetImageDumpMask(out);
     } else if (args.size() >= 2 && args[0] == String16("set-camera-mute")) {
         return handleSetCameraMute(args);
+    } else if (args.size() >= 2 && args[0] == String16("watch")) {
+        return handleWatchCommand(args, out);
     } else if (args.size() == 1 && args[0] == String16("help")) {
         printHelp(out);
-        return NO_ERROR;
+        return OK;
     }
     printHelp(err);
     return BAD_VALUE;
@@ -4692,6 +4736,233 @@
     return OK;
 }
 
+status_t CameraService::handleWatchCommand(const Vector<String16>& args, int outFd) {
+    if (args.size() >= 3 && args[1] == String16("start")) {
+        return startWatchingTags(args, outFd);
+    } else if (args.size() == 2 && args[1] == String16("dump")) {
+        return camera3::CameraTraces::dump(outFd);
+    } else if (args.size() == 2 && args[1] == String16("stop")) {
+        return stopWatchingTags(outFd);
+    } else if (args.size() >= 2 && args[1] == String16("print")) {
+        return printWatchedTags(args, outFd);
+    }
+    dprintf(outFd, "Camera service watch commands:\n"
+                 "  start -m <comma_separated_tag_list> [-c <comma_separated_client_list>]\n"
+                 "        starts watching the provided tags for clients with provided package\n"
+                 "        recognizes tag shorthands like '3a'\n"
+                 "        watches all clients if no client is passed, or if 'all' is listed\n"
+                 "  dump dumps camera trace\n"
+                 "  stop stops watching all tags\n"
+                 "  print [-n <refresh_interval_ms>]\n"
+                 "        prints the monitored information in real time\n"
+                 "        Hit Ctrl+C to exit\n");
+  return BAD_VALUE;
+}
+
+status_t CameraService::startWatchingTags(const Vector<String16> &args, int outFd) {
+    Mutex::Autolock lock(mLogLock);
+    size_t tagsIdx; // index of '-m'
+    String16 tags("");
+    for (tagsIdx = 2; tagsIdx < args.size() && args[tagsIdx] != String16("-m"); tagsIdx++);
+    if (tagsIdx < args.size() - 1) {
+        tags = args[tagsIdx + 1];
+    } else {
+        dprintf(outFd, "No tags provided.\n");
+        return BAD_VALUE;
+    }
+
+    size_t clientsIdx; // index of '-c'
+    String16 clients = kWatchAllClientsFlag; // watch all clients if no clients are provided
+    for (clientsIdx = 2; clientsIdx < args.size() && args[clientsIdx] != String16("-c");
+         clientsIdx++);
+    if (clientsIdx < args.size() - 1) {
+        clients = args[clientsIdx + 1];
+    }
+    parseClientsToWatchLocked(String8(clients));
+
+    // track tags to initialize future clients with the monitoring information
+    mMonitorTags = String8(tags);
+
+    bool serviceLock = tryLock(mServiceLock);
+    int numWatchedClients = 0;
+    auto cameraClients = mActiveClientManager.getAll();
+    for (const auto &clientDescriptor: cameraClients) {
+        if (clientDescriptor == nullptr) { continue; }
+        sp<BasicClient> client = clientDescriptor->getValue();
+        if (client.get() == nullptr) { continue; }
+
+        if (isClientWatchedLocked(client.get())) {
+            client->startWatchingTags(mMonitorTags, outFd);
+            numWatchedClients++;
+        }
+    }
+    dprintf(outFd, "Started watching %d active clients\n", numWatchedClients);
+
+    if (serviceLock) { mServiceLock.unlock(); }
+    return OK;
+}
+
+status_t CameraService::stopWatchingTags(int outFd) {
+    // clear mMonitorTags to prevent new clients from monitoring tags at initialization
+    Mutex::Autolock lock(mLogLock);
+    mMonitorTags = String8::empty();
+
+    mWatchedClientPackages.clear();
+    mWatchedClientsDumpCache.clear();
+
+    bool serviceLock = tryLock(mServiceLock);
+    auto cameraClients = mActiveClientManager.getAll();
+    for (const auto &clientDescriptor : cameraClients) {
+        if (clientDescriptor == nullptr) { continue; }
+        sp<BasicClient> client = clientDescriptor->getValue();
+        if (client.get() == nullptr) { continue; }
+        client->stopWatchingTags(outFd);
+    }
+    dprintf(outFd, "Stopped watching all clients.\n");
+    if (serviceLock) { mServiceLock.unlock(); }
+    return OK;
+}
+
+status_t CameraService::printWatchedTags(const Vector<String16> &args, int outFd) {
+    // Figure outFd refresh interval, if present in args
+    useconds_t refreshTimeoutMs = 1000; // refresh every 1s by default
+    if (args.size() > 2) {
+        size_t intervalIdx; // index of '-n'
+        for (intervalIdx = 2; intervalIdx < args.size() && String16("-n") != args[intervalIdx];
+             intervalIdx++);
+
+        size_t intervalValIdx = intervalIdx + 1;
+        if (intervalValIdx < args.size()) {
+            refreshTimeoutMs = strtol(String8(args[intervalValIdx].string()), nullptr, 10);
+            if (errno) { return BAD_VALUE; }
+        }
+    }
+
+    mLogLock.lock();
+    bool serviceLock = tryLock(mServiceLock);
+    // get all watched clients that are currently connected
+    std::set<String16> connectedMoniterdClients;
+    for (const auto &clientDescriptor: mActiveClientManager.getAll()) {
+        if (clientDescriptor == nullptr) { continue; }
+
+        sp<BasicClient> client = clientDescriptor->getValue();
+        if (client.get() == nullptr) { continue; }
+        if (!isClientWatchedLocked(client.get())) { continue; }
+
+        connectedMoniterdClients.emplace(client->getPackageName());
+    }
+    if (serviceLock) { mServiceLock.unlock(); }
+
+    // Print entries in mWatchedClientsDumpCache for clients that are not connected
+    for (const auto &kv: mWatchedClientsDumpCache) {
+        const String16 &package = kv.first;
+        if (connectedMoniterdClients.find(package) != connectedMoniterdClients.end()) {
+            continue;
+        }
+
+        dprintf(outFd, "Client: %s\n", String8(package).string());
+        dprintf(outFd, "%s\n", kv.second.c_str());
+    }
+    mLogLock.unlock();
+
+    if (connectedMoniterdClients.empty()) {
+        dprintf(outFd, "No watched client active.\n");
+        return OK;
+    }
+
+    // For connected watched clients, print monitored tags live
+    return printWatchedTagsUntilInterrupt(refreshTimeoutMs  * 1000, outFd);
+}
+
+status_t CameraService::printWatchedTagsUntilInterrupt(useconds_t refreshMicros, int outFd) {
+    std::unordered_map<std::string, std::string> cameraToLastEvent;
+    auto cameraClients = mActiveClientManager.getAll();
+
+    if (cameraClients.empty()) {
+        dprintf(outFd, "No clients connected.\n");
+        return OK;
+    }
+
+    dprintf(outFd, "Press Ctrl + C to exit...\n\n");
+    while (true) {
+        for (const auto& clientDescriptor : cameraClients) {
+            Mutex::Autolock lock(mLogLock);
+            if (clientDescriptor == nullptr) { continue; }
+            const char* cameraId = clientDescriptor->getKey().string();
+
+            // This also initializes the map entries with an empty string
+            const std::string& lastPrintedEvent = cameraToLastEvent[cameraId];
+
+            sp<BasicClient> client = clientDescriptor->getValue();
+            if (client.get() == nullptr) { continue; }
+            if (!isClientWatchedLocked(client.get())) { continue; }
+
+            std::vector<std::string> latestEvents;
+            client->dumpWatchedEventsToVector(latestEvents);
+
+            if (!latestEvents.empty()) {
+                printNewWatchedEvents(outFd,
+                                      cameraId,
+                                      client->getPackageName(),
+                                      latestEvents,
+                                      lastPrintedEvent);
+                cameraToLastEvent[cameraId] = latestEvents[0];
+            }
+        }
+        usleep(refreshMicros);  // convert ms to us
+    }
+    return OK;
+}
+
+void CameraService::printNewWatchedEvents(int outFd,
+                                          const char *cameraId,
+                                          const String16 &packageName,
+                                          const std::vector<std::string> &events,
+                                          const std::string &lastPrintedEvent) {
+    if (events.empty()) { return; }
+
+    // index of lastPrintedEvent in events.
+    // lastPrintedIdx = events.size() if lastPrintedEvent is not in events
+    size_t lastPrintedIdx;
+    for (lastPrintedIdx = 0;
+         lastPrintedIdx < events.size() && lastPrintedEvent != events[lastPrintedIdx];
+         lastPrintedIdx++);
+
+    if (lastPrintedIdx == 0) { return; } // early exit if no new event in `events`
+
+    const char *printPackageName = String8(packageName).string();
+    // print events in chronological order (latest event last)
+    size_t idxToPrint = lastPrintedIdx;
+    do {
+        idxToPrint--;
+        dprintf(outFd, "%s:%s  %s", cameraId, printPackageName, events[idxToPrint].c_str());
+    } while (idxToPrint != 0);
+}
+
+void CameraService::parseClientsToWatchLocked(String8 clients) {
+    mWatchedClientPackages.clear();
+
+    const char *allSentinel = String8(kWatchAllClientsFlag).string();
+
+    char *tokenized = clients.lockBuffer(clients.size());
+    char *savePtr;
+    char *nextClient = strtok_r(tokenized, ",", &savePtr);
+
+    while (nextClient != nullptr) {
+        if (strcmp(nextClient, allSentinel) == 0) {
+            // Don't need to track any other package if 'all' is present
+            mWatchedClientPackages.clear();
+            mWatchedClientPackages.emplace(kWatchAllClientsFlag);
+            break;
+        }
+
+        // track package names
+        mWatchedClientPackages.emplace(nextClient);
+        nextClient = strtok_r(nullptr, ",", &savePtr);
+    }
+    clients.unlockBuffer();
+}
+
 status_t CameraService::printHelp(int out) {
     return dprintf(out, "Camera service commands:\n"
         "  get-uid-state <PACKAGE> [--user USER_ID] gets the uid state\n"
@@ -4704,9 +4975,20 @@
         "      Valid values 0=OFF, 1=ON for JPEG\n"
         "  get-image-dump-mask returns the current image-dump-mask value\n"
         "  set-camera-mute <0/1> enable or disable camera muting\n"
+        "  watch <start|stop|dump|live> manages tag monitoring in connected clients\n"
         "  help print this message\n");
 }
 
+bool CameraService::isClientWatched(const BasicClient *client) {
+    Mutex::Autolock lock(mLogLock);
+    return isClientWatchedLocked(client);
+}
+
+bool CameraService::isClientWatchedLocked(const BasicClient *client) {
+    return mWatchedClientPackages.find(kWatchAllClientsFlag) != mWatchedClientPackages.end() ||
+           mWatchedClientPackages.find(client->getPackageName()) != mWatchedClientPackages.end();
+}
+
 int32_t CameraService::updateAudioRestriction() {
     Mutex::Autolock lock(mServiceLock);
     return updateAudioRestrictionLocked();
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 7f18794..cb26763 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -280,6 +280,10 @@
         // Internal dump method to be called by CameraService
         virtual status_t dumpClient(int fd, const Vector<String16>& args) = 0;
 
+        virtual status_t startWatchingTags(const String8 &tags, int outFd);
+        virtual status_t stopWatchingTags(int outFd);
+        virtual status_t dumpWatchedEventsToVector(std::vector<std::string> &out);
+
         // Return the package name for this client
         virtual String16 getPackageName() const;
 
@@ -833,6 +837,14 @@
     RingBuffer<String8> mEventLog;
     Mutex mLogLock;
 
+    // set of client package names to watch. if this set contains 'all', then all clients will
+    // be watched. Access should be guarded by mLogLock
+    std::set<String16> mWatchedClientPackages;
+    // cache of last monitored tags dump immediately before the client disconnects. If a client
+    // re-connects, its entry is not updated until it disconnects again. Access should be guarded
+    // by mLogLock
+    std::map<String16, std::string> mWatchedClientsDumpCache;
+
     // The last monitored tags set by client
     String8 mMonitorTags;
 
@@ -965,6 +977,8 @@
      */
     void dumpEventLog(int fd);
 
+    void cacheClientTagDumpIfNeeded(const char *cameraId, BasicClient *client);
+
     /**
      * This method will acquire mServiceLock
      */
@@ -1157,9 +1171,47 @@
     // Set the camera mute state
     status_t handleSetCameraMute(const Vector<String16>& args);
 
+    // Handle 'watch' command as passed through 'cmd'
+    status_t handleWatchCommand(const Vector<String16> &args, int outFd);
+
+    // Enable tag monitoring of the given tags in provided clients
+    status_t startWatchingTags(const Vector<String16> &args, int outFd);
+
+    // Disable tag monitoring
+    status_t stopWatchingTags(int outFd);
+
+    // Print events of monitored tags in all cached and attached clients
+    status_t printWatchedTags(const Vector<String16> &args, int outFd);
+
+    // Print events of monitored tags in all attached clients as they are captured. New events are
+    // fetched every `refreshMicros` us
+    // NOTE: This function does not terminate unless interrupted.
+    status_t printWatchedTagsUntilInterrupt(useconds_t refreshMicros, int outFd);
+
+    // Print all events in vector `events' that came after lastPrintedEvent
+    static void printNewWatchedEvents(int outFd,
+                                      const char *cameraId,
+                                      const String16 &packageName,
+                                      const std::vector<std::string> &events,
+                                      const std::string &lastPrintedEvent);
+
+    // Parses comma separated clients list and adds them to mWatchedClientPackages.
+    // Does not acquire mLogLock before modifying mWatchedClientPackages. It is the caller's
+    // responsibility to acquire mLogLock before calling this function.
+    void parseClientsToWatchLocked(String8 clients);
+
     // Prints the shell command help
     status_t printHelp(int out);
 
+    // Returns true if client should monitor tags based on the contents of mWatchedClientPackages.
+    // Acquires mLogLock before querying mWatchedClientPackages.
+    bool isClientWatched(const BasicClient *client);
+
+    // Returns true if client should monitor tags based on the contents of mWatchedClientPackages.
+    // Does not acquire mLogLock before querying mWatchedClientPackages. It is the caller's
+    // responsibility to acquire mLogLock before calling this functions.
+    bool isClientWatchedLocked(const BasicClient *client);
+
     /**
      * Get the current system time as a formatted string.
      */
@@ -1190,6 +1242,10 @@
     // Use separate keys for offline devices.
     static const String8 kOfflineDevice;
 
+    // Sentinel value to be stored in `mWatchedClientsPackages` to indicate that all clients should
+    // be watched.
+    static const String16 kWatchAllClientsFlag;
+
     // TODO: right now each BasicClient holds one AppOpsManager instance.
     // We can refactor the code so all of clients share this instance
     AppOpsManager mAppOps;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 1f3d478..67ec150 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -1797,6 +1797,35 @@
     return dumpDevice(fd, args);
 }
 
+status_t CameraDeviceClient::startWatchingTags(const String8 &tags, int out) {
+    sp<CameraDeviceBase> device = mDevice;
+    if (!device) {
+        dprintf(out, "  Device is detached.");
+        return OK;
+    }
+    device->startWatchingTags(tags);
+    return OK;
+}
+
+status_t CameraDeviceClient::stopWatchingTags(int out) {
+    sp<CameraDeviceBase> device = mDevice;
+    if (!device) {
+        dprintf(out, "  Device is detached.");
+        return OK;
+    }
+    device->stopWatchingTags();
+    return OK;
+}
+
+status_t CameraDeviceClient::dumpWatchedEventsToVector(std::vector<std::string> &out) {
+    sp<CameraDeviceBase> device = mDevice;
+    if (!device) {
+        return OK;
+    }
+    device->dumpWatchedEventsToVector(out);
+    return OK;
+}
+
 void CameraDeviceClient::notifyError(int32_t errorCode,
                                      const CaptureResultExtras& resultExtras) {
     // Thread safe. Don't bother locking.
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 76b3f53..288f2d7 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -199,6 +199,10 @@
 
     virtual status_t      dumpClient(int fd, const Vector<String16>& args);
 
+    virtual status_t      startWatchingTags(const String8 &tags, int out);
+    virtual status_t      stopWatchingTags(int out);
+    virtual status_t      dumpWatchedEventsToVector(std::vector<std::string> &out);
+
     /**
      * Device listener interface
      */
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 652842b..10fa33f 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -110,6 +110,18 @@
     return OK;
 }
 
+status_t CameraOfflineSessionClient::startWatchingTags(const String8 &tags, int outFd) {
+    return BasicClient::startWatchingTags(tags, outFd);
+}
+
+status_t CameraOfflineSessionClient::stopWatchingTags(int outFd) {
+    return BasicClient::stopWatchingTags(outFd);
+}
+
+status_t CameraOfflineSessionClient::dumpWatchedEventsToVector(std::vector<std::string> &out) {
+    return BasicClient::dumpWatchedEventsToVector(out);
+}
+
 binder::Status CameraOfflineSessionClient::disconnect() {
     Mutex::Autolock icl(mBinderSerializationLock);
 
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index b5238b8..920a176 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -71,6 +71,10 @@
 
     status_t dumpClient(int /*fd*/, const Vector<String16>& /*args*/) override;
 
+    status_t startWatchingTags(const String8 &tags, int outFd) override;
+    status_t stopWatchingTags(int outFd) override;
+    status_t dumpWatchedEventsToVector(std::vector<std::string> &out) override;
+
     status_t initialize(sp<CameraProviderManager> /*manager*/,
             const String8& /*monitorTags*/) override;
 
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 1147e23..0283d01 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -155,6 +155,38 @@
 }
 
 template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::startWatchingTags(const String8 &tags, int out) {
+  sp<CameraDeviceBase> device = mDevice;
+  if (!device) {
+    dprintf(out, "  Device is detached");
+    return OK;
+  }
+
+  return device->startWatchingTags(tags);
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::stopWatchingTags(int out) {
+  sp<CameraDeviceBase> device = mDevice;
+  if (!device) {
+    dprintf(out, "  Device is detached");
+    return OK;
+  }
+
+  return device->stopWatchingTags();
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::dumpWatchedEventsToVector(std::vector<std::string> &out) {
+    sp<CameraDeviceBase> device = mDevice;
+    if (!device) {
+        // Nothing to dump if the device is detached
+        return OK;
+    }
+    return device->dumpWatchedEventsToVector(out);
+}
+
+template <typename TClientBase>
 status_t Camera2ClientBase<TClientBase>::dumpDevice(
                                                 int fd,
                                                 const Vector<String16>& args) {
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index b593bfa..ba6a230 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -61,6 +61,9 @@
 
     virtual status_t      initialize(sp<CameraProviderManager> manager, const String8& monitorTags);
     virtual status_t      dumpClient(int fd, const Vector<String16>& args);
+    virtual status_t      startWatchingTags(const String8 &tags, int out);
+    virtual status_t      stopWatchingTags(int out);
+    virtual status_t      dumpWatchedEventsToVector(std::vector<std::string> &out);
 
     /**
      * NotificationListener implementation
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 3c95ed3..8168821 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -97,6 +97,9 @@
     virtual status_t disconnect() = 0;
 
     virtual status_t dump(int fd, const Vector<String16> &args) = 0;
+    virtual status_t startWatchingTags(const String8 &tags) = 0;
+    virtual status_t stopWatchingTags() = 0;
+    virtual status_t dumpWatchedEventsToVector(std::vector<std::string> &out) = 0;
 
     /**
      * The physical camera device's static characteristics metadata buffer
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 91fc483..75b2f80 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -1631,6 +1631,7 @@
         case 3:
             deviceInfo = initializeDeviceInfo<DeviceInfo3>(name, mProviderTagid,
                     id, minor);
+            deviceInfo->notifyDeviceStateChange(mDeviceState);
             break;
         default:
             ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 67f99bf..8925b15 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -848,6 +848,21 @@
     return OK;
 }
 
+status_t Camera3Device::startWatchingTags(const String8 &tags) {
+    mTagMonitor.parseTagsToMonitor(tags);
+    return OK;
+}
+
+status_t Camera3Device::stopWatchingTags() {
+    mTagMonitor.disableMonitoring();
+    return OK;
+}
+
+status_t Camera3Device::dumpWatchedEventsToVector(std::vector<std::string> &out) {
+    mTagMonitor.getLatestMonitoredTagEvents(out);
+    return OK;
+}
+
 const CameraMetadata& Camera3Device::infoPhysical(const String8& physicalId) const {
     ALOGVV("%s: E", __FUNCTION__);
     if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 4ffdc5f..f2394ad 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -106,6 +106,9 @@
     status_t initialize(sp<CameraProviderManager> manager, const String8& monitorTags) override;
     status_t disconnect() override;
     status_t dump(int fd, const Vector<String16> &args) override;
+    status_t startWatchingTags(const String8 &tags) override;
+    status_t stopWatchingTags() override;
+    status_t dumpWatchedEventsToVector(std::vector<std::string> &out) override;
     const CameraMetadata& info() const override;
     const CameraMetadata& infoPhysical(const String8& physicalId) const override;
 
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
index 76927c0..8d170f1 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
@@ -120,13 +120,11 @@
     proxyBinder->pingForUserUpdate();
 }
 
-bool CameraServiceProxyWrapper::isRotateAndCropOverrideNeeded(
-        String16 packageName, int sensorOrientation, int lensFacing) {
+int CameraServiceProxyWrapper::getRotateAndCropOverride(String16 packageName, int lensFacing) {
     sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
     if (proxyBinder == nullptr) return true;
-    bool ret = true;
-    auto status = proxyBinder->isRotateAndCropOverrideNeeded(packageName, sensorOrientation,
-            lensFacing, &ret);
+    int ret = 0;
+    auto status = proxyBinder->getRotateAndCropOverride(packageName, lensFacing, &ret);
     if (!status.isOk()) {
         ALOGE("%s: Failed during top activity orientation query: %s", __FUNCTION__,
                 status.exceptionMessage().c_str());
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
index ad9db68..a51e568 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
@@ -91,9 +91,8 @@
     // Ping camera service proxy for user update
     static void pingCameraServiceProxy();
 
-    // Check whether the current top activity needs a rotate and crop override.
-    static bool isRotateAndCropOverrideNeeded(String16 packageName, int sensorOrientation,
-            int lensFacing);
+    // Return the current top activity rotate and crop override.
+    static int getRotateAndCropOverride(String16 packageName, int lensFacing);
 };
 
 } // android
diff --git a/services/camera/libcameraservice/utils/CameraTraces.cpp b/services/camera/libcameraservice/utils/CameraTraces.cpp
index 0198690..0cd4f5d 100644
--- a/services/camera/libcameraservice/utils/CameraTraces.cpp
+++ b/services/camera/libcameraservice/utils/CameraTraces.cpp
@@ -64,7 +64,7 @@
     ATRACE_END();
 }
 
-status_t CameraTraces::dump(int fd, const Vector<String16> &args __attribute__((unused))) {
+status_t CameraTraces::dump(int fd) {
     ALOGV("%s: fd = %d", __FUNCTION__, fd);
     Mutex::Autolock al(sImpl.tracesLock);
     List<ProcessCallStack>& pcsList = sImpl.pcsList;
diff --git a/services/camera/libcameraservice/utils/CameraTraces.h b/services/camera/libcameraservice/utils/CameraTraces.h
index 13ca16d..71fa334 100644
--- a/services/camera/libcameraservice/utils/CameraTraces.h
+++ b/services/camera/libcameraservice/utils/CameraTraces.h
@@ -42,7 +42,7 @@
      *
      * <p>Each line is indented by DUMP_INDENT spaces.</p>
      */
-    static status_t dump(int fd, const Vector<String16>& args);
+    static status_t dump(int fd);
 
 private:
     enum {
diff --git a/services/camera/libcameraservice/utils/TagMonitor.cpp b/services/camera/libcameraservice/utils/TagMonitor.cpp
index 4488098..461f5e9 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.cpp
+++ b/services/camera/libcameraservice/utils/TagMonitor.cpp
@@ -239,38 +239,59 @@
     } else {
         dprintf(fd, "     Tag monitoring disabled (enable with -m <name1,..,nameN>)\n");
     }
-    if (mMonitoringEvents.size() > 0) {
-        dprintf(fd, "     Monitored tag event log:\n");
-        for (const auto& event : mMonitoringEvents) {
-            int indentation = (event.source == REQUEST) ? 15 : 30;
-            dprintf(fd, "        f%d:%" PRId64 "ns:%*s%*s%s.%s: ",
-                    event.frameNumber, event.timestamp,
-                    2, event.cameraId.c_str(),
-                    indentation,
-                    event.source == REQUEST ? "REQ:" : "RES:",
-                    get_local_camera_metadata_section_name_vendor_id(event.tag,
-                            mVendorTagId),
-                    get_local_camera_metadata_tag_name_vendor_id(event.tag,
-                            mVendorTagId));
-            if (event.newData.size() == 0) {
-                dprintf(fd, " (Removed)\n");
-            } else {
-                printData(fd, event.newData.data(), event.tag,
-                        event.type, event.newData.size() / camera_metadata_type_size[event.type],
-                        indentation + 18, event.outputStreamIds, event.inputStreamId);
-            }
-        }
-    }
 
+    if (mMonitoringEvents.size() == 0) { return; }
+
+    dprintf(fd, "     Monitored tag event log:\n");
+
+    std::vector<std::string> eventStrs;
+    dumpMonitoredTagEventsToVectorLocked(eventStrs);
+    for (const std::string &eventStr : eventStrs) {
+        dprintf(fd, "        %s", eventStr.c_str());
+    }
 }
 
-// TODO: Consolidate with printData from camera_metadata.h
+void TagMonitor::getLatestMonitoredTagEvents(std::vector<std::string> &out) {
+    std::lock_guard<std::mutex> lock(mMonitorMutex);
+    dumpMonitoredTagEventsToVectorLocked(out);
+}
+
+void TagMonitor::dumpMonitoredTagEventsToVectorLocked(std::vector<std::string> &vec) {
+    if (mMonitoringEvents.size() == 0) { return; }
+
+    for (const auto& event : mMonitoringEvents) {
+        int indentation = (event.source == REQUEST) ? 15 : 30;
+        String8 eventString = String8::format("f%d:%" PRId64 "ns:%*s%*s%s.%s: ",
+                event.frameNumber, event.timestamp,
+                2, event.cameraId.c_str(),
+                indentation,
+                event.source == REQUEST ? "REQ:" : "RES:",
+                get_local_camera_metadata_section_name_vendor_id(event.tag, mVendorTagId),
+                get_local_camera_metadata_tag_name_vendor_id(event.tag, mVendorTagId));
+        if (event.newData.size() == 0) {
+            eventString += " (Removed)";
+        } else {
+            eventString += getEventDataString(event.newData.data(),
+                                    event.tag,
+                                    event.type,
+                                    event.newData.size() / camera_metadata_type_size[event.type],
+                                    indentation + 18,
+                                    event.outputStreamIds,
+                                    event.inputStreamId);
+        }
+        vec.emplace_back(eventString.string());
+    }
+}
 
 #define CAMERA_METADATA_ENUM_STRING_MAX_SIZE 29
 
-void TagMonitor::printData(int fd, const uint8_t *data_ptr, uint32_t tag,
-        int type, int count, int indentation, const std::unordered_set<int32_t> &outputStreamIds,
-        int32_t inputStreamId) {
+String8 TagMonitor::getEventDataString(const uint8_t* data_ptr,
+                                    uint32_t tag,
+                                    int type,
+                                    int count,
+                                    int indentation,
+                                    const std::unordered_set<int32_t>& outputStreamIds,
+                                    int32_t inputStreamId) {
     static int values_per_line[NUM_TYPES] = {
         [TYPE_BYTE]     = 16,
         [TYPE_INT32]    = 8,
@@ -279,6 +300,7 @@
         [TYPE_DOUBLE]   = 4,
         [TYPE_RATIONAL] = 4,
     };
+
     size_t type_size = camera_metadata_type_size[type];
     char value_string_tmp[CAMERA_METADATA_ENUM_STRING_MAX_SIZE];
     uint32_t value;
@@ -286,10 +308,11 @@
     int lines = count / values_per_line[type];
     if (count % values_per_line[type] != 0) lines++;
 
+    String8 returnStr = String8();
     int index = 0;
     int j, k;
     for (j = 0; j < lines; j++) {
-        dprintf(fd, "%*s[", (j != 0) ? indentation + 4 : 0, "");
+        returnStr.appendFormat("%*s[", (j != 0) ? indentation + 4 : 0, "");
         for (k = 0;
              k < values_per_line[type] && count > 0;
              k++, count--, index += type_size) {
@@ -302,10 +325,9 @@
                                                      value_string_tmp,
                                                      sizeof(value_string_tmp))
                         == OK) {
-                        dprintf(fd, "%s ", value_string_tmp);
+                        returnStr += value_string_tmp;
                     } else {
-                        dprintf(fd, "%hhu ",
-                                *(data_ptr + index));
+                        returnStr.appendFormat("%hhu", *(data_ptr + index));
                     }
                     break;
                 case TYPE_INT32:
@@ -316,47 +338,43 @@
                                                      value_string_tmp,
                                                      sizeof(value_string_tmp))
                         == OK) {
-                        dprintf(fd, "%s ", value_string_tmp);
+                        returnStr += value_string_tmp;
                     } else {
-                        dprintf(fd, "%" PRId32 " ",
-                                *(int32_t*)(data_ptr + index));
+                        returnStr.appendFormat("%" PRId32 " ", *(int32_t*)(data_ptr + index));
                     }
                     break;
                 case TYPE_FLOAT:
-                    dprintf(fd, "%0.8f ",
-                            *(float*)(data_ptr + index));
+                    returnStr.appendFormat("%0.8f", *(float*)(data_ptr + index));
                     break;
                 case TYPE_INT64:
-                    dprintf(fd, "%" PRId64 " ",
-                            *(int64_t*)(data_ptr + index));
+                    returnStr.appendFormat("%" PRId64 " ", *(int64_t*)(data_ptr + index));
                     break;
                 case TYPE_DOUBLE:
-                    dprintf(fd, "%0.8f ",
-                            *(double*)(data_ptr + index));
+                    returnStr.appendFormat("%0.8f ", *(double*)(data_ptr + index));
                     break;
                 case TYPE_RATIONAL: {
                     int32_t numerator = *(int32_t*)(data_ptr + index);
                     int32_t denominator = *(int32_t*)(data_ptr + index + 4);
-                    dprintf(fd, "(%d / %d) ",
-                            numerator, denominator);
+                    returnStr.appendFormat("(%d / %d) ", numerator, denominator);
                     break;
                 }
                 default:
-                    dprintf(fd, "??? ");
+                    returnStr += "??? ";
             }
         }
-        dprintf(fd, "] ");
-        if (outputStreamIds.size() > 0) {
-            dprintf(fd, "output stream ids: ");
+        returnStr += "] ";
+        if (!outputStreamIds.empty()) {
+            returnStr += "output stream ids: ";
             for (const auto &id : outputStreamIds) {
-                dprintf(fd, " %d ", id);
+                returnStr.appendFormat(" %d ", id);
             }
         }
         if (inputStreamId != -1) {
-            dprintf(fd, "input stream id: %d", inputStreamId);
+            returnStr.appendFormat("input stream id: %d", inputStreamId);
         }
-        dprintf(fd, "\n");
+        returnStr += "\n";
     }
+    return returnStr;
 }
 
 template<typename T>
diff --git a/services/camera/libcameraservice/utils/TagMonitor.h b/services/camera/libcameraservice/utils/TagMonitor.h
index f6df4b7..088d6fe 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.h
+++ b/services/camera/libcameraservice/utils/TagMonitor.h
@@ -74,11 +74,23 @@
     // Dump current event log to the provided fd
     void dumpMonitoredMetadata(int fd);
 
-  private:
+    // Dumps the latest monitored Tag events to the passed vector.
+    // NOTE: The events are appended to the vector in reverser chronological order
+    // (i.e. most recent first)
+    void getLatestMonitoredTagEvents(std::vector<std::string> &out);
 
-    static void printData(int fd, const uint8_t *data_ptr, uint32_t tag,
-            int type, int count, int indentation,
-            const std::unordered_set<int32_t> &outputStreamIds, int32_t inputStreamId);
+  private:
+    // Dumps monitored tag events to the passed vector without acquiring
+    // mMonitorMutex. mMonitorMutex must be acquired before calling this
+    // function.
+    void dumpMonitoredTagEventsToVectorLocked(std::vector<std::string> &out);
+
+    static String8 getEventDataString(const uint8_t *data_ptr,
+                                       uint32_t tag, int type,
+                                       int count,
+                                       int indentation,
+                                       const std::unordered_set<int32_t> &outputStreamIds,
+                                       int32_t inputStreamId);
 
     void monitorSingleMetadata(TagMonitor::eventSource source, int64_t frameNumber,
             nsecs_t timestamp, const std::string& cameraId, uint32_t tag,
diff --git a/services/medialog/Android.bp b/services/medialog/Android.bp
index cfc4c40..8088ef0 100644
--- a/services/medialog/Android.bp
+++ b/services/medialog/Android.bp
@@ -26,6 +26,7 @@
         "libmediautils",
         "libnblog",
         "libutils",
+        "packagemanager_aidl-cpp",
     ],
 
     cflags: [
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
index 04fc430..74e4715 100644
--- a/services/mediametrics/Android.bp
+++ b/services/mediametrics/Android.bp
@@ -114,6 +114,7 @@
         "libmediautils",
         "libutils",
         "mediametricsservice-aidl-cpp",
+        "packagemanager_aidl-cpp",
     ],
     header_libs: [
         "libaudioutils_headers",
@@ -178,7 +179,6 @@
     export_shared_lib_headers: [
         "libstatspull",
         "libstatssocket",
-        "packagemanager_aidl-cpp",
     ],
 
     static_libs: [
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
index b03e518..9da7282 100644
--- a/services/mediametrics/fuzzer/Android.bp
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -56,6 +56,7 @@
         "libstatssocket",
         "libutils",
         "mediametricsservice-aidl-cpp",
+        "packagemanager_aidl-cpp",
     ],
 
     include_dirs: [
diff --git a/services/mediametrics/tests/Android.bp b/services/mediametrics/tests/Android.bp
index 3baf739..f46fbad 100644
--- a/services/mediametrics/tests/Android.bp
+++ b/services/mediametrics/tests/Android.bp
@@ -33,6 +33,7 @@
         "libmediautils",
         "libutils",
         "mediametricsservice-aidl-cpp",
+        "packagemanager_aidl-cpp",
     ],
 
     header_libs: [
diff --git a/services/oboeservice/Android.bp b/services/oboeservice/Android.bp
index 4c58040..3563d66 100644
--- a/services/oboeservice/Android.bp
+++ b/services/oboeservice/Android.bp
@@ -68,6 +68,7 @@
         "aaudio-aidl-cpp",
         "framework-permission-aidl-cpp",
         "libaudioclient_aidl_conversion",
+        "packagemanager_aidl-cpp",
     ],
 
     export_shared_lib_headers: [