[automerger skipped] [RESTRICT AUTOMERGE] C2AllocatorIon:protect mMappings using mutex am: ac5f5cade2 am: 3b8914d681 -s ours am: 21f7fa7ba4 -s ours

am skip reason: subject contains skip directive

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

Change-Id: I372af53d0188575f89678097d035a1b6e267cde3
diff --git a/apex/Android.bp b/apex/Android.bp
index c1ef3d8..be6185e 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -31,6 +31,8 @@
                 "libmpeg2extractor",
                 "liboggextractor",
                 "libwavextractor",
+                // JNI
+                "libmediaparser-jni"
             ],
         },
     },
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index aecb70a..0b0f584 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -29,6 +29,7 @@
 #include <binder/IMemory.h>
 
 #include <camera/CameraBase.h>
+#include <camera/CameraUtils.h>
 
 // needed to instantiate
 #include <camera/Camera.h>
@@ -124,9 +125,7 @@
 {
     Mutex::Autolock _l(gLock);
     if (gCameraService.get() == 0) {
-        char value[PROPERTY_VALUE_MAX];
-        property_get("config.disable_cameraservice", value, "0");
-        if (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0) {
+        if (CameraUtils::isCameraServiceDisabled()) {
             return gCameraService;
         }
 
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index 135384a..024311f 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -169,6 +169,11 @@
     return entryCount() == 0;
 }
 
+size_t CameraMetadata::bufferSize() const {
+    return (mBuffer == NULL) ? 0 :
+            get_camera_metadata_size(mBuffer);
+}
+
 status_t CameraMetadata::sort() {
     if (mLocked) {
         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
diff --git a/camera/CameraUtils.cpp b/camera/CameraUtils.cpp
index 67fc116..f9b1b37 100644
--- a/camera/CameraUtils.cpp
+++ b/camera/CameraUtils.cpp
@@ -23,6 +23,7 @@
 #include <system/window.h>
 #include <system/graphics.h>
 
+#include <cutils/properties.h>
 #include <utils/Log.h>
 
 namespace android {
@@ -122,4 +123,10 @@
     return OK;
 }
 
+bool CameraUtils::isCameraServiceDisabled() {
+    char value[PROPERTY_VALUE_MAX];
+    property_get("config.disable_cameraservice", value, "0");
+    return (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0);
+}
+
 } /* namespace android */
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index c02c81b..bef2ea0 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -142,7 +142,8 @@
             camera_frame_metadata_t metadata;
             if (data.dataAvail() > 0) {
                 metadata.number_of_faces = data.readInt32();
-                if (metadata.number_of_faces <= 0 ||
+                // Zero faces is a valid case, to notify clients that no faces are now visible
+                if (metadata.number_of_faces < 0 ||
                         metadata.number_of_faces > (int32_t)(INT32_MAX / sizeof(camera_face_t))) {
                     ALOGE("%s: Too large face count: %d", __FUNCTION__, metadata.number_of_faces);
                     return BAD_VALUE;
diff --git a/camera/include/camera/CameraMetadata.h b/camera/include/camera/CameraMetadata.h
index 9d1b5c7..e883ffa 100644
--- a/camera/include/camera/CameraMetadata.h
+++ b/camera/include/camera/CameraMetadata.h
@@ -128,6 +128,11 @@
     bool isEmpty() const;
 
     /**
+     * Return the allocated camera metadata buffer size in bytes.
+     */
+    size_t bufferSize() const;
+
+    /**
      * Sort metadata buffer for faster find
      */
     status_t sort();
diff --git a/camera/include/camera/CameraUtils.h b/camera/include/camera/CameraUtils.h
index f596f80..a397ccd 100644
--- a/camera/include/camera/CameraUtils.h
+++ b/camera/include/camera/CameraUtils.h
@@ -47,6 +47,11 @@
          */
         static bool isNativeHandleMetadata(const sp<IMemory>& imageData);
 
+        /**
+         * Check if camera service is disabled on this device
+         */
+        static bool isCameraServiceDisabled();
+
     private:
         CameraUtils();
 };
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index c15c5a5..78974ae 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -1361,31 +1361,11 @@
                 it->second.isSequenceCompleted = true;
             }
 
-            if (it->second.isSequenceCompleted && hasCallback) {
-                auto cbIt = mSequenceCallbackMap.find(sequenceId);
-                CallbackHolder cbh = cbIt->second;
-
-                // send seq complete callback
-                sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
-                msg->setPointer(kContextKey, cbh.mContext);
-                msg->setObject(kSessionSpKey, cbh.mSession);
-                msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
-                msg->setInt32(kSequenceIdKey, sequenceId);
-                msg->setInt64(kFrameNumberKey, lastFrameNumber);
-
-                // Clear the session sp before we send out the message
-                // This will guarantee the rare case where the message is processed
-                // before cbh goes out of scope and causing we call the session
-                // destructor while holding device lock
-                cbh.mSession.clear();
-                postSessionMsgAndCleanup(msg);
-            }
         }
 
         if (it->second.isSequenceCompleted && it->second.isInflightCompleted) {
-            if (mSequenceCallbackMap.find(sequenceId) != mSequenceCallbackMap.end()) {
-                mSequenceCallbackMap.erase(sequenceId);
-            }
+            sendCaptureSequenceCompletedLocked(sequenceId, lastFrameNumber);
+
             it = mSequenceLastFrameNumberMap.erase(it);
             ALOGV("%s: Remove holder for sequenceId %d", __FUNCTION__, sequenceId);
         } else {
@@ -1412,13 +1392,7 @@
                 lastCompletedRegularFrameNumber);
         if (lastFrameNumber <= lastCompletedRegularFrameNumber) {
             if (it->second.isSequenceCompleted) {
-                // Check if there is callback for this sequence
-                // This should not happen because we always register callback (with nullptr inside)
-                if (mSequenceCallbackMap.count(sequenceId) == 0) {
-                    ALOGW("No callback found for sequenceId %d", sequenceId);
-                } else {
-                    mSequenceCallbackMap.erase(sequenceId);
-                }
+                sendCaptureSequenceCompletedLocked(sequenceId, lastFrameNumber);
 
                 it = mSequenceLastFrameNumberMap.erase(it);
                 ALOGV("%s: Remove holder for sequenceId %d", __FUNCTION__, sequenceId);
@@ -1709,5 +1683,33 @@
     return ret;
 }
 
+void
+CameraDevice::sendCaptureSequenceCompletedLocked(int sequenceId, int64_t lastFrameNumber) {
+    auto cbIt = mSequenceCallbackMap.find(sequenceId);
+    if (cbIt != mSequenceCallbackMap.end()) {
+        CallbackHolder cbh = cbIt->second;
+        mSequenceCallbackMap.erase(cbIt);
+
+        // send seq complete callback
+        sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
+        msg->setPointer(kContextKey, cbh.mContext);
+        msg->setObject(kSessionSpKey, cbh.mSession);
+        msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
+        msg->setInt32(kSequenceIdKey, sequenceId);
+        msg->setInt64(kFrameNumberKey, lastFrameNumber);
+
+        // Clear the session sp before we send out the message
+        // This will guarantee the rare case where the message is processed
+        // before cbh goes out of scope and causing we call the session
+        // destructor while holding device lock
+        cbh.mSession.clear();
+        postSessionMsgAndCleanup(msg);
+    } else {
+        // Check if there is callback for this sequence
+        // This should not happen because we always register callback (with nullptr inside)
+        ALOGW("No callback found for sequenceId %d", sequenceId);
+    }
+}
+
 } // namespace acam
 } // namespace android
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index d937865..3073dfb 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -354,6 +354,7 @@
     void checkRepeatingSequenceCompleteLocked(const int sequenceId, const int64_t lastFrameNumber);
     void checkAndFireSequenceCompleteLocked();
     void removeCompletedCallbackHolderLocked(int64_t lastCompletedRegularFrameNumber);
+    void sendCaptureSequenceCompletedLocked(int sequenceId, int64_t lastFrameNumber);
 
     // Misc variables
     int32_t mShadingMapSize[2];   // const after constructor
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index b58ebe2..2cba665 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -24,6 +24,7 @@
 #include <utils/Vector.h>
 #include <cutils/properties.h>
 #include <stdlib.h>
+#include <camera/CameraUtils.h>
 #include <camera/VendorTagDescriptor.h>
 
 using namespace android::acam;
@@ -70,12 +71,6 @@
     mCameraService.clear();
 }
 
-static bool isCameraServiceDisabled() {
-    char value[PROPERTY_VALUE_MAX];
-    property_get("config.disable_cameraservice", value, "0");
-    return (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0);
-}
-
 sp<hardware::ICameraService> CameraManagerGlobal::getCameraService() {
     Mutex::Autolock _l(mLock);
     return getCameraServiceLocked();
@@ -83,7 +78,7 @@
 
 sp<hardware::ICameraService> CameraManagerGlobal::getCameraServiceLocked() {
     if (mCameraService.get() == nullptr) {
-        if (isCameraServiceDisabled()) {
+        if (CameraUtils::isCameraServiceDisabled()) {
             return mCameraService;
         }
 
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 1354fce..5634982 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -1957,7 +1957,10 @@
      * explicitly set ACAMERA_CONTROL_ZOOM_RATIO, its value defaults to 1.0.</p>
      * <p>One limitation of controlling zoom using zoomRatio is that the ACAMERA_SCALER_CROP_REGION
      * must only be used for letterboxing or pillarboxing of the sensor active array, and no
-     * FREEFORM cropping can be used with ACAMERA_CONTROL_ZOOM_RATIO other than 1.0.</p>
+     * FREEFORM cropping can be used with ACAMERA_CONTROL_ZOOM_RATIO other than 1.0. If
+     * ACAMERA_CONTROL_ZOOM_RATIO is not 1.0, and ACAMERA_SCALER_CROP_REGION is set to be
+     * windowboxing, the camera framework will override the ACAMERA_SCALER_CROP_REGION to be
+     * the active array.</p>
      *
      * @see ACAMERA_CONTROL_AE_REGIONS
      * @see ACAMERA_CONTROL_ZOOM_RATIO
@@ -3651,7 +3654,9 @@
      * </ol>
      * </li>
      * <li>Setting ACAMERA_CONTROL_ZOOM_RATIO to values different than 1.0 and
-     * ACAMERA_SCALER_CROP_REGION to be windowboxing at the same time is undefined behavior.</li>
+     * ACAMERA_SCALER_CROP_REGION to be windowboxing at the same time are not supported. In this
+     * case, the camera framework will override the ACAMERA_SCALER_CROP_REGION to be the active
+     * array.</li>
      * </ul>
      * <p>LEGACY capability devices will only support CENTER_ONLY cropping.</p>
      *
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index f4b8164..e000633 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -272,7 +272,7 @@
 status_t SimplePlayer::onPrepare() {
     CHECK_EQ(mState, UNPREPARED);
 
-    mExtractor = new NuMediaExtractor;
+    mExtractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
 
     status_t err = mExtractor->setDataSource(
             NULL /* httpService */, mPath.c_str());
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index c26e0b9..33c4663 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -79,7 +79,7 @@
 
     static int64_t kTimeout = 500ll;
 
-    sp<NuMediaExtractor> extractor = new NuMediaExtractor;
+    sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
     if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
         fprintf(stderr, "unable to instantiate extractor.\n");
         return 1;
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
index b894545..ca058ab 100644
--- a/cmds/stagefright/mediafilter.cpp
+++ b/cmds/stagefright/mediafilter.cpp
@@ -319,7 +319,8 @@
 
     static int64_t kTimeout = 500ll;
 
-    sp<NuMediaExtractor> extractor = new NuMediaExtractor;
+    sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
+
     if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
         fprintf(stderr, "unable to instantiate extractor.\n");
         return 1;
diff --git a/cmds/stagefright/muxer.cpp b/cmds/stagefright/muxer.cpp
index 4a83a4a..bc7e41e 100644
--- a/cmds/stagefright/muxer.cpp
+++ b/cmds/stagefright/muxer.cpp
@@ -62,7 +62,7 @@
         int trimEndTimeMs,
         int rotationDegrees,
         MediaMuxer::OutputFormat container = MediaMuxer::OUTPUT_FORMAT_MPEG_4) {
-    sp<NuMediaExtractor> extractor = new NuMediaExtractor;
+    sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
     if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
         fprintf(stderr, "unable to instantiate extractor. %s\n", path);
         return 1;
diff --git a/drm/common/Android.bp b/drm/common/Android.bp
index 272684c..248570e 100644
--- a/drm/common/Android.bp
+++ b/drm/common/Android.bp
@@ -14,7 +14,7 @@
 // limitations under the License.
 //
 
-cc_library_static {
+cc_library {
     name: "libdrmframeworkcommon",
 
     srcs: [
@@ -35,7 +35,11 @@
 
     cflags: ["-Wall", "-Werror"],
 
-    shared_libs: ["libbinder"],
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libutils"
+    ],
 
     export_include_dirs: ["include"],
 }
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index b68e6c2..141fe70 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -31,12 +31,11 @@
         "liblog",
         "libbinder",
         "libdl",
+        "libdrmframeworkcommon",
         "libselinux",
         "libstagefright_foundation",
     ],
 
-    static_libs: ["libdrmframeworkcommon"],
-
     cflags: [
         "-Wall",
         "-Wextra",
diff --git a/drm/libdrmframework/Android.bp b/drm/libdrmframework/Android.bp
index 940c17d..b4a7b25 100644
--- a/drm/libdrmframework/Android.bp
+++ b/drm/libdrmframework/Android.bp
@@ -29,12 +29,11 @@
         "liblog",
         "libbinder",
         "libdl",
+        "libdrmframeworkcommon",
     ],
 
-    static_libs: ["libdrmframeworkcommon"],
-
     export_include_dirs: ["include"],
-    export_static_lib_headers: ["libdrmframeworkcommon"],
+    export_shared_lib_headers: ["libdrmframeworkcommon"],
 
     cflags: ["-Werror"],
 }
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
index bb9d7ec..9f52f7a 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
@@ -36,11 +36,11 @@
         "libcrypto",
         "libssl",
         "libdrmframework",
+        "libdrmframeworkcommon",
     ],
 
     static_libs: [
         "libdrmutility",
-        "libdrmframeworkcommon",
         "libfwdlock-common",
         "libfwdlock-converter",
         "libfwdlock-decoder",
diff --git a/drm/libdrmframework/plugins/passthru/Android.bp b/drm/libdrmframework/plugins/passthru/Android.bp
index 05b6440..8045586 100644
--- a/drm/libdrmframework/plugins/passthru/Android.bp
+++ b/drm/libdrmframework/plugins/passthru/Android.bp
@@ -19,12 +19,11 @@
 
     srcs: ["src/DrmPassthruPlugIn.cpp"],
 
-    static_libs: ["libdrmframeworkcommon"],
-
     shared_libs: [
         "libutils",
         "liblog",
         "libdl",
+        "libdrmframeworkcommon",
     ],
 
     local_include_dirs: ["include"],
diff --git a/drm/libmediadrm/DrmMetricsConsumer.cpp b/drm/libmediadrm/DrmMetricsConsumer.cpp
index b47b4ff..5f0b26e 100644
--- a/drm/libmediadrm/DrmMetricsConsumer.cpp
+++ b/drm/libmediadrm/DrmMetricsConsumer.cpp
@@ -37,8 +37,8 @@
 template <> std::string GetAttributeName<KeyStatusType>(KeyStatusType type) {
     static const char *type_names[] = {"USABLE", "EXPIRED",
                                        "OUTPUT_NOT_ALLOWED", "STATUS_PENDING",
-                                       "INTERNAL_ERROR"};
-    if (((size_t)type) > arraysize(type_names)) {
+                                       "INTERNAL_ERROR", "USABLE_IN_FUTURE"};
+    if (((size_t)type) >= arraysize(type_names)) {
         return "UNKNOWN_TYPE";
     }
     return type_names[(size_t)type];
@@ -48,7 +48,7 @@
     static const char *type_names[] = {"PROVISION_REQUIRED", "KEY_NEEDED",
                                        "KEY_EXPIRED", "VENDOR_DEFINED",
                                        "SESSION_RECLAIMED"};
-    if (((size_t)type) > arraysize(type_names)) {
+    if (((size_t)type) >= arraysize(type_names)) {
         return "UNKNOWN_TYPE";
     }
     return type_names[(size_t)type];
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index f05c2d2..f75e4c7 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -6,8 +6,11 @@
     capabilities BLOCK_SUSPEND
     ioprio rt 4
     task_profiles ProcessCapacityHigh HighPerformance
-
-    onrestart setprop sys.audio.restart.hal 1
+    onrestart restart vendor.audio-hal
+    onrestart restart vendor.audio-hal-4-0-msd
+    # Keep the original service names for backward compatibility
+    onrestart restart vendor.audio-hal-2-0
+    onrestart restart audio-hal-2-0
 
 on property:vts.native_server.on=1
     stop audioserver
@@ -37,11 +40,16 @@
     start audio-hal-2-0
 
 on property:sys.audio.restart.hal=1
-    restart vendor.audio-hal
-    restart vendor.audio-hal-4-0-msd
+    # See b/159966243. Avoid restart loop between audioserver and HAL.
     # Keep the original service names for backward compatibility
-    restart vendor.audio-hal-2-0
-    restart audio-hal-2-0
+    stop vendor.audio-hal
+    stop vendor.audio-hal-4-0-msd
+    stop vendor.audio-hal-2-0
+    stop audio-hal-2-0
+    start vendor.audio-hal
+    start vendor.audio-hal-4-0-msd
+    start vendor.audio-hal-2-0
+    start audio-hal-2-0
     # reset the property
     setprop sys.audio.restart.hal 0
 
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index ab93ce3..566895f 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -1328,13 +1328,13 @@
             ps_inp_raw_buf->apv_bufs[1] = uPlane;
             ps_inp_raw_buf->apv_bufs[2] = vPlane;
 
-            ps_inp_raw_buf->au4_wd[0] = input->width();
-            ps_inp_raw_buf->au4_wd[1] = input->width() / 2;
-            ps_inp_raw_buf->au4_wd[2] = input->width() / 2;
+            ps_inp_raw_buf->au4_wd[0] = mSize->width;
+            ps_inp_raw_buf->au4_wd[1] = mSize->width / 2;
+            ps_inp_raw_buf->au4_wd[2] = mSize->width / 2;
 
-            ps_inp_raw_buf->au4_ht[0] = input->height();
-            ps_inp_raw_buf->au4_ht[1] = input->height() / 2;
-            ps_inp_raw_buf->au4_ht[2] = input->height() / 2;
+            ps_inp_raw_buf->au4_ht[0] = mSize->height;
+            ps_inp_raw_buf->au4_ht[1] = mSize->height / 2;
+            ps_inp_raw_buf->au4_ht[2] = mSize->height / 2;
 
             ps_inp_raw_buf->au4_strd[0] = yStride;
             ps_inp_raw_buf->au4_strd[1] = uStride;
@@ -1359,11 +1359,11 @@
             ps_inp_raw_buf->apv_bufs[0] = yPlane;
             ps_inp_raw_buf->apv_bufs[1] = uPlane;
 
-            ps_inp_raw_buf->au4_wd[0] = input->width();
-            ps_inp_raw_buf->au4_wd[1] = input->width();
+            ps_inp_raw_buf->au4_wd[0] = mSize->width;
+            ps_inp_raw_buf->au4_wd[1] = mSize->width;
 
-            ps_inp_raw_buf->au4_ht[0] = input->height();
-            ps_inp_raw_buf->au4_ht[1] = input->height() / 2;
+            ps_inp_raw_buf->au4_ht[0] = mSize->height;
+            ps_inp_raw_buf->au4_ht[1] = mSize->height / 2;
 
             ps_inp_raw_buf->au4_strd[0] = yStride;
             ps_inp_raw_buf->au4_strd[1] = uStride;
diff --git a/media/codec2/components/gav1/Android.bp b/media/codec2/components/gav1/Android.bp
index 5c4abb7..f374089 100644
--- a/media/codec2/components/gav1/Android.bp
+++ b/media/codec2/components/gav1/Android.bp
@@ -13,8 +13,4 @@
 
     srcs: ["C2SoftGav1Dec.cpp"],
     static_libs: ["libgav1"],
-
-    include_dirs: [
-        "external/libgav1/libgav1/",
-    ],
 }
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index ec5f549..120ba7a 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -288,9 +288,7 @@
 void C2SoftGav1Dec::onRelease() { destroyDecoder(); }
 
 c2_status_t C2SoftGav1Dec::onFlush_sm() {
-  Libgav1StatusCode status =
-      mCodecCtx->EnqueueFrame(/*data=*/nullptr, /*size=*/0,
-                              /*user_private_data=*/0);
+  Libgav1StatusCode status = mCodecCtx->SignalEOS();
   if (status != kLibgav1StatusOk) {
     ALOGE("Failed to flush av1 decoder. status: %d.", status);
     return C2_CORRUPTED;
@@ -299,7 +297,7 @@
   // Dequeue frame (if any) that was enqueued previously.
   const libgav1::DecoderBuffer *buffer;
   status = mCodecCtx->DequeueFrame(&buffer);
-  if (status != kLibgav1StatusOk) {
+  if (status != kLibgav1StatusOk && status != kLibgav1StatusNothingToDequeue) {
     ALOGE("Failed to dequeue frame after flushing the av1 decoder. status: %d",
           status);
     return C2_CORRUPTED;
@@ -433,7 +431,8 @@
     TIME_DIFF(mTimeEnd, mTimeStart, delay);
 
     const Libgav1StatusCode status =
-        mCodecCtx->EnqueueFrame(bitstream, inSize, frameIndex);
+        mCodecCtx->EnqueueFrame(bitstream, inSize, frameIndex,
+                                /*buffer_private_data=*/nullptr);
 
     GETTIME(&mTimeEnd, nullptr);
     TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
@@ -447,17 +446,6 @@
       return;
     }
 
-  } else {
-    const Libgav1StatusCode status =
-        mCodecCtx->EnqueueFrame(/*data=*/nullptr, /*size=*/0,
-                                /*user_private_data=*/0);
-    if (status != kLibgav1StatusOk) {
-      ALOGE("Failed to flush av1 decoder. status: %d.", status);
-      work->result = C2_CORRUPTED;
-      work->workletsProcessed = 1u;
-      mSignalledError = true;
-      return;
-    }
   }
 
   (void)outputBuffer(pool, work);
@@ -470,13 +458,12 @@
   }
 }
 
-static void copyOutputBufferToYV12Frame(uint8_t *dst, const uint8_t *srcY,
-                                        const uint8_t *srcU,
-                                        const uint8_t *srcV, size_t srcYStride,
-                                        size_t srcUStride, size_t srcVStride,
-                                        uint32_t width, uint32_t height) {
-  const size_t dstYStride = align(width, 16);
-  const size_t dstUVStride = align(dstYStride / 2, 16);
+static void copyOutputBufferToYuvPlanarFrame(uint8_t *dst, const uint8_t *srcY,
+                                             const uint8_t *srcU,
+                                             const uint8_t *srcV, size_t srcYStride,
+                                             size_t srcUStride, size_t srcVStride,
+                                             size_t dstYStride, size_t dstUVStride,
+                                             uint32_t width, uint32_t height) {
   uint8_t *const dstStart = dst;
 
   for (size_t i = 0; i < height; ++i) {
@@ -570,10 +557,10 @@
 static void convertYUV420Planar16ToYUV420Planar(
     uint8_t *dst, const uint16_t *srcY, const uint16_t *srcU,
     const uint16_t *srcV, size_t srcYStride, size_t srcUStride,
-    size_t srcVStride, size_t dstStride, size_t width, size_t height) {
+    size_t srcVStride, size_t dstYStride, size_t dstUVStride,
+    size_t width, size_t height) {
   uint8_t *dstY = (uint8_t *)dst;
-  size_t dstYSize = dstStride * height;
-  size_t dstUVStride = align(dstStride / 2, 16);
+  size_t dstYSize = dstYStride * height;
   size_t dstUVSize = dstUVStride * height / 2;
   uint8_t *dstV = dstY + dstYSize;
   uint8_t *dstU = dstV + dstUVSize;
@@ -584,7 +571,7 @@
     }
 
     srcY += srcYStride;
-    dstY += dstStride;
+    dstY += dstYStride;
   }
 
   for (size_t y = 0; y < (height + 1) / 2; ++y) {
@@ -607,13 +594,14 @@
   const libgav1::DecoderBuffer *buffer;
   const Libgav1StatusCode status = mCodecCtx->DequeueFrame(&buffer);
 
-  if (status != kLibgav1StatusOk) {
+  if (status != kLibgav1StatusOk && status != kLibgav1StatusNothingToDequeue) {
     ALOGE("av1 decoder DequeueFrame failed. status: %d.", status);
     return false;
   }
 
-  // |buffer| can be NULL if status was equal to kLibgav1StatusOk. This is not
-  // an error. This could mean one of two things:
+  // |buffer| can be NULL if status was equal to kLibgav1StatusOk or
+  // kLibgav1StatusNothingToDequeue. This is not an error. This could mean one
+  // of two things:
   //  - The EnqueueFrame() call was either a flush (called with nullptr).
   //  - The enqueued frame did not have any displayable frames.
   if (!buffer) {
@@ -683,6 +671,9 @@
   size_t srcYStride = buffer->stride[0];
   size_t srcUStride = buffer->stride[1];
   size_t srcVStride = buffer->stride[2];
+  C2PlanarLayout layout = wView.layout();
+  size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
+  size_t dstUVStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
 
   if (buffer->bitdepth == 10) {
     const uint16_t *srcY = (const uint16_t *)buffer->plane[0];
@@ -692,18 +683,19 @@
     if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
       convertYUV420Planar16ToY410(
           (uint32_t *)dst, srcY, srcU, srcV, srcYStride / 2, srcUStride / 2,
-          srcVStride / 2, align(mWidth, 16), mWidth, mHeight);
+          srcVStride / 2, dstYStride / sizeof(uint32_t), mWidth, mHeight);
     } else {
       convertYUV420Planar16ToYUV420Planar(dst, srcY, srcU, srcV, srcYStride / 2,
                                           srcUStride / 2, srcVStride / 2,
-                                          align(mWidth, 16), mWidth, mHeight);
+                                          dstYStride, dstUVStride, mWidth, mHeight);
     }
   } else {
     const uint8_t *srcY = (const uint8_t *)buffer->plane[0];
     const uint8_t *srcU = (const uint8_t *)buffer->plane[1];
     const uint8_t *srcV = (const uint8_t *)buffer->plane[2];
-    copyOutputBufferToYV12Frame(dst, srcY, srcU, srcV, srcYStride, srcUStride,
-                                srcVStride, mWidth, mHeight);
+    copyOutputBufferToYuvPlanarFrame(dst, srcY, srcU, srcV, srcYStride, srcUStride,
+                                     srcVStride, dstYStride, dstUVStride,
+                                     mWidth, mHeight);
   }
   finishWork(buffer->user_private_data, work, std::move(block));
   block = nullptr;
@@ -722,9 +714,7 @@
     return C2_OMITTED;
   }
 
-  Libgav1StatusCode status =
-      mCodecCtx->EnqueueFrame(/*data=*/nullptr, /*size=*/0,
-                              /*user_private_data=*/0);
+  const Libgav1StatusCode status = mCodecCtx->SignalEOS();
   if (status != kLibgav1StatusOk) {
     ALOGE("Failed to flush av1 decoder. status: %d.", status);
     return C2_CORRUPTED;
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h
index a7c08bb..555adc9 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.h
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.h
@@ -18,8 +18,8 @@
 #define ANDROID_C2_SOFT_GAV1_DEC_H_
 
 #include <SimpleC2Component.h>
-#include "libgav1/src/decoder.h"
-#include "libgav1/src/decoder_settings.h"
+#include "libgav1/src/gav1/decoder.h"
+#include "libgav1/src/gav1/decoder_settings.h"
 
 #define GETTIME(a, b) gettimeofday(a, b);
 #define TIME_DIFF(start, end, diff)     \
diff --git a/media/codec2/components/vorbis/C2SoftVorbisDec.cpp b/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
index 15564d9..a8b5377 100644
--- a/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
+++ b/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
@@ -279,6 +279,8 @@
         // skip 7 <type + "vorbis"> bytes
         makeBitReader((const uint8_t *)data + 7, inSize - 7, &buf, &ref, &bits);
         if (data[0] == 1) {
+            // release any memory that vorbis_info_init will blindly overwrite
+            vorbis_info_clear(mVi);
             vorbis_info_init(mVi);
             if (0 != _vorbis_unpack_info(mVi, &bits)) {
                 ALOGE("Encountered error while unpacking info");
@@ -323,6 +325,8 @@
                 work->result = C2_CORRUPTED;
                 return;
             }
+            // release any memory that vorbis_dsp_init will blindly overwrite
+            vorbis_dsp_clear(mState);
             if (0 != vorbis_dsp_init(mState, mVi)) {
                 ALOGE("Encountered error while dsp init");
                 mSignalledError = true;
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 1972d3f..54107bd 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1331,8 +1331,6 @@
         mCallback->onError(err2, ACTION_CODE_FATAL);
         return;
     }
-    // We're not starting after flush.
-    (void)mSentConfigAfterResume.test_and_set();
     err2 = mChannel->start(inputFormat, outputFormat, buffersBoundToCodec);
     if (err2 != OK) {
         mCallback->onError(err2, ACTION_CODE_FATAL);
@@ -1580,7 +1578,6 @@
         return;
     }
 
-    mSentConfigAfterResume.clear();
     {
         Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
         const std::unique_ptr<Config> &config = *configLocked;
@@ -1797,7 +1794,7 @@
             // handle configuration changes in work done
             Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
             const std::unique_ptr<Config> &config = *configLocked;
-            bool changed = !mSentConfigAfterResume.test_and_set();
+            bool changed = false;
             Config::Watcher<C2StreamInitDataInfo::output> initData =
                 config->watch<C2StreamInitDataInfo::output>();
             if (!work->worklets.empty()
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 0626c8d..1654b11 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -618,25 +618,26 @@
 }
 
 void CCodecBufferChannel::feedInputBufferIfAvailableInternal() {
-    if (mInputMetEos || mPipelineWatcher.lock()->pipelineFull()) {
+    if (mInputMetEos) {
         return;
     }
     {
         Mutexed<Output>::Locked output(mOutput);
         if (!output->buffers ||
                 output->buffers->hasPending() ||
-                output->buffers->numClientBuffers() >= output->numSlots) {
+                output->buffers->numActiveSlots() >= output->numSlots) {
             return;
         }
     }
-    size_t numInputSlots = mInput.lock()->numSlots;
-    for (size_t i = 0; i < numInputSlots; ++i) {
+    size_t numActiveSlots = 0;
+    while (!mPipelineWatcher.lock()->pipelineFull()) {
         sp<MediaCodecBuffer> inBuffer;
         size_t index;
         {
             Mutexed<Input>::Locked input(mInput);
-            if (input->buffers->numClientBuffers() >= input->numSlots) {
-                return;
+            numActiveSlots = input->buffers->numActiveSlots();
+            if (numActiveSlots >= input->numSlots) {
+                break;
             }
             if (!input->buffers->requestNewBuffer(&index, &inBuffer)) {
                 ALOGV("[%s] no new buffer available", mName);
@@ -646,6 +647,7 @@
         ALOGV("[%s] new input index = %zu [%p]", mName, index, inBuffer.get());
         mCallback->onInputBufferAvailable(index, inBuffer);
     }
+    ALOGV("[%s] # active slots after feedInputBufferIfAvailable = %zu", mName, numActiveSlots);
 }
 
 status_t CCodecBufferChannel::renderOutputBuffer(
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index e58a1e4..bddaa9f 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -272,8 +272,6 @@
 
     // The output format can be processed without a registered slot.
     if (outputFormat) {
-        ALOGD("[%s] popFromStashAndRegister: output format changed to %s",
-                mName, outputFormat->debugString().c_str());
         updateSkipCutBuffer(outputFormat, entry.notify);
     }
 
@@ -301,6 +299,10 @@
     }
 
     if (!entry.notify) {
+        if (outputFormat) {
+            ALOGD("[%s] popFromStashAndRegister: output format changed to %s",
+                    mName, outputFormat->debugString().c_str());
+        }
         mPending.pop_front();
         return DISCARD;
     }
@@ -317,6 +319,10 @@
     // Append information from the front stash entry to outBuffer.
     (*outBuffer)->meta()->setInt64("timeUs", entry.timestamp);
     (*outBuffer)->meta()->setInt32("flags", entry.flags);
+    if (outputFormat) {
+        ALOGD("[%s] popFromStashAndRegister: output format changed to %s",
+                mName, outputFormat->debugString().c_str());
+    }
     ALOGV("[%s] popFromStashAndRegister: "
           "out buffer index = %zu [%p] => %p + %zu (%lld)",
           mName, *index, outBuffer->get(),
@@ -487,11 +493,12 @@
     mBuffers.clear();
 }
 
-size_t FlexBuffersImpl::numClientBuffers() const {
+size_t FlexBuffersImpl::numActiveSlots() const {
     return std::count_if(
             mBuffers.begin(), mBuffers.end(),
             [](const Entry &entry) {
-                return (entry.clientBuffer != nullptr);
+                return (entry.clientBuffer != nullptr
+                        || !entry.compBuffer.expired());
             });
 }
 
@@ -637,11 +644,11 @@
     }
 }
 
-size_t BuffersArrayImpl::numClientBuffers() const {
+size_t BuffersArrayImpl::numActiveSlots() const {
     return std::count_if(
             mBuffers.begin(), mBuffers.end(),
             [](const Entry &entry) {
-                return entry.ownedByClient;
+                return entry.ownedByClient || !entry.compBuffer.expired();
             });
 }
 
@@ -691,8 +698,8 @@
     mImpl.flush();
 }
 
-size_t InputBuffersArray::numClientBuffers() const {
-    return mImpl.numClientBuffers();
+size_t InputBuffersArray::numActiveSlots() const {
+    return mImpl.numActiveSlots();
 }
 
 sp<Codec2Buffer> InputBuffersArray::createNewBuffer() {
@@ -729,8 +736,8 @@
     return nullptr;
 }
 
-size_t SlotInputBuffers::numClientBuffers() const {
-    return mImpl.numClientBuffers();
+size_t SlotInputBuffers::numActiveSlots() const {
+    return mImpl.numActiveSlots();
 }
 
 sp<Codec2Buffer> SlotInputBuffers::createNewBuffer() {
@@ -781,8 +788,8 @@
     return std::move(array);
 }
 
-size_t LinearInputBuffers::numClientBuffers() const {
-    return mImpl.numClientBuffers();
+size_t LinearInputBuffers::numActiveSlots() const {
+    return mImpl.numActiveSlots();
 }
 
 // static
@@ -958,8 +965,8 @@
     return std::move(array);
 }
 
-size_t GraphicMetadataInputBuffers::numClientBuffers() const {
-    return mImpl.numClientBuffers();
+size_t GraphicMetadataInputBuffers::numActiveSlots() const {
+    return mImpl.numActiveSlots();
 }
 
 sp<Codec2Buffer> GraphicMetadataInputBuffers::createNewBuffer() {
@@ -1023,8 +1030,8 @@
     return std::move(array);
 }
 
-size_t GraphicInputBuffers::numClientBuffers() const {
-    return mImpl.numClientBuffers();
+size_t GraphicInputBuffers::numActiveSlots() const {
+    return mImpl.numActiveSlots();
 }
 
 sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
@@ -1113,8 +1120,8 @@
     mImpl.getArray(array);
 }
 
-size_t OutputBuffersArray::numClientBuffers() const {
-    return mImpl.numClientBuffers();
+size_t OutputBuffersArray::numActiveSlots() const {
+    return mImpl.numActiveSlots();
 }
 
 void OutputBuffersArray::realloc(const std::shared_ptr<C2Buffer> &c2buffer) {
@@ -1224,8 +1231,8 @@
     return array;
 }
 
-size_t FlexOutputBuffers::numClientBuffers() const {
-    return mImpl.numClientBuffers();
+size_t FlexOutputBuffers::numActiveSlots() const {
+    return mImpl.numActiveSlots();
 }
 
 // LinearOutputBuffers
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index 0d4fa81..4772ab5 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -72,7 +72,7 @@
     /**
      * Return number of buffers the client owns.
      */
-    virtual size_t numClientBuffers() const = 0;
+    virtual size_t numActiveSlots() const = 0;
 
     /**
      * Examine image data from the buffer and update the format if necessary.
@@ -584,7 +584,7 @@
      * Return the number of buffers that are sent to the client but not released
      * yet.
      */
-    size_t numClientBuffers() const;
+    size_t numActiveSlots() const;
 
     /**
      * Return the number of buffers that are sent to the component but not
@@ -705,7 +705,7 @@
      * Return the number of buffers that are sent to the client but not released
      * yet.
      */
-    size_t numClientBuffers() const;
+    size_t numActiveSlots() const;
 
     /**
      * Return the size of the array.
@@ -765,7 +765,7 @@
 
     void flush() override;
 
-    size_t numClientBuffers() const final;
+    size_t numActiveSlots() const final;
 
 protected:
     sp<Codec2Buffer> createNewBuffer() override;
@@ -796,7 +796,7 @@
 
     std::unique_ptr<InputBuffers> toArrayMode(size_t size) final;
 
-    size_t numClientBuffers() const final;
+    size_t numActiveSlots() const final;
 
 protected:
     sp<Codec2Buffer> createNewBuffer() final;
@@ -826,7 +826,7 @@
 
     std::unique_ptr<InputBuffers> toArrayMode(size_t size) override;
 
-    size_t numClientBuffers() const final;
+    size_t numActiveSlots() const final;
 
 protected:
     sp<Codec2Buffer> createNewBuffer() override;
@@ -894,7 +894,7 @@
 
     std::unique_ptr<InputBuffers> toArrayMode(size_t size) final;
 
-    size_t numClientBuffers() const final;
+    size_t numActiveSlots() const final;
 
 protected:
     sp<Codec2Buffer> createNewBuffer() override;
@@ -924,7 +924,7 @@
     std::unique_ptr<InputBuffers> toArrayMode(
             size_t size) final;
 
-    size_t numClientBuffers() const final;
+    size_t numActiveSlots() const final;
 
 protected:
     sp<Codec2Buffer> createNewBuffer() override;
@@ -965,7 +965,7 @@
         array->clear();
     }
 
-    size_t numClientBuffers() const final {
+    size_t numActiveSlots() const final {
         return 0u;
     }
 
@@ -1019,7 +1019,7 @@
 
     void getArray(Vector<sp<MediaCodecBuffer>> *array) const final;
 
-    size_t numClientBuffers() const final;
+    size_t numActiveSlots() const final;
 
     /**
      * Reallocate the array, filled with buffers with the same size as given
@@ -1073,7 +1073,7 @@
 
     std::unique_ptr<OutputBuffersArray> toArrayMode(size_t size) override;
 
-    size_t numClientBuffers() const final;
+    size_t numActiveSlots() const final;
 
     /**
      * Return an appropriate Codec2Buffer object for the type of buffers.
diff --git a/media/codec2/sfplugin/InputSurfaceWrapper.h b/media/codec2/sfplugin/InputSurfaceWrapper.h
index bb35763..479acb1 100644
--- a/media/codec2/sfplugin/InputSurfaceWrapper.h
+++ b/media/codec2/sfplugin/InputSurfaceWrapper.h
@@ -61,24 +61,24 @@
     /// Input Surface configuration
     struct Config {
         // IN PARAMS (GBS)
-        float mMinFps; // minimum fps (repeat frame to achieve this)
-        float mMaxFps; // max fps (via frame drop)
-        float mCaptureFps; // capture fps
-        float mCodedFps;   // coded fps
-        bool mSuspended; // suspended
-        int64_t mTimeOffsetUs; // time offset (input => codec)
-        int64_t mSuspendAtUs; // suspend/resume time
-        int64_t mStartAtUs; // start time
-        bool mStopped; // stopped
-        int64_t mStopAtUs; // stop time
+        float mMinFps = 0.0; // minimum fps (repeat frame to achieve this)
+        float mMaxFps = 0.0; // max fps (via frame drop)
+        float mCaptureFps = 0.0; // capture fps
+        float mCodedFps = 0.0;   // coded fps
+        bool mSuspended = false; // suspended
+        int64_t mTimeOffsetUs = 0; // time offset (input => codec)
+        int64_t mSuspendAtUs = 0; // suspend/resume time
+        int64_t mStartAtUs = 0; // start time
+        bool mStopped = false; // stopped
+        int64_t mStopAtUs = 0; // stop time
 
         // OUT PARAMS (GBS)
-        int64_t mInputDelayUs; // delay between encoder input and surface input
+        int64_t mInputDelayUs = 0; // delay between encoder input and surface input
 
         // IN PARAMS (CODEC WRAPPER)
-        float mFixedAdjustedFps; // fixed fps via PTS manipulation
-        float mMinAdjustedFps; // minimum fps via PTS manipulation
-        uint64_t mUsage; // consumer usage
+        float mFixedAdjustedFps = 0.0; // fixed fps via PTS manipulation
+        float mMinAdjustedFps = 0.0; // minimum fps via PTS manipulation
+        uint64_t mUsage = 0; // consumer usage
     };
 
     /**
diff --git a/media/codec2/sfplugin/include/media/stagefright/CCodec.h b/media/codec2/sfplugin/include/media/stagefright/CCodec.h
index ecb2506..dbbb5d5 100644
--- a/media/codec2/sfplugin/include/media/stagefright/CCodec.h
+++ b/media/codec2/sfplugin/include/media/stagefright/CCodec.h
@@ -193,7 +193,6 @@
 
     Mutexed<std::unique_ptr<CCodecConfig>> mConfig;
     Mutexed<std::list<std::unique_ptr<C2Work>>> mWorkDoneQueue;
-    std::atomic_flag mSentConfigAfterResume;
 
     friend class CCodecCallbackImpl;
 
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index b88e4e8..27bd357 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -840,7 +840,7 @@
         }
 
         if (err != OK) {
-            mPendingFrames.clear();
+            clearPendingFrames();
 
             mBlockIter.advance();
             mbuf->release();
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index a47f189..cab8929 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -1035,6 +1035,11 @@
  * but still allow queries to the stream to occur from other threads. This often
  * happens if you are monitoring stream progress from a UI thread.
  *
+ * NOTE: This function is only fully implemented for MMAP streams,
+ * which are low latency streams supported by some devices.
+ * On other "Legacy" streams some audio resources will still be in use
+ * and some callbacks may still be in process after this call.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return {@link #AAUDIO_OK} or a negative error.
  */
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
index 9fa2e40..fce322b 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG (mInService ? "AudioStreamInternalCapture_Service" \
-                          : "AudioStreamInternalCapture_Client")
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
@@ -29,6 +27,14 @@
 #define ATRACE_TAG ATRACE_TAG_AUDIO
 #include <utils/Trace.h>
 
+// We do this after the #includes because if a header uses ALOG.
+// it would fail on the reference to mInService.
+#undef LOG_TAG
+// This file is used in both client and server processes.
+// This is needed to make sense of the logs more easily.
+#define LOG_TAG (mInService ? "AudioStreamInternalCapture_Service" \
+                          : "AudioStreamInternalCapture_Client")
+
 using android::WrappingBuffer;
 
 using namespace aaudio;
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index 1303daf..d6b73b4 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG (mInService ? "AudioStreamInternalPlay_Service" \
-                          : "AudioStreamInternalPlay_Client")
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
@@ -26,6 +24,14 @@
 #include "client/AudioStreamInternalPlay.h"
 #include "utility/AudioClock.h"
 
+// We do this after the #includes because if a header uses ALOG.
+// it would fail on the reference to mInService.
+#undef LOG_TAG
+// This file is used in both client and server processes.
+// This is needed to make sense of the logs more easily.
+#define LOG_TAG (mInService ? "AudioStreamInternalPlay_Service" \
+                            : "AudioStreamInternalPlay_Client")
+
 using android::WrappingBuffer;
 
 using namespace aaudio;
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 8965875..cfa7221 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -255,17 +255,16 @@
     if (audioStream != nullptr) {
         aaudio_stream_id_t id = audioStream->getId();
         ALOGD("%s(s#%u) called ---------------", __func__, id);
-        result = audioStream->safeRelease();
-        // safeRelease will only fail if called illegally, for example, from a callback.
+        result = audioStream->safeReleaseClose();
+        // safeReleaseClose will only fail if called illegally, for example, from a callback.
         // That would result in deleting an active stream, which would cause a crash.
         if (result != AAUDIO_OK) {
             ALOGW("%s(s#%u) failed. Close it from another thread.",
                   __func__, id);
         } else {
             audioStream->unregisterPlayerBase();
-             // Mark CLOSED to keep destructors from asserting.
-            audioStream->closeFinal();
-            delete audioStream;
+            // Allow the stream to be deleted.
+            AudioStreamBuilder::stopUsingStream(audioStream);
         }
         ALOGD("%s(s#%u) returned %d ---------", __func__, id, result);
     }
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index f5c75ca..f439310 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -39,7 +39,7 @@
 }
 
 AudioStream::AudioStream()
-        : mPlayerBase(new MyPlayerBase(this))
+        : mPlayerBase(new MyPlayerBase())
         , mStreamId(AAudio_getNextStreamId())
         {
     // mThread is a pthread_t of unknown size so we need memset.
@@ -48,6 +48,10 @@
 }
 
 AudioStream::~AudioStream() {
+    // Please preserve this log because there have been several bugs related to
+    // AudioStream deletion and late callbacks.
+    ALOGD("%s(s#%u) mPlayerBase strongCount = %d",
+            __func__, getId(), mPlayerBase->getStrongCount());
     // If the stream is deleted when OPEN or in use then audio resources will leak.
     // This would indicate an internal error. So we want to find this ASAP.
     LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
@@ -55,8 +59,6 @@
                           || getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
                         "~AudioStream() - still in use, state = %s",
                         AudioGlobal_convertStreamStateToText(getState()));
-
-    mPlayerBase->clearParentReference(); // remove reference to this AudioStream
 }
 
 aaudio_result_t AudioStream::open(const AudioStreamBuilder& builder)
@@ -301,18 +303,29 @@
 }
 
 aaudio_result_t AudioStream::safeRelease() {
-    // This get temporarily unlocked in the release() when joining callback threads.
+    // This get temporarily unlocked in the MMAP release() when joining callback threads.
     std::lock_guard<std::mutex> lock(mStreamLock);
     if (collidesWithCallback()) {
         ALOGE("%s cannot be called from a callback!", __func__);
         return AAUDIO_ERROR_INVALID_STATE;
     }
-    if (getState() == AAUDIO_STREAM_STATE_CLOSING) {
+    if (getState() == AAUDIO_STREAM_STATE_CLOSING) { // already released?
         return AAUDIO_OK;
     }
     return release_l();
 }
 
+aaudio_result_t AudioStream::safeReleaseClose() {
+    // This get temporarily unlocked in the MMAP release() when joining callback threads.
+    std::lock_guard<std::mutex> lock(mStreamLock);
+    if (collidesWithCallback()) {
+        ALOGE("%s cannot be called from a callback!", __func__);
+        return AAUDIO_ERROR_INVALID_STATE;
+    }
+    releaseCloseFinal();
+    return AAUDIO_OK;
+}
+
 void AudioStream::setState(aaudio_stream_state_t state) {
     ALOGD("%s(s#%d) from %d to %d", __func__, getId(), mState, state);
     // Track transition to DISCONNECTED state.
@@ -391,7 +404,9 @@
 // It converts the 'C' function call to a C++ method call.
 static void* AudioStream_internalThreadProc(void* threadArg) {
     AudioStream *audioStream = (AudioStream *) threadArg;
-    return audioStream->wrapUserThread();
+    // Use an sp<> to prevent the stream from being deleted while running.
+    android::sp<AudioStream> protectedStream(audioStream);
+    return protectedStream->wrapUserThread();
 }
 
 // This is not exposed in the API.
@@ -520,11 +535,18 @@
 }
 
 #if AAUDIO_USE_VOLUME_SHAPER
-android::media::VolumeShaper::Status AudioStream::applyVolumeShaper(
-        const android::media::VolumeShaper::Configuration& configuration __unused,
-        const android::media::VolumeShaper::Operation& operation __unused) {
-    ALOGW("applyVolumeShaper() is not supported");
-    return android::media::VolumeShaper::Status::ok();
+::android::binder::Status AudioStream::MyPlayerBase::applyVolumeShaper(
+        const ::android::media::VolumeShaper::Configuration& configuration,
+        const ::android::media::VolumeShaper::Operation& operation) {
+    android::sp<AudioStream> audioStream;
+    {
+        std::lock_guard<std::mutex> lock(mParentLock);
+        audioStream = mParent.promote();
+    }
+    if (audioStream) {
+        return audioStream->applyVolumeShaper(configuration, operation);
+    }
+    return android::NO_ERROR;
 }
 #endif
 
@@ -534,26 +556,36 @@
     doSetVolume(); // apply this change
 }
 
-AudioStream::MyPlayerBase::MyPlayerBase(AudioStream *parent) : mParent(parent) {
-}
-
-AudioStream::MyPlayerBase::~MyPlayerBase() {
-}
-
-void AudioStream::MyPlayerBase::registerWithAudioManager() {
+void AudioStream::MyPlayerBase::registerWithAudioManager(const android::sp<AudioStream>& parent) {
+    std::lock_guard<std::mutex> lock(mParentLock);
+    mParent = parent;
     if (!mRegistered) {
-        init(android::PLAYER_TYPE_AAUDIO, AAudioConvert_usageToInternal(mParent->getUsage()));
+        init(android::PLAYER_TYPE_AAUDIO, AAudioConvert_usageToInternal(parent->getUsage()));
         mRegistered = true;
     }
 }
 
 void AudioStream::MyPlayerBase::unregisterWithAudioManager() {
+    std::lock_guard<std::mutex> lock(mParentLock);
     if (mRegistered) {
         baseDestroy();
         mRegistered = false;
     }
 }
 
+android::status_t AudioStream::MyPlayerBase::playerSetVolume() {
+    android::sp<AudioStream> audioStream;
+    {
+        std::lock_guard<std::mutex> lock(mParentLock);
+        audioStream = mParent.promote();
+    }
+    if (audioStream) {
+        // No pan and only left volume is taken into account from IPLayer interface
+        audioStream->setDuckAndMuteVolume(mVolumeMultiplierL  /* * mPanMultiplierL */);
+    }
+    return android::NO_ERROR;
+}
+
 void AudioStream::MyPlayerBase::destroy() {
     unregisterWithAudioManager();
 }
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index fb71c36..e0bd9d8 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -25,8 +25,10 @@
 #include <binder/Status.h>
 #include <utils/StrongPointer.h>
 
-#include "media/VolumeShaper.h"
-#include "media/PlayerBase.h"
+#include <media/AudioSystem.h>
+#include <media/PlayerBase.h>
+#include <media/VolumeShaper.h>
+
 #include "utility/AAudioUtilities.h"
 #include "utility/MonotonicCounter.h"
 
@@ -45,7 +47,8 @@
 /**
  * AAudio audio stream.
  */
-class AudioStream {
+// By extending AudioDeviceCallback, we also inherit from RefBase.
+class AudioStream : public android::AudioSystem::AudioDeviceCallback {
 public:
 
     AudioStream();
@@ -117,6 +120,17 @@
     virtual void logOpen();
     void logReleaseBufferState();
 
+    /* Note about naming for "release"  and "close" related methods.
+     *
+     * These names are intended to match the public AAudio API.
+     * The original AAudio API had an AAudioStream_close() function that
+     * released the hardware and deleted the stream. That made it difficult
+     * because apps want to release the HW ASAP but are not in a rush to delete
+     * the stream object. So in R we added an AAudioStream_release() function
+     * that just released the hardware.
+     * The AAudioStream_close() method releases if needed and then closes.
+     */
+
     /**
      * Free any hardware or system resources from the open() call.
      * It is safe to call release_l() multiple times.
@@ -126,22 +140,27 @@
         return AAUDIO_OK;
     }
 
-    aaudio_result_t closeFinal() {
+    /**
+     * Free any resources not already freed by release_l().
+     * Assume release_l() already called.
+     */
+    virtual void close_l() {
+        // Releasing the stream will set the state to CLOSING.
+        assert(getState() == AAUDIO_STREAM_STATE_CLOSING);
+        // setState() prevents a transition from CLOSING to any state other than CLOSED.
         // State is checked by destructor.
         setState(AAUDIO_STREAM_STATE_CLOSED);
-        return AAUDIO_OK;
     }
 
     /**
      * Release then close the stream.
-     * @return AAUDIO_OK or negative error.
      */
-    aaudio_result_t releaseCloseFinal() {
-        aaudio_result_t result = release_l(); // TODO review locking
-        if (result == AAUDIO_OK) {
-          result = closeFinal();
+    void releaseCloseFinal() {
+        if (getState() != AAUDIO_STREAM_STATE_CLOSING) { // not already released?
+            // Ignore result and keep closing.
+            (void) release_l();
         }
-        return result;
+        close_l();
     }
 
     // This is only used to identify a stream in the logs without
@@ -328,6 +347,10 @@
      */
     bool collidesWithCallback() const;
 
+    // Implement AudioDeviceCallback
+    void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+            audio_port_handle_t deviceId) override {};
+
     // ============== I/O ===========================
     // A Stream will only implement read() or write() depending on its direction.
     virtual aaudio_result_t write(const void *buffer __unused,
@@ -366,7 +389,7 @@
      */
     void registerPlayerBase() {
         if (getDirection() == AAUDIO_DIRECTION_OUTPUT) {
-            mPlayerBase->registerWithAudioManager();
+            mPlayerBase->registerWithAudioManager(this);
         }
     }
 
@@ -395,21 +418,33 @@
      */
     aaudio_result_t systemStopFromCallback();
 
+    /**
+     * Safely RELEASE a stream after taking mStreamLock and checking
+     * to make sure we are not being called from a callback.
+     * @return AAUDIO_OK or a negative error
+     */
     aaudio_result_t safeRelease();
 
+    /**
+     * Safely RELEASE and CLOSE a stream after taking mStreamLock and checking
+     * to make sure we are not being called from a callback.
+     * @return AAUDIO_OK or a negative error
+     */
+    aaudio_result_t safeReleaseClose();
+
 protected:
 
     // PlayerBase allows the system to control the stream volume.
     class MyPlayerBase : public android::PlayerBase {
     public:
-        explicit MyPlayerBase(AudioStream *parent);
+        MyPlayerBase() {};
 
-        virtual ~MyPlayerBase();
+        virtual ~MyPlayerBase() = default;
 
         /**
          * Register for volume changes and remote control.
          */
-        void registerWithAudioManager();
+        void registerWithAudioManager(const android::sp<AudioStream>& parent);
 
         /**
          * UnRegister.
@@ -421,8 +456,6 @@
          */
         void destroy() override;
 
-        void clearParentReference() { mParent = nullptr; }
-
         // Just a stub. The ability to start audio through PlayerBase is being deprecated.
         android::status_t playerStart() override {
             return android::NO_ERROR;
@@ -438,18 +471,10 @@
             return android::NO_ERROR;
         }
 
-        android::status_t playerSetVolume() override {
-            // No pan and only left volume is taken into account from IPLayer interface
-            mParent->setDuckAndMuteVolume(mVolumeMultiplierL  /* * mPanMultiplierL */);
-            return android::NO_ERROR;
-        }
+        android::status_t playerSetVolume() override;
 
 #if AAUDIO_USE_VOLUME_SHAPER
-        ::android::binder::Status applyVolumeShaper(
-                const ::android::media::VolumeShaper::Configuration& configuration,
-                const ::android::media::VolumeShaper::Operation& operation) {
-            return mParent->applyVolumeShaper(configuration, operation);
-        }
+        ::android::binder::Status applyVolumeShaper();
 #endif
 
         aaudio_result_t getResult() {
@@ -457,9 +482,12 @@
         }
 
     private:
-        AudioStream          *mParent;
-        aaudio_result_t       mResult = AAUDIO_OK;
-        bool                  mRegistered = false;
+        // Use a weak pointer so the AudioStream can be deleted.
+
+        std::mutex               mParentLock;
+        android::wp<AudioStream> mParent;
+        aaudio_result_t          mResult = AAUDIO_OK;
+        bool                     mRegistered = false;
     };
 
     /**
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index 60dad84..630b289 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -63,27 +63,26 @@
 static aaudio_result_t builder_createStream(aaudio_direction_t direction,
                                          aaudio_sharing_mode_t sharingMode,
                                          bool tryMMap,
-                                         AudioStream **audioStreamPtr) {
-    *audioStreamPtr = nullptr;
+                                         android::sp<AudioStream> &stream) {
     aaudio_result_t result = AAUDIO_OK;
 
     switch (direction) {
 
         case AAUDIO_DIRECTION_INPUT:
             if (tryMMap) {
-                *audioStreamPtr = new AudioStreamInternalCapture(AAudioBinderClient::getInstance(),
+                stream = new AudioStreamInternalCapture(AAudioBinderClient::getInstance(),
                                                                  false);
             } else {
-                *audioStreamPtr = new AudioStreamRecord();
+                stream = new AudioStreamRecord();
             }
             break;
 
         case AAUDIO_DIRECTION_OUTPUT:
             if (tryMMap) {
-                *audioStreamPtr = new AudioStreamInternalPlay(AAudioBinderClient::getInstance(),
+                stream = new AudioStreamInternalPlay(AAudioBinderClient::getInstance(),
                                                               false);
             } else {
-                *audioStreamPtr = new AudioStreamTrack();
+                stream = new AudioStreamTrack();
             }
             break;
 
@@ -98,7 +97,7 @@
 // Fall back to Legacy path if MMAP not available.
 // Exact behavior is controlled by MMapPolicy.
 aaudio_result_t AudioStreamBuilder::build(AudioStream** streamPtr) {
-    AudioStream *audioStream = nullptr;
+
     if (streamPtr == nullptr) {
         ALOGE("%s() streamPtr is null", __func__);
         return AAUDIO_ERROR_NULL;
@@ -171,41 +170,48 @@
         setPrivacySensitive(true);
     }
 
-    result = builder_createStream(getDirection(), sharingMode, allowMMap, &audioStream);
+    android::sp<AudioStream> audioStream;
+    result = builder_createStream(getDirection(), sharingMode, allowMMap, audioStream);
     if (result == AAUDIO_OK) {
         // Open the stream using the parameters from the builder.
         result = audioStream->open(*this);
-        if (result == AAUDIO_OK) {
-            *streamPtr = audioStream;
-        } else {
+        if (result != AAUDIO_OK) {
             bool isMMap = audioStream->isMMap();
-            delete audioStream;
-            audioStream = nullptr;
-
             if (isMMap && allowLegacy) {
                 ALOGV("%s() MMAP stream did not open so try Legacy path", __func__);
                 // If MMAP stream failed to open then TRY using a legacy stream.
                 result = builder_createStream(getDirection(), sharingMode,
-                                              false, &audioStream);
+                                              false, audioStream);
                 if (result == AAUDIO_OK) {
                     result = audioStream->open(*this);
-                    if (result == AAUDIO_OK) {
-                        *streamPtr = audioStream;
-                    } else {
-                        delete audioStream;
-                        audioStream = nullptr;
-                    }
                 }
             }
         }
-        if (audioStream != nullptr) {
+        if (result == AAUDIO_OK) {
             audioStream->logOpen();
-        }
+            *streamPtr = startUsingStream(audioStream);
+        } // else audioStream will go out of scope and be deleted
     }
 
     return result;
 }
 
+AudioStream *AudioStreamBuilder::startUsingStream(android::sp<AudioStream> &audioStream) {
+    // Increment the smart pointer so it will not get deleted when
+    // we pass it to the C caller and it goes out of scope.
+    // The C code cannot hold a smart pointer so we increment the reference
+    // count to indicate that the C app owns a reference.
+    audioStream->incStrong(nullptr);
+    return audioStream.get();
+}
+
+void AudioStreamBuilder::stopUsingStream(AudioStream *stream) {
+    // Undo the effect of startUsingStream()
+    android::sp<AudioStream> spAudioStream(stream);
+    ALOGV("%s() strongCount = %d", __func__, spAudioStream->getStrongCount());
+    spAudioStream->decStrong(nullptr);
+}
+
 aaudio_result_t AudioStreamBuilder::validate() const {
 
     // Check for values that are ridiculously out of range to prevent math overflow exploits.
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.h b/media/libaaudio/src/core/AudioStreamBuilder.h
index d5fb80d..9f93341 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.h
+++ b/media/libaaudio/src/core/AudioStreamBuilder.h
@@ -108,9 +108,16 @@
 
     virtual aaudio_result_t validate() const override;
 
+
     void logParameters() const;
 
+    // Mark the stream so it can be deleted.
+    static void stopUsingStream(AudioStream *stream);
+
 private:
+    // Extract a raw pointer that we can pass to a 'C' app.
+    static AudioStream *startUsingStream(android::sp<AudioStream> &spAudioStream);
+
     bool                       mSharingModeMatchRequired = false; // must match sharing mode requested
     aaudio_performance_mode_t  mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
 
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index c062882..33c1bf5 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -34,8 +34,7 @@
 using namespace aaudio;
 
 AudioStreamLegacy::AudioStreamLegacy()
-        : AudioStream()
-        , mDeviceCallback(new StreamDeviceCallback(this)) {
+        : AudioStream() {
 }
 
 AudioStreamLegacy::~AudioStreamLegacy() {
@@ -163,7 +162,11 @@
 }
 
 void AudioStreamLegacy::forceDisconnect(bool errorCallbackEnabled) {
-    if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
+    // There is no need to disconnect if already in these states.
+    if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED
+            && getState() != AAUDIO_STREAM_STATE_CLOSING
+            && getState() != AAUDIO_STREAM_STATE_CLOSED
+            ) {
         setState(AAUDIO_STREAM_STATE_DISCONNECTED);
         if (errorCallbackEnabled) {
             maybeCallErrorCallback(AAUDIO_ERROR_DISCONNECTED);
@@ -205,24 +208,30 @@
     return AAudioConvert_androidToAAudioResult(status);
 }
 
-void AudioStreamLegacy::onAudioDeviceUpdate(audio_port_handle_t deviceId)
-{
+void AudioStreamLegacy::onAudioDeviceUpdate(audio_io_handle_t /* audioIo */,
+            audio_port_handle_t deviceId) {
     // Device routing is a common source of errors and DISCONNECTS.
-    // Please leave this log in place.
-    ALOGD("%s() devId %d => %d", __func__, (int) getDeviceId(), (int)deviceId);
-    if (getDeviceId() != AAUDIO_UNSPECIFIED && getDeviceId() != deviceId &&
-            getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
+    // Please leave this log in place. If there is a bug then this might
+    // get called after the stream has been deleted so log before we
+    // touch the stream object.
+    ALOGD("%s(deviceId = %d)", __func__, (int)deviceId);
+    if (getDeviceId() != AAUDIO_UNSPECIFIED
+            && getDeviceId() != deviceId
+            && getState() != AAUDIO_STREAM_STATE_DISCONNECTED
+            ) {
         // Note that isDataCallbackActive() is affected by state so call it before DISCONNECTING.
         // If we have a data callback and the stream is active, then ask the data callback
         // to DISCONNECT and call the error callback.
         if (isDataCallbackActive()) {
-            ALOGD("onAudioDeviceUpdate() request DISCONNECT in data callback due to device change");
+            ALOGD("%s() request DISCONNECT in data callback, device %d => %d",
+                  __func__, (int) getDeviceId(), (int) deviceId);
             // If the stream is stopped before the data callback has a chance to handle the
             // request then the requestStop() and requestPause() methods will handle it after
             // the callback has stopped.
             mRequestDisconnect.request();
         } else {
-            ALOGD("onAudioDeviceUpdate() DISCONNECT the stream now");
+            ALOGD("%s() DISCONNECT the stream now, device %d => %d",
+                  __func__, (int) getDeviceId(), (int) deviceId);
             forceDisconnect();
         }
     }
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.h b/media/libaaudio/src/legacy/AudioStreamLegacy.h
index 9c24b2b..fefe6e0 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.h
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.h
@@ -87,29 +87,13 @@
 
 protected:
 
-    class StreamDeviceCallback : public android::AudioSystem::AudioDeviceCallback
-    {
-    public:
-
-        StreamDeviceCallback(AudioStreamLegacy *parent) : mParent(parent) {}
-        virtual ~StreamDeviceCallback() {}
-
-        virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo __unused,
-                                         audio_port_handle_t deviceId) {
-            if (mParent != nullptr) {
-                mParent->onAudioDeviceUpdate(deviceId);
-            }
-        }
-
-        AudioStreamLegacy *mParent;
-    };
-
     aaudio_result_t getBestTimestamp(clockid_t clockId,
                                      int64_t *framePosition,
                                      int64_t *timeNanoseconds,
                                      android::ExtendedTimestamp *extendedTimestamp);
 
-    void onAudioDeviceUpdate(audio_port_handle_t deviceId);
+    void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+            audio_port_handle_t deviceId) override;
 
     /*
      * Check to see whether a callback thread has requested a disconnected.
@@ -140,7 +124,6 @@
     int32_t                    mBlockAdapterBytesPerFrame = 0;
     aaudio_wrapping_frames_t   mPositionWhenStarting = 0;
     int32_t                    mCallbackBufferSize = 0;
-    const android::sp<StreamDeviceCallback>   mDeviceCallback;
 
     AtomicRequestor            mRequestDisconnect;
 
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index b0dc59e..d62951e 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -282,7 +282,7 @@
             : (aaudio_session_id_t) mAudioRecord->getSessionId();
     setSessionId(actualSessionId);
 
-    mAudioRecord->addAudioDeviceCallback(mDeviceCallback);
+    mAudioRecord->addAudioDeviceCallback(this);
 
     return AAUDIO_OK;
 }
@@ -291,16 +291,24 @@
     // TODO add close() or release() to AudioFlinger's AudioRecord API.
     //  Then call it from here
     if (getState() != AAUDIO_STREAM_STATE_CLOSING) {
-        mAudioRecord->removeAudioDeviceCallback(mDeviceCallback);
+        mAudioRecord->removeAudioDeviceCallback(this);
         logReleaseBufferState();
-        mAudioRecord.clear();
-        mFixedBlockWriter.close();
+        // Data callbacks may still be running!
         return AudioStream::release_l();
     } else {
         return AAUDIO_OK; // already released
     }
 }
 
+void AudioStreamRecord::close_l() {
+    mAudioRecord.clear();
+    // Do not close mFixedBlockWriter because a data callback
+    // thread might still be running if someone else has a reference
+    // to mAudioRecord.
+    // It has a unique_ptr to its buffer so it will clean up by itself.
+    AudioStream::close_l();
+}
+
 const void * AudioStreamRecord::maybeConvertDeviceData(const void *audioData, int32_t numFrames) {
     if (mFormatConversionBufferFloat.get() != nullptr) {
         LOG_ALWAYS_FATAL_IF(numFrames > mFormatConversionBufferSizeInFrames,
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.h b/media/libaaudio/src/legacy/AudioStreamRecord.h
index c5944c7..e4ef1c0 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.h
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.h
@@ -39,6 +39,7 @@
 
     aaudio_result_t open(const AudioStreamBuilder & builder) override;
     aaudio_result_t release_l() override;
+    void close_l() override;
 
     aaudio_result_t requestStart() override;
     aaudio_result_t requestStop() override;
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 4869480..3831046 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -224,7 +224,7 @@
     mInitialBufferCapacity = getBufferCapacity();
     mInitialFramesPerBurst = getFramesPerBurst();
 
-    mAudioTrack->addAudioDeviceCallback(mDeviceCallback);
+    mAudioTrack->addAudioDeviceCallback(this);
 
     // Update performance mode based on the actual stream flags.
     // For example, if the sample rate is not allowed then you won't get a FAST track.
@@ -253,19 +253,26 @@
 
 aaudio_result_t AudioStreamTrack::release_l() {
     if (getState() != AAUDIO_STREAM_STATE_CLOSING) {
-        mAudioTrack->removeAudioDeviceCallback(mDeviceCallback);
+        status_t err = mAudioTrack->removeAudioDeviceCallback(this);
+        ALOGE_IF(err, "%s() removeAudioDeviceCallback returned %d", __func__, err);
         logReleaseBufferState();
-        // TODO Investigate why clear() causes a hang in test_various.cpp
-        // if I call close() from a data callback.
-        // But the same thing in AudioRecord is OK!
-        // mAudioTrack.clear();
-        mFixedBlockReader.close();
+        // Data callbacks may still be running!
         return AudioStream::release_l();
     } else {
         return AAUDIO_OK; // already released
     }
 }
 
+void AudioStreamTrack::close_l() {
+    // Stop callbacks before deleting mFixedBlockReader memory.
+    mAudioTrack.clear();
+    // Do not close mFixedBlockReader because a data callback
+    // thread might still be running if someone else has a reference
+    // to mAudioRecord.
+    // It has a unique_ptr to its buffer so it will clean up by itself.
+    AudioStream::close_l();
+}
+
 void AudioStreamTrack::processCallback(int event, void *info) {
 
     switch (event) {
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.h b/media/libaaudio/src/legacy/AudioStreamTrack.h
index 93a1ff4..6334f66 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.h
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.h
@@ -42,6 +42,7 @@
 
     aaudio_result_t open(const AudioStreamBuilder & builder) override;
     aaudio_result_t release_l() override;
+    void close_l() override;
 
     aaudio_result_t requestStart() override;
     aaudio_result_t requestPause() override;
diff --git a/media/libaaudio/tests/test_various.cpp b/media/libaaudio/tests/test_various.cpp
index a20c799..cbf863f 100644
--- a/media/libaaudio/tests/test_various.cpp
+++ b/media/libaaudio/tests/test_various.cpp
@@ -33,6 +33,11 @@
         void *audioData,
         int32_t numFrames
 ) {
+    aaudio_direction_t direction = AAudioStream_getDirection(stream);
+    if (direction == AAUDIO_DIRECTION_INPUT) {
+        return AAUDIO_CALLBACK_RESULT_CONTINUE;
+    }
+    // Check to make sure the buffer is initialized to all zeros.
     int channels = AAudioStream_getChannelCount(stream);
     int numSamples = channels * numFrames;
     bool allZeros = true;
@@ -48,7 +53,8 @@
 constexpr int64_t NANOS_PER_MILLISECOND = 1000 * 1000;
 
 void checkReleaseThenClose(aaudio_performance_mode_t perfMode,
-        aaudio_sharing_mode_t sharingMode) {
+        aaudio_sharing_mode_t sharingMode,
+        aaudio_direction_t direction = AAUDIO_DIRECTION_OUTPUT) {
     AAudioStreamBuilder* aaudioBuilder = nullptr;
     AAudioStream* aaudioStream = nullptr;
 
@@ -61,6 +67,7 @@
                                         nullptr);
     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
     AAudioStreamBuilder_setSharingMode(aaudioBuilder, sharingMode);
+    AAudioStreamBuilder_setDirection(aaudioBuilder, direction);
     AAudioStreamBuilder_setFormat(aaudioBuilder, AAUDIO_FORMAT_PCM_FLOAT);
 
     // Create an AAudioStream using the Builder.
@@ -88,14 +95,28 @@
     // We should NOT be able to start or change a stream after it has been released.
     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestStart(aaudioStream));
     EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
-    EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestPause(aaudioStream));
+    // Pause is only implemented for OUTPUT.
+    if (direction == AAUDIO_DIRECTION_OUTPUT) {
+        EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE,
+                  AAudioStream_requestPause(aaudioStream));
+    }
     EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
     EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestStop(aaudioStream));
     EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
 
     // Does this crash?
-    EXPECT_LT(0, AAudioStream_getFramesRead(aaudioStream));
-    EXPECT_LT(0, AAudioStream_getFramesWritten(aaudioStream));
+    EXPECT_GT(AAudioStream_getFramesRead(aaudioStream), 0);
+    EXPECT_GT(AAudioStream_getFramesWritten(aaudioStream), 0);
+    EXPECT_GT(AAudioStream_getFramesPerBurst(aaudioStream), 0);
+    EXPECT_GE(AAudioStream_getXRunCount(aaudioStream), 0);
+    EXPECT_GT(AAudioStream_getBufferCapacityInFrames(aaudioStream), 0);
+    EXPECT_GT(AAudioStream_getBufferSizeInFrames(aaudioStream), 0);
+
+    int64_t timestampFrames = 0;
+    int64_t timestampNanos = 0;
+    aaudio_result_t result = AAudioStream_getTimestamp(aaudioStream, CLOCK_MONOTONIC,
+            &timestampFrames, &timestampNanos);
+    EXPECT_TRUE(result == AAUDIO_ERROR_INVALID_STATE || result == AAUDIO_ERROR_UNIMPLEMENTED);
 
     // Verify Closing State. Does this crash?
     aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
@@ -107,20 +128,42 @@
     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
 }
 
-TEST(test_various, aaudio_release_close_none) {
+TEST(test_various, aaudio_release_close_none_output) {
     checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_NONE,
-            AAUDIO_SHARING_MODE_SHARED);
+            AAUDIO_SHARING_MODE_SHARED,
+            AAUDIO_DIRECTION_OUTPUT);
     // No EXCLUSIVE streams with MODE_NONE.
 }
 
-TEST(test_various, aaudio_release_close_low_shared) {
-    checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
-            AAUDIO_SHARING_MODE_SHARED);
+TEST(test_various, aaudio_release_close_none_input) {
+    checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_NONE,
+            AAUDIO_SHARING_MODE_SHARED,
+            AAUDIO_DIRECTION_INPUT);
+    // No EXCLUSIVE streams with MODE_NONE.
 }
 
-TEST(test_various, aaudio_release_close_low_exclusive) {
+TEST(test_various, aaudio_release_close_low_shared_output) {
     checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
-            AAUDIO_SHARING_MODE_EXCLUSIVE);
+            AAUDIO_SHARING_MODE_SHARED,
+            AAUDIO_DIRECTION_OUTPUT);
+}
+
+TEST(test_various, aaudio_release_close_low_shared_input) {
+    checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+            AAUDIO_SHARING_MODE_SHARED,
+            AAUDIO_DIRECTION_INPUT);
+}
+
+TEST(test_various, aaudio_release_close_low_exclusive_output) {
+    checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+            AAUDIO_SHARING_MODE_EXCLUSIVE,
+            AAUDIO_DIRECTION_OUTPUT);
+}
+
+TEST(test_various, aaudio_release_close_low_exclusive_input) {
+    checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+            AAUDIO_SHARING_MODE_EXCLUSIVE,
+            AAUDIO_DIRECTION_INPUT);
 }
 
 enum FunctionToCall {
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 0c40cbb..fa2a159 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -63,6 +63,7 @@
 
         "AudioEffect.cpp",
         "AudioRecord.cpp",
+        "AudioSanitizer.cpp",
         "AudioSystem.cpp",
         "AudioTrack.cpp",
         "AudioTrackShared.cpp",
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index 3ead6cb..73b96ab 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -36,64 +36,10 @@
 // ---------------------------------------------------------------------------
 
 AudioEffect::AudioEffect(const String16& opPackageName)
-    : mStatus(NO_INIT), mProbe(false), mOpPackageName(opPackageName)
+    : mOpPackageName(opPackageName)
 {
 }
 
-
-AudioEffect::AudioEffect(const effect_uuid_t *type,
-                const String16& opPackageName,
-                const effect_uuid_t *uuid,
-                int32_t priority,
-                effect_callback_t cbf,
-                void* user,
-                audio_session_t sessionId,
-                audio_io_handle_t io,
-                const AudioDeviceTypeAddr& device,
-                bool probe
-                )
-    : mStatus(NO_INIT), mProbe(false), mOpPackageName(opPackageName)
-{
-    AutoMutex lock(mConstructLock);
-    mStatus = set(type, uuid, priority, cbf, user, sessionId, io, device, probe);
-}
-
-AudioEffect::AudioEffect(const char *typeStr,
-                const String16& opPackageName,
-                const char *uuidStr,
-                int32_t priority,
-                effect_callback_t cbf,
-                void* user,
-                audio_session_t sessionId,
-                audio_io_handle_t io,
-                const AudioDeviceTypeAddr& device,
-                bool probe
-                )
-    : mStatus(NO_INIT), mProbe(false), mOpPackageName(opPackageName)
-{
-    effect_uuid_t type;
-    effect_uuid_t *pType = NULL;
-    effect_uuid_t uuid;
-    effect_uuid_t *pUuid = NULL;
-
-    ALOGV("Constructor string\n - type: %s\n - uuid: %s", typeStr, uuidStr);
-
-    if (typeStr != NULL) {
-        if (stringToGuid(typeStr, &type) == NO_ERROR) {
-            pType = &type;
-        }
-    }
-
-    if (uuidStr != NULL) {
-        if (stringToGuid(uuidStr, &uuid) == NO_ERROR) {
-            pUuid = &uuid;
-        }
-    }
-
-    AutoMutex lock(mConstructLock);
-    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io, device, probe);
-}
-
 status_t AudioEffect::set(const effect_uuid_t *type,
                 const effect_uuid_t *uuid,
                 int32_t priority,
@@ -194,6 +140,34 @@
     return mStatus;
 }
 
+status_t AudioEffect::set(const char *typeStr,
+                const char *uuidStr,
+                int32_t priority,
+                effect_callback_t cbf,
+                void* user,
+                audio_session_t sessionId,
+                audio_io_handle_t io,
+                const AudioDeviceTypeAddr& device,
+                bool probe)
+{
+    effect_uuid_t type;
+    effect_uuid_t *pType = nullptr;
+    effect_uuid_t uuid;
+    effect_uuid_t *pUuid = nullptr;
+
+    ALOGV("AudioEffect::set string\n - type: %s\n - uuid: %s",
+            typeStr ? typeStr : "nullptr", uuidStr ? uuidStr : "nullptr");
+
+    if (stringToGuid(typeStr, &type) == NO_ERROR) {
+        pType = &type;
+    }
+    if (stringToGuid(uuidStr, &uuid) == NO_ERROR) {
+        pUuid = &uuid;
+    }
+
+    return set(pType, pUuid, priority, cbf, user, sessionId, io, device, probe);
+}
+
 
 AudioEffect::~AudioEffect()
 {
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index df47def..9568e83 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -742,6 +742,8 @@
     void *iMemPointer;
     audio_track_cblk_t* cblk;
     status_t status;
+    static const int32_t kMaxCreateAttempts = 3;
+    int32_t remainingAttempts = kMaxCreateAttempts;
 
     if (audioFlinger == 0) {
         ALOGE("%s(%d): Could not get audioflinger", __func__, mPortId);
@@ -803,15 +805,24 @@
     input.sessionId = mSessionId;
     originalSessionId = mSessionId;
 
-    record = audioFlinger->createRecord(input,
-                                                              output,
-                                                              &status);
+    do {
+        record = audioFlinger->createRecord(input, output, &status);
+        if (status == NO_ERROR) {
+            break;
+        }
+        if (status != FAILED_TRANSACTION || --remainingAttempts <= 0) {
+            ALOGE("%s(%d): AudioFlinger could not create record track, status: %d",
+                  __func__, mPortId, status);
+            goto exit;
+        }
+        // FAILED_TRANSACTION happens under very specific conditions causing a state mismatch
+        // between audio policy manager and audio flinger during the input stream open sequence
+        // and can be recovered by retrying.
+        // Leave time for race condition to clear before retrying and randomize delay
+        // to reduce the probability of concurrent retries in locked steps.
+        usleep((20 + rand() % 30) * 10000);
+    } while (1);
 
-    if (status != NO_ERROR) {
-        ALOGE("%s(%d): AudioFlinger could not create record track, status: %d",
-              __func__, mPortId, status);
-        goto exit;
-    }
     ALOG_ASSERT(record != 0);
 
     // AudioFlinger now owns the reference to the I/O handle,
diff --git a/media/libaudioclient/AudioSanitizer.cpp b/media/libaudioclient/AudioSanitizer.cpp
new file mode 100644
index 0000000..44ca956
--- /dev/null
+++ b/media/libaudioclient/AudioSanitizer.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <media/AudioSanitizer.h>
+
+namespace android {
+
+    /** returns true if string overflow was prevented by zero termination */
+template <size_t size>
+bool preventStringOverflow(char (&s)[size]) {
+    if (strnlen(s, size) < size) return false;
+    s[size - 1] = '\0';
+    return true;
+}
+
+status_t safetyNetLog(status_t status, const char *bugNumber) {
+    if (status != NO_ERROR && bugNumber != nullptr) {
+        android_errorWriteLog(0x534e4554, bugNumber); // SafetyNet logging
+    }
+    return status;
+}
+
+status_t AudioSanitizer::sanitizeAudioAttributes(
+        audio_attributes_t *attr, const char *bugNumber)
+{
+    status_t status = NO_ERROR;
+    const size_t tagsMaxSize = AUDIO_ATTRIBUTES_TAGS_MAX_SIZE;
+    if (strnlen(attr->tags, tagsMaxSize) >= tagsMaxSize) {
+        status = BAD_VALUE;
+    }
+    attr->tags[tagsMaxSize - 1] = '\0';
+    return safetyNetLog(status, bugNumber);
+}
+
+/** returns BAD_VALUE if sanitization was required. */
+status_t AudioSanitizer::sanitizeEffectDescriptor(
+        effect_descriptor_t *desc, const char *bugNumber)
+{
+    status_t status = NO_ERROR;
+    if (preventStringOverflow(desc->name)
+        | /* always */ preventStringOverflow(desc->implementor)) {
+        status = BAD_VALUE;
+    }
+    return safetyNetLog(status, bugNumber);
+}
+
+/** returns BAD_VALUE if sanitization was required. */
+status_t AudioSanitizer::sanitizeAudioPortConfig(
+        struct audio_port_config *config, const char *bugNumber)
+{
+    status_t status = NO_ERROR;
+    if (config->type == AUDIO_PORT_TYPE_DEVICE &&
+        preventStringOverflow(config->ext.device.address)) {
+        status = BAD_VALUE;
+    }
+    return safetyNetLog(status, bugNumber);
+}
+
+/** returns BAD_VALUE if sanitization was required. */
+status_t AudioSanitizer::sanitizeAudioPort(
+        struct audio_port *port, const char *bugNumber)
+{
+    status_t status = NO_ERROR;
+    if (preventStringOverflow(port->name)) {
+        status = BAD_VALUE;
+    }
+    if (sanitizeAudioPortConfig(&port->active_config) != NO_ERROR) {
+        status = BAD_VALUE;
+    }
+    if (port->type == AUDIO_PORT_TYPE_DEVICE &&
+        preventStringOverflow(port->ext.device.address)) {
+        status = BAD_VALUE;
+    }
+    return safetyNetLog(status, bugNumber);
+}
+
+/** returns BAD_VALUE if sanitization was required. */
+status_t AudioSanitizer::sanitizeAudioPatch(
+        struct audio_patch *patch, const char *bugNumber)
+{
+    status_t status = NO_ERROR;
+    if (patch->num_sources > AUDIO_PATCH_PORTS_MAX) {
+        patch->num_sources = AUDIO_PATCH_PORTS_MAX;
+        status = BAD_VALUE;
+    }
+    if (patch->num_sinks > AUDIO_PATCH_PORTS_MAX) {
+        patch->num_sinks = AUDIO_PATCH_PORTS_MAX;
+        status = BAD_VALUE;
+    }
+    for (size_t i = 0; i < patch->num_sources; i++) {
+        if (sanitizeAudioPortConfig(&patch->sources[i]) != NO_ERROR) {
+            status = BAD_VALUE;
+        }
+    }
+    for (size_t i = 0; i < patch->num_sinks; i++) {
+        if (sanitizeAudioPortConfig(&patch->sinks[i]) != NO_ERROR) {
+            status = BAD_VALUE;
+        }
+    }
+    return safetyNetLog(status, bugNumber);
+}
+
+}; // namespace android
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 6357da4..e26a831 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -47,8 +47,9 @@
 record_config_callback AudioSystem::gRecordConfigCallback = NULL;
 
 // Required to be held while calling into gSoundTriggerCaptureStateListener.
+class CaptureStateListenerImpl;
 Mutex gSoundTriggerCaptureStateListenerLock;
-sp<AudioSystem::CaptureStateListener> gSoundTriggerCaptureStateListener = nullptr;
+sp<CaptureStateListenerImpl> gSoundTriggerCaptureStateListener = nullptr;
 
 // establish binder interface to AudioFlinger service
 const sp<IAudioFlinger> AudioSystem::get_audio_flinger()
@@ -1634,42 +1635,54 @@
 class CaptureStateListenerImpl : public media::BnCaptureStateListener,
                                  public IBinder::DeathRecipient {
 public:
+    CaptureStateListenerImpl(
+            const sp<IAudioPolicyService>& aps,
+            const sp<AudioSystem::CaptureStateListener>& listener)
+            : mAps(aps), mListener(listener) {}
+
+    void init() {
+        bool active;
+        status_t status = mAps->registerSoundTriggerCaptureStateListener(this, &active);
+        if (status != NO_ERROR) {
+            mListener->onServiceDied();
+            return;
+        }
+        mListener->onStateChanged(active);
+        IInterface::asBinder(mAps)->linkToDeath(this);
+    }
+
     binder::Status setCaptureState(bool active) override {
         Mutex::Autolock _l(gSoundTriggerCaptureStateListenerLock);
-        gSoundTriggerCaptureStateListener->onStateChanged(active);
+        mListener->onStateChanged(active);
         return binder::Status::ok();
     }
 
     void binderDied(const wp<IBinder>&) override {
         Mutex::Autolock _l(gSoundTriggerCaptureStateListenerLock);
-        gSoundTriggerCaptureStateListener->onServiceDied();
+        mListener->onServiceDied();
         gSoundTriggerCaptureStateListener = nullptr;
     }
+
+private:
+    // Need this in order to keep the death receipent alive.
+    sp<IAudioPolicyService> mAps;
+    sp<AudioSystem::CaptureStateListener> mListener;
 };
 
 status_t AudioSystem::registerSoundTriggerCaptureStateListener(
     const sp<CaptureStateListener>& listener) {
+    LOG_ALWAYS_FATAL_IF(listener == nullptr);
+
     const sp<IAudioPolicyService>& aps =
             AudioSystem::get_audio_policy_service();
     if (aps == 0) {
         return PERMISSION_DENIED;
     }
 
-    sp<CaptureStateListenerImpl> wrapper = new CaptureStateListenerImpl();
-
     Mutex::Autolock _l(gSoundTriggerCaptureStateListenerLock);
+    gSoundTriggerCaptureStateListener = new CaptureStateListenerImpl(aps, listener);
+    gSoundTriggerCaptureStateListener->init();
 
-    bool active;
-    status_t status =
-        aps->registerSoundTriggerCaptureStateListener(wrapper, &active);
-    if (status != NO_ERROR) {
-        listener->onServiceDied();
-        return NO_ERROR;
-    }
-    gSoundTriggerCaptureStateListener = listener;
-    listener->onStateChanged(active);
-    sp<IBinder> binder = IInterface::asBinder(aps);
-    binder->linkToDeath(wrapper);
     return NO_ERROR;
 }
 
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 32129f0..68d11d4 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -210,7 +210,11 @@
     return NO_ERROR;
 }
 
-AudioTrack::AudioTrack()
+AudioTrack::AudioTrack() : AudioTrack("" /*opPackageName*/)
+{
+}
+
+AudioTrack::AudioTrack(const std::string& opPackageName)
     : mStatus(NO_INIT),
       mState(STATE_STOPPED),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
@@ -218,6 +222,7 @@
       mPausedPosition(0),
       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
       mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
+      mOpPackageName(opPackageName),
       mAudioTrackCallback(new AudioTrackCallback())
 {
     mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
@@ -244,12 +249,14 @@
         const audio_attributes_t* pAttributes,
         bool doNotReconnect,
         float maxRequiredSpeed,
-        audio_port_handle_t selectedDeviceId)
+        audio_port_handle_t selectedDeviceId,
+        const std::string& opPackageName)
     : mStatus(NO_INIT),
       mState(STATE_STOPPED),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT),
       mPausedPosition(0),
+      mOpPackageName(opPackageName),
       mAudioTrackCallback(new AudioTrackCallback())
 {
     mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
@@ -277,13 +284,15 @@
         pid_t pid,
         const audio_attributes_t* pAttributes,
         bool doNotReconnect,
-        float maxRequiredSpeed)
+        float maxRequiredSpeed,
+        const std::string& opPackageName)
     : mStatus(NO_INIT),
       mState(STATE_STOPPED),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT),
       mPausedPosition(0),
       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+      mOpPackageName(opPackageName),
       mAudioTrackCallback(new AudioTrackCallback())
 {
     mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
@@ -1555,6 +1564,7 @@
     input.selectedDeviceId = mSelectedDeviceId;
     input.sessionId = mSessionId;
     input.audioTrackCallback = mAudioTrackCallback;
+    input.opPackageName = mOpPackageName;
 
     IAudioFlinger::CreateTrackOutput output;
 
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 16d2232..d3a037c 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -24,6 +24,7 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
+#include <media/AudioSanitizer.h>
 #include <mediautils/ServiceUtilities.h>
 #include <mediautils/TimeCheck.h>
 #include "IAudioFlinger.h"
@@ -1483,10 +1484,15 @@
         case GET_AUDIO_PORT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             struct audio_port port = {};
-            if (data.read(&port, sizeof(struct audio_port)) != NO_ERROR) {
+            status_t status = data.read(&port, sizeof(struct audio_port));
+            if (status != NO_ERROR) {
                 ALOGE("b/23905951");
+                return status;
             }
-            status_t status = getAudioPort(&port);
+            status = AudioSanitizer::sanitizeAudioPort(&port);
+            if (status == NO_ERROR) {
+                status = getAudioPort(&port);
+            }
             reply->writeInt32(status);
             if (status == NO_ERROR) {
                 reply->write(&port, sizeof(struct audio_port));
@@ -1496,12 +1502,20 @@
         case CREATE_AUDIO_PATCH: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             struct audio_patch patch;
-            data.read(&patch, sizeof(struct audio_patch));
-            audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
-            if (data.read(&handle, sizeof(audio_patch_handle_t)) != NO_ERROR) {
-                ALOGE("b/23905951");
+            status_t status = data.read(&patch, sizeof(struct audio_patch));
+            if (status != NO_ERROR) {
+                return status;
             }
-            status_t status = createAudioPatch(&patch, &handle);
+            audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
+            status = data.read(&handle, sizeof(audio_patch_handle_t));
+            if (status != NO_ERROR) {
+                ALOGE("b/23905951");
+                return status;
+            }
+            status = AudioSanitizer::sanitizeAudioPatch(&patch);
+            if (status == NO_ERROR) {
+                status = createAudioPatch(&patch, &handle);
+            }
             reply->writeInt32(status);
             if (status == NO_ERROR) {
                 reply->write(&handle, sizeof(audio_patch_handle_t));
@@ -1546,8 +1560,14 @@
         case SET_AUDIO_PORT_CONFIG: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             struct audio_port_config config;
-            data.read(&config, sizeof(struct audio_port_config));
-            status_t status = setAudioPortConfig(&config);
+            status_t status = data.read(&config, sizeof(struct audio_port_config));
+            if (status != NO_ERROR) {
+                return status;
+            }
+            status = AudioSanitizer::sanitizeAudioPortConfig(&config);
+            if (status == NO_ERROR) {
+                status = setAudioPortConfig(&config);
+            }
             reply->writeInt32(status);
             return NO_ERROR;
         } break;
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 60af84b..43a5369 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -26,6 +26,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
 #include <media/AudioEffect.h>
+#include <media/AudioSanitizer.h>
 #include <media/IAudioPolicyService.h>
 #include <mediautils/ServiceUtilities.h>
 #include <mediautils/TimeCheck.h>
@@ -1685,7 +1686,6 @@
             if (status != NO_ERROR) {
                 return status;
             }
-            sanetizeAudioAttributes(&attr);
             audio_session_t session = (audio_session_t)data.readInt32();
             audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
             bool hasStream = data.readInt32() != 0;
@@ -1703,10 +1703,14 @@
             audio_port_handle_t portId = (audio_port_handle_t)data.readInt32();
             audio_io_handle_t output = 0;
             std::vector<audio_io_handle_t> secondaryOutputs;
-            status = getOutputForAttr(&attr,
-                    &output, session, &stream, pid, uid,
-                    &config,
-                    flags, &selectedDeviceId, &portId, &secondaryOutputs);
+
+            status = AudioSanitizer::sanitizeAudioAttributes(&attr, "68953950");
+            if (status == NO_ERROR) {
+                status = getOutputForAttr(&attr,
+                                          &output, session, &stream, pid, uid,
+                                          &config,
+                                          flags, &selectedDeviceId, &portId, &secondaryOutputs);
+            }
             reply->writeInt32(status);
             status = reply->write(&attr, sizeof(audio_attributes_t));
             if (status != NO_ERROR) {
@@ -1745,8 +1749,11 @@
         case GET_INPUT_FOR_ATTR: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_attributes_t attr = {};
-            data.read(&attr, sizeof(audio_attributes_t));
-            sanetizeAudioAttributes(&attr);
+            status_t status = data.read(&attr, sizeof(audio_attributes_t));
+            if (status != NO_ERROR) {
+                return status;
+            }
+
             audio_io_handle_t input = (audio_io_handle_t)data.readInt32();
             audio_unique_id_t riid = (audio_unique_id_t)data.readInt32();
             audio_session_t session = (audio_session_t)data.readInt32();
@@ -1759,9 +1766,13 @@
             audio_input_flags_t flags = (audio_input_flags_t) data.readInt32();
             audio_port_handle_t selectedDeviceId = (audio_port_handle_t) data.readInt32();
             audio_port_handle_t portId = (audio_port_handle_t)data.readInt32();
-            status_t status = getInputForAttr(&attr, &input, riid, session, pid, uid,
-                                              opPackageName, &config,
-                                              flags, &selectedDeviceId, &portId);
+
+            status = AudioSanitizer::sanitizeAudioAttributes(&attr, "68953950");
+            if (status == NO_ERROR) {
+                status = getInputForAttr(&attr, &input, riid, session, pid, uid,
+                                         opPackageName, &config,
+                                         flags, &selectedDeviceId, &portId);
+            }
             reply->writeInt32(status);
             if (status == NO_ERROR) {
                 reply->writeInt32(input);
@@ -1842,11 +1853,15 @@
             if (status != NO_ERROR) {
                 return status;
             }
+
             int index = data.readInt32();
             audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
 
-            reply->writeInt32(static_cast <uint32_t>(setVolumeIndexForAttributes(attributes,
-                                                                                 index, device)));
+            status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+            if (status == NO_ERROR) {
+                status = setVolumeIndexForAttributes(attributes, index, device);
+            }
+            reply->writeInt32(static_cast <int32_t>(status));
             return NO_ERROR;
         } break;
 
@@ -1860,8 +1875,11 @@
             audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
 
             int index = 0;
-            status = getVolumeIndexForAttributes(attributes, index, device);
-            reply->writeInt32(static_cast <uint32_t>(status));
+            status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+            if (status == NO_ERROR) {
+                status = getVolumeIndexForAttributes(attributes, index, device);
+            }
+            reply->writeInt32(static_cast <int32_t>(status));
             if (status == NO_ERROR) {
                 reply->writeInt32(index);
             }
@@ -1877,8 +1895,11 @@
             }
 
             int index = 0;
-            status = getMinVolumeIndexForAttributes(attributes, index);
-            reply->writeInt32(static_cast <uint32_t>(status));
+            status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+            if (status == NO_ERROR) {
+                status = getMinVolumeIndexForAttributes(attributes, index);
+            }
+            reply->writeInt32(static_cast <int32_t>(status));
             if (status == NO_ERROR) {
                 reply->writeInt32(index);
             }
@@ -1894,8 +1915,11 @@
             }
 
             int index = 0;
-            status = getMaxVolumeIndexForAttributes(attributes, index);
-            reply->writeInt32(static_cast <uint32_t>(status));
+            status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+            if (status == NO_ERROR) {
+                status = getMaxVolumeIndexForAttributes(attributes, index);
+            }
+            reply->writeInt32(static_cast <int32_t>(status));
             if (status == NO_ERROR) {
                 reply->writeInt32(index);
             }
@@ -1913,31 +1937,37 @@
         case GET_OUTPUT_FOR_EFFECT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             effect_descriptor_t desc = {};
-            if (data.read(&desc, sizeof(desc)) != NO_ERROR) {
+            status_t status = data.read(&desc, sizeof(desc));
+            if (status != NO_ERROR) {
                 android_errorWriteLog(0x534e4554, "73126106");
+                return status;
             }
-            (void)sanitizeEffectDescriptor(&desc);
-            audio_io_handle_t output = getOutputForEffect(&desc);
-            reply->writeInt32(static_cast <int>(output));
+            audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+            status = AudioSanitizer::sanitizeEffectDescriptor(&desc, "73126106");
+            if (status == NO_ERROR) {
+                output = getOutputForEffect(&desc);
+            }
+            reply->writeInt32(static_cast <int32_t>(output));
             return NO_ERROR;
         } break;
 
         case REGISTER_EFFECT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             effect_descriptor_t desc = {};
-            if (data.read(&desc, sizeof(desc)) != NO_ERROR) {
+            status_t status = data.read(&desc, sizeof(desc));
+            if (status != NO_ERROR) {
                 android_errorWriteLog(0x534e4554, "73126106");
+                return status;
             }
-            (void)sanitizeEffectDescriptor(&desc);
             audio_io_handle_t io = data.readInt32();
             uint32_t strategy = data.readInt32();
             audio_session_t session = (audio_session_t) data.readInt32();
             int id = data.readInt32();
-            reply->writeInt32(static_cast <int32_t>(registerEffect(&desc,
-                                                                   io,
-                                                                   strategy,
-                                                                   session,
-                                                                   id)));
+            status = AudioSanitizer::sanitizeEffectDescriptor(&desc, "73126106");
+            if (status == NO_ERROR) {
+                status = registerEffect(&desc, io, strategy, session, id);
+            }
+            reply->writeInt32(static_cast <int32_t>(status));
             return NO_ERROR;
         } break;
 
@@ -2046,7 +2076,11 @@
             if (status != NO_ERROR) return status;
             status = data.read(&attributes, sizeof(audio_attributes_t));
             if (status != NO_ERROR) return status;
-            reply->writeInt32(isDirectOutputSupported(config, attributes));
+            status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "169572641");
+            if (status == NO_ERROR) {
+                status = isDirectOutputSupported(config, attributes);
+            }
+            reply->writeInt32(static_cast <int32_t>(status));
             return NO_ERROR;
         }
 
@@ -2085,10 +2119,15 @@
         case GET_AUDIO_PORT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             struct audio_port port = {};
-            if (data.read(&port, sizeof(struct audio_port)) != NO_ERROR) {
+            status_t status = data.read(&port, sizeof(struct audio_port));
+            if (status != NO_ERROR) {
                 ALOGE("b/23912202");
+                return status;
             }
-            status_t status = getAudioPort(&port);
+            status = AudioSanitizer::sanitizeAudioPort(&port);
+            if (status == NO_ERROR) {
+                status = getAudioPort(&port);
+            }
             reply->writeInt32(status);
             if (status == NO_ERROR) {
                 reply->write(&port, sizeof(struct audio_port));
@@ -2099,12 +2138,20 @@
         case CREATE_AUDIO_PATCH: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             struct audio_patch patch = {};
-            data.read(&patch, sizeof(struct audio_patch));
-            audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
-            if (data.read(&handle, sizeof(audio_patch_handle_t)) != NO_ERROR) {
-                ALOGE("b/23912202");
+            status_t status = data.read(&patch, sizeof(struct audio_patch));
+            if (status != NO_ERROR) {
+                return status;
             }
-            status_t status = createAudioPatch(&patch, &handle);
+            audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
+            status = data.read(&handle, sizeof(audio_patch_handle_t));
+            if (status != NO_ERROR) {
+                ALOGE("b/23912202");
+                return status;
+            }
+            status = AudioSanitizer::sanitizeAudioPatch(&patch);
+            if (status == NO_ERROR) {
+                status = createAudioPatch(&patch, &handle);
+            }
             reply->writeInt32(status);
             if (status == NO_ERROR) {
                 reply->write(&handle, sizeof(audio_patch_handle_t));
@@ -2154,9 +2201,12 @@
         case SET_AUDIO_PORT_CONFIG: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             struct audio_port_config config = {};
-            data.read(&config, sizeof(struct audio_port_config));
-            (void)sanitizeAudioPortConfig(&config);
-            status_t status = setAudioPortConfig(&config);
+            status_t status = data.read(&config, sizeof(struct audio_port_config));
+            if (status != NO_ERROR) {
+                return status;
+            }
+            (void)AudioSanitizer::sanitizeAudioPortConfig(&config);
+            status = setAudioPortConfig(&config);
             reply->writeInt32(status);
             return NO_ERROR;
         }
@@ -2232,13 +2282,25 @@
         case START_AUDIO_SOURCE: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             struct audio_port_config source = {};
-            data.read(&source, sizeof(struct audio_port_config));
-            (void)sanitizeAudioPortConfig(&source);
+            status_t status = data.read(&source, sizeof(struct audio_port_config));
+            if (status != NO_ERROR) {
+                return status;
+            }
             audio_attributes_t attributes = {};
-            data.read(&attributes, sizeof(audio_attributes_t));
-            sanetizeAudioAttributes(&attributes);
+            status = data.read(&attributes, sizeof(audio_attributes_t));
+            if (status != NO_ERROR) {
+                return status;
+            }
+            status = AudioSanitizer::sanitizeAudioPortConfig(&source);
+            if (status == NO_ERROR) {
+                // OK to not always sanitize attributes as startAudioSource() is not called if
+                // the port config is invalid.
+                status = AudioSanitizer::sanitizeAudioAttributes(&attributes, "68953950");
+            }
             audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
-            status_t status = startAudioSource(&source, &attributes, &portId);
+            if (status == NO_ERROR) {
+                status = startAudioSource(&source, &attributes, &portId);
+            }
             reply->writeInt32(status);
             reply->writeInt32(portId);
             return NO_ERROR;
@@ -2762,44 +2824,6 @@
     }
 }
 
-/** returns true if string overflow was prevented by zero termination */
-template <size_t size>
-static bool preventStringOverflow(char (&s)[size]) {
-    if (strnlen(s, size) < size) return false;
-    s[size - 1] = '\0';
-    return true;
-}
-
-void BnAudioPolicyService::sanetizeAudioAttributes(audio_attributes_t* attr)
-{
-    const size_t tagsMaxSize = AUDIO_ATTRIBUTES_TAGS_MAX_SIZE;
-    if (strnlen(attr->tags, tagsMaxSize) >= tagsMaxSize) {
-        android_errorWriteLog(0x534e4554, "68953950"); // SafetyNet logging
-    }
-    attr->tags[tagsMaxSize - 1] = '\0';
-}
-
-/** returns BAD_VALUE if sanitization was required. */
-status_t BnAudioPolicyService::sanitizeEffectDescriptor(effect_descriptor_t* desc)
-{
-    if (preventStringOverflow(desc->name)
-        | /* always */ preventStringOverflow(desc->implementor)) {
-        android_errorWriteLog(0x534e4554, "73126106"); // SafetyNet logging
-        return BAD_VALUE;
-    }
-    return NO_ERROR;
-}
-
-/** returns BAD_VALUE if sanitization was required. */
-status_t BnAudioPolicyService::sanitizeAudioPortConfig(struct audio_port_config* config)
-{
-    if (config->type == AUDIO_PORT_TYPE_DEVICE &&
-        preventStringOverflow(config->ext.device.address)) {
-        return BAD_VALUE;
-    }
-    return NO_ERROR;
-}
-
 // ----------------------------------------------------------------------------
 
 } // namespace android
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index 050ad65..ee78a2d 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -853,6 +853,11 @@
                       { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
           .repeatCnt = ToneGenerator::TONEGEN_INF,
           .repeatSegment = 0 },                               // TONE_INDIA_RINGTONE
+        { .segments = { { .duration = 1000, .waveFreq = { 440, 480, 0 }, 0, 0 },
+                        { .duration = 2000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                               // TONE_TW_RINGTONE
 };
 
 // Used by ToneGenerator::getToneForRegion() to convert user specified supervisory tone type
@@ -937,6 +942,16 @@
             TONE_SUP_ERROR,              // TONE_SUP_ERROR
             TONE_INDIA_CALL_WAITING,     // TONE_SUP_CALL_WAITING
             TONE_INDIA_RINGTONE          // TONE_SUP_RINGTONE
+        },
+        {   // TAIWAN
+            TONE_SUP_DIAL,               // TONE_SUP_DIAL
+            TONE_SUP_BUSY,               // TONE_SUP_BUSY
+            TONE_SUP_CONGESTION,         // TONE_SUP_CONGESTION
+            TONE_SUP_RADIO_ACK,          // TONE_SUP_RADIO_ACK
+            TONE_SUP_RADIO_NOTAVAIL,     // TONE_SUP_RADIO_NOTAVAIL
+            TONE_SUP_ERROR,              // TONE_SUP_ERROR
+            TONE_SUP_CALL_WAITING,       // TONE_SUP_CALL_WAITING
+            TONE_TW_RINGTONE             // TONE_SUP_RINGTONE
         }
 };
 
@@ -1010,6 +1025,8 @@
         mRegion = IRELAND;
     } else if (strstr(value, "in") != NULL) {
         mRegion = INDIA;
+    } else if (strstr(value, "tw") != NULL) {
+        mRegion = TAIWAN;
     } else {
         mRegion = CEPT;
     }
diff --git a/media/libaudioclient/include/media/AudioEffect.h b/media/libaudioclient/include/media/AudioEffect.h
index cb76252..3d4bb4e 100644
--- a/media/libaudioclient/include/media/AudioEffect.h
+++ b/media/libaudioclient/include/media/AudioEffect.h
@@ -339,16 +339,21 @@
      *
      * opPackageName:      The package name used for app op checks.
      */
-    AudioEffect(const String16& opPackageName);
+    explicit AudioEffect(const String16& opPackageName);
 
+    /* Terminates the AudioEffect and unregisters it from AudioFlinger.
+     * The effect engine is also destroyed if this AudioEffect was the last controlling
+     * the engine.
+     */
+                        ~AudioEffect();
 
-    /* Constructor.
+    /**
+     * Initialize an uninitialized AudioEffect.
      *
      * Parameters:
      *
      * type:  type of effect created: can be null if uuid is specified. This corresponds to
      *        the OpenSL ES interface implemented by this effect.
-     * opPackageName:  The package name used for app op checks.
      * uuid:  Uuid of effect created: can be null if type is specified. This uuid corresponds to
      *        a particular implementation of an effect type.
      * priority:    requested priority for effect control: the priority level corresponds to the
@@ -356,7 +361,7 @@
      *      higher priorities, 0 being the normal priority.
      * cbf:         optional callback function (see effect_callback_t)
      * user:        pointer to context for use by the callback receiver.
-     * sessionID:   audio session this effect is associated to.
+     * sessionId:   audio session this effect is associated to.
      *      If equal to AUDIO_SESSION_OUTPUT_MIX, the effect will be global to
      *      the output mix.  Otherwise, the effect will be applied to all players
      *      (AudioTrack or MediaPLayer) within the same audio session.
@@ -369,46 +374,13 @@
      *        In this mode, no IEffect interface to AudioFlinger is created and all actions
      *        besides getters implemented in client AudioEffect object are no ops
      *        after effect creation.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR or ALREADY_EXISTS: successful initialization
+     *  - INVALID_OPERATION: AudioEffect is already initialized
+     *  - BAD_VALUE: invalid parameter
+     *  - NO_INIT: audio flinger or audio hardware not initialized
      */
-
-    AudioEffect(const effect_uuid_t *type,
-                const String16& opPackageName,
-                const effect_uuid_t *uuid = NULL,
-                int32_t priority = 0,
-                effect_callback_t cbf = NULL,
-                void* user = NULL,
-                audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
-                audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
-                const AudioDeviceTypeAddr& device = {},
-                bool probe = false);
-
-    /* Constructor.
-     *      Same as above but with type and uuid specified by character strings
-     */
-    AudioEffect(const char *typeStr,
-                    const String16& opPackageName,
-                    const char *uuidStr = NULL,
-                    int32_t priority = 0,
-                    effect_callback_t cbf = NULL,
-                    void* user = NULL,
-                    audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
-                    audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
-                    const AudioDeviceTypeAddr& device = {},
-                    bool probe = false);
-
-    /* Terminates the AudioEffect and unregisters it from AudioFlinger.
-     * The effect engine is also destroyed if this AudioEffect was the last controlling
-     * the engine.
-     */
-                        ~AudioEffect();
-
-    /* Initialize an uninitialized AudioEffect.
-    * Returned status (from utils/Errors.h) can be:
-    *  - NO_ERROR or ALREADY_EXISTS: successful initialization
-    *  - INVALID_OPERATION: AudioEffect is already initialized
-    *  - BAD_VALUE: invalid parameter
-    *  - NO_INIT: audio flinger or audio hardware not initialized
-    * */
             status_t    set(const effect_uuid_t *type,
                             const effect_uuid_t *uuid = NULL,
                             int32_t priority = 0,
@@ -418,6 +390,18 @@
                             audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
                             const AudioDeviceTypeAddr& device = {},
                             bool probe = false);
+    /*
+     * Same as above but with type and uuid specified by character strings.
+     */
+            status_t    set(const char *typeStr,
+                            const char *uuidStr = NULL,
+                            int32_t priority = 0,
+                            effect_callback_t cbf = NULL,
+                            void* user = NULL,
+                            audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
+                            audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
+                            const AudioDeviceTypeAddr& device = {},
+                            bool probe = false);
 
     /* Result of constructing the AudioEffect. This must be checked
      * before using any AudioEffect API.
@@ -547,21 +531,20 @@
      static const uint32_t kMaxPreProcessing = 10;
 
 protected:
-     bool                    mEnabled;           // enable state
-     audio_session_t         mSessionId;         // audio session ID
-     int32_t                 mPriority;          // priority for effect control
-     status_t                mStatus;            // effect status
-     bool                    mProbe;             // effect created in probe mode: all commands
+     const String16          mOpPackageName;     // The package name used for app op checks.
+     bool                    mEnabled = false;   // enable state
+     audio_session_t         mSessionId = AUDIO_SESSION_OUTPUT_MIX; // audio session ID
+     int32_t                 mPriority = 0;      // priority for effect control
+     status_t                mStatus = NO_INIT;  // effect status
+     bool                    mProbe = false;     // effect created in probe mode: all commands
                                                  // are no ops because mIEffect is NULL
-     effect_callback_t       mCbf;               // callback function for status, control and
+     effect_callback_t       mCbf = nullptr;     // callback function for status, control and
                                                  // parameter changes notifications
-     void*                   mUserData;          // client context for callback function
-     effect_descriptor_t     mDescriptor;        // effect descriptor
-     int32_t                 mId;                // system wide unique effect engine instance ID
+     void*                   mUserData = nullptr;// client context for callback function
+     effect_descriptor_t     mDescriptor = {};   // effect descriptor
+     int32_t                 mId = -1;           // system wide unique effect engine instance ID
      Mutex                   mLock;              // Mutex for mEnabled access
-     Mutex                   mConstructLock;     // Mutex for integrality construction
 
-     String16                mOpPackageName;     // The package name used for app op checks.
 
      // IEffectClient
      virtual void controlStatusChanged(bool controlGranted);
@@ -586,22 +569,12 @@
         virtual void controlStatusChanged(bool controlGranted) {
             sp<AudioEffect> effect = mEffect.promote();
             if (effect != 0) {
-                {
-                    // Got the mConstructLock means the construction of AudioEffect
-                    // has finished, we should release the mConstructLock immediately.
-                    AutoMutex lock(effect->mConstructLock);
-                }
                 effect->controlStatusChanged(controlGranted);
             }
         }
         virtual void enableStatusChanged(bool enabled) {
             sp<AudioEffect> effect = mEffect.promote();
             if (effect != 0) {
-                {
-                    // Got the mConstructLock means the construction of AudioEffect
-                    // has finished, we should release the mConstructLock immediately.
-                    AutoMutex lock(effect->mConstructLock);
-                }
                 effect->enableStatusChanged(enabled);
             }
         }
@@ -612,11 +585,6 @@
                                      void *pReplyData) {
             sp<AudioEffect> effect = mEffect.promote();
             if (effect != 0) {
-                {
-                    // Got the mConstructLock means the construction of AudioEffect
-                    // has finished, we should release the mConstructLock immediately.
-                    AutoMutex lock(effect->mConstructLock);
-                }
                 effect->commandExecuted(
                     cmdCode, cmdSize, pCmdData, replySize, pReplyData);
             }
@@ -626,11 +594,6 @@
         virtual void binderDied(const wp<IBinder>& /*who*/) {
             sp<AudioEffect> effect = mEffect.promote();
             if (effect != 0) {
-                {
-                    // Got the mConstructLock means the construction of AudioEffect
-                    // has finished, we should release the mConstructLock immediately.
-                    AutoMutex lock(effect->mConstructLock);
-                }
                 effect->binderDied();
             }
         }
@@ -644,7 +607,7 @@
     sp<IEffect>             mIEffect;           // IEffect binder interface
     sp<EffectClient>        mIEffectClient;     // IEffectClient implementation
     sp<IMemory>             mCblkMemory;        // shared memory for deferred parameter setting
-    effect_param_cblk_t*    mCblk;              // control block for deferred parameter setting
+    effect_param_cblk_t*    mCblk = nullptr;    // control block for deferred parameter setting
     pid_t                   mClientPid = (pid_t)-1;
     uid_t                   mClientUid = (uid_t)-1;
 };
diff --git a/media/libaudioclient/include/media/AudioSanitizer.h b/media/libaudioclient/include/media/AudioSanitizer.h
new file mode 100644
index 0000000..1475c7b
--- /dev/null
+++ b/media/libaudioclient/include/media/AudioSanitizer.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_AUDIO_SANITIZER_H_
+#define ANDROID_AUDIO_SANITIZER_H_
+
+#include <system/audio.h>
+#include <system/audio_effect.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+namespace android {
+
+class AudioSanitizer {
+public:
+    static status_t sanitizeAudioAttributes(
+            audio_attributes_t *attr, const char *bugNumber = nullptr);
+
+    static status_t sanitizeEffectDescriptor(
+            effect_descriptor_t *desc, const char *bugNumber = nullptr);
+
+    static status_t sanitizeAudioPortConfig(
+            struct audio_port_config *config, const char *bugNumber = nullptr);
+
+    static status_t sanitizeAudioPort(
+            struct audio_port *port, const char *bugNumber = nullptr);
+
+    static status_t sanitizeAudioPatch(
+            struct audio_patch *patch, const char *bugNumber = nullptr);
+};
+
+}; // namespace android
+
+#endif  /*ANDROID_AUDIO_SANITIZER_H_*/
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 0dbd842..a9946da 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -26,6 +26,8 @@
 #include <media/Modulo.h>
 #include <utils/threads.h>
 
+#include <string>
+
 #include "android/media/BnAudioTrackCallback.h"
 #include "android/media/IAudioTrackCallback.h"
 
@@ -177,6 +179,8 @@
      */
                         AudioTrack();
 
+                        AudioTrack(const std::string& opPackageName);
+
     /* Creates an AudioTrack object and registers it with AudioFlinger.
      * Once created, the track needs to be started before it can be used.
      * Unspecified values are set to appropriate default values.
@@ -258,7 +262,8 @@
                                     const audio_attributes_t* pAttributes = NULL,
                                     bool doNotReconnect = false,
                                     float maxRequiredSpeed = 1.0f,
-                                    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
+                                    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE,
+                                    const std::string& opPackageName = "");
 
     /* Creates an audio track and registers it with AudioFlinger.
      * With this constructor, the track is configured for static buffer mode.
@@ -288,7 +293,8 @@
                                     pid_t pid = -1,
                                     const audio_attributes_t* pAttributes = NULL,
                                     bool doNotReconnect = false,
-                                    float maxRequiredSpeed = 1.0f);
+                                    float maxRequiredSpeed = 1.0f,
+                                    const std::string& opPackageName = "");
 
     /* Terminates the AudioTrack and unregisters it from AudioFlinger.
      * Also destroys all resources associated with the AudioTrack.
@@ -1236,6 +1242,8 @@
 
     sp<media::VolumeHandler>       mVolumeHandler;
 
+    const std::string      mOpPackageName;
+
 private:
     class DeathNotifier : public IBinder::DeathRecipient {
     public:
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 612ce7a..bcc11f4 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -37,6 +37,7 @@
 #include <media/IEffectClient.h>
 #include <utils/String8.h>
 #include <media/MicrophoneInfo.h>
+#include <string>
 #include <vector>
 
 #include "android/media/IAudioRecord.h"
@@ -85,6 +86,11 @@
             speed = parcel->readFloat();
             audioTrackCallback = interface_cast<media::IAudioTrackCallback>(
                     parcel->readStrongBinder());
+            const char* opPackageNamePtr = parcel->readCString();
+            if (opPackageNamePtr == nullptr) {
+                return FAILED_TRANSACTION;
+            }
+            opPackageName = opPackageNamePtr;
 
             /* input/output arguments*/
             (void)parcel->read(&flags, sizeof(audio_output_flags_t));
@@ -109,6 +115,7 @@
             (void)parcel->writeInt32(notificationsPerBuffer);
             (void)parcel->writeFloat(speed);
             (void)parcel->writeStrongBinder(IInterface::asBinder(audioTrackCallback));
+            (void)parcel->writeCString(opPackageName.c_str());
 
             /* input/output arguments*/
             (void)parcel->write(&flags, sizeof(audio_output_flags_t));
@@ -127,6 +134,7 @@
         uint32_t notificationsPerBuffer;
         float speed;
         sp<media::IAudioTrackCallback> audioTrackCallback;
+        std::string opPackageName;
 
         /* input/output */
         audio_output_flags_t flags;
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index bb1c07f..376c6eb 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -266,10 +266,6 @@
                                     const Parcel& data,
                                     Parcel* reply,
                                     uint32_t flags = 0);
-private:
-    void sanetizeAudioAttributes(audio_attributes_t* attr);
-    status_t sanitizeEffectDescriptor(effect_descriptor_t* desc);
-    status_t sanitizeAudioPortConfig(struct audio_port_config* config);
 };
 
 // ----------------------------------------------------------------------------
diff --git a/media/libaudioclient/include/media/ToneGenerator.h b/media/libaudioclient/include/media/ToneGenerator.h
index 5b0689a..04357a8 100644
--- a/media/libaudioclient/include/media/ToneGenerator.h
+++ b/media/libaudioclient/include/media/ToneGenerator.h
@@ -218,6 +218,7 @@
         TONE_INDIA_CONGESTION,      // Congestion tone: 400 Hz, 250ms ON, 250ms OFF...
         TONE_INDIA_CALL_WAITING,    // Call waiting tone: 400 Hz, tone repeated in a 0.2s on, 0.1s off, 0.2s on, 7.5s off pattern.
         TONE_INDIA_RINGTONE,        // Ring tone: 400 Hz tone modulated with 25Hz, 0.4 on 0.2 off 0.4 on 2..0 off
+        TONE_TW_RINGTONE,           // Ring Tone: 440 Hz + 480 Hz repeated with pattern 1s on, 3s off.
         NUM_ALTERNATE_TONES
     };
 
@@ -230,6 +231,7 @@
         HONGKONG,
         IRELAND,
         INDIA,
+        TAIWAN,
         CEPT,
         NUM_REGIONS
     };
diff --git a/media/libaudioprocessing/AudioMixerOps.h b/media/libaudioprocessing/AudioMixerOps.h
index 80bd093..8d374c9 100644
--- a/media/libaudioprocessing/AudioMixerOps.h
+++ b/media/libaudioprocessing/AudioMixerOps.h
@@ -234,17 +234,20 @@
     static_assert(NCHAN > 0 && NCHAN <= 8);
     static_assert(MIXTYPE == MIXTYPE_MULTI_STEREOVOL
             || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
-            || MIXTYPE == MIXTYPE_STEREOEXPAND);
+            || MIXTYPE == MIXTYPE_STEREOEXPAND
+            || MIXTYPE == MIXTYPE_MONOEXPAND);
     auto proc = [](auto& a, const auto& b) {
         if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
-                || MIXTYPE == MIXTYPE_STEREOEXPAND) {
+                || MIXTYPE == MIXTYPE_STEREOEXPAND
+                || MIXTYPE == MIXTYPE_MONOEXPAND) {
             a += b;
         } else {
             a = b;
         }
     };
     auto inp = [&in]() -> const TI& {
-        if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) {
+        if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND
+                || MIXTYPE == MIXTYPE_MONOEXPAND) {
             return *in;
         } else {
             return *in++;
@@ -312,6 +315,8 @@
  *   TV/TAV: int32_t (U4.28) or int16_t (U4.12) or float
  *   Input channel count is 1.
  *   vol: represents volume array.
+ *   This uses stereo balanced volume vol[0] and vol[1].
+ *   Before R, this was a full volume array but was called only for channels <= 2.
  *
  *   This accumulates into the out pointer.
  *
@@ -356,17 +361,13 @@
         do {
             TA auxaccum = 0;
             if constexpr (MIXTYPE == MIXTYPE_MULTI) {
+                static_assert(NCHAN <= 2);
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
                     vol[i] += volinc[i];
                 }
-            } else if constexpr (MIXTYPE == MIXTYPE_MONOEXPAND) {
-                for (int i = 0; i < NCHAN; ++i) {
-                    *out++ += MixMulAux<TO, TI, TV, TA>(*in, vol[i], &auxaccum);
-                    vol[i] += volinc[i];
-                }
-                in++;
             } else if constexpr (MIXTYPE == MIXTYPE_MULTI_SAVEONLY) {
+                static_assert(NCHAN <= 2);
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
                     vol[i] += volinc[i];
@@ -383,11 +384,13 @@
                 vol[0] += volinc[0];
             } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
                     || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+                    || MIXTYPE == MIXTYPE_MONOEXPAND
                     || MIXTYPE == MIXTYPE_STEREOEXPAND) {
                 stereoVolumeHelper<MIXTYPE, NCHAN>(
                         out, in, vol, [&auxaccum] (auto &a, const auto &b) {
                     return MixMulAux<TO, TI, TV, TA>(a, b, &auxaccum);
                 });
+                if constexpr (MIXTYPE == MIXTYPE_MONOEXPAND) in += 1;
                 if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
                 vol[0] += volinc[0];
                 vol[1] += volinc[1];
@@ -401,17 +404,13 @@
     } else {
         do {
             if constexpr (MIXTYPE == MIXTYPE_MULTI) {
+                static_assert(NCHAN <= 2);
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMul<TO, TI, TV>(*in++, vol[i]);
                     vol[i] += volinc[i];
                 }
-            } else if constexpr (MIXTYPE == MIXTYPE_MONOEXPAND) {
-                for (int i = 0; i < NCHAN; ++i) {
-                    *out++ += MixMul<TO, TI, TV>(*in, vol[i]);
-                    vol[i] += volinc[i];
-                }
-                in++;
             } else if constexpr (MIXTYPE == MIXTYPE_MULTI_SAVEONLY) {
+                static_assert(NCHAN <= 2);
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ = MixMul<TO, TI, TV>(*in++, vol[i]);
                     vol[i] += volinc[i];
@@ -428,10 +427,12 @@
                 vol[0] += volinc[0];
             } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
                     || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+                    || MIXTYPE == MIXTYPE_MONOEXPAND
                     || MIXTYPE == MIXTYPE_STEREOEXPAND) {
                 stereoVolumeHelper<MIXTYPE, NCHAN>(out, in, vol, [] (auto &a, const auto &b) {
                     return MixMul<TO, TI, TV>(a, b);
                 });
+                if constexpr (MIXTYPE == MIXTYPE_MONOEXPAND) in += 1;
                 if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
                 vol[0] += volinc[0];
                 vol[1] += volinc[1];
@@ -454,15 +455,12 @@
         do {
             TA auxaccum = 0;
             if constexpr (MIXTYPE == MIXTYPE_MULTI) {
+                static_assert(NCHAN <= 2);
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
                 }
-            } else if constexpr (MIXTYPE == MIXTYPE_MONOEXPAND) {
-                for (int i = 0; i < NCHAN; ++i) {
-                    *out++ += MixMulAux<TO, TI, TV, TA>(*in, vol[i], &auxaccum);
-                }
-                in++;
             } else if constexpr (MIXTYPE == MIXTYPE_MULTI_SAVEONLY) {
+                static_assert(NCHAN <= 2);
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
                 }
@@ -476,11 +474,13 @@
                 }
             } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
                     || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+                    || MIXTYPE == MIXTYPE_MONOEXPAND
                     || MIXTYPE == MIXTYPE_STEREOEXPAND) {
                 stereoVolumeHelper<MIXTYPE, NCHAN>(
                         out, in, vol, [&auxaccum] (auto &a, const auto &b) {
                     return MixMulAux<TO, TI, TV, TA>(a, b, &auxaccum);
                 });
+                if constexpr (MIXTYPE == MIXTYPE_MONOEXPAND) in += 1;
                 if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
             } else /* constexpr */ {
                 static_assert(dependent_false<MIXTYPE>, "invalid mixtype");
@@ -490,16 +490,14 @@
         } while (--frameCount);
     } else {
         do {
+            // ALOGD("Mixtype:%d NCHAN:%d", MIXTYPE, NCHAN);
             if constexpr (MIXTYPE == MIXTYPE_MULTI) {
+                static_assert(NCHAN <= 2);
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMul<TO, TI, TV>(*in++, vol[i]);
                 }
-            } else if constexpr (MIXTYPE == MIXTYPE_MONOEXPAND) {
-                for (int i = 0; i < NCHAN; ++i) {
-                    *out++ += MixMul<TO, TI, TV>(*in, vol[i]);
-                }
-                in++;
             } else if constexpr (MIXTYPE == MIXTYPE_MULTI_SAVEONLY) {
+                static_assert(NCHAN <= 2);
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ = MixMul<TO, TI, TV>(*in++, vol[i]);
                 }
@@ -513,10 +511,12 @@
                 }
             } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
                     || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+                    || MIXTYPE == MIXTYPE_MONOEXPAND
                     || MIXTYPE == MIXTYPE_STEREOEXPAND) {
                 stereoVolumeHelper<MIXTYPE, NCHAN>(out, in, vol, [] (auto &a, const auto &b) {
                     return MixMul<TO, TI, TV>(a, b);
                 });
+                if constexpr (MIXTYPE == MIXTYPE_MONOEXPAND) in += 1;
                 if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
             } else /* constexpr */ {
                 static_assert(dependent_false<MIXTYPE>, "invalid mixtype");
diff --git a/media/libaudioprocessing/tests/mixerops_benchmark.cpp b/media/libaudioprocessing/tests/mixerops_benchmark.cpp
index 86f5429..7a4c5c7 100644
--- a/media/libaudioprocessing/tests/mixerops_benchmark.cpp
+++ b/media/libaudioprocessing/tests/mixerops_benchmark.cpp
@@ -74,28 +74,32 @@
     }
 }
 
-BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI, 2);
-BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY, 2);
+// MULTI mode and MULTI_SAVEONLY mode are not used by AudioMixer for channels > 2,
+// which is ensured by a static_assert (won't compile for those configurations).
+// So we benchmark MIXTYPE_MULTI_MONOVOL and MIXTYPE_MULTI_SAVEONLY_MONOVOL compared
+// with MIXTYPE_MULTI_STEREOVOL and MIXTYPE_MULTI_SAVEONLY_STEREOVOL.
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_MONOVOL, 2);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY_MONOVOL, 2);
 BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_STEREOVOL, 2);
 BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY_STEREOVOL, 2);
 
-BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI, 4);
-BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY, 4);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_MONOVOL, 4);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY_MONOVOL, 4);
 BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_STEREOVOL, 4);
 BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY_STEREOVOL, 4);
 
-BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI, 5);
-BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY, 5);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_MONOVOL, 5);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY_MONOVOL, 5);
 BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_STEREOVOL, 5);
 BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY_STEREOVOL, 5);
 
-BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI, 8);
-BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY, 8);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_MONOVOL, 8);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY_MONOVOL, 8);
 BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_STEREOVOL, 8);
 BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY_STEREOVOL, 8);
 
-BENCHMARK_TEMPLATE(BM_VolumeMulti, MIXTYPE_MULTI, 8);
-BENCHMARK_TEMPLATE(BM_VolumeMulti, MIXTYPE_MULTI_SAVEONLY, 8);
+BENCHMARK_TEMPLATE(BM_VolumeMulti, MIXTYPE_MULTI_MONOVOL, 8);
+BENCHMARK_TEMPLATE(BM_VolumeMulti, MIXTYPE_MULTI_SAVEONLY_MONOVOL, 8);
 BENCHMARK_TEMPLATE(BM_VolumeMulti, MIXTYPE_MULTI_STEREOVOL, 8);
 BENCHMARK_TEMPLATE(BM_VolumeMulti, MIXTYPE_MULTI_SAVEONLY_STEREOVOL, 8);
 
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index 39caf53..7ed76d8 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -38,7 +38,8 @@
     FLAGS,
     SETMEDIACAS,
     NAME,
-    GETMETRICS
+    GETMETRICS,
+    SETENTRYPOINT
 };
 
 class BpMediaExtractor : public BpInterface<IMediaExtractor> {
@@ -142,6 +143,13 @@
         }
         return nm;
     }
+
+    virtual status_t setEntryPoint(EntryPoint entryPoint) {
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+        data.writeInt32(static_cast<int32_t>(entryPoint));
+        return remote()->transact(SETENTRYPOINT, data, &reply);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(MediaExtractor, "android.media.IMediaExtractor");
@@ -232,6 +240,16 @@
             reply->writeString8(nm);
             return NO_ERROR;
         }
+        case SETENTRYPOINT: {
+            ALOGV("setEntryPoint");
+            CHECK_INTERFACE(IMediaExtractor, data, reply);
+            int32_t entryPoint;
+            status_t err = data.readInt32(&entryPoint);
+            if (err == OK) {
+                setEntryPoint(EntryPoint(entryPoint));
+            }
+            return err;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index bd18a40..11005c6 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -62,11 +62,13 @@
     }
 
     virtual sp<IMediaPlayer> create(
-            const sp<IMediaPlayerClient>& client, audio_session_t audioSessionId) {
+            const sp<IMediaPlayerClient>& client, audio_session_t audioSessionId,
+            const std::string opPackageName) {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
         data.writeStrongBinder(IInterface::asBinder(client));
         data.writeInt32(audioSessionId);
+        data.writeCString(opPackageName.c_str());
 
         remote()->transact(CREATE, data, &reply);
         return interface_cast<IMediaPlayer>(reply.readStrongBinder());
@@ -127,7 +129,12 @@
             sp<IMediaPlayerClient> client =
                 interface_cast<IMediaPlayerClient>(data.readStrongBinder());
             audio_session_t audioSessionId = (audio_session_t) data.readInt32();
-            sp<IMediaPlayer> player = create(client, audioSessionId);
+            const char* opPackageName = data.readCString();
+            if (opPackageName == nullptr) {
+                return FAILED_TRANSACTION;
+            }
+            std::string opPackageNameStr(opPackageName);
+            sp<IMediaPlayer> player = create(client, audioSessionId, opPackageNameStr);
             reply->writeStrongBinder(IInterface::asBinder(player));
             return NO_ERROR;
         } break;
diff --git a/media/libmedia/aidl/android/media/IResourceManagerService.aidl b/media/libmedia/aidl/android/media/IResourceManagerService.aidl
index 1b2d522..621bd84 100644
--- a/media/libmedia/aidl/android/media/IResourceManagerService.aidl
+++ b/media/libmedia/aidl/android/media/IResourceManagerService.aidl
@@ -102,4 +102,11 @@
      * @param clientId clientId within the pid that will be removed.
      */
     void markClientForPendingRemoval(int pid, long clientId);
+
+    /**
+     * Reclaim resources from clients pending removal, if any.
+     *
+     * @param pid pid from which resources will be reclaimed.
+     */
+    void reclaimResourcesFromClientsPendingRemoval(int pid);
 }
diff --git a/media/libmedia/include/android/IMediaExtractor.h b/media/libmedia/include/android/IMediaExtractor.h
index 3e035ad..f9cafde 100644
--- a/media/libmedia/include/android/IMediaExtractor.h
+++ b/media/libmedia/include/android/IMediaExtractor.h
@@ -63,6 +63,15 @@
     virtual status_t setMediaCas(const HInterfaceToken &casToken) = 0;
 
     virtual String8 name() = 0;
+
+    enum class EntryPoint {
+        SDK = 1,
+        NDK_WITH_JVM = 2,
+        NDK_NO_JVM = 3,
+        OTHER = 4,
+    };
+
+    virtual status_t setEntryPoint(EntryPoint entryPoint) = 0;
 };
 
 
diff --git a/media/libmedia/include/media/IMediaPlayerService.h b/media/libmedia/include/media/IMediaPlayerService.h
index f2e2060..a4207eb 100644
--- a/media/libmedia/include/media/IMediaPlayerService.h
+++ b/media/libmedia/include/media/IMediaPlayerService.h
@@ -28,6 +28,8 @@
 #include <media/IMediaPlayerClient.h>
 #include <media/IMediaMetadataRetriever.h>
 
+#include <string>
+
 namespace android {
 
 class IMediaPlayer;
@@ -47,7 +49,8 @@
     virtual sp<IMediaRecorder> createMediaRecorder(const String16 &opPackageName) = 0;
     virtual sp<IMediaMetadataRetriever> createMetadataRetriever() = 0;
     virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client,
-            audio_session_t audioSessionId = AUDIO_SESSION_ALLOCATE) = 0;
+            audio_session_t audioSessionId = AUDIO_SESSION_ALLOCATE,
+            const std::string opPackage = "") = 0;
     virtual sp<IMediaCodecList> getCodecList() const = 0;
 
     // Connects to a remote display.
diff --git a/media/libmedia/include/media/mediaplayer.h b/media/libmedia/include/media/mediaplayer.h
index 2335c5a..7c29e50 100644
--- a/media/libmedia/include/media/mediaplayer.h
+++ b/media/libmedia/include/media/mediaplayer.h
@@ -33,6 +33,8 @@
 #include <utils/KeyedVector.h>
 #include <utils/String8.h>
 
+#include <string>
+
 struct ANativeWindow;
 
 namespace android {
@@ -205,7 +207,7 @@
                     public virtual IMediaDeathNotifier
 {
 public:
-    MediaPlayer();
+    MediaPlayer(const std::string opPackageName = "");
     ~MediaPlayer();
             void            died();
             void            disconnect();
@@ -308,6 +310,7 @@
     float                       mSendLevel;
     struct sockaddr_in          mRetransmitEndpoint;
     bool                        mRetransmitEndpointValid;
+    const std::string           mOpPackageName;
 };
 
 }; // namespace android
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 1fadc94..6079a2d 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -41,7 +41,7 @@
 
 using media::VolumeShaper;
 
-MediaPlayer::MediaPlayer()
+MediaPlayer::MediaPlayer(const std::string opPackageName) : mOpPackageName(opPackageName)
 {
     ALOGV("constructor");
     mListener = NULL;
@@ -152,7 +152,7 @@
     if (url != NULL) {
         const sp<IMediaPlayerService> service(getMediaPlayerService());
         if (service != 0) {
-            sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
+            sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mOpPackageName));
             if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
                 (NO_ERROR != player->setDataSource(httpService, url, headers))) {
                 player.clear();
@@ -169,7 +169,7 @@
     status_t err = UNKNOWN_ERROR;
     const sp<IMediaPlayerService> service(getMediaPlayerService());
     if (service != 0) {
-        sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
+        sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mOpPackageName));
         if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
             (NO_ERROR != player->setDataSource(fd, offset, length))) {
             player.clear();
@@ -185,7 +185,7 @@
     status_t err = UNKNOWN_ERROR;
     const sp<IMediaPlayerService> service(getMediaPlayerService());
     if (service != 0) {
-        sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
+        sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mOpPackageName));
         if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
             (NO_ERROR != player->setDataSource(source))) {
             player.clear();
diff --git a/media/libmediahelper/Android.bp b/media/libmediahelper/Android.bp
index 6fcbc7b..fbe7f87 100644
--- a/media/libmediahelper/Android.bp
+++ b/media/libmediahelper/Android.bp
@@ -12,7 +12,10 @@
         enabled: true,
     },
     double_loadable: true,
-    srcs: ["AudioParameter.cpp", "TypeConverter.cpp"],
+    srcs: [
+        "AudioParameter.cpp",
+        "TypeConverter.cpp",
+    ],
     cflags: [
         "-Werror",
         "-Wextra",
diff --git a/media/libmediametrics/Android.bp b/media/libmediametrics/Android.bp
index 03068c7..a63b8b4 100644
--- a/media/libmediametrics/Android.bp
+++ b/media/libmediametrics/Android.bp
@@ -53,6 +53,7 @@
     visibility: [
         "//cts/tests/tests/nativemedia/mediametrics",
         "//frameworks/av:__subpackages__",
+        "//frameworks/base/apex/media/framework",
         "//frameworks/base/core/jni",
         "//frameworks/base/media/jni",
     ],
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index c0da0ce..016f622 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -480,14 +480,14 @@
 }
 
 sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
-        audio_session_t audioSessionId)
+        audio_session_t audioSessionId, std::string opPackageName)
 {
     pid_t pid = IPCThreadState::self()->getCallingPid();
     int32_t connId = android_atomic_inc(&mNextConnId);
 
     sp<Client> c = new Client(
             this, pid, connId, client, audioSessionId,
-            IPCThreadState::self()->getCallingUid());
+            IPCThreadState::self()->getCallingUid(), opPackageName);
 
     ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
          IPCThreadState::self()->getCallingUid());
@@ -733,7 +733,8 @@
 MediaPlayerService::Client::Client(
         const sp<MediaPlayerService>& service, pid_t pid,
         int32_t connId, const sp<IMediaPlayerClient>& client,
-        audio_session_t audioSessionId, uid_t uid)
+        audio_session_t audioSessionId, uid_t uid, const std::string& opPackageName)
+        : mOpPackageName(opPackageName)
 {
     ALOGV("Client(%d) constructor", connId);
     mPid = pid;
@@ -922,7 +923,7 @@
 
     if (!p->hardwareOutput()) {
         mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
-                mPid, mAudioAttributes, mAudioDeviceUpdatedListener);
+                mPid, mAudioAttributes, mAudioDeviceUpdatedListener, mOpPackageName);
         static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
     }
 
@@ -1761,7 +1762,8 @@
 #undef LOG_TAG
 #define LOG_TAG "AudioSink"
 MediaPlayerService::AudioOutput::AudioOutput(audio_session_t sessionId, uid_t uid, int pid,
-        const audio_attributes_t* attr, const sp<AudioSystem::AudioDeviceCallback>& deviceCallback)
+        const audio_attributes_t* attr, const sp<AudioSystem::AudioDeviceCallback>& deviceCallback,
+        const std::string& opPackageName)
     : mCallback(NULL),
       mCallbackCookie(NULL),
       mCallbackData(NULL),
@@ -1782,7 +1784,8 @@
       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
       mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
       mDeviceCallbackEnabled(false),
-      mDeviceCallback(deviceCallback)
+      mDeviceCallback(deviceCallback),
+      mOpPackageName(opPackageName)
 {
     ALOGV("AudioOutput(%d)", sessionId);
     if (attr != NULL) {
@@ -2176,7 +2179,8 @@
                     mAttributes,
                     doNotReconnect,
                     1.0f,  // default value for maxRequiredSpeed
-                    mSelectedDeviceId);
+                    mSelectedDeviceId,
+                    mOpPackageName);
         } else {
             // TODO: Due to buffer memory concerns, we use a max target playback speed
             // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
@@ -2204,7 +2208,8 @@
                     mAttributes,
                     doNotReconnect,
                     targetSpeed,
-                    mSelectedDeviceId);
+                    mSelectedDeviceId,
+                    mOpPackageName);
         }
         // Set caller name so it can be logged in destructor.
         // MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_MEDIA
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 6431ca1..a7de3f3 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -19,6 +19,7 @@
 #define ANDROID_MEDIAPLAYERSERVICE_H
 
 #include <arpa/inet.h>
+#include <string>
 
 #include <utils/threads.h>
 #include <utils/Errors.h>
@@ -81,7 +82,8 @@
                                         uid_t uid,
                                         int pid,
                                         const audio_attributes_t * attr,
-                                        const sp<AudioSystem::AudioDeviceCallback>& deviceCallback);
+                                        const sp<AudioSystem::AudioDeviceCallback>& deviceCallback,
+                                        const std::string& opPackageName);
         virtual                 ~AudioOutput();
 
         virtual bool            ready() const { return mTrack != 0; }
@@ -178,6 +180,7 @@
         bool                    mDeviceCallbackEnabled;
         wp<AudioSystem::AudioDeviceCallback>        mDeviceCallback;
         mutable Mutex           mLock;
+        const std::string       mOpPackageName;
 
         // static variables below not protected by mutex
         static bool             mIsOnEmulator;
@@ -235,7 +238,8 @@
     virtual sp<IMediaMetadataRetriever> createMetadataRetriever();
 
     virtual sp<IMediaPlayer>    create(const sp<IMediaPlayerClient>& client,
-                                       audio_session_t audioSessionId);
+                                       audio_session_t audioSessionId,
+                                       const std::string opPackageName);
 
     virtual sp<IMediaCodecList> getCodecList() const;
 
@@ -410,7 +414,8 @@
                                         int32_t connId,
                                         const sp<IMediaPlayerClient>& client,
                                         audio_session_t audioSessionId,
-                                        uid_t uid);
+                                        uid_t uid,
+                                        const std::string& opPackageName);
                                 Client();
         virtual                 ~Client();
 
@@ -467,6 +472,7 @@
                     bool                          mRetransmitEndpointValid;
                     sp<Client>                    mNextClient;
                     sp<MediaPlayerBase::Listener> mListener;
+                    const std::string             mOpPackageName;
 
         // Metadata filters.
         media::Metadata::Filter mMetadataAllow;  // protected by mLock
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 9b1974b..1cc255d 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -28,6 +28,7 @@
 #include <binder/IServiceManager.h>
 #include <binder/MemoryHeapBase.h>
 #include <binder/MemoryBase.h>
+#include <camera/CameraUtils.h>
 #include <codec2/hidl/client.h>
 #include <cutils/atomic.h>
 #include <cutils/properties.h> // for property_get
@@ -423,30 +424,35 @@
 
     sp<IServiceManager> sm = defaultServiceManager();
 
-    // WORKAROUND: We don't know if camera exists here and getService might block for 5 seconds.
-    // Use checkService for camera if we don't know it exists.
-    static std::atomic<bool> sCameraChecked(false);  // once true never becomes false.
-    static std::atomic<bool> sCameraVerified(false); // once true never becomes false.
-    sp<IBinder> binder = (sCameraVerified || !sCameraChecked)
-        ? sm->getService(String16("media.camera")) : sm->checkService(String16("media.camera"));
-    // If the device does not have a camera, do not create a death listener for it.
-    if (binder != NULL) {
-        sCameraVerified = true;
-        mDeathNotifiers.emplace_back(
-                binder, [l = wp<IMediaRecorderClient>(listener)](){
-            sp<IMediaRecorderClient> listener = l.promote();
-            if (listener) {
-                ALOGV("media.camera service died. "
-                      "Sending death notification.");
-                listener->notify(
-                        MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
-                        MediaPlayerService::CAMERA_PROCESS_DEATH);
-            } else {
-                ALOGW("media.camera service died without a death handler.");
-            }
-        });
+    static const bool sCameraDisabled = CameraUtils::isCameraServiceDisabled();
+
+    if (!sCameraDisabled) {
+        // WORKAROUND: We don't know if camera exists here and getService might block for 5 seconds.
+        // Use checkService for camera if we don't know it exists.
+        static std::atomic<bool> sCameraChecked(false);  // once true never becomes false.
+        static std::atomic<bool> sCameraVerified(false); // once true never becomes false.
+
+        sp<IBinder> binder = (sCameraVerified || !sCameraChecked)
+            ? sm->getService(String16("media.camera")) : sm->checkService(String16("media.camera"));
+        // If the device does not have a camera, do not create a death listener for it.
+        if (binder != NULL) {
+            sCameraVerified = true;
+            mDeathNotifiers.emplace_back(
+                    binder, [l = wp<IMediaRecorderClient>(listener)](){
+                sp<IMediaRecorderClient> listener = l.promote();
+                if (listener) {
+                    ALOGV("media.camera service died. "
+                          "Sending death notification.");
+                    listener->notify(
+                            MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
+                            MediaPlayerService::CAMERA_PROCESS_DEATH);
+                } else {
+                    ALOGW("media.camera service died without a death handler.");
+                }
+            });
+        }
+        sCameraChecked = true;
     }
-    sCameraChecked = true;
 
     {
         using ::android::hidl::base::V1_0::IBase;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index 83da092..9533ae5 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -146,7 +146,9 @@
     }
 
     // Close socket before posting message to RTSPSource message handler.
-    close(mHandler->getARTSPConnection()->getSocket());
+    if (mHandler != NULL) {
+        close(mHandler->getARTSPConnection()->getSocket());
+    }
 
     sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
 
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 63ab654..8e480bf 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -5283,6 +5283,34 @@
                     if (mChannelMaskPresent) {
                         notify->setInt32("channel-mask", mChannelMask);
                     }
+
+                    if (!mIsEncoder && portIndex == kPortIndexOutput) {
+                        AString mime;
+                        if (mConfigFormat->findString("mime", &mime)
+                                && !strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime.c_str())) {
+
+                            OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE presentation;
+                            InitOMXParams(&presentation);
+                            err = mOMXNode->getParameter(
+                                    (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacDrcPresentation,
+                                    &presentation, sizeof(presentation));
+                            if (err != OK) {
+                                return err;
+                            }
+                            notify->setInt32("aac-encoded-target-level",
+                                             presentation.nEncodedTargetLevel);
+                            notify->setInt32("aac-drc-cut-level", presentation.nDrcCut);
+                            notify->setInt32("aac-drc-boost-level", presentation.nDrcBoost);
+                            notify->setInt32("aac-drc-heavy-compression",
+                                             presentation.nHeavyCompression);
+                            notify->setInt32("aac-target-ref-level",
+                                             presentation.nTargetReferenceLevel);
+                            notify->setInt32("aac-drc-effect-type", presentation.nDrcEffectType);
+                            notify->setInt32("aac-drc-album-mode", presentation.nDrcAlbumMode);
+                            notify->setInt32("aac-drc-output-loudness",
+                                             presentation.nDrcOutputLoudness);
+                        }
+                    }
                     break;
                 }
 
@@ -6947,10 +6975,9 @@
         return err;
     }
 
-    using hardware::media::omx::V1_0::utils::TWOmxNode;
     err = statusFromBinderStatus(
             mCodec->mGraphicBufferSource->configure(
-                    new TWOmxNode(mCodec->mOMXNode),
+                    mCodec->mOMXNode->getHalInterface<IOmxNode>(),
                     static_cast<hardware::graphics::common::V1_0::Dataspace>(dataSpace)));
     if (err != OK) {
         ALOGE("[%s] Unable to configure for node (err %d)",
@@ -7704,6 +7731,58 @@
     // Ignore errors as failure is expected for codecs that aren't video encoders.
     (void)configureTemporalLayers(params, false /* inConfigure */, mOutputFormat);
 
+    AString mime;
+    if (!mIsEncoder
+            && (mConfigFormat->findString("mime", &mime))
+            && !strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime.c_str())) {
+        OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE presentation;
+        InitOMXParams(&presentation);
+        mOMXNode->getParameter(
+                    (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacDrcPresentation,
+                    &presentation, sizeof(presentation));
+        int32_t value32 = 0;
+        bool updated = false;
+        if (params->findInt32("aac-pcm-limiter-enable", &value32)) {
+            presentation.nPCMLimiterEnable = value32;
+            updated = true;
+        }
+        if (params->findInt32("aac-encoded-target-level", &value32)) {
+            presentation.nEncodedTargetLevel = value32;
+            updated = true;
+        }
+        if (params->findInt32("aac-drc-cut-level", &value32)) {
+            presentation.nDrcCut = value32;
+            updated = true;
+        }
+        if (params->findInt32("aac-drc-boost-level", &value32)) {
+            presentation.nDrcBoost = value32;
+            updated = true;
+        }
+        if (params->findInt32("aac-drc-heavy-compression", &value32)) {
+            presentation.nHeavyCompression = value32;
+            updated = true;
+        }
+        if (params->findInt32("aac-target-ref-level", &value32)) {
+            presentation.nTargetReferenceLevel = value32;
+            updated = true;
+        }
+        if (params->findInt32("aac-drc-effect-type", &value32)) {
+            presentation.nDrcEffectType = value32;
+            updated = true;
+        }
+        if (params->findInt32("aac-drc-album-mode", &value32)) {
+            presentation.nDrcAlbumMode = value32;
+            updated = true;
+        }
+        if (!params->findInt32("aac-drc-output-loudness", &value32)) {
+            presentation.nDrcOutputLoudness = value32;
+            updated = true;
+        }
+        if (updated) {
+            mOMXNode->setParameter((OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacDrcPresentation,
+                &presentation, sizeof(presentation));
+        }
+    }
     return setVendorParameters(params);
 }
 
diff --git a/media/libstagefright/FrameCaptureProcessor.cpp b/media/libstagefright/FrameCaptureProcessor.cpp
index 96c1195..63238bc 100644
--- a/media/libstagefright/FrameCaptureProcessor.cpp
+++ b/media/libstagefright/FrameCaptureProcessor.cpp
@@ -171,6 +171,8 @@
     if (err != OK) {
         ALOGW("wait for fence returned err %d", err);
     }
+
+    mRE->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL);
     return OK;
 }
 
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 8f7d4bf..d99596e 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -2774,7 +2774,7 @@
         // even if the file is well-formed and the primary picture is correct.
 
         // Reserve item ids for samples + grid
-        size_t numItemsToReserve = mNumTiles + (mNumTiles > 1);
+        size_t numItemsToReserve = mNumTiles + (mNumTiles > 0);
         status_t err = mOwner->reserveItemId_l(numItemsToReserve, &mItemIdBase);
         if (err != OK) {
             return err;
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 40d8ba2..553f59a 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -258,6 +258,9 @@
 
     // after this, require mLock whenever using mService
     AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
+
+    // Kill clients pending removal.
+    mService->reclaimResourcesFromClientsPendingRemoval(mPid);
 }
 
 //static
@@ -651,7 +654,10 @@
     return new PersistentSurface(bufferProducer, bufferSource);
 }
 
-MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid)
+MediaCodec::MediaCodec(
+        const sp<ALooper> &looper, pid_t pid, uid_t uid,
+        std::function<sp<CodecBase>(const AString &, const char *)> getCodecBase,
+        std::function<status_t(const AString &, sp<MediaCodecInfo> *)> getCodecInfo)
     : mState(UNINITIALIZED),
       mReleasedByResourceManager(false),
       mLooper(looper),
@@ -676,7 +682,9 @@
       mNumLowLatencyDisables(0),
       mIsLowLatencyModeOn(false),
       mIndexOfFirstFrameWhenLowLatencyOn(-1),
-      mInputBufferCounter(0) {
+      mInputBufferCounter(0),
+      mGetCodecBase(getCodecBase),
+      mGetCodecInfo(getCodecInfo) {
     if (uid == kNoUid) {
         mUid = AIBinder_getCallingUid();
     } else {
@@ -684,6 +692,33 @@
     }
     mResourceManagerProxy = new ResourceManagerServiceProxy(pid, mUid,
             ::ndk::SharedRefBase::make<ResourceManagerClient>(this));
+    if (!mGetCodecBase) {
+        mGetCodecBase = [](const AString &name, const char *owner) {
+            return GetCodecBase(name, owner);
+        };
+    }
+    if (!mGetCodecInfo) {
+        mGetCodecInfo = [](const AString &name, sp<MediaCodecInfo> *info) -> status_t {
+            *info = nullptr;
+            const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
+            if (!mcl) {
+                return NO_INIT;  // if called from Java should raise IOException
+            }
+            AString tmp = name;
+            if (tmp.endsWith(".secure")) {
+                tmp.erase(tmp.size() - 7, 7);
+            }
+            for (const AString &codecName : { name, tmp }) {
+                ssize_t codecIdx = mcl->findCodecByName(codecName.c_str());
+                if (codecIdx < 0) {
+                    continue;
+                }
+                *info = mcl->getCodecInfo(codecIdx);
+                return OK;
+            }
+            return NAME_NOT_FOUND;
+        };
+    }
 
     initMediametrics();
 }
@@ -1045,6 +1080,12 @@
     return err;
 }
 
+void MediaCodec::PostReplyWithError(const sp<AMessage> &msg, int32_t err) {
+    sp<AReplyToken> replyID;
+    CHECK(msg->senderAwaitsResponse(&replyID));
+    PostReplyWithError(replyID, err);
+}
+
 void MediaCodec::PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err) {
     int32_t finalErr = err;
     if (mReleasedByResourceManager) {
@@ -1121,40 +1162,30 @@
     bool secureCodec = false;
     const char *owner = "";
     if (!name.startsWith("android.filter.")) {
-        AString tmp = name;
-        if (tmp.endsWith(".secure")) {
-            secureCodec = true;
-            tmp.erase(tmp.size() - 7, 7);
-        }
-        const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
-        if (mcl == NULL) {
+        status_t err = mGetCodecInfo(name, &mCodecInfo);
+        if (err != OK) {
             mCodec = NULL;  // remove the codec.
-            return NO_INIT; // if called from Java should raise IOException
-        }
-        for (const AString &codecName : { name, tmp }) {
-            ssize_t codecIdx = mcl->findCodecByName(codecName.c_str());
-            if (codecIdx < 0) {
-                continue;
-            }
-            mCodecInfo = mcl->getCodecInfo(codecIdx);
-            Vector<AString> mediaTypes;
-            mCodecInfo->getSupportedMediaTypes(&mediaTypes);
-            for (size_t i = 0; i < mediaTypes.size(); i++) {
-                if (mediaTypes[i].startsWith("video/")) {
-                    mIsVideo = true;
-                    break;
-                }
-            }
-            break;
+            return err;
         }
         if (mCodecInfo == nullptr) {
+            ALOGE("Getting codec info with name '%s' failed", name.c_str());
             return NAME_NOT_FOUND;
         }
+        secureCodec = name.endsWith(".secure");
+        Vector<AString> mediaTypes;
+        mCodecInfo->getSupportedMediaTypes(&mediaTypes);
+        for (size_t i = 0; i < mediaTypes.size(); ++i) {
+            if (mediaTypes[i].startsWith("video/")) {
+                mIsVideo = true;
+                break;
+            }
+        }
         owner = mCodecInfo->getOwnerName();
     }
 
-    mCodec = GetCodecBase(name, owner);
+    mCodec = mGetCodecBase(name, owner);
     if (mCodec == NULL) {
+        ALOGE("Getting codec base with name '%s' (owner='%s') failed", name.c_str(), owner);
         return NAME_NOT_FOUND;
     }
 
@@ -1548,7 +1579,6 @@
     mStickyError = OK;
 
     // reset state not reset by setState(UNINITIALIZED)
-    mReplyID = 0;
     mDequeueInputReplyID = 0;
     mDequeueOutputReplyID = 0;
     mDequeueInputTimeoutGeneration = 0;
@@ -2080,20 +2110,25 @@
     } else if (mFlags & kFlagOutputBuffersChanged) {
         PostReplyWithError(replyID, INFO_OUTPUT_BUFFERS_CHANGED);
         mFlags &= ~kFlagOutputBuffersChanged;
-    } else if (mFlags & kFlagOutputFormatChanged) {
-        PostReplyWithError(replyID, INFO_FORMAT_CHANGED);
-        mFlags &= ~kFlagOutputFormatChanged;
     } else {
         sp<AMessage> response = new AMessage;
-        ssize_t index = dequeuePortBuffer(kPortIndexOutput);
-
-        if (index < 0) {
-            CHECK_EQ(index, -EAGAIN);
+        BufferInfo *info = peekNextPortBuffer(kPortIndexOutput);
+        if (!info) {
             return false;
         }
 
-        const sp<MediaCodecBuffer> &buffer =
-            mPortBuffers[kPortIndexOutput][index].mData;
+        // In synchronous mode, output format change should be handled
+        // at dequeue to put the event at the correct order.
+
+        const sp<MediaCodecBuffer> &buffer = info->mData;
+        handleOutputFormatChangeIfNeeded(buffer);
+        if (mFlags & kFlagOutputFormatChanged) {
+            PostReplyWithError(replyID, INFO_FORMAT_CHANGED);
+            mFlags &= ~kFlagOutputFormatChanged;
+            return true;
+        }
+
+        ssize_t index = dequeuePortBuffer(kPortIndexOutput);
 
         response->setSize("index", index);
         response->setSize("offset", buffer->offset());
@@ -2138,6 +2173,8 @@
                     }
 
                     bool sendErrorResponse = true;
+                    std::string origin{"kWhatError:"};
+                    origin += stateString(mState);
 
                     switch (mState) {
                         case INITIALIZING:
@@ -2189,14 +2226,14 @@
                                 // be a shutdown complete notification after
                                 // all.
 
-                                // note that we're directly going from
+                                // note that we may be directly going from
                                 // STOPPING->UNINITIALIZED, instead of the
                                 // usual STOPPING->INITIALIZED state.
                                 setState(UNINITIALIZED);
                                 if (mState == RELEASING) {
                                     mComponentName.clear();
                                 }
-                                (new AMessage)->postReply(mReplyID);
+                                postPendingRepliesAndDeferredMessages(origin + ":dead");
                                 sendErrorResponse = false;
                             }
                             break;
@@ -2222,7 +2259,7 @@
                         case FLUSHED:
                         case STARTED:
                         {
-                            sendErrorResponse = false;
+                            sendErrorResponse = (mReplyID != nullptr);
 
                             setStickyError(err);
                             postActivityNotificationIfPossible();
@@ -2252,7 +2289,7 @@
 
                         default:
                         {
-                            sendErrorResponse = false;
+                            sendErrorResponse = (mReplyID != nullptr);
 
                             setStickyError(err);
                             postActivityNotificationIfPossible();
@@ -2279,7 +2316,15 @@
                     }
 
                     if (sendErrorResponse) {
-                        PostReplyWithError(mReplyID, err);
+                        // TRICKY: replicate PostReplyWithError logic for
+                        //         err code override
+                        int32_t finalErr = err;
+                        if (mReleasedByResourceManager) {
+                            // override the err code if MediaCodec has been
+                            // released by ResourceManager.
+                            finalErr = DEAD_OBJECT;
+                        }
+                        postPendingRepliesAndDeferredMessages(origin, finalErr);
                     }
                     break;
                 }
@@ -2327,7 +2372,7 @@
                                 MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo));
                     }
 
-                    (new AMessage)->postReply(mReplyID);
+                    postPendingRepliesAndDeferredMessages("kWhatComponentAllocated");
                     break;
                 }
 
@@ -2366,7 +2411,7 @@
                         mFlags |= kFlagUsesSoftwareRenderer;
                     }
                     setState(CONFIGURED);
-                    (new AMessage)->postReply(mReplyID);
+                    postPendingRepliesAndDeferredMessages("kWhatComponentConfigured");
 
                     // augment our media metrics info, now that we know more things
                     // such as what the codec extracted from any CSD passed in.
@@ -2411,6 +2456,12 @@
 
                 case kWhatInputSurfaceCreated:
                 {
+                    if (mState != CONFIGURED) {
+                        // state transitioned unexpectedly; we should have replied already.
+                        ALOGD("received kWhatInputSurfaceCreated message in state %s",
+                                stateString(mState).c_str());
+                        break;
+                    }
                     // response to initiateCreateInputSurface()
                     status_t err = NO_ERROR;
                     sp<AMessage> response = new AMessage;
@@ -2429,12 +2480,18 @@
                     } else {
                         response->setInt32("err", err);
                     }
-                    response->postReply(mReplyID);
+                    postPendingRepliesAndDeferredMessages("kWhatInputSurfaceCreated", response);
                     break;
                 }
 
                 case kWhatInputSurfaceAccepted:
                 {
+                    if (mState != CONFIGURED) {
+                        // state transitioned unexpectedly; we should have replied already.
+                        ALOGD("received kWhatInputSurfaceAccepted message in state %s",
+                                stateString(mState).c_str());
+                        break;
+                    }
                     // response to initiateSetInputSurface()
                     status_t err = NO_ERROR;
                     sp<AMessage> response = new AMessage();
@@ -2445,19 +2502,25 @@
                     } else {
                         response->setInt32("err", err);
                     }
-                    response->postReply(mReplyID);
+                    postPendingRepliesAndDeferredMessages("kWhatInputSurfaceAccepted", response);
                     break;
                 }
 
                 case kWhatSignaledInputEOS:
                 {
+                    if (!isExecuting()) {
+                        // state transitioned unexpectedly; we should have replied already.
+                        ALOGD("received kWhatSignaledInputEOS message in state %s",
+                                stateString(mState).c_str());
+                        break;
+                    }
                     // response to signalEndOfInputStream()
                     sp<AMessage> response = new AMessage;
                     status_t err;
                     if (msg->findInt32("err", &err)) {
                         response->setInt32("err", err);
                     }
-                    response->postReply(mReplyID);
+                    postPendingRepliesAndDeferredMessages("kWhatSignaledInputEOS", response);
                     break;
                 }
 
@@ -2476,7 +2539,7 @@
                                 MediaResource::GraphicMemoryResource(getGraphicBufferSize()));
                     }
                     setState(STARTED);
-                    (new AMessage)->postReply(mReplyID);
+                    postPendingRepliesAndDeferredMessages("kWhatStartCompleted");
                     break;
                 }
 
@@ -2577,107 +2640,13 @@
                         break;
                     }
 
-                    sp<RefBase> obj;
-                    CHECK(msg->findObject("buffer", &obj));
-                    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
-
-                    if (mOutputFormat != buffer->format()) {
-                        if (mFlags & kFlagUseBlockModel) {
-                            sp<AMessage> diff1 = mOutputFormat->changesFrom(buffer->format());
-                            sp<AMessage> diff2 = buffer->format()->changesFrom(mOutputFormat);
-                            std::set<std::string> keys;
-                            size_t numEntries = diff1->countEntries();
-                            AMessage::Type type;
-                            for (size_t i = 0; i < numEntries; ++i) {
-                                keys.emplace(diff1->getEntryNameAt(i, &type));
-                            }
-                            numEntries = diff2->countEntries();
-                            for (size_t i = 0; i < numEntries; ++i) {
-                                keys.emplace(diff2->getEntryNameAt(i, &type));
-                            }
-                            sp<WrapperObject<std::set<std::string>>> changedKeys{
-                                new WrapperObject<std::set<std::string>>{std::move(keys)}};
-                            buffer->meta()->setObject("changedKeys", changedKeys);
-                        }
-                        mOutputFormat = buffer->format();
-                        ALOGV("[%s] output format changed to: %s",
-                                mComponentName.c_str(), mOutputFormat->debugString(4).c_str());
-
-                        if (mSoftRenderer == NULL &&
-                                mSurface != NULL &&
-                                (mFlags & kFlagUsesSoftwareRenderer)) {
-                            AString mime;
-                            CHECK(mOutputFormat->findString("mime", &mime));
-
-                            // TODO: propagate color aspects to software renderer to allow better
-                            // color conversion to RGB. For now, just mark dataspace for YUV
-                            // rendering.
-                            int32_t dataSpace;
-                            if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) {
-                                ALOGD("[%s] setting dataspace on output surface to #%x",
-                                        mComponentName.c_str(), dataSpace);
-                                int err = native_window_set_buffers_data_space(
-                                        mSurface.get(), (android_dataspace)dataSpace);
-                                ALOGW_IF(err != 0, "failed to set dataspace on surface (%d)", err);
-                            }
-                            if (mOutputFormat->contains("hdr-static-info")) {
-                                HDRStaticInfo info;
-                                if (ColorUtils::getHDRStaticInfoFromFormat(mOutputFormat, &info)) {
-                                    setNativeWindowHdrMetadata(mSurface.get(), &info);
-                                }
-                            }
-
-                            sp<ABuffer> hdr10PlusInfo;
-                            if (mOutputFormat->findBuffer("hdr10-plus-info", &hdr10PlusInfo)
-                                    && hdr10PlusInfo != nullptr && hdr10PlusInfo->size() > 0) {
-                                native_window_set_buffers_hdr10_plus_metadata(mSurface.get(),
-                                        hdr10PlusInfo->size(), hdr10PlusInfo->data());
-                            }
-
-                            if (mime.startsWithIgnoreCase("video/")) {
-                                mSurface->setDequeueTimeout(-1);
-                                mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees);
-                            }
-                        }
-
-                        requestCpuBoostIfNeeded();
-
-                        if (mFlags & kFlagIsEncoder) {
-                            // Before we announce the format change we should
-                            // collect codec specific data and amend the output
-                            // format as necessary.
-                            int32_t flags = 0;
-                            (void) buffer->meta()->findInt32("flags", &flags);
-                            if ((flags & BUFFER_FLAG_CODECCONFIG) && !(mFlags & kFlagIsSecure)) {
-                                status_t err =
-                                    amendOutputFormatWithCodecSpecificData(buffer);
-
-                                if (err != OK) {
-                                    ALOGE("Codec spit out malformed codec "
-                                          "specific data!");
-                                }
-                            }
-                        }
-                        if (mFlags & kFlagIsAsync) {
-                            onOutputFormatChanged();
-                        } else {
-                            mFlags |= kFlagOutputFormatChanged;
-                            postActivityNotificationIfPossible();
-                        }
-
-                        // Notify mCrypto of video resolution changes
-                        if (mCrypto != NULL) {
-                            int32_t left, top, right, bottom, width, height;
-                            if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
-                                mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
-                            } else if (mOutputFormat->findInt32("width", &width)
-                                    && mOutputFormat->findInt32("height", &height)) {
-                                mCrypto->notifyResolution(width, height);
-                            }
-                        }
-                    }
-
                     if (mFlags & kFlagIsAsync) {
+                        sp<RefBase> obj;
+                        CHECK(msg->findObject("buffer", &obj));
+                        sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
+
+                        // In asynchronous mode, output format change is processed immediately.
+                        handleOutputFormatChangeIfNeeded(buffer);
                         onOutputBufferAvailable();
                     } else if (mFlags & kFlagDequeueOutputPending) {
                         CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
@@ -2706,7 +2675,13 @@
                         break;
                     }
                     setState(INITIALIZED);
-                    (new AMessage)->postReply(mReplyID);
+                    if (mReplyID) {
+                        postPendingRepliesAndDeferredMessages("kWhatStopCompleted");
+                    } else {
+                        ALOGW("kWhatStopCompleted: presumably an error occurred earlier, "
+                              "but the operation completed anyway. (last reply origin=%s)",
+                              mLastReplyOrigin.c_str());
+                    }
                     break;
                 }
 
@@ -2730,7 +2705,7 @@
                     mReleaseSurface.reset();
 
                     if (mReplyID != nullptr) {
-                        (new AMessage)->postReply(mReplyID);
+                        postPendingRepliesAndDeferredMessages("kWhatReleaseCompleted");
                     }
                     if (mAsyncReleaseCompleteNotification != nullptr) {
                         flushMediametrics();
@@ -2755,7 +2730,7 @@
                         mCodec->signalResume();
                     }
 
-                    (new AMessage)->postReply(mReplyID);
+                    postPendingRepliesAndDeferredMessages("kWhatFlushCompleted");
                     break;
                 }
 
@@ -2767,14 +2742,18 @@
 
         case kWhatInit:
         {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
             if (mState != UNINITIALIZED) {
-                PostReplyWithError(replyID, INVALID_OPERATION);
+                PostReplyWithError(msg, INVALID_OPERATION);
                 break;
             }
 
+            if (mReplyID) {
+                mDeferredMessages.push_back(msg);
+                break;
+            }
+            sp<AReplyToken> replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+
             mReplyID = replyID;
             setState(INITIALIZING);
 
@@ -2836,14 +2815,18 @@
 
         case kWhatConfigure:
         {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
             if (mState != INITIALIZED) {
-                PostReplyWithError(replyID, INVALID_OPERATION);
+                PostReplyWithError(msg, INVALID_OPERATION);
                 break;
             }
 
+            if (mReplyID) {
+                mDeferredMessages.push_back(msg);
+                break;
+            }
+            sp<AReplyToken> replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+
             sp<RefBase> obj;
             CHECK(msg->findObject("surface", &obj));
 
@@ -2981,15 +2964,19 @@
         case kWhatCreateInputSurface:
         case kWhatSetInputSurface:
         {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
             // Must be configured, but can't have been started yet.
             if (mState != CONFIGURED) {
-                PostReplyWithError(replyID, INVALID_OPERATION);
+                PostReplyWithError(msg, INVALID_OPERATION);
                 break;
             }
 
+            if (mReplyID) {
+                mDeferredMessages.push_back(msg);
+                break;
+            }
+            sp<AReplyToken> replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+
             mReplyID = replyID;
             if (msg->what() == kWhatCreateInputSurface) {
                 mCodec->initiateCreateInputSurface();
@@ -3004,9 +2991,6 @@
         }
         case kWhatStart:
         {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
             if (mState == FLUSHED) {
                 setState(STARTED);
                 if (mHavePendingInputBuffers) {
@@ -3014,13 +2998,20 @@
                     mHavePendingInputBuffers = false;
                 }
                 mCodec->signalResume();
-                PostReplyWithError(replyID, OK);
+                PostReplyWithError(msg, OK);
                 break;
             } else if (mState != CONFIGURED) {
-                PostReplyWithError(replyID, INVALID_OPERATION);
+                PostReplyWithError(msg, INVALID_OPERATION);
                 break;
             }
 
+            if (mReplyID) {
+                mDeferredMessages.push_back(msg);
+                break;
+            }
+            sp<AReplyToken> replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+
             mReplyID = replyID;
             setState(STARTING);
 
@@ -3028,15 +3019,42 @@
             break;
         }
 
-        case kWhatStop:
+        case kWhatStop: {
+            if (mReplyID) {
+                mDeferredMessages.push_back(msg);
+                break;
+            }
+            [[fallthrough]];
+        }
         case kWhatRelease:
         {
             State targetState =
                 (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
 
+            if ((mState == RELEASING && targetState == UNINITIALIZED)
+                    || (mState == STOPPING && targetState == INITIALIZED)) {
+                mDeferredMessages.push_back(msg);
+                break;
+            }
+
             sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
+            sp<AMessage> asyncNotify;
+            (void)msg->findMessage("async", &asyncNotify);
+            // post asyncNotify if going out of scope.
+            struct AsyncNotifyPost {
+                AsyncNotifyPost(const sp<AMessage> &asyncNotify) : mAsyncNotify(asyncNotify) {}
+                ~AsyncNotifyPost() {
+                    if (mAsyncNotify) {
+                        mAsyncNotify->post();
+                    }
+                }
+                void clear() { mAsyncNotify.clear(); }
+            private:
+                sp<AMessage> mAsyncNotify;
+            } asyncNotifyPost{asyncNotify};
+
             // already stopped/released
             if (mState == UNINITIALIZED && mReleasedByResourceManager) {
                 sp<AMessage> response = new AMessage;
@@ -3100,12 +3118,15 @@
             // after this, and we'll no longer be able to reply.
             if (mState == FLUSHING || mState == STOPPING
                     || mState == CONFIGURING || mState == STARTING) {
-                (new AMessage)->postReply(mReplyID);
+                // mReply is always set if in these states.
+                postPendingRepliesAndDeferredMessages(
+                        std::string("kWhatRelease:") + stateString(mState));
             }
 
             if (mFlags & kFlagSawMediaServerDie) {
                 // It's dead, Jim. Don't expect initiateShutdown to yield
                 // any useful results now...
+                // Any pending reply would have been handled at kWhatError.
                 setState(UNINITIALIZED);
                 if (targetState == UNINITIALIZED) {
                     mComponentName.clear();
@@ -3119,12 +3140,12 @@
             // reply now with an error to unblock the client, client can
             // release after the failure (instead of ANR).
             if (msg->what() == kWhatStop && (mFlags & kFlagStickyError)) {
+                // Any pending reply would have been handled at kWhatError.
                 PostReplyWithError(replyID, getStickyError());
                 break;
             }
 
-            sp<AMessage> asyncNotify;
-            if (msg->findMessage("async", &asyncNotify) && asyncNotify != nullptr) {
+            if (asyncNotify != nullptr) {
                 if (mSurface != NULL) {
                     if (!mReleaseSurface) {
                         uint64_t usage = 0;
@@ -3148,6 +3169,12 @@
                 }
             }
 
+            if (mReplyID) {
+                // State transition replies are handled above, so this reply
+                // would not be related to state transition. As we are
+                // shutting down the component, just fail the operation.
+                postPendingRepliesAndDeferredMessages("kWhatRelease:reply", UNKNOWN_ERROR);
+            }
             mReplyID = replyID;
             setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
 
@@ -3162,8 +3189,8 @@
 
             if (asyncNotify != nullptr) {
                 mResourceManagerProxy->markClientForPendingRemoval();
-                (new AMessage)->postReply(mReplyID);
-                mReplyID = 0;
+                postPendingRepliesAndDeferredMessages("kWhatRelease:async");
+                asyncNotifyPost.clear();
                 mAsyncReleaseCompleteNotification = asyncNotify;
             }
 
@@ -3334,17 +3361,21 @@
 
         case kWhatSignalEndOfInputStream:
         {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
             if (!isExecuting() || !mHaveInputSurface) {
-                PostReplyWithError(replyID, INVALID_OPERATION);
+                PostReplyWithError(msg, INVALID_OPERATION);
                 break;
             } else if (mFlags & kFlagStickyError) {
-                PostReplyWithError(replyID, getStickyError());
+                PostReplyWithError(msg, getStickyError());
                 break;
             }
 
+            if (mReplyID) {
+                mDeferredMessages.push_back(msg);
+                break;
+            }
+            sp<AReplyToken> replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+
             mReplyID = replyID;
             mCodec->signalEndOfInputStream();
             break;
@@ -3386,17 +3417,21 @@
 
         case kWhatFlush:
         {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
             if (!isExecuting()) {
-                PostReplyWithError(replyID, INVALID_OPERATION);
+                PostReplyWithError(msg, INVALID_OPERATION);
                 break;
             } else if (mFlags & kFlagStickyError) {
-                PostReplyWithError(replyID, getStickyError());
+                PostReplyWithError(msg, getStickyError());
                 break;
             }
 
+            if (mReplyID) {
+                mDeferredMessages.push_back(msg);
+                break;
+            }
+            sp<AReplyToken> replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+
             mReplyID = replyID;
             // TODO: skip flushing if already FLUSHED
             setState(FLUSHING);
@@ -3510,6 +3545,106 @@
     }
 }
 
+void MediaCodec::handleOutputFormatChangeIfNeeded(const sp<MediaCodecBuffer> &buffer) {
+    sp<AMessage> format = buffer->format();
+    if (mOutputFormat == format) {
+        return;
+    }
+    if (mFlags & kFlagUseBlockModel) {
+        sp<AMessage> diff1 = mOutputFormat->changesFrom(format);
+        sp<AMessage> diff2 = format->changesFrom(mOutputFormat);
+        std::set<std::string> keys;
+        size_t numEntries = diff1->countEntries();
+        AMessage::Type type;
+        for (size_t i = 0; i < numEntries; ++i) {
+            keys.emplace(diff1->getEntryNameAt(i, &type));
+        }
+        numEntries = diff2->countEntries();
+        for (size_t i = 0; i < numEntries; ++i) {
+            keys.emplace(diff2->getEntryNameAt(i, &type));
+        }
+        sp<WrapperObject<std::set<std::string>>> changedKeys{
+            new WrapperObject<std::set<std::string>>{std::move(keys)}};
+        buffer->meta()->setObject("changedKeys", changedKeys);
+    }
+    mOutputFormat = format;
+    ALOGV("[%s] output format changed to: %s",
+            mComponentName.c_str(), mOutputFormat->debugString(4).c_str());
+
+    if (mSoftRenderer == NULL &&
+            mSurface != NULL &&
+            (mFlags & kFlagUsesSoftwareRenderer)) {
+        AString mime;
+        CHECK(mOutputFormat->findString("mime", &mime));
+
+        // TODO: propagate color aspects to software renderer to allow better
+        // color conversion to RGB. For now, just mark dataspace for YUV
+        // rendering.
+        int32_t dataSpace;
+        if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) {
+            ALOGD("[%s] setting dataspace on output surface to #%x",
+                    mComponentName.c_str(), dataSpace);
+            int err = native_window_set_buffers_data_space(
+                    mSurface.get(), (android_dataspace)dataSpace);
+            ALOGW_IF(err != 0, "failed to set dataspace on surface (%d)", err);
+        }
+        if (mOutputFormat->contains("hdr-static-info")) {
+            HDRStaticInfo info;
+            if (ColorUtils::getHDRStaticInfoFromFormat(mOutputFormat, &info)) {
+                setNativeWindowHdrMetadata(mSurface.get(), &info);
+            }
+        }
+
+        sp<ABuffer> hdr10PlusInfo;
+        if (mOutputFormat->findBuffer("hdr10-plus-info", &hdr10PlusInfo)
+                && hdr10PlusInfo != nullptr && hdr10PlusInfo->size() > 0) {
+            native_window_set_buffers_hdr10_plus_metadata(mSurface.get(),
+                    hdr10PlusInfo->size(), hdr10PlusInfo->data());
+        }
+
+        if (mime.startsWithIgnoreCase("video/")) {
+            mSurface->setDequeueTimeout(-1);
+            mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees);
+        }
+    }
+
+    requestCpuBoostIfNeeded();
+
+    if (mFlags & kFlagIsEncoder) {
+        // Before we announce the format change we should
+        // collect codec specific data and amend the output
+        // format as necessary.
+        int32_t flags = 0;
+        (void) buffer->meta()->findInt32("flags", &flags);
+        if ((flags & BUFFER_FLAG_CODECCONFIG) && !(mFlags & kFlagIsSecure)) {
+            status_t err =
+                amendOutputFormatWithCodecSpecificData(buffer);
+
+            if (err != OK) {
+                ALOGE("Codec spit out malformed codec "
+                      "specific data!");
+            }
+        }
+    }
+    if (mFlags & kFlagIsAsync) {
+        onOutputFormatChanged();
+    } else {
+        mFlags |= kFlagOutputFormatChanged;
+        postActivityNotificationIfPossible();
+    }
+
+    // Notify mCrypto of video resolution changes
+    if (mCrypto != NULL) {
+        int32_t left, top, right, bottom, width, height;
+        if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
+            mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
+        } else if (mOutputFormat->findInt32("width", &width)
+                && mOutputFormat->findInt32("height", &height)) {
+            mCrypto->notifyResolution(width, height);
+        }
+    }
+}
+
 void MediaCodec::extractCSD(const sp<AMessage> &format) {
     mCSD.clear();
 
@@ -3975,19 +4110,31 @@
     return OK;
 }
 
-ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
+MediaCodec::BufferInfo *MediaCodec::peekNextPortBuffer(int32_t portIndex) {
     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
 
     List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
 
     if (availBuffers->empty()) {
+        return nullptr;
+    }
+
+    return &mPortBuffers[portIndex][*availBuffers->begin()];
+}
+
+ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
+    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
+
+    BufferInfo *info = peekNextPortBuffer(portIndex);
+    if (!info) {
         return -EAGAIN;
     }
 
+    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
     size_t index = *availBuffers->begin();
+    CHECK_EQ(info, &mPortBuffers[portIndex][index]);
     availBuffers->erase(availBuffers->begin());
 
-    BufferInfo *info = &mPortBuffers[portIndex][index];
     CHECK(!info->mOwnedByClient);
     {
         Mutex::Autolock al(mBufferLock);
@@ -4229,6 +4376,33 @@
     return OK;
 }
 
+void MediaCodec::postPendingRepliesAndDeferredMessages(
+        std::string origin, status_t err /* = OK */) {
+    sp<AMessage> response{new AMessage};
+    if (err != OK) {
+        response->setInt32("err", err);
+    }
+    postPendingRepliesAndDeferredMessages(origin, response);
+}
+
+void MediaCodec::postPendingRepliesAndDeferredMessages(
+        std::string origin, const sp<AMessage> &response) {
+    LOG_ALWAYS_FATAL_IF(
+            !mReplyID,
+            "postPendingRepliesAndDeferredMessages: mReplyID == null, from %s following %s",
+            origin.c_str(),
+            mLastReplyOrigin.c_str());
+    mLastReplyOrigin = origin;
+    response->postReply(mReplyID);
+    mReplyID.clear();
+    ALOGV_IF(!mDeferredMessages.empty(),
+            "posting %zu deferred messages", mDeferredMessages.size());
+    for (sp<AMessage> msg : mDeferredMessages) {
+        msg->post();
+    }
+    mDeferredMessages.clear();
+}
+
 std::string MediaCodec::stateString(State state) {
     const char *rval = NULL;
     char rawbuffer[16]; // room for "%d"
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 1395c27..c6ae159 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -168,9 +168,7 @@
 }
 
 status_t MediaCodecSource::Puller::setStopTimeUs(int64_t stopTimeUs) {
-    sp<AMessage> msg = new AMessage(kWhatSetStopTimeUs, this);
-    msg->setInt64("stop-time-us", stopTimeUs);
-    return postSynchronouslyAndReturnError(msg);
+    return mSource->setStopTimeUs(stopTimeUs);
 }
 
 status_t MediaCodecSource::Puller::start(const sp<MetaData> &meta, const sp<AMessage> &notify) {
@@ -188,19 +186,11 @@
 }
 
 void MediaCodecSource::Puller::stop() {
-    bool interrupt = false;
-    {
-        // mark stopping before actually reaching kWhatStop on the looper, so the pulling will
-        // stop.
-        Mutexed<Queue>::Locked queue(mQueue);
-        queue->mPulling = false;
-        interrupt = queue->mReadPendingSince && (queue->mReadPendingSince < ALooper::GetNowUs() - 1000000);
-        queue->flush(); // flush any unprocessed pulled buffers
-    }
-
-    if (interrupt) {
-        interruptSource();
-    }
+    // mark stopping before actually reaching kWhatStop on the looper, so the pulling will
+    // stop.
+    Mutexed<Queue>::Locked queue(mQueue);
+    queue->mPulling = false;
+    queue->flush(); // flush any unprocessed pulled buffers
 }
 
 void MediaCodecSource::Puller::interruptSource() {
@@ -660,9 +650,9 @@
     if (mStopping && reachedEOS) {
         ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio");
         if (mPuller != NULL) {
-            mPuller->stopSource();
+            mPuller->interruptSource();
         }
-        ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
+        ALOGI("source (%s) stopped", mIsVideo ? "video" : "audio");
         // posting reply to everyone that's waiting
         List<sp<AReplyToken>>::iterator it;
         for (it = mStopReplyIDQueue.begin();
@@ -851,7 +841,7 @@
     {
         int32_t eos = 0;
         if (msg->findInt32("eos", &eos) && eos) {
-            ALOGV("puller (%s) reached EOS", mIsVideo ? "video" : "audio");
+            ALOGI("puller (%s) reached EOS", mIsVideo ? "video" : "audio");
             signalEOS();
             break;
         }
@@ -1069,12 +1059,7 @@
         if (generation != mGeneration) {
              break;
         }
-
-        if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
-            ALOGV("source (%s) stopping", mIsVideo ? "video" : "audio");
-            mPuller->interruptSource();
-            ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
-        }
+        ALOGD("source (%s) stopping stalled", mIsVideo ? "video" : "audio");
         signalEOS();
         break;
     }
diff --git a/media/libstagefright/MediaMuxer.cpp b/media/libstagefright/MediaMuxer.cpp
index cab4ebd..8d9bc06 100644
--- a/media/libstagefright/MediaMuxer.cpp
+++ b/media/libstagefright/MediaMuxer.cpp
@@ -92,7 +92,9 @@
     }
 
     sp<MetaData> trackMeta = new MetaData;
-    convertMessageToMetaData(format, trackMeta);
+    if (convertMessageToMetaData(format, trackMeta) != OK) {
+        return BAD_VALUE;
+    }
 
     sp<MediaAdapter> newTrack = new MediaAdapter(trackMeta);
     status_t result = mWriter->addSource(newTrack);
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 050d7c2..c638507 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -50,8 +50,9 @@
       mSampleTimeUs(timeUs) {
 }
 
-NuMediaExtractor::NuMediaExtractor()
-    : mTotalBitrate(-1LL),
+NuMediaExtractor::NuMediaExtractor(EntryPoint entryPoint)
+    : mEntryPoint(entryPoint),
+      mTotalBitrate(-1LL),
       mDurationUs(-1LL) {
 }
 
@@ -93,6 +94,7 @@
     if (mImpl == NULL) {
         return ERROR_UNSUPPORTED;
     }
+    setEntryPointToRemoteMediaExtractor();
 
     status_t err = OK;
     if (!mCasToken.empty()) {
@@ -134,6 +136,7 @@
     if (mImpl == NULL) {
         return ERROR_UNSUPPORTED;
     }
+    setEntryPointToRemoteMediaExtractor();
 
     if (!mCasToken.empty()) {
         err = mImpl->setMediaCas(mCasToken);
@@ -168,6 +171,7 @@
     if (mImpl == NULL) {
         return ERROR_UNSUPPORTED;
     }
+    setEntryPointToRemoteMediaExtractor();
 
     if (!mCasToken.empty()) {
         err = mImpl->setMediaCas(mCasToken);
@@ -468,6 +472,16 @@
     }
 }
 
+void NuMediaExtractor::setEntryPointToRemoteMediaExtractor() {
+    if (mImpl == NULL) {
+        return;
+    }
+    status_t err = mImpl->setEntryPoint(mEntryPoint);
+    if (err != OK) {
+        ALOGW("Failed to set entry point with error %d.", err);
+    }
+}
+
 ssize_t NuMediaExtractor::fetchAllTrackSamples(
         int64_t seekTimeUs, MediaSource::ReadOptions::SeekMode mode) {
     TrackInfo *minInfo = NULL;
diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp
index 25e43c2..381eb1a 100644
--- a/media/libstagefright/RemoteMediaExtractor.cpp
+++ b/media/libstagefright/RemoteMediaExtractor.cpp
@@ -39,6 +39,12 @@
 static const char *kExtractorFormat = "android.media.mediaextractor.fmt";
 static const char *kExtractorMime = "android.media.mediaextractor.mime";
 static const char *kExtractorTracks = "android.media.mediaextractor.ntrk";
+static const char *kExtractorEntryPoint = "android.media.mediaextractor.entry";
+
+static const char *kEntryPointSdk = "sdk";
+static const char *kEntryPointWithJvm = "ndk-with-jvm";
+static const char *kEntryPointNoJvm = "ndk-no-jvm";
+static const char *kEntryPointOther = "other";
 
 RemoteMediaExtractor::RemoteMediaExtractor(
         MediaExtractor *extractor,
@@ -74,6 +80,9 @@
             }
             // what else is interesting and not already available?
         }
+        // By default, we set the entry point to be "other". Clients of this
+        // class will override this value by calling setEntryPoint.
+        mMetricsItem->setCString(kExtractorEntryPoint, kEntryPointOther);
     }
 }
 
@@ -143,6 +152,28 @@
     return String8(mExtractor->name());
 }
 
+status_t RemoteMediaExtractor::setEntryPoint(EntryPoint entryPoint) {
+    const char* entryPointString;
+    switch (entryPoint) {
+      case EntryPoint::SDK:
+            entryPointString = kEntryPointSdk;
+            break;
+        case EntryPoint::NDK_WITH_JVM:
+            entryPointString = kEntryPointWithJvm;
+            break;
+        case EntryPoint::NDK_NO_JVM:
+            entryPointString = kEntryPointNoJvm;
+            break;
+        case EntryPoint::OTHER:
+            entryPointString = kEntryPointOther;
+            break;
+        default:
+            return BAD_VALUE;
+    }
+    mMetricsItem->setCString(kExtractorEntryPoint, entryPointString);
+    return OK;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 // static
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index 4c94baa..c284ef7 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -132,37 +132,47 @@
 }
 
 void setNativeWindowHdrMetadata(ANativeWindow *nativeWindow, HDRStaticInfo *info) {
-    struct android_smpte2086_metadata smpte2086_meta = {
-            .displayPrimaryRed = {
-                    info->sType1.mR.x * 0.00002f,
-                    info->sType1.mR.y * 0.00002f
-            },
-            .displayPrimaryGreen = {
-                    info->sType1.mG.x * 0.00002f,
-                    info->sType1.mG.y * 0.00002f
-            },
-            .displayPrimaryBlue = {
-                    info->sType1.mB.x * 0.00002f,
-                    info->sType1.mB.y * 0.00002f
-            },
-            .whitePoint = {
-                    info->sType1.mW.x * 0.00002f,
-                    info->sType1.mW.y * 0.00002f
-            },
-            .maxLuminance = (float) info->sType1.mMaxDisplayLuminance,
-            .minLuminance = info->sType1.mMinDisplayLuminance * 0.0001f
-    };
+    // If mastering max and min luminance fields are 0, do not use them.
+    // It indicates the value may not be present in the stream.
+    if ((float)info->sType1.mMaxDisplayLuminance > 0.0f &&
+        (info->sType1.mMinDisplayLuminance * 0.0001f) > 0.0f) {
+        struct android_smpte2086_metadata smpte2086_meta = {
+                .displayPrimaryRed = {
+                        info->sType1.mR.x * 0.00002f,
+                        info->sType1.mR.y * 0.00002f
+                },
+                .displayPrimaryGreen = {
+                        info->sType1.mG.x * 0.00002f,
+                        info->sType1.mG.y * 0.00002f
+                },
+                .displayPrimaryBlue = {
+                        info->sType1.mB.x * 0.00002f,
+                        info->sType1.mB.y * 0.00002f
+                },
+                .whitePoint = {
+                        info->sType1.mW.x * 0.00002f,
+                        info->sType1.mW.y * 0.00002f
+                },
+                .maxLuminance = (float) info->sType1.mMaxDisplayLuminance,
+                .minLuminance = info->sType1.mMinDisplayLuminance * 0.0001f
+        };
 
-    int err = native_window_set_buffers_smpte2086_metadata(nativeWindow, &smpte2086_meta);
-    ALOGW_IF(err != 0, "failed to set smpte2086 metadata on surface (%d)", err);
+        int err = native_window_set_buffers_smpte2086_metadata(nativeWindow, &smpte2086_meta);
+        ALOGW_IF(err != 0, "failed to set smpte2086 metadata on surface (%d)", err);
+    }
 
-    struct android_cta861_3_metadata cta861_meta = {
-            .maxContentLightLevel = (float) info->sType1.mMaxContentLightLevel,
-            .maxFrameAverageLightLevel = (float) info->sType1.mMaxFrameAverageLightLevel
-    };
+    // If the content light level fields are 0, do not use them, it
+    // indicates the value may not be present in the stream.
+    if ((float)info->sType1.mMaxContentLightLevel > 0.0f &&
+        (float)info->sType1.mMaxFrameAverageLightLevel > 0.0f) {
+        struct android_cta861_3_metadata cta861_meta = {
+                .maxContentLightLevel = (float) info->sType1.mMaxContentLightLevel,
+                .maxFrameAverageLightLevel = (float) info->sType1.mMaxFrameAverageLightLevel
+        };
 
-    err = native_window_set_buffers_cta861_3_metadata(nativeWindow, &cta861_meta);
-    ALOGW_IF(err != 0, "failed to set cta861_3 metadata on surface (%d)", err);
+        int err = native_window_set_buffers_cta861_3_metadata(nativeWindow, &cta861_meta);
+        ALOGW_IF(err != 0, "failed to set cta861_3 metadata on surface (%d)", err);
+    }
 }
 
 status_t pushBlankBuffersToNativeWindow(ANativeWindow *nativeWindow /* nonnull */) {
diff --git a/media/libstagefright/TEST_MAPPING b/media/libstagefright/TEST_MAPPING
index 8b36ea5..5e537dd 100644
--- a/media/libstagefright/TEST_MAPPING
+++ b/media/libstagefright/TEST_MAPPING
@@ -17,6 +17,9 @@
           "exclude-filter": "android.media.cts.AudioRecordTest"
         }
       ]
+    },
+    {
+      "name": "mediacodecTest"
     }
   ],
   "postsubmit": [
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index a1e4d43..ece79c4 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -1663,13 +1663,16 @@
         meta->setInt32(kKeyColorMatrix, colorAspects.mMatrixCoeffs);
     }
 }
-
-void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
+/* Converts key and value pairs in AMessage format to MetaData format.
+ * Also checks for the presence of required keys.
+ */
+status_t convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
     AString mime;
     if (msg->findString("mime", &mime)) {
         meta->setCString(kKeyMIMEType, mime.c_str());
     } else {
-        ALOGW("did not find mime type");
+        ALOGE("did not find mime type");
+        return BAD_VALUE;
     }
 
     convertMessageToMetaDataFromMappings(msg, meta);
@@ -1718,7 +1721,8 @@
             meta->setInt32(kKeyWidth, width);
             meta->setInt32(kKeyHeight, height);
         } else {
-            ALOGV("did not find width and/or height");
+            ALOGE("did not find width and/or height");
+            return BAD_VALUE;
         }
 
         int32_t sarWidth, sarHeight;
@@ -1803,14 +1807,14 @@
             }
         }
     } else if (mime.startsWith("audio/")) {
-        int32_t numChannels;
-        if (msg->findInt32("channel-count", &numChannels)) {
-            meta->setInt32(kKeyChannelCount, numChannels);
+        int32_t numChannels, sampleRate;
+        if (!msg->findInt32("channel-count", &numChannels) ||
+                !msg->findInt32("sample-rate", &sampleRate)) {
+            ALOGE("did not find channel-count and/or sample-rate");
+            return BAD_VALUE;
         }
-        int32_t sampleRate;
-        if (msg->findInt32("sample-rate", &sampleRate)) {
-            meta->setInt32(kKeySampleRate, sampleRate);
-        }
+        meta->setInt32(kKeyChannelCount, numChannels);
+        meta->setInt32(kKeySampleRate, sampleRate);
         int32_t bitsPerSample;
         if (msg->findInt32("bits-per-sample", &bitsPerSample)) {
             meta->setInt32(kKeyBitsPerSample, bitsPerSample);
@@ -1925,7 +1929,8 @@
                     }
                 }
             } else {
-                ALOGW("We need csd-2!!. %s", msg->debugString().c_str());
+                ALOGE("We need csd-2!!. %s", msg->debugString().c_str());
+                return BAD_VALUE;
             }
         } else if (mime == MEDIA_MIMETYPE_VIDEO_VP9) {
             meta->setData(kKeyVp9CodecPrivate, 0, csd0->data(), csd0->size());
@@ -1991,6 +1996,7 @@
     ALOGI("converted %s to:", msg->debugString(0).c_str());
     meta->dumpToLog();
 #endif
+    return OK;
 }
 
 status_t sendMetaDataToHal(sp<MediaPlayerBase::AudioSink>& sink,
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 2aeddd7..28a7a1e 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -38,6 +38,7 @@
 #define DRC_DEFAULT_MOBILE_DRC_HEAVY 1   /* switch for heavy compression for mobile conf */
 #define DRC_DEFAULT_MOBILE_DRC_EFFECT 3  /* MPEG-D DRC effect type; 3 => Limited playback range */
 #define DRC_DEFAULT_MOBILE_DRC_ALBUM 0  /* MPEG-D DRC album mode; 0 => album mode is disabled, 1 => album mode is enabled */
+#define DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS -1 /* decoder output loudness; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
 #define DRC_DEFAULT_MOBILE_ENC_LEVEL (-1) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
 #define MAX_CHANNEL_COUNT            8  /* maximum number of audio channels that can be decoded */
 // names of properties that can be used to override the default DRC settings
@@ -230,6 +231,15 @@
     // For seven and eight channel input streams, enable 6.1 and 7.1 channel output
     aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, -1);
 
+    mDrcCompressMode = DRC_DEFAULT_MOBILE_DRC_HEAVY;
+    mDrcTargetRefLevel = DRC_DEFAULT_MOBILE_REF_LEVEL;
+    mDrcEncTargetLevel = DRC_DEFAULT_MOBILE_ENC_LEVEL;
+    mDrcBoostFactor = DRC_DEFAULT_MOBILE_DRC_BOOST;
+    mDrcAttenuationFactor = DRC_DEFAULT_MOBILE_DRC_CUT;
+    mDrcEffectType = DRC_DEFAULT_MOBILE_DRC_EFFECT;
+    mDrcAlbumMode = DRC_DEFAULT_MOBILE_DRC_ALBUM;
+    mDrcOutputLoudness = DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS;
+
     return status;
 }
 
@@ -358,6 +368,27 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioAndroidAacDrcPresentation:
+        {
+             OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE *aacPresParams =
+                    (OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE *)params;
+
+            ALOGD("get OMX_IndexParamAudioAndroidAacDrcPresentation");
+
+            if (!isValidOMXParam(aacPresParams)) {
+                return OMX_ErrorBadParameter;
+            }
+            aacPresParams->nDrcEffectType = mDrcEffectType;
+            aacPresParams->nDrcAlbumMode = mDrcAlbumMode;
+            aacPresParams->nDrcBoost =  mDrcBoostFactor;
+            aacPresParams->nDrcCut = mDrcAttenuationFactor;
+            aacPresParams->nHeavyCompression = mDrcCompressMode;
+            aacPresParams->nTargetReferenceLevel = mDrcTargetRefLevel;
+            aacPresParams->nEncodedTargetLevel = mDrcEncTargetLevel;
+            aacPresParams ->nDrcOutputLoudness = mDrcOutputLoudness;
+            return OMX_ErrorNone;
+        }
+
         default:
             return SimpleSoftOMXComponent::internalGetParameter(index, params);
     }
@@ -464,11 +495,13 @@
             if (aacPresParams->nDrcEffectType >= -1) {
                 ALOGV("set nDrcEffectType=%d", aacPresParams->nDrcEffectType);
                 aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, aacPresParams->nDrcEffectType);
+                mDrcEffectType = aacPresParams->nDrcEffectType;
             }
             if (aacPresParams->nDrcAlbumMode >= -1) {
                 ALOGV("set nDrcAlbumMode=%d", aacPresParams->nDrcAlbumMode);
                 aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE,
                         aacPresParams->nDrcAlbumMode);
+                mDrcAlbumMode = aacPresParams->nDrcAlbumMode;
             }
             bool updateDrcWrapper = false;
             if (aacPresParams->nDrcBoost >= 0) {
@@ -476,34 +509,42 @@
                 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR,
                         aacPresParams->nDrcBoost);
                 updateDrcWrapper = true;
+                mDrcBoostFactor = aacPresParams->nDrcBoost;
             }
             if (aacPresParams->nDrcCut >= 0) {
                 ALOGV("set nDrcCut=%d", aacPresParams->nDrcCut);
                 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, aacPresParams->nDrcCut);
                 updateDrcWrapper = true;
+                mDrcAttenuationFactor = aacPresParams->nDrcCut;
             }
             if (aacPresParams->nHeavyCompression >= 0) {
                 ALOGV("set nHeavyCompression=%d", aacPresParams->nHeavyCompression);
                 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY,
                         aacPresParams->nHeavyCompression);
                 updateDrcWrapper = true;
+                mDrcCompressMode = aacPresParams->nHeavyCompression;
             }
             if (aacPresParams->nTargetReferenceLevel >= -1) {
                 ALOGV("set nTargetReferenceLevel=%d", aacPresParams->nTargetReferenceLevel);
                 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET,
                         aacPresParams->nTargetReferenceLevel);
                 updateDrcWrapper = true;
+                mDrcTargetRefLevel = aacPresParams->nTargetReferenceLevel;
             }
             if (aacPresParams->nEncodedTargetLevel >= 0) {
                 ALOGV("set nEncodedTargetLevel=%d", aacPresParams->nEncodedTargetLevel);
                 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET,
                         aacPresParams->nEncodedTargetLevel);
                 updateDrcWrapper = true;
+                mDrcEncTargetLevel = aacPresParams->nEncodedTargetLevel;
             }
             if (aacPresParams->nPCMLimiterEnable >= 0) {
                 aacDecoder_SetParam(mAACDecoder, AAC_PCM_LIMITER_ENABLE,
                         (aacPresParams->nPCMLimiterEnable != 0));
             }
+            if (aacPresParams ->nDrcOutputLoudness != DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS) {
+                mDrcOutputLoudness = aacPresParams ->nDrcOutputLoudness;
+            }
             if (updateDrcWrapper) {
                 mDrcWrap.update();
             }
@@ -854,6 +895,11 @@
                     // fall through
                 }
 
+                if ( mDrcOutputLoudness != mStreamInfo->outputLoudness) {
+                    ALOGD("update Loudness, before = %d, now = %d", mDrcOutputLoudness, mStreamInfo->outputLoudness);
+                    mDrcOutputLoudness = mStreamInfo->outputLoudness;
+                }
+
                 /*
                  * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
                  * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h
index 5bee710..9f98aa1 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.h
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h
@@ -85,6 +85,17 @@
     int32_t mOutputDelayRingBufferWritePos;
     int32_t mOutputDelayRingBufferReadPos;
     int32_t mOutputDelayRingBufferFilled;
+
+    //drc
+    int32_t mDrcCompressMode;
+    int32_t mDrcTargetRefLevel;
+    int32_t mDrcEncTargetLevel;
+    int32_t mDrcBoostFactor;
+    int32_t mDrcAttenuationFactor;
+    int32_t mDrcEffectType;
+    int32_t mDrcAlbumMode;
+    int32_t mDrcOutputLoudness;
+
     bool outputDelayRingBufferPutSamples(INT_PCM *samples, int numSamples);
     int32_t outputDelayRingBufferGetSamples(INT_PCM *samples, int numSamples);
     int32_t outputDelayRingBufferSamplesAvailable();
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp b/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp
index 5a846fa..584f79b 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp
@@ -570,12 +570,14 @@
     Word16 corr[],     /* i   : normalized correlation  */
     Word16 flag3,      /* i   : subsample resolution
                                 (3: =1 / 6: =0)         */
-    Flag   *pOverflow
+    Flag   *pOverflow,
+    enum Mode mode
 )
 {
     Word16 i;
     Word16 max;
     Word16 corr_int;
+    Word16 minPitch;
 
     /* Test the fractions around T0 and choose the one which maximizes   */
     /* the interpolated normalized correlation.                          */
@@ -593,14 +595,22 @@
         }
     }
 
+    minPitch = (mode == MR122) ? PIT_MIN_MR122 : PIT_MIN;
     if (flag3 == 0)
     {
         /* Limit the fraction value in the interval [-2,-1,0,1,2,3] */
 
         if (*frac == -3)
         {
-            *frac = 3;
-            (*lag)--;
+            if (*lag > minPitch)
+            {
+                *frac = 3;
+                (*lag)--;
+            }
+            else
+            {
+                *frac = -2;
+            }
         }
     }
     else
@@ -609,13 +619,27 @@
 
         if (*frac == -2)
         {
-            *frac = 1;
-            (*lag)--;
+            if (*lag > minPitch)
+            {
+                *frac = 1;
+                (*lag)--;
+            }
+            else
+            {
+                *frac = -1;
+            }
         }
-        if (*frac == 2)
+        else if (*frac == 2)
         {
-            *frac = -1;
-            (*lag)++;
+            if (*lag < PIT_MAX)
+            {
+                *frac = -1;
+                (*lag)++;
+            }
+            else
+            {
+                *frac = 1;
+            }
         }
     }
 }
@@ -1533,20 +1557,20 @@
 
                 /* normal search in fractions around T0 */
 
-                searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow);
+                searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow, mode);
 
             }
             else if (lag == (tmp_lag - 2))
             {
                 /* limit search around T0 to the right side */
                 frac = 0;
-                searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow);
+                searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow, mode);
             }
             else if (lag == (tmp_lag + 1))
             {
                 /* limit search around T0 to the left side */
                 last_frac = 0;
-                searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow);
+                searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow, mode);
             }
             else
             {
@@ -1556,7 +1580,7 @@
         }
         else
             /* test the fractions around T0 */
-            searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow);
+            searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow, mode);
     }
 
     /*-----------------------------------------------------------------------*
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.cpp
index 37250f3..5b19db4 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.cpp
@@ -649,8 +649,11 @@
 
 
 
-void PVLocateM4VFrameBoundary(BitstreamDecVideo *stream)
+PV_STATUS PVLocateM4VFrameBoundary(BitstreamDecVideo *stream)
 {
+    PV_STATUS status = BitstreamCheckEndBuffer(stream);
+    if (status == PV_END_OF_VOP) return status;
+
     uint8 *ptr;
     int32 byte_pos = (stream->bitcnt >> 3);
 
@@ -658,10 +661,14 @@
     ptr = stream->bitstreamBuffer + byte_pos;
 
     stream->data_end_pos = PVLocateFrameHeader(ptr, (int32)stream->data_end_pos - byte_pos) + byte_pos;
+    return PV_SUCCESS;
 }
 
-void PVLocateH263FrameBoundary(BitstreamDecVideo *stream)
+PV_STATUS PVLocateH263FrameBoundary(BitstreamDecVideo *stream)
 {
+    PV_STATUS status = BitstreamCheckEndBuffer(stream);
+    if (status == PV_END_OF_VOP) return status;
+
     uint8 *ptr;
     int32 byte_pos = (stream->bitcnt >> 3);
 
@@ -669,6 +676,7 @@
     ptr = stream->bitstreamBuffer + byte_pos;
 
     stream->data_end_pos = PVLocateH263FrameHeader(ptr, (int32)stream->data_end_pos - byte_pos) + byte_pos;
+    return PV_SUCCESS;
 }
 
 /* ======================================================================== */
@@ -687,7 +695,8 @@
 
     if (stream->searched_frame_boundary == 0)
     {
-        PVLocateM4VFrameBoundary(stream);
+        status = PVLocateM4VFrameBoundary(stream);
+        if (status != PV_SUCCESS) return status;
     }
 
     do
@@ -711,7 +720,8 @@
 
     if (stream->searched_frame_boundary == 0)
     {
-        PVLocateH263FrameBoundary(stream);
+        status = PVLocateH263FrameBoundary(stream);
+        if (status != PV_SUCCESS) return status;
     }
 
     do
@@ -789,7 +799,8 @@
 
     if (stream->searched_frame_boundary == 0)
     {
-        PVLocateM4VFrameBoundary(stream);
+        status = PVLocateM4VFrameBoundary(stream);
+        if (status != PV_SUCCESS) return status;
     }
 
     while (TRUE)
@@ -880,7 +891,8 @@
 
     if (stream->searched_frame_boundary == 0)
     {
-        PVLocateM4VFrameBoundary(stream);
+        status = PVLocateM4VFrameBoundary(stream);
+        if (status != PV_SUCCESS) return status;
     }
 
     while (TRUE)
@@ -956,7 +968,8 @@
 
     if (stream->searched_frame_boundary == 0)
     {
-        PVLocateH263FrameBoundary(stream);
+        status = PVLocateH263FrameBoundary(stream);
+        if (status != PV_SUCCESS) return status;
     }
 
     while (TRUE)
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.h b/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.h
index d52fa87..0cf903d 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.h
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.h
@@ -156,8 +156,8 @@
 
 
     /* for error concealment & soft-decoding */
-    void PVLocateM4VFrameBoundary(BitstreamDecVideo *stream);
-    void PVSearchH263FrameBoundary(BitstreamDecVideo *stream);
+    PV_STATUS PVLocateM4VFrameBoundary(BitstreamDecVideo *stream);
+    PV_STATUS PVSearchH263FrameBoundary(BitstreamDecVideo *stream);
 
     PV_STATUS quickSearchMotionMarker(BitstreamDecVideo *stream);
     PV_STATUS quickSearchDCM(BitstreamDecVideo *stream);
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp
index 997b78d..9deb023 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp
@@ -1576,7 +1576,7 @@
 
     /* find the last refresh MB */
     indx = 0;
-    while (intraArray[indx] == 1 && indx < totalMB)
+    while (indx < totalMB && intraArray[indx] == 1)
         indx++;
 
     /* add more  */
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
index 7ab8f45..30e4fda 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
@@ -491,6 +491,9 @@
     }
     for (i = 0; i < encParams->nLayers; i++)
     {
+        if (encOption->encHeight[i] == 0 || encOption->encWidth[i] == 0 ||
+                encOption->encHeight[i] % 16 != 0 || encOption->encWidth[i] % 16 != 0)
+            goto CLEAN_UP;
         encParams->LayerHeight[i] = encOption->encHeight[i];
         encParams->LayerWidth[i] = encOption->encWidth[i];
     }
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
index a5c7f5e..5cf1ed3 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
@@ -219,6 +219,11 @@
 
     if (info->error_protection)
     {
+        if (!bitsAvailable(&pVars->inputStream, 16))
+        {
+            return SIDE_INFO_ERROR;
+        }
+
         /*
          *  Get crc content
          */
@@ -593,18 +598,10 @@
         }
         else
         {
-            int32 tmp1 = *(ptr++);
-            for (int32 nBytes = temp >> 1; nBytes != 0; nBytes--)  /* read main data. */
+            for (int32 nBytes = temp; nBytes != 0; nBytes--)  /* read main data. */
             {
-                int32 tmp2 = *(ptr++);
-                fillDataBuf(&pVars->mainDataStream, tmp1);
-                fillDataBuf(&pVars->mainDataStream, tmp2);
-                tmp1 = *(ptr++);
-            }
-
-            if (temp&1)
-            {
-                fillDataBuf(&pVars->mainDataStream, tmp1);
+                int32 tmp = *(ptr++);
+                fillDataBuf(&pVars->mainDataStream, tmp);
             }
 
             /* adjust circular buffer counter */
@@ -613,14 +610,9 @@
     }
     else
     {
-        for (int32 nBytes = temp >> 1; nBytes != 0; nBytes--)  /* read main data. */
+        for (int32 nBytes = temp; nBytes != 0; nBytes--)  /* read main data. */
         {
             fillDataBuf(&pVars->mainDataStream, *(pVars->inputStream.pBuffer + module(offset++  , BUFSIZE)));
-            fillDataBuf(&pVars->mainDataStream, *(pVars->inputStream.pBuffer + module(offset++  , BUFSIZE)));
-        }
-        if (temp&1)
-        {
-            fillDataBuf(&pVars->mainDataStream, *(pVars->inputStream.pBuffer + module(offset  , BUFSIZE)));
         }
     }
 
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
index d644207..1a3fca5 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
@@ -73,6 +73,7 @@
 
 #include "pvmp3_get_side_info.h"
 #include "pvmp3_crc.h"
+#include "pvmp3_getbits.h"
 
 
 /*----------------------------------------------------------------------------
@@ -125,12 +126,22 @@
     {
         if (stereo == 1)
         {
+            if (!bitsAvailable(inputStream, 14))
+            {
+                return SIDE_INFO_ERROR;
+            }
+
             tmp = getbits_crc(inputStream, 14, crc, info->error_protection);
             si->main_data_begin = (tmp << 18) >> 23;    /* 9 */
             si->private_bits    = (tmp << 27) >> 27;    /* 5 */
         }
         else
         {
+            if (!bitsAvailable(inputStream, 12))
+            {
+                return SIDE_INFO_ERROR;
+            }
+
             tmp = getbits_crc(inputStream, 12, crc, info->error_protection);
             si->main_data_begin = (tmp << 20) >> 23;    /* 9 */
             si->private_bits    = (tmp << 29) >> 29;    /* 3 */
@@ -139,6 +150,11 @@
 
         for (ch = 0; ch < stereo; ch++)
         {
+            if (!bitsAvailable(inputStream, 4))
+            {
+                return SIDE_INFO_ERROR;
+            }
+
             tmp = getbits_crc(inputStream, 4, crc, info->error_protection);
             si->ch[ch].scfsi[0] = (tmp << 28) >> 31;    /* 1 */
             si->ch[ch].scfsi[1] = (tmp << 29) >> 31;    /* 1 */
@@ -150,6 +166,11 @@
         {
             for (ch = 0; ch < stereo; ch++)
             {
+                if (!bitsAvailable(inputStream, 34))
+                {
+                    return SIDE_INFO_ERROR;
+                }
+
                 si->ch[ch].gran[gr].part2_3_length    = getbits_crc(inputStream, 12, crc, info->error_protection);
                 tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
 
@@ -160,6 +181,11 @@
 
                 if (si->ch[ch].gran[gr].window_switching_flag)
                 {
+                    if (!bitsAvailable(inputStream, 22))
+                    {
+                        return SIDE_INFO_ERROR;
+                    }
+
                     tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
 
                     si->ch[ch].gran[gr].block_type       = (tmp << 10) >> 30;   /* 2 */;
@@ -192,6 +218,11 @@
                 }
                 else
                 {
+                    if (!bitsAvailable(inputStream, 22))
+                    {
+                        return SIDE_INFO_ERROR;
+                    }
+
                     tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
 
                     si->ch[ch].gran[gr].table_select[0] = (tmp << 10) >> 27;   /* 5 */;
@@ -204,6 +235,11 @@
                     si->ch[ch].gran[gr].block_type      = 0;
                 }
 
+                if (!bitsAvailable(inputStream, 3))
+                {
+                    return SIDE_INFO_ERROR;
+                }
+
                 tmp = getbits_crc(inputStream, 3, crc, info->error_protection);
                 si->ch[ch].gran[gr].preflag            = (tmp << 29) >> 31;    /* 1 */
                 si->ch[ch].gran[gr].scalefac_scale     = (tmp << 30) >> 31;    /* 1 */
@@ -213,11 +249,21 @@
     }
     else /* Layer 3 LSF */
     {
+        if (!bitsAvailable(inputStream, 8 + stereo))
+        {
+            return SIDE_INFO_ERROR;
+        }
+
         si->main_data_begin = getbits_crc(inputStream,      8, crc, info->error_protection);
         si->private_bits    = getbits_crc(inputStream, stereo, crc, info->error_protection);
 
         for (ch = 0; ch < stereo; ch++)
         {
+            if (!bitsAvailable(inputStream, 39))
+            {
+                return SIDE_INFO_ERROR;
+            }
+
             tmp = getbits_crc(inputStream, 21, crc, info->error_protection);
             si->ch[ch].gran[0].part2_3_length    = (tmp << 11) >> 20;  /* 12 */
             si->ch[ch].gran[0].big_values        = (tmp << 23) >> 23;  /*  9 */
@@ -230,6 +276,11 @@
             if (si->ch[ch].gran[0].window_switching_flag)
             {
 
+                if (!bitsAvailable(inputStream, 22))
+                {
+                    return SIDE_INFO_ERROR;
+                }
+
                 tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
 
                 si->ch[ch].gran[0].block_type       = (tmp << 10) >> 30;   /* 2 */;
@@ -262,6 +313,11 @@
             }
             else
             {
+                if (!bitsAvailable(inputStream, 22))
+                {
+                    return SIDE_INFO_ERROR;
+                }
+
                 tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
 
                 si->ch[ch].gran[0].table_select[0] = (tmp << 10) >> 27;   /* 5 */;
@@ -274,6 +330,11 @@
                 si->ch[ch].gran[0].block_type      = 0;
             }
 
+            if (!bitsAvailable(inputStream, 2))
+            {
+                return SIDE_INFO_ERROR;
+            }
+
             tmp = getbits_crc(inputStream, 2, crc, info->error_protection);
             si->ch[ch].gran[0].scalefac_scale     =  tmp >> 1;  /* 1 */
             si->ch[ch].gran[0].count1table_select =  tmp & 1;  /* 1 */
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp
index 8ff7953..4d252ef 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp
@@ -113,10 +113,11 @@
 
     uint32    offset;
     uint32    bitIndex;
-    uint8     Elem;         /* Needs to be same type as pInput->pBuffer */
-    uint8     Elem1;
-    uint8     Elem2;
-    uint8     Elem3;
+    uint32    bytesToFetch;
+    uint8     Elem  = 0;         /* Needs to be same type as pInput->pBuffer */
+    uint8     Elem1 = 0;
+    uint8     Elem2 = 0;
+    uint8     Elem3 = 0;
     uint32   returnValue = 0;
 
     if (!neededBits)
@@ -126,10 +127,25 @@
 
     offset = (ptBitStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
 
-    Elem  = *(ptBitStream->pBuffer + module(offset  , BUFSIZE));
-    Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
-    Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
-    Elem3 = *(ptBitStream->pBuffer + module(offset + 3, BUFSIZE));
+    /* Remove extra high bits by shifting up */
+    bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
+
+    bytesToFetch = (bitIndex + neededBits + 7 ) >> 3 ;
+
+    switch (bytesToFetch)
+    {
+    case 4:
+        Elem3 = *(ptBitStream->pBuffer + module(offset + 3, BUFSIZE));
+        [[fallthrough]];
+    case 3:
+        Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
+        [[fallthrough]];
+    case 2:
+        Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+        [[fallthrough]];
+    case 1:
+        Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
+    }
 
 
     returnValue = (((uint32)(Elem)) << 24) |
@@ -137,9 +153,6 @@
                   (((uint32)(Elem2)) << 8) |
                   ((uint32)(Elem3));
 
-    /* Remove extra high bits by shifting up */
-    bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
-
     /* This line is faster than to mask off the high bits. */
     returnValue <<= bitIndex;
 
@@ -161,22 +174,32 @@
 
     uint32    offset;
     uint32    bitIndex;
-    uint8    Elem;         /* Needs to be same type as pInput->pBuffer */
-    uint8    Elem1;
+    uint32    bytesToFetch;
+    uint8    Elem  = 0;         /* Needs to be same type as pInput->pBuffer */
+    uint8    Elem1 = 0;
     uint16   returnValue;
 
     offset = (ptBitStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
 
-    Elem  = *(ptBitStream->pBuffer + module(offset  , BUFSIZE));
-    Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+    /* Remove extra high bits by shifting up */
+    bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
+
+    bytesToFetch = (bitIndex + neededBits + 7 ) >> 3 ;
+
+    if (bytesToFetch > 1)
+    {
+        Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
+        Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+    }
+    else if (bytesToFetch > 0)
+    {
+        Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
+    }
 
 
     returnValue = (((uint16)(Elem)) << 8) |
                   ((uint16)(Elem1));
 
-    /* Remove extra high bits by shifting up */
-    bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
-
     ptBitStream->usedBits += neededBits;
     /* This line is faster than to mask off the high bits. */
     returnValue = (returnValue << (bitIndex));
@@ -197,25 +220,40 @@
 
     uint32    offset;
     uint32    bitIndex;
-    uint8     Elem;         /* Needs to be same type as pInput->pBuffer */
-    uint8     Elem1;
-    uint8     Elem2;
+    uint32    bytesToFetch;
+    uint8     Elem  = 0;         /* Needs to be same type as pInput->pBuffer */
+    uint8     Elem1 = 0;
+    uint8     Elem2 = 0;
     uint32   returnValue;
 
     offset = (ptBitStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
 
-    Elem  = *(ptBitStream->pBuffer + module(offset  , BUFSIZE));
-    Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
-    Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
+    /* Remove extra high bits by shifting up */
+    bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
+
+    bytesToFetch = (bitIndex + neededBits + 7 ) >> 3 ;
+
+    if (bytesToFetch > 2)
+    {
+        Elem  = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
+        Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+        Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
+    }
+    else if (bytesToFetch > 1)
+    {
+        Elem  = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
+        Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+    }
+    else if (bytesToFetch > 0)
+    {
+        Elem = *(ptBitStream->pBuffer + module(offset, BUFSIZE));
+    }
 
 
     returnValue = (((uint32)(Elem)) << 16) |
                   (((uint32)(Elem1)) << 8) |
                   ((uint32)(Elem2));
 
-    /* Remove extra high bits by shifting up */
-    bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
-
     ptBitStream->usedBits += neededBits;
     /* This line is faster than to mask off the high bits. */
     returnValue = 0xFFFFFF & (returnValue << (bitIndex));
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h
index b058b00..b04fe6d 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h
@@ -104,6 +104,11 @@
 ; Function Prototype declaration
 ----------------------------------------------------------------------------*/
 
+static inline bool bitsAvailable(tmp3Bits *inputStream, uint32 neededBits)
+{
+    return (inputStream->inputBufferCurrentLength << 3) >= (neededBits + inputStream->usedBits);
+}
+
 /*----------------------------------------------------------------------------
 ; END
 ----------------------------------------------------------------------------*/
diff --git a/media/libstagefright/foundation/ABuffer.cpp b/media/libstagefright/foundation/ABuffer.cpp
index c8965d9..c79384c 100644
--- a/media/libstagefright/foundation/ABuffer.cpp
+++ b/media/libstagefright/foundation/ABuffer.cpp
@@ -67,7 +67,7 @@
 
 void ABuffer::setRange(size_t offset, size_t size) {
     CHECK_LE(offset, mCapacity);
-    CHECK_LE(offset + size, mCapacity);
+    CHECK_LE(size, mCapacity - offset);
 
     mRangeOffset = offset;
     mRangeLength = size;
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index f7e6c27..7614ba5 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -366,6 +366,8 @@
     AString mOwnerName;
     sp<MediaCodecInfo> mCodecInfo;
     sp<AReplyToken> mReplyID;
+    std::string mLastReplyOrigin;
+    std::vector<sp<AMessage>> mDeferredMessages;
     uint32_t mFlags;
     status_t mStickyError;
     sp<Surface> mSurface;
@@ -428,13 +430,17 @@
 
     std::shared_ptr<BufferChannelBase> mBufferChannel;
 
-    MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid);
+    MediaCodec(
+            const sp<ALooper> &looper, pid_t pid, uid_t uid,
+            std::function<sp<CodecBase>(const AString &, const char *)> getCodecBase = nullptr,
+            std::function<status_t(const AString &, sp<MediaCodecInfo> *)> getCodecInfo = nullptr);
 
     static sp<CodecBase> GetCodecBase(const AString &name, const char *owner = nullptr);
 
     static status_t PostAndAwaitResponse(
             const sp<AMessage> &msg, sp<AMessage> *response);
 
+    void PostReplyWithError(const sp<AMessage> &msg, int32_t err);
     void PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err);
 
     status_t init(const AString &name);
@@ -445,6 +451,7 @@
     size_t updateBuffers(int32_t portIndex, const sp<AMessage> &msg);
     status_t onQueueInputBuffer(const sp<AMessage> &msg);
     status_t onReleaseOutputBuffer(const sp<AMessage> &msg);
+    BufferInfo *peekNextPortBuffer(int32_t portIndex);
     ssize_t dequeuePortBuffer(int32_t portIndex);
 
     status_t getBufferAndFormat(
@@ -476,6 +483,7 @@
     status_t onSetParameters(const sp<AMessage> &params);
 
     status_t amendOutputFormatWithCodecSpecificData(const sp<MediaCodecBuffer> &buffer);
+    void handleOutputFormatChangeIfNeeded(const sp<MediaCodecBuffer> &buffer);
     bool isExecuting() const;
 
     uint64_t getGraphicBufferSize();
@@ -484,6 +492,9 @@
     bool hasPendingBuffer(int portIndex);
     bool hasPendingBuffer();
 
+    void postPendingRepliesAndDeferredMessages(std::string origin, status_t err = OK);
+    void postPendingRepliesAndDeferredMessages(std::string origin, const sp<AMessage> &response);
+
     /* called to get the last codec error when the sticky flag is set.
      * if no such codec error is found, returns UNKNOWN_ERROR.
      */
@@ -569,6 +580,10 @@
 
     Histogram mLatencyHist;
 
+    std::function<sp<CodecBase>(const AString &, const char *)> mGetCodecBase;
+    std::function<status_t(const AString &, sp<MediaCodecInfo> *)> mGetCodecInfo;
+    friend class MediaTestHelper;
+
     DISALLOW_EVIL_CONSTRUCTORS(MediaCodec);
 };
 
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecListWriter.h b/media/libstagefright/include/media/stagefright/MediaCodecListWriter.h
index f53b23e..bf85d7e 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecListWriter.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecListWriter.h
@@ -19,7 +19,6 @@
 #define MEDIA_CODEC_LIST_WRITER_H_
 
 #include <media/stagefright/foundation/ABase.h>
-#include <media/stagefright/MediaCodecListWriter.h>
 #include <media/MediaCodecInfo.h>
 
 #include <utils/Errors.h>
@@ -65,6 +64,7 @@
     std::vector<sp<MediaCodecInfo>> mCodecInfos;
 
     friend struct MediaCodecList;
+    friend class MediaTestHelper;
 };
 
 /**
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index 227cead..d8f2b00 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -47,12 +47,14 @@
         SAMPLE_FLAG_ENCRYPTED   = 2,
     };
 
+    typedef IMediaExtractor::EntryPoint EntryPoint;
+
     // identical to IMediaExtractor::GetTrackMetaDataFlags
     enum GetTrackFormatFlags {
         kIncludeExtensiveMetaData = 1, // reads sample table and possibly stream headers
     };
 
-    NuMediaExtractor();
+    explicit NuMediaExtractor(EntryPoint entryPoint);
 
     status_t setDataSource(
             const sp<MediaHTTPService> &httpService,
@@ -128,6 +130,8 @@
         uint32_t mTrackFlags;  // bitmask of "TrackFlags"
     };
 
+    const EntryPoint mEntryPoint;
+
     mutable Mutex mLock;
 
     sp<DataSource> mDataSource;
@@ -139,6 +143,8 @@
     int64_t mTotalBitrate;  // in bits/sec
     int64_t mDurationUs;
 
+    void setEntryPointToRemoteMediaExtractor();
+
     ssize_t fetchAllTrackSamples(
             int64_t seekTimeUs = -1ll,
             MediaSource::ReadOptions::SeekMode mode =
diff --git a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
index 2ce7bc7..25125f2 100644
--- a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
@@ -42,6 +42,7 @@
     virtual uint32_t flags() const;
     virtual status_t setMediaCas(const HInterfaceToken &casToken);
     virtual String8 name();
+    virtual status_t setEntryPoint(EntryPoint entryPoint);
 
 private:
     MediaExtractor *mExtractor;
diff --git a/media/libstagefright/include/media/stagefright/Utils.h b/media/libstagefright/include/media/stagefright/Utils.h
index 2b9b759..1673120 100644
--- a/media/libstagefright/include/media/stagefright/Utils.h
+++ b/media/libstagefright/include/media/stagefright/Utils.h
@@ -33,7 +33,7 @@
         const MetaDataBase *meta, sp<AMessage> *format);
 status_t convertMetaDataToMessage(
         const sp<MetaData> &meta, sp<AMessage> *format);
-void convertMessageToMetaData(
+status_t convertMessageToMetaData(
         const sp<AMessage> &format, sp<MetaData> &meta);
 
 // Returns a pointer to the next NAL start code in buffer of size |length| starting at |data|, or
diff --git a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
index ddb459f..44415aa 100644
--- a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
+++ b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
@@ -17,6 +17,10 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "SimpleSoftOMXComponent"
 #include <utils/Log.h>
+#include <OMX_Core.h>
+#include <OMX_Audio.h>
+#include <OMX_IndexExt.h>
+#include <OMX_AudioExt.h>
 
 #include <media/stagefright/omx/SimpleSoftOMXComponent.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -74,7 +78,7 @@
 
     OMX_U32 portIndex;
 
-    switch (index) {
+    switch ((int)index) {
         case OMX_IndexParamPortDefinition:
         {
             const OMX_PARAM_PORTDEFINITIONTYPE *portDefs =
@@ -108,6 +112,19 @@
             break;
         }
 
+         case OMX_IndexParamAudioAndroidAacDrcPresentation:
+        {
+            if (mState == OMX_StateInvalid) {
+                return false;
+            }
+            const OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE *aacPresParams =
+                            (const OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE *)params;
+            if (!isValidOMXParam(aacPresParams)) {
+                return false;
+            }
+            return true;
+         }
+
         default:
             return false;
     }
diff --git a/media/libstagefright/tests/mediacodec/Android.bp b/media/libstagefright/tests/mediacodec/Android.bp
new file mode 100644
index 0000000..0bd0639
--- /dev/null
+++ b/media/libstagefright/tests/mediacodec/Android.bp
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+cc_test {
+    name: "mediacodecTest",
+    gtest: true,
+
+    srcs: [
+        "MediaCodecTest.cpp",
+        "MediaTestHelper.cpp",
+    ],
+
+    header_libs: [
+        "libmediadrm_headers",
+    ],
+
+    shared_libs: [
+        "libgui",
+        "libmedia",
+        "libmedia_codeclist",
+        "libmediametrics",
+        "libmediandk",
+        "libstagefright",
+        "libstagefright_codecbase",
+        "libstagefright_foundation",
+        "libutils",
+    ],
+
+    static_libs: [
+        "libgmock",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+
+    test_suites: [
+        "general-tests",
+    ],
+}
diff --git a/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp b/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
new file mode 100644
index 0000000..d00a50f
--- /dev/null
+++ b/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <future>
+#include <thread>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <gui/Surface.h>
+#include <mediadrm/ICrypto.h>
+#include <media/stagefright/CodecBase.h>
+#include <media/stagefright/MediaCodec.h>
+#include <media/stagefright/MediaCodecListWriter.h>
+#include <media/MediaCodecInfo.h>
+
+#include "MediaTestHelper.h"
+
+namespace android {
+
+class MockBufferChannel : public BufferChannelBase {
+public:
+    ~MockBufferChannel() override = default;
+
+    MOCK_METHOD(void, setCrypto, (const sp<ICrypto> &crypto), (override));
+    MOCK_METHOD(void, setDescrambler, (const sp<IDescrambler> &descrambler), (override));
+    MOCK_METHOD(status_t, queueInputBuffer, (const sp<MediaCodecBuffer> &buffer), (override));
+    MOCK_METHOD(status_t, queueSecureInputBuffer,
+            (const sp<MediaCodecBuffer> &buffer,
+             bool secure,
+             const uint8_t *key,
+             const uint8_t *iv,
+             CryptoPlugin::Mode mode,
+             CryptoPlugin::Pattern pattern,
+             const CryptoPlugin::SubSample *subSamples,
+             size_t numSubSamples,
+             AString *errorDetailMsg),
+            (override));
+    MOCK_METHOD(status_t, attachBuffer,
+            (const std::shared_ptr<C2Buffer> &c2Buffer, const sp<MediaCodecBuffer> &buffer),
+            (override));
+    MOCK_METHOD(status_t, attachEncryptedBuffer,
+            (const sp<hardware::HidlMemory> &memory,
+             bool secure,
+             const uint8_t *key,
+             const uint8_t *iv,
+             CryptoPlugin::Mode mode,
+             CryptoPlugin::Pattern pattern,
+             size_t offset,
+             const CryptoPlugin::SubSample *subSamples,
+             size_t numSubSamples,
+             const sp<MediaCodecBuffer> &buffer),
+            (override));
+    MOCK_METHOD(status_t, renderOutputBuffer,
+            (const sp<MediaCodecBuffer> &buffer, int64_t timestampNs),
+            (override));
+    MOCK_METHOD(status_t, discardBuffer, (const sp<MediaCodecBuffer> &buffer), (override));
+    MOCK_METHOD(void, getInputBufferArray, (Vector<sp<MediaCodecBuffer>> *array), (override));
+    MOCK_METHOD(void, getOutputBufferArray, (Vector<sp<MediaCodecBuffer>> *array), (override));
+};
+
+class MockCodec : public CodecBase {
+public:
+    MockCodec(std::function<void(const std::shared_ptr<MockBufferChannel> &)> mock) {
+        mMockBufferChannel = std::make_shared<MockBufferChannel>();
+        mock(mMockBufferChannel);
+    }
+    ~MockCodec() override = default;
+
+    MOCK_METHOD(void, initiateAllocateComponent, (const sp<AMessage> &msg), (override));
+    MOCK_METHOD(void, initiateConfigureComponent, (const sp<AMessage> &msg), (override));
+    MOCK_METHOD(void, initiateCreateInputSurface, (), (override));
+    MOCK_METHOD(void, initiateSetInputSurface, (const sp<PersistentSurface> &surface), (override));
+    MOCK_METHOD(void, initiateStart, (), (override));
+    MOCK_METHOD(void, initiateShutdown, (bool keepComponentAllocated), (override));
+    MOCK_METHOD(void, onMessageReceived, (const sp<AMessage> &msg), (override));
+    MOCK_METHOD(status_t, setSurface, (const sp<Surface> &surface), (override));
+    MOCK_METHOD(void, signalFlush, (), (override));
+    MOCK_METHOD(void, signalResume, (), (override));
+    MOCK_METHOD(void, signalRequestIDRFrame, (), (override));
+    MOCK_METHOD(void, signalSetParameters, (const sp<AMessage> &msg), (override));
+    MOCK_METHOD(void, signalEndOfInputStream, (), (override));
+
+    std::shared_ptr<BufferChannelBase> getBufferChannel() override {
+        return mMockBufferChannel;
+    }
+
+    const std::unique_ptr<CodecCallback> &callback() {
+        return mCallback;
+    }
+
+    std::shared_ptr<MockBufferChannel> mMockBufferChannel;
+};
+
+class Counter {
+public:
+    Counter() = default;
+    explicit Counter(int32_t initCount) : mCount(initCount) {}
+    ~Counter() = default;
+
+    int32_t advance() {
+        std::unique_lock<std::mutex> lock(mMutex);
+        ++mCount;
+        mCondition.notify_all();
+        return mCount;
+    }
+
+    template <typename Rep, typename Period, typename ...Args>
+    int32_t waitFor(const std::chrono::duration<Rep, Period> &duration, Args... values) {
+        std::initializer_list<int32_t> list = {values...};
+        std::unique_lock<std::mutex> lock(mMutex);
+        mCondition.wait_for(
+                lock,
+                duration,
+                [&list, this]{
+                    return std::find(list.begin(), list.end(), mCount) != list.end();
+                });
+        return mCount;
+    }
+
+    template <typename ...Args>
+    int32_t wait(Args... values) {
+        std::initializer_list<int32_t> list = {values...};
+        std::unique_lock<std::mutex> lock(mMutex);
+        mCondition.wait(
+                lock,
+                [&list, this]{
+                    return std::find(list.begin(), list.end(), mCount) != list.end();
+                });
+        return mCount;
+    }
+
+private:
+    std::mutex mMutex;
+    std::condition_variable mCondition;
+    int32_t mCount = 0;
+};
+
+}  // namespace android
+
+using namespace android;
+using ::testing::_;
+
+static sp<MediaCodec> SetupMediaCodec(
+        const AString &owner,
+        const AString &codecName,
+        const AString &mediaType,
+        const sp<ALooper> &looper,
+        std::function<sp<CodecBase>(const AString &name, const char *owner)> getCodecBase) {
+    std::shared_ptr<MediaCodecListWriter> listWriter =
+        MediaTestHelper::CreateCodecListWriter();
+    std::unique_ptr<MediaCodecInfoWriter> infoWriter = listWriter->addMediaCodecInfo();
+    infoWriter->setName(codecName.c_str());
+    infoWriter->setOwner(owner.c_str());
+    infoWriter->addMediaType(mediaType.c_str());
+    std::vector<sp<MediaCodecInfo>> codecInfos;
+    MediaTestHelper::WriteCodecInfos(listWriter, &codecInfos);
+    std::function<status_t(const AString &, sp<MediaCodecInfo> *)> getCodecInfo =
+        [codecInfos](const AString &name, sp<MediaCodecInfo> *info) -> status_t {
+            auto it = std::find_if(
+                    codecInfos.begin(), codecInfos.end(),
+                    [&name](const sp<MediaCodecInfo> &info) {
+                        return name.equalsIgnoreCase(info->getCodecName());
+                    });
+
+            *info = (it == codecInfos.end()) ? nullptr : *it;
+            return (*info) ? OK : NAME_NOT_FOUND;
+        };
+
+    looper->start();
+    return MediaTestHelper::CreateCodec(
+            codecName, looper, getCodecBase, getCodecInfo);
+}
+
+TEST(MediaCodecTest, ReclaimReleaseRace) {
+    // Test scenario:
+    //
+    // 1) ResourceManager thread calls reclaim(), message posted to
+    //    MediaCodec looper thread.
+    // 2) MediaCodec looper thread calls initiateShutdown(), shutdown being
+    //    handled at the component thread.
+    // 3) Client thread calls release(), message posted to & handle at
+    //    MediaCodec looper thread.
+    // 4) MediaCodec looper thread may call initiateShutdown().
+    // 5) initiateShutdown() from 2) is handled at onReleaseComplete() event
+    //    posted to MediaCodec looper thread.
+    // 6) If called, initiateShutdown() from 4) is handled and
+    //    onReleaseComplete() event posted to MediaCodec looper thread.
+
+    static const AString kCodecName{"test.codec"};
+    static const AString kCodecOwner{"nobody"};
+    static const AString kMediaType{"video/x-test"};
+
+    enum {
+        kInit,
+        kShutdownFromReclaimReceived,
+        kReleaseCalled,
+    };
+    Counter counter{kInit};
+    sp<MockCodec> mockCodec;
+    std::function<sp<CodecBase>(const AString &name, const char *owner)> getCodecBase =
+        [&mockCodec, &counter](const AString &, const char *) {
+            mockCodec = new MockCodec([](const std::shared_ptr<MockBufferChannel> &) {
+                // No mock setup, as we don't expect any buffer operations
+                // in this scenario.
+            });
+            ON_CALL(*mockCodec, initiateAllocateComponent(_))
+                .WillByDefault([mockCodec](const sp<AMessage> &) {
+                    mockCodec->callback()->onComponentAllocated(kCodecName.c_str());
+                });
+            ON_CALL(*mockCodec, initiateShutdown(_))
+                .WillByDefault([mockCodec, &counter](bool) {
+                    int32_t stage = counter.wait(kInit, kReleaseCalled);
+                    if (stage == kInit) {
+                        // Mark that 2) happened, so test can proceed to 3)
+                        counter.advance();
+                    } else if (stage == kReleaseCalled) {
+                        // Handle 6)
+                        mockCodec->callback()->onReleaseCompleted();
+                    }
+                });
+            return mockCodec;
+        };
+
+    sp<ALooper> looper{new ALooper};
+    sp<MediaCodec> codec = SetupMediaCodec(
+            kCodecOwner, kCodecName, kMediaType, looper, getCodecBase);
+    ASSERT_NE(nullptr, codec) << "Codec must not be null";
+    ASSERT_NE(nullptr, mockCodec) << "MockCodec must not be null";
+    std::promise<void> reclaimCompleted;
+    std::promise<void> releaseCompleted;
+    Counter threadExitCounter;
+    std::thread([codec, &reclaimCompleted]{
+        // Simulate ResourceManager thread. Proceed with 1)
+        MediaTestHelper::Reclaim(codec, true /* force */);
+        reclaimCompleted.set_value();
+    }).detach();
+    std::thread([codec, &counter, &releaseCompleted]{
+        // Simulate client thread. Wait until 2) is complete
+        (void)counter.wait(kShutdownFromReclaimReceived);
+        // Proceed to 3), and mark that 5) is ready to happen.
+        // NOTE: it's difficult to pinpoint when 4) happens, so we will sleep
+        //       to meet the timing.
+        counter.advance();
+        codec->release();
+        releaseCompleted.set_value();
+    }).detach();
+    std::thread([mockCodec, &counter]{
+        // Simulate component thread. Wait until 3) is complete
+        (void)counter.wait(kReleaseCalled);
+        // We want 4) to complete before moving forward, but it is hard to
+        // wait for this exact event. Just sleep so that the other thread can
+        // proceed and complete 4).
+        std::this_thread::sleep_for(std::chrono::milliseconds(100));
+        // Proceed to 5).
+        mockCodec->callback()->onReleaseCompleted();
+    }).detach();
+    EXPECT_EQ(
+            std::future_status::ready,
+            reclaimCompleted.get_future().wait_for(std::chrono::seconds(5)))
+        << "reclaim timed out";
+    EXPECT_EQ(
+            std::future_status::ready,
+            releaseCompleted.get_future().wait_for(std::chrono::seconds(5)))
+        << "release timed out";
+    looper->stop();
+}
+
+TEST(MediaCodecTest, ErrorWhileStopping) {
+    // Test scenario:
+    //
+    // 1) Client thread calls stop(); MediaCodec looper thread calls
+    //    initiateShutdown(); shutdown is being handled at the component thread.
+    // 2) Error occurred, but the shutdown operation is still being done.
+    // 3) MediaCodec looper thread handles the error.
+    // 4) Component thread completes shutdown and posts onStopCompleted()
+
+    static const AString kCodecName{"test.codec"};
+    static const AString kCodecOwner{"nobody"};
+    static const AString kMediaType{"video/x-test"};
+
+    std::promise<void> errorOccurred;
+    sp<MockCodec> mockCodec;
+    std::function<sp<CodecBase>(const AString &name, const char *owner)> getCodecBase =
+        [&mockCodec, &errorOccurred](const AString &, const char *) {
+            mockCodec = new MockCodec([](const std::shared_ptr<MockBufferChannel> &) {
+                // No mock setup, as we don't expect any buffer operations
+                // in this scenario.
+            });
+            ON_CALL(*mockCodec, initiateAllocateComponent(_))
+                .WillByDefault([mockCodec](const sp<AMessage> &) {
+                    mockCodec->callback()->onComponentAllocated(kCodecName.c_str());
+                });
+            ON_CALL(*mockCodec, initiateConfigureComponent(_))
+                .WillByDefault([mockCodec](const sp<AMessage> &msg) {
+                    mockCodec->callback()->onComponentConfigured(
+                            msg->dup(), msg->dup());
+                });
+            ON_CALL(*mockCodec, initiateStart())
+                .WillByDefault([mockCodec]() {
+                    mockCodec->callback()->onStartCompleted();
+                });
+            ON_CALL(*mockCodec, initiateShutdown(true))
+                .WillByDefault([mockCodec, &errorOccurred](bool) {
+                    mockCodec->callback()->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
+                    // Mark that 1) and 2) are complete.
+                    errorOccurred.set_value();
+                });
+            ON_CALL(*mockCodec, initiateShutdown(false))
+                .WillByDefault([mockCodec](bool) {
+                    mockCodec->callback()->onReleaseCompleted();
+                });
+            return mockCodec;
+        };
+
+    sp<ALooper> looper{new ALooper};
+    sp<MediaCodec> codec = SetupMediaCodec(
+            kCodecOwner, kCodecName, kMediaType, looper, getCodecBase);
+    ASSERT_NE(nullptr, codec) << "Codec must not be null";
+    ASSERT_NE(nullptr, mockCodec) << "MockCodec must not be null";
+
+    std::thread([mockCodec, &errorOccurred]{
+        // Simulate component thread that handles stop()
+        errorOccurred.get_future().wait();
+        // Error occurred but shutdown request still got processed.
+        mockCodec->callback()->onStopCompleted();
+    }).detach();
+
+    codec->configure(new AMessage, nullptr, nullptr, 0);
+    codec->start();
+    codec->stop();
+    // Sleep here to give time for the MediaCodec looper thread
+    // to process the messages.
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    codec->release();
+    looper->stop();
+}
diff --git a/media/libstagefright/tests/mediacodec/MediaTestHelper.cpp b/media/libstagefright/tests/mediacodec/MediaTestHelper.cpp
new file mode 100644
index 0000000..bbe3c05
--- /dev/null
+++ b/media/libstagefright/tests/mediacodec/MediaTestHelper.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <media/stagefright/MediaCodec.h>
+#include <media/stagefright/MediaCodecListWriter.h>
+
+#include "MediaTestHelper.h"
+
+namespace android {
+
+// static
+sp<MediaCodec> MediaTestHelper::CreateCodec(
+        const AString &name,
+        const sp<ALooper> &looper,
+        std::function<sp<CodecBase>(const AString &, const char *)> getCodecBase,
+        std::function<status_t(const AString &, sp<MediaCodecInfo> *)> getCodecInfo) {
+    sp<MediaCodec> codec = new MediaCodec(
+            looper, MediaCodec::kNoPid, MediaCodec::kNoUid, getCodecBase, getCodecInfo);
+    if (codec->init(name) != OK) {
+        return nullptr;
+    }
+    return codec;
+}
+
+// static
+void MediaTestHelper::Reclaim(const sp<MediaCodec> &codec, bool force) {
+    codec->reclaim(force);
+}
+
+// static
+std::shared_ptr<MediaCodecListWriter> MediaTestHelper::CreateCodecListWriter() {
+    return std::shared_ptr<MediaCodecListWriter>(new MediaCodecListWriter);
+}
+
+// static
+void MediaTestHelper::WriteCodecInfos(
+        const std::shared_ptr<MediaCodecListWriter> &writer,
+        std::vector<sp<MediaCodecInfo>> *codecInfos) {
+    writer->writeCodecInfos(codecInfos);
+}
+
+}  // namespace android
diff --git a/media/libstagefright/tests/mediacodec/MediaTestHelper.h b/media/libstagefright/tests/mediacodec/MediaTestHelper.h
new file mode 100644
index 0000000..f3d6110
--- /dev/null
+++ b/media/libstagefright/tests/mediacodec/MediaTestHelper.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_TEST_HELPER_H_
+
+#define MEDIA_TEST_HELPER_H_
+
+#include <media/stagefright/foundation/AString.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+struct ALooper;
+struct CodecBase;
+struct MediaCodec;
+struct MediaCodecInfo;
+struct MediaCodecListWriter;
+
+class MediaTestHelper {
+public:
+    // MediaCodec
+    static sp<MediaCodec> CreateCodec(
+            const AString &name,
+            const sp<ALooper> &looper,
+            std::function<sp<CodecBase>(const AString &, const char *)> getCodecBase,
+            std::function<status_t(const AString &, sp<MediaCodecInfo> *)> getCodecInfo);
+    static void Reclaim(const sp<MediaCodec> &codec, bool force);
+
+    // MediaCodecListWriter
+    static std::shared_ptr<MediaCodecListWriter> CreateCodecListWriter();
+    static void WriteCodecInfos(
+            const std::shared_ptr<MediaCodecListWriter> &writer,
+            std::vector<sp<MediaCodecInfo>> *codecInfos);
+};
+
+}  // namespace android
+
+#endif  // MEDIA_TEST_HELPER_H_
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index 0da0740..0c65e9e 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -22,6 +22,7 @@
 #include <media/NdkMediaExtractor.h>
 #include <media/NdkMediaErrorPriv.h>
 #include <media/NdkMediaFormatPriv.h>
+#include "NdkJavaVMHelperPriv.h"
 #include "NdkMediaDataSourcePriv.h"
 
 
@@ -63,7 +64,10 @@
 AMediaExtractor* AMediaExtractor_new() {
     ALOGV("ctor");
     AMediaExtractor *mData = new AMediaExtractor();
-    mData->mImpl = new NuMediaExtractor();
+    mData->mImpl = new NuMediaExtractor(
+        NdkJavaVMHelper::getJNIEnv() != nullptr
+                ? NuMediaExtractor::EntryPoint::NDK_WITH_JVM
+                : NuMediaExtractor::EntryPoint::NDK_NO_JVM );
     return mData;
 }
 
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 87ea084..7699700 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -62,7 +62,7 @@
 }
 
 static bool checkRecordingInternal(const String16& opPackageName, pid_t pid,
-        uid_t uid, bool start) {
+        uid_t uid, bool start, bool isHotwordSource) {
     // Okay to not track in app ops as audio server or media server is us and if
     // device is rooted security model is considered compromised.
     // system_server loses its RECORD_AUDIO permission when a secondary
@@ -87,16 +87,21 @@
     }
 
     AppOpsManager appOps;
-    const int32_t op = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+    const int32_t opRecordAudio = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+
     if (start) {
+        const int32_t op = isHotwordSource ?
+                AppOpsManager::OP_RECORD_AUDIO_HOTWORD : opRecordAudio;
         if (appOps.startOpNoThrow(op, uid, resolvedOpPackageName, /*startIfModeDefault*/ false)
                 != AppOpsManager::MODE_ALLOWED) {
             ALOGE("Request denied by app op: %d", op);
             return false;
         }
     } else {
-        if (appOps.checkOp(op, uid, resolvedOpPackageName) != AppOpsManager::MODE_ALLOWED) {
-            ALOGE("Request denied by app op: %d", op);
+        // Always use OP_RECORD_AUDIO for checks at creation time.
+        if (appOps.checkOp(opRecordAudio, uid, resolvedOpPackageName)
+                != AppOpsManager::MODE_ALLOWED) {
+            ALOGE("Request denied by app op: %d", opRecordAudio);
             return false;
         }
     }
@@ -105,14 +110,15 @@
 }
 
 bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid) {
-    return checkRecordingInternal(opPackageName, pid, uid, /*start*/ false);
+    return checkRecordingInternal(opPackageName, pid, uid, /*start*/ false,
+            /*is_hotword_source*/ false);
 }
 
-bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid) {
-     return checkRecordingInternal(opPackageName, pid, uid, /*start*/ true);
+bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, bool isHotwordSource) {
+     return checkRecordingInternal(opPackageName, pid, uid, /*start*/ true, isHotwordSource);
 }
 
-void finishRecording(const String16& opPackageName, uid_t uid) {
+void finishRecording(const String16& opPackageName, uid_t uid, bool isHotwordSource) {
     // Okay to not track in app ops as audio server is us and if
     // device is rooted security model is considered compromised.
     if (isAudioServerOrRootUid(uid)) return;
@@ -125,7 +131,8 @@
     }
 
     AppOpsManager appOps;
-    const int32_t op = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
+    const int32_t op = isHotwordSource ? AppOpsManager::OP_RECORD_AUDIO_HOTWORD
+            : appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
     appOps.finishOp(op, uid, resolvedOpPackageName);
 }
 
diff --git a/media/utils/TimeCheck.cpp b/media/utils/TimeCheck.cpp
index 59d74de..819e146 100644
--- a/media/utils/TimeCheck.cpp
+++ b/media/utils/TimeCheck.cpp
@@ -39,10 +39,9 @@
     static std::atomic<int> curAudioHalPids = 0;
 
     if (update) {
-        audioHalPids[(curAudioHalPids + 1) % kNumAudioHalPidsVectors] = *pids;
-        curAudioHalPids++;
+        audioHalPids[(curAudioHalPids++ + 1) % kNumAudioHalPidsVectors] = *pids;
     } else {
-        *pids = audioHalPids[curAudioHalPids];
+        *pids = audioHalPids[curAudioHalPids % kNumAudioHalPidsVectors];
     }
 }
 
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 212599a..431dd7a 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -79,8 +79,8 @@
 }
 
 bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
-bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid);
-void finishRecording(const String16& opPackageName, uid_t uid);
+bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid, bool isHotwordSource);
+void finishRecording(const String16& opPackageName, uid_t uid, bool isHotwordSource);
 bool captureAudioOutputAllowed(pid_t pid, uid_t uid);
 bool captureMediaOutputAllowed(pid_t pid, uid_t uid);
 bool captureVoiceCommunicationOutputAllowed(pid_t pid, uid_t uid);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index f014209..764fdc3 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -852,7 +852,8 @@
                                       input.notificationsPerBuffer, input.speed,
                                       input.sharedBuffer, sessionId, &output.flags,
                                       callingPid, input.clientInfo.clientTid, clientUid,
-                                      &lStatus, portId, input.audioTrackCallback);
+                                      &lStatus, portId, input.audioTrackCallback,
+                                      input.opPackageName);
         LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
         // we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
 
@@ -2068,8 +2069,8 @@
         Mutex::Autolock _l(mLock);
         RecordThread *thread = checkRecordThread_l(output.inputId);
         if (thread == NULL) {
-            ALOGE("createRecord() checkRecordThread_l failed, input handle %d", output.inputId);
-            lStatus = BAD_VALUE;
+            ALOGW("createRecord() checkRecordThread_l failed, input handle %d", output.inputId);
+            lStatus = FAILED_TRANSACTION;
             goto Exit;
         }
 
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index d8eebf3..a2df29b 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -26,10 +26,11 @@
     bool hasOpPlayAudio() const;
 
     static sp<OpPlayAudioMonitor> createIfNeeded(
-            uid_t uid, const audio_attributes_t& attr, int id, audio_stream_type_t streamType);
+            uid_t uid, const audio_attributes_t& attr, int id, audio_stream_type_t streamType,
+            const std::string& opPackageName);
 
 private:
-    OpPlayAudioMonitor(uid_t uid, audio_usage_t usage, int id);
+    OpPlayAudioMonitor(uid_t uid, audio_usage_t usage, int id, const String16& opPackageName);
     void onFirstRef() override;
     static void getPackagesForUid(uid_t uid, Vector<String16>& packages);
 
@@ -49,10 +50,10 @@
     void checkPlayAudioForUsage();
 
     std::atomic_bool mHasOpPlayAudio;
-    Vector<String16> mPackages;
     const uid_t mUid;
     const int32_t mUsage; // on purpose not audio_usage_t because always checked in appOps as int32_t
     const int mId; // for logging purposes only
+    const String16 mOpPackageName;
 };
 
 // playback track
@@ -77,7 +78,8 @@
                                 audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
                                 /** default behaviour is to start when there are as many frames
                                   * ready as possible (aka. Buffer is full). */
-                                size_t frameCountToBeReady = SIZE_MAX);
+                                size_t frameCountToBeReady = SIZE_MAX,
+                                const std::string opPackageName = "");
     virtual             ~Track();
     virtual status_t    initCheck() const;
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 2af27d8..1d0147d 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2067,7 +2067,8 @@
         uid_t uid,
         status_t *status,
         audio_port_handle_t portId,
-        const sp<media::IAudioTrackCallback>& callback)
+        const sp<media::IAudioTrackCallback>& callback,
+        const std::string& opPackageName)
 {
     size_t frameCount = *pFrameCount;
     size_t notificationFrameCount = *pNotificationFrameCount;
@@ -2348,7 +2349,8 @@
         track = new Track(this, client, streamType, attr, sampleRate, format,
                           channelMask, frameCount,
                           nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,
-                          sessionId, creatorPid, uid, *flags, TrackBase::TYPE_DEFAULT, portId);
+                          sessionId, creatorPid, uid, *flags, TrackBase::TYPE_DEFAULT, portId,
+                          SIZE_MAX /*frameCountToBeReady*/, opPackageName);
 
         lStatus = track != 0 ? track->initCheck() : (status_t) NO_MEMORY;
         if (lStatus != NO_ERROR) {
@@ -2360,7 +2362,7 @@
         {
             Mutex::Autolock _atCbL(mAudioTrackCbLock);
             if (callback.get() != nullptr) {
-                mAudioTrackCallbacks.emplace(callback);
+                mAudioTrackCallbacks.emplace(track, callback);
             }
         }
 
@@ -2588,6 +2590,10 @@
     mLocalLog.log("removeTrack_l (%p) %s", track.get(), result.string());
 
     mTracks.remove(track);
+    {
+        Mutex::Autolock _atCbL(mAudioTrackCbLock);
+        mAudioTrackCallbacks.erase(track);
+    }
     if (track->isFastTrack()) {
         int index = track->mFastIndex;
         ALOG_ASSERT(0 < index && index < (int)FastMixerState::sMaxFastTracks);
@@ -2683,8 +2689,8 @@
                     audio_utils::metadata::byteStringFromData(metadata);
             std::vector metadataVec(metaDataStr.begin(), metaDataStr.end());
             Mutex::Autolock _l(mAudioTrackCbLock);
-            for (const auto& callback : mAudioTrackCallbacks) {
-                callback->onCodecFormatChanged(metadataVec);
+            for (const auto& callbackPair : mAudioTrackCallbacks) {
+                callbackPair.second->onCodecFormatChanged(metadataVec);
             }
     }).detach();
 }
@@ -7869,7 +7875,8 @@
         AutoMutex lock(mLock);
         if (recordTrack->isInvalid()) {
             recordTrack->clearSyncStartEvent();
-            return INVALID_OPERATION;
+            ALOGW("%s track %d: invalidated before startInput", __func__, recordTrack->portId());
+            return DEAD_OBJECT;
         }
         if (mActiveTracks.indexOf(recordTrack) >= 0) {
             if (recordTrack->mState == TrackBase::PAUSING) {
@@ -7899,7 +7906,8 @@
                     recordTrack->mState = TrackBase::STARTING_2;
                     // STARTING_2 forces destroy to call stopInput.
                 }
-                return INVALID_OPERATION;
+                ALOGW("%s track %d: invalidated after startInput", __func__, recordTrack->portId());
+                return DEAD_OBJECT;
             }
             if (recordTrack->mState != TrackBase::STARTING_1) {
                 ALOGW("%s(%d): unsynchronized mState:%d change",
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index c1ac2e4..6b33ad5 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -864,7 +864,8 @@
                                 uid_t uid,
                                 status_t *status /*non-NULL*/,
                                 audio_port_handle_t portId,
-                                const sp<media::IAudioTrackCallback>& callback);
+                                const sp<media::IAudioTrackCallback>& callback,
+                                const std::string& opPackageName);
 
                 AudioStreamOut* getOutput() const;
                 AudioStreamOut* clearOutput();
@@ -1186,7 +1187,7 @@
 
     Mutex                                    mAudioTrackCbLock;
     // Record of IAudioTrackCallback
-    std::set<sp<media::IAudioTrackCallback>> mAudioTrackCallbacks;
+    std::map<sp<Track>, sp<media::IAudioTrackCallback>> mAudioTrackCallbacks;
 
 private:
     // The HAL output sink is treated as non-blocking, but current implementation is blocking
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 126015f..f286d8a 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -386,11 +386,12 @@
 // static
 sp<AudioFlinger::PlaybackThread::OpPlayAudioMonitor>
 AudioFlinger::PlaybackThread::OpPlayAudioMonitor::createIfNeeded(
-            uid_t uid, const audio_attributes_t& attr, int id, audio_stream_type_t streamType)
+            uid_t uid, const audio_attributes_t& attr, int id, audio_stream_type_t streamType,
+            const std::string& opPackageName)
 {
+    Vector <String16> packages;
+    getPackagesForUid(uid, packages);
     if (isServiceUid(uid)) {
-        Vector <String16> packages;
-        getPackagesForUid(uid, packages);
         if (packages.isEmpty()) {
             ALOGD("OpPlayAudio: not muting track:%d usage:%d for service UID %d",
                   id,
@@ -410,12 +411,32 @@
             id, attr.flags);
         return nullptr;
     }
-    return new OpPlayAudioMonitor(uid, attr.usage, id);
+
+    String16 opPackageNameStr(opPackageName.c_str());
+    if (opPackageName.empty()) {
+        // If no package name is provided by the client, use the first associated with the uid
+        if (!packages.isEmpty()) {
+            opPackageNameStr = packages[0];
+        }
+    } else {
+        // If the provided package name is invalid, we force app ops denial by clearing the package
+        // name passed to OpPlayAudioMonitor
+        if (std::find_if(packages.begin(), packages.end(),
+                [&opPackageNameStr](const auto& package) {
+                return opPackageNameStr == package; }) == packages.end()) {
+            ALOGW("The package name(%s) provided does not correspond to the uid %d, "
+                  "force muting the track", opPackageName.c_str(), uid);
+            // Set package name as an empty string so that hasOpPlayAudio will always return false.
+            opPackageNameStr = String16("");
+        }
+    }
+    return new OpPlayAudioMonitor(uid, attr.usage, id, opPackageNameStr);
 }
 
 AudioFlinger::PlaybackThread::OpPlayAudioMonitor::OpPlayAudioMonitor(
-        uid_t uid, audio_usage_t usage, int id)
-        : mHasOpPlayAudio(true), mUid(uid), mUsage((int32_t) usage), mId(id)
+        uid_t uid, audio_usage_t usage, int id, const String16& opPackageName)
+        : mHasOpPlayAudio(true), mUid(uid), mUsage((int32_t) usage), mId(id),
+          mOpPackageName(opPackageName)
 {
 }
 
@@ -429,11 +450,10 @@
 
 void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::onFirstRef()
 {
-    getPackagesForUid(mUid, mPackages);
     checkPlayAudioForUsage();
-    if (!mPackages.isEmpty()) {
+    if (mOpPackageName.size() != 0) {
         mOpCallback = new PlayAudioOpCallback(this);
-        mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackages[0], mOpCallback);
+        mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mOpPackageName, mOpCallback);
     }
 }
 
@@ -446,18 +466,11 @@
 // - not called from PlayAudioOpCallback because the callback is not installed in this case
 void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::checkPlayAudioForUsage()
 {
-    if (mPackages.isEmpty()) {
+    if (mOpPackageName.size() == 0) {
         mHasOpPlayAudio.store(false);
     } else {
-        bool hasIt = true;
-        for (const String16& packageName : mPackages) {
-            const int32_t mode = mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO,
-                    mUsage, mUid, packageName);
-            if (mode != AppOpsManager::MODE_ALLOWED) {
-                hasIt = false;
-                break;
-            }
-        }
+        bool hasIt = mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO,
+                    mUsage, mUid, mOpPackageName) == AppOpsManager::MODE_ALLOWED;
         ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasIt ? "not " : "");
         mHasOpPlayAudio.store(hasIt);
     }
@@ -511,7 +524,8 @@
             audio_output_flags_t flags,
             track_type type,
             audio_port_handle_t portId,
-            size_t frameCountToBeReady)
+            size_t frameCountToBeReady,
+            const std::string opPackageName)
     :   TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
                   // TODO: Using unsecurePointer() has some associated security pitfalls
                   //       (see declaration for details).
@@ -534,7 +548,8 @@
     mPresentationCompleteFrames(0),
     mFrameMap(16 /* sink-frame-to-track-frame map memory */),
     mVolumeHandler(new media::VolumeHandler(sampleRate)),
-    mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(uid, attr, id(), streamType)),
+    mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(
+            uid, attr, id(), streamType, opPackageName)),
     // mSinkTimestamp
     mFrameCountToBeReady(frameCountToBeReady),
     mFastIndex(-1),
@@ -598,7 +613,7 @@
     if (channelMask & AUDIO_CHANNEL_HAPTIC_ALL) {
         mAudioVibrationController = new AudioVibrationController(this);
         mExternalVibration = new os::ExternalVibration(
-                mUid, "" /* pkg */, mAttr, mAudioVibrationController);
+                mUid, opPackageName, mAttr, mAudioVibrationController);
     }
 
     // Once this item is logged by the server, the client can add properties.
@@ -2207,7 +2222,8 @@
         RecordThread *recordThread = (RecordThread *)thread.get();
         return recordThread->start(this, event, triggerSession);
     } else {
-        return BAD_VALUE;
+        ALOGW("%s track %d: thread was destroyed", __func__, portId());
+        return DEAD_OBJECT;
     }
 }
 
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index 981582e..1821140 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -136,7 +136,7 @@
     {"rerouting",
      {
          {"", AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
-          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}}
+          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VIRTUAL_SOURCE, AUDIO_SOURCE_DEFAULT, 0, ""}}
          }
      },
     },
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c5c13e9..a592dea 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2256,7 +2256,7 @@
     sp<AudioInputDescriptor> inputDesc = mInputs.getInputForClient(portId);
     if (inputDesc == 0) {
         ALOGW("%s no input for client %d", __FUNCTION__, portId);
-        return BAD_VALUE;
+        return DEAD_OBJECT;
     }
     audio_io_handle_t input = inputDesc->mIoHandle;
     sp<RecordClientDescriptor> client = inputDesc->getClient(portId);
@@ -3161,6 +3161,8 @@
     if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
         DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, true /*fromCache*/);
         waitMs = updateCallRouting(newDevices, delayMs);
+        // Only apply special touch sound delay once
+        delayMs = 0;
     }
     for (size_t i = 0; i < mOutputs.size(); i++) {
         sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
@@ -3170,6 +3172,8 @@
             // preventing the force re-routing in case of default dev that distinguishes on address.
             // Let's give back to engine full device choice decision however.
             waitMs = setOutputDevices(outputDesc, newDevices, !newDevices.isEmpty(), delayMs);
+            // Only apply special touch sound delay once
+            delayMs = 0;
         }
         if (forceVolumeReeval && !newDevices.isEmpty()) {
             applyStreamVolumes(outputDesc, newDevices.types(), waitMs, true);
@@ -5648,7 +5652,7 @@
             sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
             setVolumeSourceMute(ttsVolumeSource, mute/*on*/, desc, 0 /*delay*/, DeviceTypeSet());
             const uint32_t latency = desc->latency() * 2;
-            if (latency > maxLatency) {
+            if (desc->isActive(latency * 2) && latency > maxLatency) {
                 maxLatency = latency;
             }
         }
@@ -6143,9 +6147,8 @@
 
     float volumeDb = computeVolume(curves, volumeSource, index, deviceTypes);
     if (outputDesc->isFixedVolume(deviceTypes) ||
-            // Force VoIP volume to max for bluetooth SCO
-
-            ((isVoiceVolSrc || isBtScoVolSrc) &&
+            // Force VoIP volume to max for bluetooth SCO device except if muted
+            (index != 0 && (isVoiceVolSrc || isBtScoVolSrc) &&
                     isSingleDeviceType(deviceTypes, audio_is_bluetooth_out_sco_device))) {
         volumeDb = 0.0f;
     }
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 1ec0c5e..b738633 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -121,8 +121,8 @@
         Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
         for (size_t i = 0; i < effects.size(); i++) {
             EffectDesc *effect = effects[i];
-            sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, -1, 0,
-                                                 0, audioSession, input);
+            sp<AudioEffect> fx = new AudioEffect(String16("android"));
+            fx->set(NULL, &effect->mUuid, -1, 0, 0, audioSession, input);
             status_t status = fx->initCheck();
             if (status != NO_ERROR && status != ALREADY_EXISTS) {
                 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
@@ -270,8 +270,8 @@
         Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
         for (size_t i = 0; i < effects.size(); i++) {
             EffectDesc *effect = effects[i];
-            sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, 0, 0, 0,
-                                                 audioSession, output);
+            sp<AudioEffect> fx = new AudioEffect(String16("android"));
+            fx->set(NULL, &effect->mUuid, 0, 0, 0, audioSession, output);
             status_t status = fx->initCheck();
             if (status != NO_ERROR && status != ALREADY_EXISTS) {
                 ALOGE("addOutputSessionEffects(): failed to create Fx  %s on session %d",
@@ -970,11 +970,11 @@
     for (const auto& deviceEffectsIter : mDeviceEffects) {
         const auto& deviceEffects =  deviceEffectsIter.second;
         for (const auto& effectDesc : deviceEffects->mEffectDescriptors->mEffects) {
-            auto fx = std::make_unique<AudioEffect>(
-                        EFFECT_UUID_NULL, String16("android"), &effectDesc->mUuid, 0, nullptr,
-                        nullptr, AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
-                        AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
-                                            deviceEffects->getDeviceAddress()});
+            auto fx = std::make_unique<AudioEffect>(String16("android"));
+            fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0, nullptr,
+                    nullptr, AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
+                    AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
+                                        deviceEffects->getDeviceAddress()});
             status_t status = fx->initCheck();
             if (status != NO_ERROR && status != ALREADY_EXISTS) {
                 ALOGE("%s(): failed to create Fx %s on port type=%d address=%s", __func__,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 34d07b6..df27f6e 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -572,7 +572,8 @@
     }
 
     // check calling permissions
-    if (!(startRecording(client->opPackageName, client->pid, client->uid)
+    if (!(startRecording(client->opPackageName, client->pid, client->uid,
+            client->attributes.source == AUDIO_SOURCE_HOTWORD)
             || client->attributes.source == AUDIO_SOURCE_FM_TUNER)) {
         ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
                 __func__, client->uid, client->pid);
@@ -660,7 +661,8 @@
         client->active = false;
         client->startTimeNs = 0;
         updateUidStates_l();
-        finishRecording(client->opPackageName, client->uid);
+        finishRecording(client->opPackageName, client->uid,
+                        client->attributes.source == AUDIO_SOURCE_HOTWORD);
     }
 
     return status;
@@ -686,7 +688,8 @@
     updateUidStates_l();
 
     // finish the recording app op
-    finishRecording(client->opPackageName, client->uid);
+    finishRecording(client->opPackageName, client->uid,
+                    client->attributes.source == AUDIO_SOURCE_HOTWORD);
     AutoCallerClear acc;
     return mAudioPolicyManager->stopInput(portId);
 }
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index e847f9f..a6e8989 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -488,9 +488,9 @@
         }
 
         bool isAccessibility = mUidPolicy->isA11yUid(current->uid);
-        // Clients capturing for Accessibility services are not considered
+        // Clients capturing for Accessibility services or virtual sources are not considered
         // for top or latest active to avoid masking regular clients started before
-        if (!isAccessibility) {
+        if (!isAccessibility && !isVirtualSource(current->attributes.source)) {
             bool isAssistant = mUidPolicy->isAssistantUid(current->uid);
             bool isPrivacySensitive =
                     (current->attributes.flags & AUDIO_FLAG_CAPTURE_PRIVATE) != 0;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index af1e01d..e2fcb5a 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -252,10 +252,16 @@
     proxyBinder->pingForUserUpdate();
 }
 
-void CameraService::broadcastTorchModeStatus(const String8& cameraId, TorchModeStatus status) {
+void CameraService::broadcastTorchModeStatus(const String8& cameraId, TorchModeStatus status,
+        SystemCameraKind systemCameraKind) {
     Mutex::Autolock lock(mStatusListenerLock);
-
     for (auto& i : mListenerList) {
+        if (shouldSkipStatusUpdates(systemCameraKind, i->isVendorListener(), i->getListenerPid(),
+                i->getListenerUid())) {
+            ALOGV("Skipping torch callback for system-only camera device %s",
+                    cameraId.c_str());
+            continue;
+        }
         i->getListener()->onTorchStatusChanged(mapToInterface(status), String16{cameraId});
     }
 }
@@ -341,7 +347,7 @@
         Mutex::Autolock al(mTorchStatusMutex);
         mTorchStatusMap.add(id, TorchModeStatus::AVAILABLE_OFF);
 
-        broadcastTorchModeStatus(id, TorchModeStatus::AVAILABLE_OFF);
+        broadcastTorchModeStatus(id, TorchModeStatus::AVAILABLE_OFF, deviceKind);
     }
 
     updateCameraNumAndIds();
@@ -502,12 +508,19 @@
 
 void CameraService::onTorchStatusChanged(const String8& cameraId,
         TorchModeStatus newStatus) {
+    SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
+    status_t res = getSystemCameraKind(cameraId, &systemCameraKind);
+    if (res != OK) {
+        ALOGE("%s: Could not get system camera kind for camera id %s", __FUNCTION__,
+                cameraId.string());
+        return;
+    }
     Mutex::Autolock al(mTorchStatusMutex);
-    onTorchStatusChangedLocked(cameraId, newStatus);
+    onTorchStatusChangedLocked(cameraId, newStatus, systemCameraKind);
 }
 
 void CameraService::onTorchStatusChangedLocked(const String8& cameraId,
-        TorchModeStatus newStatus) {
+        TorchModeStatus newStatus, SystemCameraKind systemCameraKind) {
     ALOGI("%s: Torch status changed for cameraId=%s, newStatus=%d",
             __FUNCTION__, cameraId.string(), newStatus);
 
@@ -556,8 +569,7 @@
             }
         }
     }
-
-    broadcastTorchModeStatus(cameraId, newStatus);
+    broadcastTorchModeStatus(cameraId, newStatus, systemCameraKind);
 }
 
 static bool hasPermissionsForSystemCamera(int callingPid, int callingUid) {
@@ -1864,6 +1876,10 @@
     String8 id = String8(cameraId.string());
     int uid = CameraThreadState::getCallingUid();
 
+    if (shouldRejectSystemCameraConnection(id)) {
+        return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to set torch mode"
+                " for system only device %s: ", id.string());
+    }
     // verify id is valid.
     auto state = getCameraState(id);
     if (state == nullptr) {
@@ -2220,6 +2236,11 @@
                     return shouldSkipStatusUpdates(deviceKind, isVendorListener, clientPid,
                             clientUid);}), cameraStatuses->end());
 
+    //cameraStatuses will have non-eligible camera ids removed.
+    std::set<String16> idsChosenForCallback;
+    for (const auto &s : *cameraStatuses) {
+        idsChosenForCallback.insert(String16(s.cameraId));
+    }
 
     /*
      * Immediately signal current torch status to this listener only
@@ -2229,7 +2250,11 @@
         Mutex::Autolock al(mTorchStatusMutex);
         for (size_t i = 0; i < mTorchStatusMap.size(); i++ ) {
             String16 id = String16(mTorchStatusMap.keyAt(i).string());
-            listener->onTorchStatusChanged(mapToInterface(mTorchStatusMap.valueAt(i)), id);
+            // The camera id is visible to the client. Fine to send torch
+            // callback.
+            if (idsChosenForCallback.find(id) != idsChosenForCallback.end()) {
+                listener->onTorchStatusChanged(mapToInterface(mTorchStatusMap.valueAt(i)), id);
+            }
         }
     }
 
@@ -3751,9 +3776,14 @@
                 __FUNCTION__, cameraId.string());
         return;
     }
+
+    // Collect the logical cameras without holding mStatusLock in updateStatus
+    // as that can lead to a deadlock(b/162192331).
+    auto logicalCameraIds = getLogicalCameras(cameraId);
     // Update the status for this camera state, then send the onStatusChangedCallbacks to each
     // of the listeners with both the mStatusLock and mStatusListenerLock held
-    state->updateStatus(status, cameraId, rejectSourceStates, [this, &deviceKind, &supportsHAL3]
+    state->updateStatus(status, cameraId, rejectSourceStates, [this, &deviceKind, &supportsHAL3,
+                        &logicalCameraIds]
             (const String8& cameraId, StatusInternal status) {
 
             if (status != StatusInternal::ENUMERATING) {
@@ -3767,14 +3797,14 @@
                             TorchModeStatus::AVAILABLE_OFF :
                             TorchModeStatus::NOT_AVAILABLE;
                     if (torchStatus != newTorchStatus) {
-                        onTorchStatusChangedLocked(cameraId, newTorchStatus);
+                        onTorchStatusChangedLocked(cameraId, newTorchStatus, deviceKind);
                     }
                 }
             }
 
             Mutex::Autolock lock(mStatusListenerLock);
-
-            notifyPhysicalCameraStatusLocked(mapToInterface(status), cameraId, deviceKind);
+            notifyPhysicalCameraStatusLocked(mapToInterface(status), String16(cameraId),
+                    logicalCameraIds, deviceKind);
 
             for (auto& listener : mListenerList) {
                 bool isVendorListener = listener->isVendorListener();
@@ -3892,8 +3922,9 @@
     return OK;
 }
 
-void CameraService::notifyPhysicalCameraStatusLocked(int32_t status, const String8& cameraId,
-        SystemCameraKind deviceKind) {
+std::list<String16> CameraService::getLogicalCameras(
+        const String8& physicalCameraId) {
+    std::list<String16> retList;
     Mutex::Autolock lock(mCameraStatesLock);
     for (const auto& state : mCameraStates) {
         std::vector<std::string> physicalCameraIds;
@@ -3901,26 +3932,39 @@
             // This is not a logical multi-camera.
             continue;
         }
-        if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(), cameraId.c_str())
+        if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(), physicalCameraId.c_str())
                 == physicalCameraIds.end()) {
             // cameraId is not a physical camera of this logical multi-camera.
             continue;
         }
 
-        String16 id16(state.first), physicalId16(cameraId);
+        retList.emplace_back(String16(state.first));
+    }
+    return retList;
+}
+
+void CameraService::notifyPhysicalCameraStatusLocked(int32_t status,
+        const String16& physicalCameraId, const std::list<String16>& logicalCameraIds,
+        SystemCameraKind deviceKind) {
+    // mStatusListenerLock is expected to be locked
+    for (const auto& logicalCameraId : logicalCameraIds) {
         for (auto& listener : mListenerList) {
+            // Note: we check only the deviceKind of the physical camera id
+            // since, logical camera ids and their physical camera ids are
+            // guaranteed to have the same system camera kind.
             if (shouldSkipStatusUpdates(deviceKind, listener->isVendorListener(),
                     listener->getListenerPid(), listener->getListenerUid())) {
                 ALOGV("Skipping discovery callback for system-only camera device %s",
-                        cameraId.c_str());
+                        String8(physicalCameraId).c_str());
                 continue;
             }
             listener->getListener()->onPhysicalCameraStatusChanged(status,
-                    id16, physicalId16);
+                    logicalCameraId, physicalCameraId);
         }
     }
 }
 
+
 void CameraService::blockClientsForUid(uid_t uid) {
     const auto clients = mActiveClientManager.getAll();
     for (auto& current : clients) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 4321201..5c4c96b 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -49,6 +49,7 @@
 
 #include <set>
 #include <string>
+#include <list>
 #include <map>
 #include <memory>
 #include <utility>
@@ -994,7 +995,8 @@
     // handle torch mode status change and invoke callbacks. mTorchStatusMutex
     // should be locked.
     void onTorchStatusChangedLocked(const String8& cameraId,
-            hardware::camera::common::V1_0::TorchModeStatus newStatus);
+            hardware::camera::common::V1_0::TorchModeStatus newStatus,
+            SystemCameraKind systemCameraKind);
 
     // get a camera's torch status. mTorchStatusMutex should be locked.
     status_t getTorchStatusLocked(const String8 &cameraId,
@@ -1005,8 +1007,13 @@
             hardware::camera::common::V1_0::TorchModeStatus status);
 
     // notify physical camera status when the physical camera is public.
-    void notifyPhysicalCameraStatusLocked(int32_t status, const String8& cameraId,
-            SystemCameraKind deviceKind);
+    // Expects mStatusListenerLock to be locked.
+    void notifyPhysicalCameraStatusLocked(int32_t status, const String16& physicalCameraId,
+            const std::list<String16>& logicalCameraIds, SystemCameraKind deviceKind);
+
+    // get list of logical cameras which are backed by physicalCameraId
+    std::list<String16> getLogicalCameras(const String8& physicalCameraId);
+
 
     // IBinder::DeathRecipient implementation
     virtual void        binderDied(const wp<IBinder> &who);
@@ -1078,7 +1085,8 @@
     static void pingCameraServiceProxy();
 
     void broadcastTorchModeStatus(const String8& cameraId,
-            hardware::camera::common::V1_0::TorchModeStatus status);
+            hardware::camera::common::V1_0::TorchModeStatus status,
+            SystemCameraKind systemCameraKind);
 
     void disconnectClient(const String8& id, sp<BasicClient> clientToDisconnect);
 
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index a63f402..2462fd5 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -65,7 +65,6 @@
         mYuvBufferAcquired(false),
         mProducerListener(new ProducerListener()),
         mDequeuedOutputBufferCnt(0),
-        mLockedAppSegmentBufferCnt(0),
         mCodecOutputCounter(0),
         mQuality(-1),
         mGridTimestampUs(0),
@@ -634,7 +633,6 @@
             mAppSegmentConsumer->unlockBuffer(imgBuffer);
         } else {
             mPendingInputFrames[frameNumber].appSegmentBuffer = imgBuffer;
-            mLockedAppSegmentBufferCnt++;
         }
         mInputAppSegmentBuffers.erase(it);
         mAppSegmentFrameNumbers.pop();
@@ -897,10 +895,6 @@
                         strerror(-res), res);
                 return res;
             }
-        } else if (mLockedAppSegmentBufferCnt == kMaxAcquiredAppSegment) {
-            ALOGE("%s: Out-of-order app segment buffers reaches limit %u", __FUNCTION__,
-                    kMaxAcquiredAppSegment);
-            return INVALID_OPERATION;
         }
     }
 
@@ -1038,7 +1032,6 @@
     mAppSegmentConsumer->unlockBuffer(inputFrame.appSegmentBuffer);
     inputFrame.appSegmentBuffer.data = nullptr;
     inputFrame.exifError = false;
-    mLockedAppSegmentBufferCnt--;
 
     return OK;
 }
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.h b/services/camera/libcameraservice/api2/HeicCompositeStream.h
index 33ca69a..a373127 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.h
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.h
@@ -253,7 +253,6 @@
 
     // Keep all incoming APP segment Blob buffer pending further processing.
     std::vector<int64_t> mInputAppSegmentBuffers;
-    int32_t           mLockedAppSegmentBufferCnt;
 
     // Keep all incoming HEIC blob buffer pending further processing.
     std::vector<CodecOutputBufferInfo> mCodecOutputBuffers;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 32d118d..876d70d 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -1344,6 +1344,20 @@
         }
     }
 
+    // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
+    // before setCallback returns
+    hardware::Return<Status> status = interface->setCallback(this);
+    if (!status.isOk()) {
+        ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
+                __FUNCTION__, mProviderName.c_str(), status.description().c_str());
+        return DEAD_OBJECT;
+    }
+    if (status != Status::OK) {
+        ALOGE("%s: Unable to register callbacks with camera provider '%s'",
+                __FUNCTION__, mProviderName.c_str());
+        return mapToStatusT(status);
+    }
+
     hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
     if (!linked.isOk()) {
         ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
@@ -1372,7 +1386,6 @@
         return res;
     }
 
-    Status status;
     // Get initial list of camera devices, if any
     std::vector<std::string> devices;
     hardware::Return<void> ret = interface->getCameraIdList([&status, this, &devices](
@@ -1437,26 +1450,43 @@
         }
     }
 
-    // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
-    // before setCallback returns. setCallback must be called after addDevice so that
-    // the physical camera status callback can look up available regular
-    // cameras.
-    hardware::Return<Status> st = interface->setCallback(this);
-    if (!st.isOk()) {
-        ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
-                __FUNCTION__, mProviderName.c_str(), st.description().c_str());
-        return DEAD_OBJECT;
-    }
-    if (st != Status::OK) {
-        ALOGE("%s: Unable to register callbacks with camera provider '%s'",
-                __FUNCTION__, mProviderName.c_str());
-        return mapToStatusT(st);
-    }
-
     ALOGI("Camera provider %s ready with %zu camera devices",
             mProviderName.c_str(), mDevices.size());
 
-    mInitialized = true;
+    // Process cached status callbacks
+    std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus =
+            std::make_unique<std::vector<CameraStatusInfoT>>();
+    {
+        std::lock_guard<std::mutex> lock(mInitLock);
+
+        for (auto& statusInfo : mCachedStatus) {
+            std::string id, physicalId;
+            status_t res = OK;
+            if (statusInfo.isPhysicalCameraStatus) {
+                res = physicalCameraDeviceStatusChangeLocked(&id, &physicalId,
+                    statusInfo.cameraId, statusInfo.physicalCameraId, statusInfo.status);
+            } else {
+                res = cameraDeviceStatusChangeLocked(&id, statusInfo.cameraId, statusInfo.status);
+            }
+            if (res == OK) {
+                cachedStatus->emplace_back(statusInfo.isPhysicalCameraStatus,
+                        id.c_str(), physicalId.c_str(), statusInfo.status);
+            }
+        }
+        mCachedStatus.clear();
+
+        mInitialized = true;
+    }
+
+    // The cached status change callbacks cannot be fired directly from this
+    // function, due to same-thread deadlock trying to acquire mInterfaceMutex
+    // twice.
+    if (listener != nullptr) {
+        mInitialStatusCallbackFuture = std::async(std::launch::async,
+                &CameraProviderManager::ProviderInfo::notifyInitialStatusChange, this,
+                listener, std::move(cachedStatus));
+    }
+
     return OK;
 }
 
@@ -1734,104 +1764,139 @@
         CameraDeviceStatus newStatus) {
     sp<StatusListener> listener;
     std::string id;
-    bool initialized = false;
+    std::lock_guard<std::mutex> lock(mInitLock);
+
+    if (!mInitialized) {
+        mCachedStatus.emplace_back(false /*isPhysicalCameraStatus*/,
+                cameraDeviceName.c_str(), std::string().c_str(), newStatus);
+        return hardware::Void();
+    }
+
     {
         std::lock_guard<std::mutex> lock(mLock);
-        bool known = false;
-        for (auto& deviceInfo : mDevices) {
-            if (deviceInfo->mName == cameraDeviceName) {
-                ALOGI("Camera device %s status is now %s, was %s", cameraDeviceName.c_str(),
-                        deviceStatusToString(newStatus), deviceStatusToString(deviceInfo->mStatus));
-                deviceInfo->mStatus = newStatus;
-                // TODO: Handle device removal (NOT_PRESENT)
-                id = deviceInfo->mId;
-                known = true;
-                break;
-            }
-        }
-        // Previously unseen device; status must not be NOT_PRESENT
-        if (!known) {
-            if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
-                ALOGW("Camera provider %s says an unknown camera device %s is not present. Curious.",
-                    mProviderName.c_str(), cameraDeviceName.c_str());
-                return hardware::Void();
-            }
-            addDevice(cameraDeviceName, newStatus, &id);
-        } else if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
-            removeDevice(id);
+        if (OK != cameraDeviceStatusChangeLocked(&id, cameraDeviceName, newStatus)) {
+            return hardware::Void();
         }
         listener = mManager->getStatusListener();
-        initialized = mInitialized;
-        if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
-            ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
-                      __FUNCTION__, mProviderName.c_str());
-        }
     }
+
     // Call without lock held to allow reentrancy into provider manager
-    // Don't send the callback if providerInfo hasn't been initialized.
-    // CameraService will initialize device status after provider is
-    // initialized
-    if (listener != nullptr && initialized) {
+    if (listener != nullptr) {
         listener->onDeviceStatusChanged(String8(id.c_str()), newStatus);
     }
+
     return hardware::Void();
 }
 
+status_t CameraProviderManager::ProviderInfo::cameraDeviceStatusChangeLocked(
+        std::string* id, const hardware::hidl_string& cameraDeviceName,
+        CameraDeviceStatus newStatus) {
+    bool known = false;
+    std::string cameraId;
+    for (auto& deviceInfo : mDevices) {
+        if (deviceInfo->mName == cameraDeviceName) {
+            ALOGI("Camera device %s status is now %s, was %s", cameraDeviceName.c_str(),
+                    deviceStatusToString(newStatus), deviceStatusToString(deviceInfo->mStatus));
+            deviceInfo->mStatus = newStatus;
+            // TODO: Handle device removal (NOT_PRESENT)
+            cameraId = deviceInfo->mId;
+            known = true;
+            break;
+        }
+    }
+    // Previously unseen device; status must not be NOT_PRESENT
+    if (!known) {
+        if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
+            ALOGW("Camera provider %s says an unknown camera device %s is not present. Curious.",
+                mProviderName.c_str(), cameraDeviceName.c_str());
+            return BAD_VALUE;
+        }
+        addDevice(cameraDeviceName, newStatus, &cameraId);
+    } else if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
+        removeDevice(cameraId);
+    }
+    if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
+        ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
+                  __FUNCTION__, mProviderName.c_str());
+    }
+    *id = cameraId;
+    return OK;
+}
+
 hardware::Return<void> CameraProviderManager::ProviderInfo::physicalCameraDeviceStatusChange(
         const hardware::hidl_string& cameraDeviceName,
         const hardware::hidl_string& physicalCameraDeviceName,
         CameraDeviceStatus newStatus) {
     sp<StatusListener> listener;
     std::string id;
-    bool initialized = false;
+    std::string physicalId;
+    std::lock_guard<std::mutex> lock(mInitLock);
+
+    if (!mInitialized) {
+        mCachedStatus.emplace_back(true /*isPhysicalCameraStatus*/, cameraDeviceName,
+                physicalCameraDeviceName, newStatus);
+        return hardware::Void();
+    }
+
     {
         std::lock_guard<std::mutex> lock(mLock);
-        bool known = false;
-        for (auto& deviceInfo : mDevices) {
-            if (deviceInfo->mName == cameraDeviceName) {
-                id = deviceInfo->mId;
 
-                if (!deviceInfo->mIsLogicalCamera) {
-                    ALOGE("%s: Invalid combination of camera id %s, physical id %s",
-                            __FUNCTION__, id.c_str(), physicalCameraDeviceName.c_str());
-                    return hardware::Void();
-                }
-                if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
-                        physicalCameraDeviceName) == deviceInfo->mPhysicalIds.end()) {
-                    ALOGE("%s: Invalid combination of camera id %s, physical id %s",
-                            __FUNCTION__, id.c_str(), physicalCameraDeviceName.c_str());
-                    return hardware::Void();
-                }
-                ALOGI("Camera device %s physical device %s status is now %s, was %s",
-                        cameraDeviceName.c_str(), physicalCameraDeviceName.c_str(),
-                        deviceStatusToString(newStatus), deviceStatusToString(
-                        deviceInfo->mPhysicalStatus[physicalCameraDeviceName]));
-                known = true;
-                break;
-            }
-        }
-        // Previously unseen device; status must not be NOT_PRESENT
-        if (!known) {
-            ALOGW("Camera provider %s says an unknown camera device %s-%s is not present. Curious.",
-                    mProviderName.c_str(), cameraDeviceName.c_str(),
-                    physicalCameraDeviceName.c_str());
+        if (OK != physicalCameraDeviceStatusChangeLocked(&id, &physicalId, cameraDeviceName,
+                physicalCameraDeviceName, newStatus)) {
             return hardware::Void();
         }
+
         listener = mManager->getStatusListener();
-        initialized = mInitialized;
     }
     // Call without lock held to allow reentrancy into provider manager
-    // Don't send the callback if providerInfo hasn't been initialized.
-    // CameraService will initialize device status after provider is
-    // initialized
-    if (listener != nullptr && initialized) {
-        String8 physicalId(physicalCameraDeviceName.c_str());
+    if (listener != nullptr) {
         listener->onDeviceStatusChanged(String8(id.c_str()),
-                physicalId, newStatus);
+                String8(physicalId.c_str()), newStatus);
     }
     return hardware::Void();
 }
 
+status_t CameraProviderManager::ProviderInfo::physicalCameraDeviceStatusChangeLocked(
+            std::string* id, std::string* physicalId,
+            const hardware::hidl_string& cameraDeviceName,
+            const hardware::hidl_string& physicalCameraDeviceName,
+            CameraDeviceStatus newStatus) {
+    bool known = false;
+    std::string cameraId;
+    for (auto& deviceInfo : mDevices) {
+        if (deviceInfo->mName == cameraDeviceName) {
+            cameraId = deviceInfo->mId;
+            if (!deviceInfo->mIsLogicalCamera) {
+                ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+                        __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
+                return BAD_VALUE;
+            }
+            if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
+                    physicalCameraDeviceName) == deviceInfo->mPhysicalIds.end()) {
+                ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+                        __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
+                return BAD_VALUE;
+            }
+            ALOGI("Camera device %s physical device %s status is now %s",
+                    cameraDeviceName.c_str(), physicalCameraDeviceName.c_str(),
+                    deviceStatusToString(newStatus));
+            known = true;
+            break;
+        }
+    }
+    // Previously unseen device; status must not be NOT_PRESENT
+    if (!known) {
+        ALOGW("Camera provider %s says an unknown camera device %s-%s is not present. Curious.",
+                mProviderName.c_str(), cameraDeviceName.c_str(),
+                physicalCameraDeviceName.c_str());
+        return BAD_VALUE;
+    }
+
+    *id = cameraId;
+    *physicalId = physicalCameraDeviceName.c_str();
+    return OK;
+}
+
 hardware::Return<void> CameraProviderManager::ProviderInfo::torchModeStatusChange(
         const hardware::hidl_string& cameraDeviceName,
         TorchModeStatus newStatus) {
@@ -1986,6 +2051,20 @@
     return INVALID_OPERATION;
 }
 
+void CameraProviderManager::ProviderInfo::notifyInitialStatusChange(
+        sp<StatusListener> listener,
+        std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus) {
+    for (auto& statusInfo : *cachedStatus) {
+        if (statusInfo.isPhysicalCameraStatus) {
+            listener->onDeviceStatusChanged(String8(statusInfo.cameraId.c_str()),
+                    String8(statusInfo.physicalCameraId.c_str()), statusInfo.status);
+        } else {
+            listener->onDeviceStatusChanged(
+                    String8(statusInfo.cameraId.c_str()), statusInfo.status);
+        }
+    }
+}
+
 template<class DeviceInfoT>
 std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
     CameraProviderManager::ProviderInfo::initializeDeviceInfo(
@@ -2689,9 +2768,11 @@
 
 
 CameraProviderManager::ProviderInfo::~ProviderInfo() {
+    if (mInitialStatusCallbackFuture.valid()) {
+        mInitialStatusCallbackFuture.wait();
+    }
     // Destruction of ProviderInfo is only supposed to happen when the respective
     // CameraProvider interface dies, so do not unregister callbacks.
-
 }
 
 status_t CameraProviderManager::mapToStatusT(const Status& s)  {
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 25d3639..a0e5f8f 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -22,6 +22,7 @@
 #include <unordered_set>
 #include <string>
 #include <mutex>
+#include <future>
 
 #include <camera/camera2/ConcurrentCamera.h>
 #include <camera/CameraParameters2.h>
@@ -403,6 +404,15 @@
                 const hardware::hidl_string& physicalCameraDeviceName,
                 hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
 
+        status_t cameraDeviceStatusChangeLocked(
+                std::string* id, const hardware::hidl_string& cameraDeviceName,
+                hardware::camera::common::V1_0::CameraDeviceStatus newStatus);
+        status_t physicalCameraDeviceStatusChangeLocked(
+                std::string* id, std::string* physicalId,
+                const hardware::hidl_string& cameraDeviceName,
+                const hardware::hidl_string& physicalCameraDeviceName,
+                hardware::camera::common::V1_0::CameraDeviceStatus newStatus);
+
         // hidl_death_recipient interface - this locks the parent mInterfaceMutex
         virtual void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override;
 
@@ -444,8 +454,6 @@
             const hardware::camera::common::V1_0::CameraResourceCost mResourceCost;
 
             hardware::camera::common::V1_0::CameraDeviceStatus mStatus;
-            std::map<std::string, hardware::camera::common::V1_0::CameraDeviceStatus>
-                    mPhysicalStatus;
 
             wp<ProviderInfo> mParentProvider;
 
@@ -600,7 +608,27 @@
 
         CameraProviderManager *mManager;
 
+        struct CameraStatusInfoT {
+            bool isPhysicalCameraStatus = false;
+            hardware::hidl_string cameraId;
+            hardware::hidl_string physicalCameraId;
+            hardware::camera::common::V1_0::CameraDeviceStatus status;
+            CameraStatusInfoT(bool isForPhysicalCamera, const hardware::hidl_string& id,
+                    const hardware::hidl_string& physicalId,
+                    hardware::camera::common::V1_0::CameraDeviceStatus s) :
+                    isPhysicalCameraStatus(isForPhysicalCamera), cameraId(id),
+                    physicalCameraId(physicalId), status(s) {}
+        };
+
+        // Lock to synchronize between initialize() and camera status callbacks
+        std::mutex mInitLock;
         bool mInitialized = false;
+        std::vector<CameraStatusInfoT> mCachedStatus;
+        // End of scope for mInitLock
+
+        std::future<void> mInitialStatusCallbackFuture;
+        void notifyInitialStatusChange(sp<StatusListener> listener,
+                std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus);
 
         std::vector<std::unordered_set<std::string>> mConcurrentCameraIdCombinations;
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 4a509aa..d5f136b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1833,10 +1833,12 @@
 
     mStatusWaiters++;
 
+    bool signalPipelineDrain = false;
     if (!active && mUseHalBufManager) {
         auto streamIds = mOutputStreams.getStreamIds();
         if (mStatus == STATUS_ACTIVE) {
             mRequestThread->signalPipelineDrain(streamIds);
+            signalPipelineDrain = true;
         }
         mRequestBufferSM.onWaitUntilIdle();
     }
@@ -1866,6 +1868,10 @@
         }
     } while (!stateSeen);
 
+    if (signalPipelineDrain) {
+        mRequestThread->resetPipelineDrain();
+    }
+
     mStatusWaiters--;
 
     return res;
@@ -2306,6 +2312,15 @@
         newRequest->mRotateAndCropAuto = false;
     }
 
+    auto zoomRatioEntry =
+            newRequest->mSettingsList.begin()->metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
+    if (zoomRatioEntry.count > 0 &&
+            zoomRatioEntry.data.f[0] == 1.0f) {
+        newRequest->mZoomRatioIs1x = true;
+    } else {
+        newRequest->mZoomRatioIs1x = false;
+    }
+
     return newRequest;
 }
 
@@ -4426,13 +4441,17 @@
                                 parent->mDistortionMappers.end()) {
                             continue;
                         }
-                        res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
-                            &(it->metadata));
-                        if (res != OK) {
-                            SET_ERR("RequestThread: Unable to correct capture requests "
-                                    "for lens distortion for request %d: %s (%d)",
-                                    halRequest->frame_number, strerror(-res), res);
-                            return INVALID_OPERATION;
+
+                        if (!captureRequest->mDistortionCorrectionUpdated) {
+                            res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
+                                    &(it->metadata));
+                            if (res != OK) {
+                                SET_ERR("RequestThread: Unable to correct capture requests "
+                                        "for lens distortion for request %d: %s (%d)",
+                                        halRequest->frame_number, strerror(-res), res);
+                                return INVALID_OPERATION;
+                            }
+                            captureRequest->mDistortionCorrectionUpdated = true;
                         }
                     }
 
@@ -4443,21 +4462,24 @@
                             continue;
                         }
 
-                        camera_metadata_entry_t e = it->metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
-                        if (e.count > 0 && e.data.f[0] != 1.0f) {
+                        if (!captureRequest->mZoomRatioIs1x) {
                             cameraIdsWithZoom.insert(it->cameraId);
                         }
 
-                        res = parent->mZoomRatioMappers[it->cameraId].updateCaptureRequest(
-                            &(it->metadata));
-                        if (res != OK) {
-                            SET_ERR("RequestThread: Unable to correct capture requests "
-                                    "for zoom ratio for request %d: %s (%d)",
-                                    halRequest->frame_number, strerror(-res), res);
-                            return INVALID_OPERATION;
+                        if (!captureRequest->mZoomRatioUpdated) {
+                            res = parent->mZoomRatioMappers[it->cameraId].updateCaptureRequest(
+                                    &(it->metadata));
+                            if (res != OK) {
+                                SET_ERR("RequestThread: Unable to correct capture requests "
+                                        "for zoom ratio for request %d: %s (%d)",
+                                        halRequest->frame_number, strerror(-res), res);
+                                return INVALID_OPERATION;
+                            }
+                            captureRequest->mZoomRatioUpdated = true;
                         }
                     }
-                    if (captureRequest->mRotateAndCropAuto) {
+                    if (captureRequest->mRotateAndCropAuto &&
+                            !captureRequest->mRotationAndCropUpdated) {
                         for (it = captureRequest->mSettingsList.begin();
                                 it != captureRequest->mSettingsList.end(); it++) {
                             auto mapper = parent->mRotateAndCropMappers.find(it->cameraId);
@@ -4471,6 +4493,7 @@
                                 }
                             }
                         }
+                        captureRequest->mRotationAndCropUpdated = true;
                     }
                 }
             }
@@ -4785,6 +4808,12 @@
     mStreamIdsToBeDrained = streamIds;
 }
 
+void Camera3Device::RequestThread::resetPipelineDrain() {
+    Mutex::Autolock pl(mPauseLock);
+    mNotifyPipelineDrain = false;
+    mStreamIdsToBeDrained.clear();
+}
+
 void Camera3Device::RequestThread::clearPreviousRequest() {
     Mutex::Autolock l(mRequestLock);
     mPrevRequest.clear();
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 408f1f9..e10da2c 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -517,6 +517,19 @@
         // overriding of ROTATE_AND_CROP value and adjustment of coordinates
         // in several other controls in both the request and the result
         bool                                mRotateAndCropAuto;
+        // Whether this capture request has its zoom ratio set to 1.0x before
+        // the framework overrides it for camera HAL consumption.
+        bool                                mZoomRatioIs1x;
+
+
+        // Whether this capture request's distortion correction update has
+        // been done.
+        bool                                mDistortionCorrectionUpdated = false;
+        // Whether this capture request's rotation and crop update has been
+        // done.
+        bool                                mRotationAndCropUpdated = false;
+        // Whether this capture request's zoom ratio update has been done.
+        bool                                mZoomRatioUpdated = false;
     };
     typedef List<sp<CaptureRequest> > RequestList;
 
@@ -832,6 +845,7 @@
         }
 
         void signalPipelineDrain(const std::vector<int>& streamIds);
+        void resetPipelineDrain();
 
         status_t switchToOffline(
                 const std::vector<int32_t>& streamsToKeep,
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index eea5ef1..08cde5d 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -1218,13 +1218,13 @@
             return;
         }
 
+        bufRet.streamId = streamId;
         if (outputStream->isAbandoned()) {
             bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
             allReqsSucceeds = false;
             continue;
         }
 
-        bufRet.streamId = streamId;
         size_t handOutBufferCount = outputStream->getOutstandingBuffersCount();
         uint32_t numBuffersRequested = bufReq.numBuffersRequested;
         size_t totalHandout = handOutBufferCount + numBuffersRequested;
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
index a87de77..4e98bf6 100644
--- a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
@@ -153,6 +153,19 @@
     entry = request->find(ANDROID_CONTROL_ZOOM_RATIO);
     if (entry.count == 1 && entry.data.f[0] != 1.0f) {
         zoomRatioIs1 = false;
+
+        // If cropRegion is windowboxing, override it with activeArray
+        camera_metadata_entry_t cropRegionEntry = request->find(ANDROID_SCALER_CROP_REGION);
+        if (cropRegionEntry.count == 4) {
+            int cropWidth = cropRegionEntry.data.i32[2];
+            int cropHeight = cropRegionEntry.data.i32[3];
+            if (cropWidth < mArrayWidth && cropHeight < mArrayHeight) {
+                cropRegionEntry.data.i32[0] = 0;
+                cropRegionEntry.data.i32[1] = 0;
+                cropRegionEntry.data.i32[2] = mArrayWidth;
+                cropRegionEntry.data.i32[3] = mArrayHeight;
+            }
+        }
     }
 
     if (mHalSupportsZoomRatio && zoomRatioIs1) {
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
index f033d5c..91590e1 100644
--- a/services/mediametrics/Android.bp
+++ b/services/mediametrics/Android.bp
@@ -131,6 +131,7 @@
         "statsd_codec.cpp",
         "statsd_drm.cpp",
         "statsd_extractor.cpp",
+        "statsd_mediaparser.cpp",
         "statsd_nuplayer.cpp",
         "statsd_recorder.cpp",
         "StringUtils.cpp"
diff --git a/services/mediametrics/AudioPowerUsage.cpp b/services/mediametrics/AudioPowerUsage.cpp
index cca6b41..33dfa8fa 100644
--- a/services/mediametrics/AudioPowerUsage.cpp
+++ b/services/mediametrics/AudioPowerUsage.cpp
@@ -200,6 +200,34 @@
     return true;
 }
 
+bool AudioPowerUsage::saveAsItems_l(
+        int32_t device, int64_t duration_ns, int32_t type, double average_vol)
+{
+    ALOGV("%s: (%#x, %d, %lld, %f)", __func__, device, type,
+                                   (long long)duration_ns, average_vol );
+    if (duration_ns == 0) {
+        return true; // skip duration 0 usage
+    }
+    if (device == 0) {
+        return true; //ignore unknown device
+    }
+
+    bool ret = false;
+    const int32_t input_bit = device & INPUT_DEVICE_BIT;
+    int32_t device_bits = device ^ input_bit;
+
+    while (device_bits != 0) {
+        int32_t tmp_device = device_bits & -device_bits; // get lowest bit
+        device_bits ^= tmp_device;  // clear lowest bit
+        tmp_device |= input_bit;    // restore input bit
+        ret = saveAsItem_l(tmp_device, duration_ns, type, average_vol);
+
+        ALOGV("%s: device %#x recorded, remaining device_bits = %#x", __func__,
+            tmp_device, device_bits);
+    }
+    return ret;
+}
+
 void AudioPowerUsage::checkTrackRecord(
         const std::shared_ptr<const mediametrics::Item>& item, bool isTrack)
 {
@@ -245,7 +273,7 @@
         ALOGV("device = %s => %d", device_strings.c_str(), device);
     }
     std::lock_guard l(mLock);
-    saveAsItem_l(device, deviceTimeNs, type, deviceVolume);
+    saveAsItems_l(device, deviceTimeNs, type, deviceVolume);
 }
 
 void AudioPowerUsage::checkMode(const std::shared_ptr<const mediametrics::Item>& item)
@@ -262,7 +290,7 @@
         if (durationNs > 0) {
             mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
                     mVoiceVolume * double(endCallNs - mVolumeTimeNs)) / durationNs;
-            saveAsItem_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume);
+            saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume);
         }
     } else if (mode == "AUDIO_MODE_IN_CALL") { // entering call mode
         mStartCallNs = item->getTimestamp(); // advisory only
@@ -321,7 +349,7 @@
         if (durationNs > 0) {
             mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
                     mVoiceVolume * double(endDeviceNs - mVolumeTimeNs)) / durationNs;
-            saveAsItem_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume);
+            saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume);
         }
         // reset statistics
         mDeviceVolume = 0;
diff --git a/services/mediametrics/AudioPowerUsage.h b/services/mediametrics/AudioPowerUsage.h
index 446ff4f..b705a6a 100644
--- a/services/mediametrics/AudioPowerUsage.h
+++ b/services/mediametrics/AudioPowerUsage.h
@@ -85,6 +85,8 @@
          REQUIRES(mLock);
     static void sendItem(const std::shared_ptr<const mediametrics::Item>& item);
     void collect();
+    bool saveAsItems_l(int32_t device, int64_t duration, int32_t type, double average_vol)
+         REQUIRES(mLock);
 
     AudioAnalytics * const mAudioAnalytics;
     const bool mDisabled;
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index 48e766e..bf6e428 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -468,6 +468,7 @@
                                      "codec",
                                      "extractor",
                                      "mediadrm",
+                                     "mediaparser",
                                      "nuplayer",
                                  }) {
         if (key == allowedKey) {
diff --git a/services/mediametrics/iface_statsd.cpp b/services/mediametrics/iface_statsd.cpp
index 6e51f72..16204de 100644
--- a/services/mediametrics/iface_statsd.cpp
+++ b/services/mediametrics/iface_statsd.cpp
@@ -64,6 +64,7 @@
     { "drmmanager", statsd_drmmanager },
     { "extractor", statsd_extractor },
     { "mediadrm", statsd_mediadrm },
+    { "mediaparser", statsd_mediaparser },
     { "nuplayer", statsd_nuplayer },
     { "nuplayer2", statsd_nuplayer },
     { "recorder", statsd_recorder },
diff --git a/services/mediametrics/iface_statsd.h b/services/mediametrics/iface_statsd.h
index 19505a4..9b49556 100644
--- a/services/mediametrics/iface_statsd.h
+++ b/services/mediametrics/iface_statsd.h
@@ -25,6 +25,7 @@
 extern bool statsd_audiotrack(const mediametrics::Item *);
 extern bool statsd_codec(const mediametrics::Item *);
 extern bool statsd_extractor(const mediametrics::Item *);
+extern bool statsd_mediaparser(const mediametrics::Item *);
 extern bool statsd_nuplayer(const mediametrics::Item *);
 extern bool statsd_recorder(const mediametrics::Item *);
 
diff --git a/services/mediametrics/statsd_extractor.cpp b/services/mediametrics/statsd_extractor.cpp
index 3d5739f..fb0924c 100644
--- a/services/mediametrics/statsd_extractor.cpp
+++ b/services/mediametrics/statsd_extractor.cpp
@@ -71,6 +71,22 @@
         metrics_proto.set_tracks(ntrk);
     }
 
+    // android.media.mediaextractor.entry       string
+    std::string entry_point_string;
+    if (item->getString("android.media.mediaextractor.entry", &entry_point_string)) {
+      stats::mediametrics::ExtractorData::EntryPoint entry_point;
+      if (entry_point_string == "sdk") {
+        entry_point = stats::mediametrics::ExtractorData_EntryPoint_SDK;
+      } else if (entry_point_string == "ndk-with-jvm") {
+        entry_point = stats::mediametrics::ExtractorData_EntryPoint_NDK_WITH_JVM;
+      } else if (entry_point_string == "ndk-no-jvm") {
+        entry_point = stats::mediametrics::ExtractorData_EntryPoint_NDK_NO_JVM;
+      } else {
+        entry_point = stats::mediametrics::ExtractorData_EntryPoint_OTHER;
+      }
+      metrics_proto.set_entry_point(entry_point);
+    }
+
     std::string serialized;
     if (!metrics_proto.SerializeToString(&serialized)) {
         ALOGE("Failed to serialize extractor metrics");
diff --git a/services/mediametrics/statsd_mediaparser.cpp b/services/mediametrics/statsd_mediaparser.cpp
new file mode 100644
index 0000000..3258ebf
--- /dev/null
+++ b/services/mediametrics/statsd_mediaparser.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "statsd_mediaparser"
+#include <utils/Log.h>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <statslog.h>
+
+#include "MediaMetricsService.h"
+#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
+#include "iface_statsd.h"
+
+namespace android {
+
+bool statsd_mediaparser(const mediametrics::Item *item)
+{
+    if (item == nullptr) {
+        return false;
+    }
+
+    // statsd wrapper data.
+    const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+    std::string pkgName = item->getPkgName();
+    int64_t pkgVersionCode = item->getPkgVersionCode();
+
+    std::string parserName;
+    item->getString("android.media.mediaparser.parserName", &parserName);
+
+    int32_t createdByName = -1;
+    item->getInt32("android.media.mediaparser.createdByName", &createdByName);
+
+    std::string parserPool;
+    item->getString("android.media.mediaparser.parserPool", &parserPool);
+
+    std::string lastException;
+    item->getString("android.media.mediaparser.lastException", &lastException);
+
+    int64_t resourceByteCount = -1;
+    item->getInt64("android.media.mediaparser.resourceByteCount", &resourceByteCount);
+
+    int64_t durationMillis = -1;
+    item->getInt64("android.media.mediaparser.durationMillis", &durationMillis);
+
+    std::string trackMimeTypes;
+    item->getString("android.media.mediaparser.trackMimeTypes", &trackMimeTypes);
+
+    std::string trackCodecs;
+    item->getString("android.media.mediaparser.trackCodecs", &trackCodecs);
+
+    std::string alteredParameters;
+    item->getString("android.media.mediaparser.alteredParameters", &alteredParameters);
+
+    int32_t videoWidth = -1;
+    item->getInt32("android.media.mediaparser.videoWidth", &videoWidth);
+
+    int32_t videoHeight = -1;
+    item->getInt32("android.media.mediaparser.videoHeight", &videoHeight);
+
+    if (enabled_statsd) {
+        (void) android::util::stats_write(android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED,
+                                   timestamp,
+                                   pkgName.c_str(),
+                                   pkgVersionCode,
+                                   parserName.c_str(),
+                                   createdByName,
+                                   parserPool.c_str(),
+                                   lastException.c_str(),
+                                   resourceByteCount,
+                                   durationMillis,
+                                   trackMimeTypes.c_str(),
+                                   trackCodecs.c_str(),
+                                   alteredParameters.c_str(),
+                                   videoWidth,
+                                   videoHeight);
+    } else {
+        ALOGV("NOT sending MediaParser media metrics.");
+    }
+
+    return true;
+}
+
+} // namespace android
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 3d36f8e..db06a36 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -575,13 +575,19 @@
         }
     }
 
+    *_aidl_return = reclaimInternal(clients);
+    return Status::ok();
+}
+
+bool ResourceManagerService::reclaimInternal(
+        const Vector<std::shared_ptr<IResourceManagerClient>> &clients) {
     if (clients.size() == 0) {
-        return Status::ok();
+        return false;
     }
 
     std::shared_ptr<IResourceManagerClient> failedClient;
     for (size_t i = 0; i < clients.size(); ++i) {
-        log = String8::format("reclaimResource from client %p", clients[i].get());
+        String8 log = String8::format("reclaimResource from client %p", clients[i].get());
         mServiceLog->add(log);
         bool success;
         Status status = clients[i]->reclaimResource(&success);
@@ -592,8 +598,7 @@
     }
 
     if (failedClient == NULL) {
-        *_aidl_return = true;
-        return Status::ok();
+        return true;
     }
 
     {
@@ -618,7 +623,7 @@
         }
     }
 
-    return Status::ok();
+    return false;
 }
 
 Status ResourceManagerService::overridePid(
@@ -681,6 +686,36 @@
     return Status::ok();
 }
 
+Status ResourceManagerService::reclaimResourcesFromClientsPendingRemoval(int32_t pid) {
+    String8 log = String8::format("reclaimResourcesFromClientsPendingRemoval(pid %d)", pid);
+    mServiceLog->add(log);
+
+    Vector<std::shared_ptr<IResourceManagerClient>> clients;
+    {
+        Mutex::Autolock lock(mLock);
+        if (!mProcessInfo->isValidPid(pid)) {
+            ALOGE("Rejected reclaimResourcesFromClientsPendingRemoval call with invalid pid.");
+            return Status::fromServiceSpecificError(BAD_VALUE);
+        }
+
+        for (MediaResource::Type type : {MediaResource::Type::kSecureCodec,
+                                         MediaResource::Type::kNonSecureCodec,
+                                         MediaResource::Type::kGraphicMemory,
+                                         MediaResource::Type::kDrmSession}) {
+            std::shared_ptr<IResourceManagerClient> client;
+            if (getBiggestClient_l(pid, type, &client, true /* pendingRemovalOnly */)) {
+                clients.add(client);
+                break;
+            }
+        }
+    }
+
+    if (!clients.empty()) {
+        reclaimInternal(clients);
+    }
+    return Status::ok();
+}
+
 bool ResourceManagerService::getPriority_l(int pid, int* priority) {
     int newPid = pid;
 
@@ -804,7 +839,8 @@
         bool pendingRemovalOnly) {
     ssize_t index = mMap.indexOfKey(pid);
     if (index < 0) {
-        ALOGE("getBiggestClient_l: can't find resource info for pid %d", pid);
+        ALOGE_IF(!pendingRemovalOnly,
+                 "getBiggestClient_l: can't find resource info for pid %d", pid);
         return false;
     }
 
@@ -828,7 +864,9 @@
     }
 
     if (clientTemp == NULL) {
-        ALOGE("getBiggestClient_l: can't find resource type %s for pid %d", asString(type), pid);
+        ALOGE_IF(!pendingRemovalOnly,
+                 "getBiggestClient_l: can't find resource type %s for pid %d",
+                 asString(type), pid);
         return false;
     }
 
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index ee982b7..3972d23 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -127,11 +127,18 @@
 
     Status markClientForPendingRemoval(int32_t pid, int64_t clientId) override;
 
+    Status reclaimResourcesFromClientsPendingRemoval(int32_t pid) override;
+
     Status removeResource(int pid, int64_t clientId, bool checkValid);
 
 private:
     friend class ResourceManagerServiceTest;
 
+    // Reclaims resources from |clients|. Returns true if reclaim succeeded
+    // for all clients.
+    bool reclaimInternal(
+            const Vector<std::shared_ptr<IResourceManagerClient>> &clients);
+
     // Gets the list of all the clients who own the specified resource type.
     // Returns false if any client belongs to a process with higher priority than the
     // calling process. The clients will remain unchanged if returns false.
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index 702935d..a6ecc09 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -520,6 +520,30 @@
             // clean up client 3 which still left
             mService->removeClient(kTestPid2, getId(mTestClient3));
         }
+
+        {
+            addResource();
+            mService->mSupportsSecureWithNonSecureCodec = true;
+
+            mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
+
+            // client marked for pending removal got reclaimed
+            EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
+            verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
+
+            // No more clients marked for removal
+            EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
+            verifyClients(false /* c1 */, false /* c2 */, false /* c3 */);
+
+            mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient3));
+
+            // client marked for pending removal got reclaimed
+            EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
+            verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
+
+            // clean up client 1 which still left
+            mService->removeClient(kTestPid1, getId(mTestClient1));
+        }
     }
 
     void testRemoveClient() {
diff --git a/services/oboeservice/AAudioServiceEndpoint.h b/services/oboeservice/AAudioServiceEndpoint.h
index a171cb0..04b906a 100644
--- a/services/oboeservice/AAudioServiceEndpoint.h
+++ b/services/oboeservice/AAudioServiceEndpoint.h
@@ -47,7 +47,11 @@
 
     virtual aaudio_result_t open(const aaudio::AAudioStreamRequest &request) = 0;
 
-    virtual aaudio_result_t close() = 0;
+    /*
+     * Perform any cleanup necessary before deleting the stream.
+     * This might include releasing and closing internal streams.
+     */
+    virtual void close() = 0;
 
     aaudio_result_t registerStream(android::sp<AAudioServiceStreamBase> stream);
 
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.cpp b/services/oboeservice/AAudioServiceEndpointCapture.cpp
index 37d105b..3ba3c28 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.cpp
+++ b/services/oboeservice/AAudioServiceEndpointCapture.cpp
@@ -36,18 +36,18 @@
 using namespace aaudio;   // TODO just import names needed
 
 AAudioServiceEndpointCapture::AAudioServiceEndpointCapture(AAudioService &audioService)
-        : mStreamInternalCapture(audioService, true) {
-    mStreamInternal = &mStreamInternalCapture;
+    : AAudioServiceEndpointShared(
+            (AudioStreamInternal *)(new AudioStreamInternalCapture(audioService, true))) {
 }
 
 AAudioServiceEndpointCapture::~AAudioServiceEndpointCapture() {
-    delete mDistributionBuffer;
+    delete[] mDistributionBuffer;
 }
 
 aaudio_result_t AAudioServiceEndpointCapture::open(const aaudio::AAudioStreamRequest &request) {
     aaudio_result_t result = AAudioServiceEndpointShared::open(request);
     if (result == AAUDIO_OK) {
-        delete mDistributionBuffer;
+        delete[] mDistributionBuffer;
         int distributionBufferSizeBytes = getStreamInternal()->getFramesPerBurst()
                                           * getStreamInternal()->getBytesPerFrame();
         mDistributionBuffer = new uint8_t[distributionBufferSizeBytes];
@@ -69,7 +69,9 @@
         // Read audio data from stream using a blocking read.
         result = getStreamInternal()->read(mDistributionBuffer, getFramesPerBurst(), timeoutNanos);
         if (result == AAUDIO_ERROR_DISCONNECTED) {
-            disconnectRegisteredStreams();
+            ALOGD("%s() read() returned AAUDIO_ERROR_DISCONNECTED", __func__);
+            // We do not need the returned vector.
+            (void) AAudioServiceEndpointShared::disconnectRegisteredStreams();
             break;
         } else if (result != getFramesPerBurst()) {
             ALOGW("callbackLoop() read %d / %d",
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.h b/services/oboeservice/AAudioServiceEndpointCapture.h
index 971da9a..2bbe81d 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.h
+++ b/services/oboeservice/AAudioServiceEndpointCapture.h
@@ -36,8 +36,7 @@
     void *callbackLoop() override;
 
 private:
-    AudioStreamInternalCapture  mStreamInternalCapture;
-    uint8_t                    *mDistributionBuffer = nullptr;
+    uint8_t        *mDistributionBuffer = nullptr;
 };
 
 } /* namespace aaudio */
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 0843e0b..04c6453 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -226,7 +226,7 @@
     return result;
 }
 
-aaudio_result_t AAudioServiceEndpointMMAP::close() {
+void AAudioServiceEndpointMMAP::close() {
     if (mMmapStream != nullptr) {
         // Needs to be explicitly cleared or CTS will fail but it is not clear why.
         mMmapStream.clear();
@@ -235,8 +235,6 @@
         // FIXME Make closing synchronous.
         AudioClock::sleepForNanos(100 * AAUDIO_NANOS_PER_MILLISECOND);
     }
-
-    return AAUDIO_OK;
 }
 
 aaudio_result_t AAudioServiceEndpointMMAP::startStream(sp<AAudioServiceStreamBase> stream,
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.h b/services/oboeservice/AAudioServiceEndpointMMAP.h
index 3d10861..b6003b6 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.h
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.h
@@ -50,7 +50,7 @@
 
     aaudio_result_t open(const aaudio::AAudioStreamRequest &request) override;
 
-    aaudio_result_t close() override;
+    void close() override;
 
     aaudio_result_t startStream(android::sp<AAudioServiceStreamBase> stream,
                                 audio_port_handle_t *clientHandle) override;
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index bda4b90..89aa70d 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -42,8 +42,8 @@
 #define BURSTS_PER_BUFFER_DEFAULT   2
 
 AAudioServiceEndpointPlay::AAudioServiceEndpointPlay(AAudioService &audioService)
-        : mStreamInternalPlay(audioService, true) {
-    mStreamInternal = &mStreamInternalPlay;
+    : AAudioServiceEndpointShared(
+        (AudioStreamInternal *)(new AudioStreamInternalPlay(audioService, true))) {
 }
 
 aaudio_result_t AAudioServiceEndpointPlay::open(const aaudio::AAudioStreamRequest &request) {
@@ -145,7 +145,9 @@
         result = getStreamInternal()->write(mMixer.getOutputBuffer(),
                                             getFramesPerBurst(), timeoutNanos);
         if (result == AAUDIO_ERROR_DISCONNECTED) {
-            AAudioServiceEndpointShared::disconnectRegisteredStreams();
+            ALOGD("%s() write() returned AAUDIO_ERROR_DISCONNECTED", __func__);
+            // We do not need the returned vector.
+            (void) AAudioServiceEndpointShared::disconnectRegisteredStreams();
             break;
         } else if (result != getFramesPerBurst()) {
             ALOGW("callbackLoop() wrote %d / %d",
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.h b/services/oboeservice/AAudioServiceEndpointPlay.h
index 981e430..160a1de 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.h
+++ b/services/oboeservice/AAudioServiceEndpointPlay.h
@@ -45,7 +45,6 @@
     void *callbackLoop() override;
 
 private:
-    AudioStreamInternalPlay  mStreamInternalPlay; // for playing output of mixer
     bool                     mLatencyTuningEnabled = false; // TODO implement tuning
     AAudioMixer              mMixer;    //
 };
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index dc21886..f5de59f 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -40,6 +40,9 @@
 // This is the maximum size in frames. The effective size can be tuned smaller at runtime.
 #define DEFAULT_BUFFER_CAPACITY   (48 * 8)
 
+AAudioServiceEndpointShared::AAudioServiceEndpointShared(AudioStreamInternal *streamInternal)
+    : mStreamInternal(streamInternal) {}
+
 std::string AAudioServiceEndpointShared::dump() const {
     std::stringstream result;
 
@@ -84,8 +87,8 @@
     return result;
 }
 
-aaudio_result_t AAudioServiceEndpointShared::close() {
-    return getStreamInternal()->releaseCloseFinal();
+void AAudioServiceEndpointShared::close() {
+    getStreamInternal()->releaseCloseFinal();
 }
 
 // Glue between C and C++ callbacks.
diff --git a/services/oboeservice/AAudioServiceEndpointShared.h b/services/oboeservice/AAudioServiceEndpointShared.h
index bfc1744..020b926 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.h
+++ b/services/oboeservice/AAudioServiceEndpointShared.h
@@ -35,12 +35,13 @@
 class AAudioServiceEndpointShared : public AAudioServiceEndpoint {
 
 public:
+    explicit AAudioServiceEndpointShared(AudioStreamInternal *streamInternal);
 
     std::string dump() const override;
 
     aaudio_result_t open(const aaudio::AAudioStreamRequest &request) override;
 
-    aaudio_result_t close() override;
+    void close() override;
 
     aaudio_result_t startStream(android::sp<AAudioServiceStreamBase> stream,
                                 audio_port_handle_t *clientHandle) override;
@@ -57,15 +58,15 @@
 protected:
 
     AudioStreamInternal *getStreamInternal() const {
-        return mStreamInternal;
+        return mStreamInternal.get();
     };
 
     aaudio_result_t          startSharingThread_l();
 
     aaudio_result_t          stopSharingThread();
 
-    // pointer to object statically allocated in subclasses
-    AudioStreamInternal     *mStreamInternal = nullptr;
+    // An MMAP stream that is shared by multiple clients.
+    android::sp<AudioStreamInternal> mStreamInternal;
 
     std::atomic<bool>        mCallbackEnabled{false};