Merge "Add fade manager aconfig to media audio" into main
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index 2e808d1..424923a 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -880,7 +880,7 @@
     return OK;
 }
 
-metadata_vendor_id_t CameraMetadata::getVendorId() {
+metadata_vendor_id_t CameraMetadata::getVendorId() const {
     return get_camera_metadata_vendor_id(mBuffer);
 }
 
diff --git a/camera/VendorTagDescriptor.cpp b/camera/VendorTagDescriptor.cpp
index fb26f83..c12a1a1 100644
--- a/camera/VendorTagDescriptor.cpp
+++ b/camera/VendorTagDescriptor.cpp
@@ -466,7 +466,7 @@
 
 int VendorTagDescriptorCache::getTagType(uint32_t tag,
         metadata_vendor_id_t id) const {
-    int ret = 0;
+    int ret = -1;
     auto desc = mVendorMap.find(id);
     if (desc != mVendorMap.end()) {
         ret = desc->second->getTagType(tag);
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index cef38d6..5d2a263 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -69,3 +69,10 @@
      description: "An AE mode that enables increased brightening in low light scenes"
      bug: "312803148"
 }
+
+flag {
+     namespace: "camera_platform"
+     name: "multiresolution_imagereader_usage_config"
+     description: "Enable creating MultiResolutionImageReader with usage flag configuration"
+     bug: "301588215"
+}
diff --git a/camera/include/camera/CameraMetadata.h b/camera/include/camera/CameraMetadata.h
index c56ee6d..2903dfb 100644
--- a/camera/include/camera/CameraMetadata.h
+++ b/camera/include/camera/CameraMetadata.h
@@ -245,7 +245,7 @@
     /**
      * Return the current vendor tag id associated with this metadata.
      */
-    metadata_vendor_id_t getVendorId();
+    metadata_vendor_id_t getVendorId() const;
 
   private:
     camera_metadata_t *mBuffer;
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 86b9e99..2c68cef 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -4658,8 +4658,8 @@
      * <p>The guaranteed stream combinations related to stream use case for a camera device with
      * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE">CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE</a>
      * capability is documented in the camera device
-     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#stream-use-case-capability-additional-guaranteed-configurations">guideline</a>. The application is strongly recommended to use one of the guaranteed stream
-     * combinations.
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#stream-use-case-capability-additional-guaranteed-configurations">guideline</a>.
+     * The application is strongly recommended to use one of the guaranteed stream combinations.
      * If the application creates a session with a stream combination not in the guaranteed
      * list, or with mixed DEFAULT and non-DEFAULT use cases within the same session,
      * the camera device may ignore some stream use cases due to hardware constraints
@@ -10175,8 +10175,8 @@
      * </ul>
      * <p><a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#SCALER_AVAILABLE_STREAM_USE_CASES">CameraCharacteristics#SCALER_AVAILABLE_STREAM_USE_CASES</a>
      * lists all of the supported stream use cases.</p>
-     * <p>Refer to
-     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#stream-use-case-capability-additional-guaranteed-configurations">CameraDevice#stream-use-case-capability-additional-guaranteed-configurations</a>
+     * <p>Refer to the
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#stream-use-case-capability-additional-guaranteed-configurations">guideline</a>
      * for the mandatory stream combinations involving stream use cases, which can also be
      * queried via <a href="https://developer.android.com/reference/android/hardware/camera2/params/MandatoryStreamCombination.html">MandatoryStreamCombination</a>.</p>
      */
@@ -11037,9 +11037,9 @@
     /**
      * <p>This camera device does not have enough capabilities to qualify as a <code>FULL</code> device or
      * better.</p>
-     * <p>Only the stream configurations listed in the <code>LEGACY</code> and <code>LIMITED</code> tables in the
-     * {@link ACameraDevice_createCaptureSession }
-     * documentation are guaranteed to be supported.</p>
+     * <p>Only the stream configurations listed in the <code>LEGACY</code> and <code>LIMITED</code>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#limited-level-additional-guaranteed-configurations">tables</a>
+     * in the documentation are guaranteed to be supported.</p>
      * <p>All <code>LIMITED</code> devices support the <code>BACKWARDS_COMPATIBLE</code> capability, indicating basic
      * support for color image capture. The only exception is that the device may
      * alternatively support only the <code>DEPTH_OUTPUT</code> capability, if it can only output depth
@@ -11064,9 +11064,9 @@
 
     /**
      * <p>This camera device is capable of supporting advanced imaging applications.</p>
-     * <p>The stream configurations listed in the <code>FULL</code>, <code>LEGACY</code> and <code>LIMITED</code> tables in the
-     * {@link ACameraDevice_createCaptureSession }
-     * documentation are guaranteed to be supported.</p>
+     * <p>The stream configurations listed in the <code>FULL</code>, <code>LEGACY</code> and <code>LIMITED</code>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#full-level-additional-guaranteed-configurations">tables</a>
+     * in the documentation are guaranteed to be supported.</p>
      * <p>A <code>FULL</code> device will support below capabilities:</p>
      * <ul>
      * <li><code>BURST_CAPTURE</code> capability (ACAMERA_REQUEST_AVAILABLE_CAPABILITIES contains
@@ -11093,9 +11093,9 @@
 
     /**
      * <p>This camera device is running in backward compatibility mode.</p>
-     * <p>Only the stream configurations listed in the <code>LEGACY</code> table in the
-     * {@link ACameraDevice_createCaptureSession }
-     * documentation are supported.</p>
+     * <p>Only the stream configurations listed in the <code>LEGACY</code>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#legacy-level-guaranteed-configurations">table</a>
+     * in the documentation are supported.</p>
      * <p>A <code>LEGACY</code> device does not support per-frame control, manual sensor control, manual
      * post-processing, arbitrary cropping regions, and has relaxed performance constraints.
      * No additional capabilities beyond <code>BACKWARD_COMPATIBLE</code> will ever be listed by a
@@ -11117,9 +11117,9 @@
      * <p>This camera device is capable of YUV reprocessing and RAW data capture, in addition to
      * FULL-level capabilities.</p>
      * <p>The stream configurations listed in the <code>LEVEL_3</code>, <code>RAW</code>, <code>FULL</code>, <code>LEGACY</code> and
-     * <code>LIMITED</code> tables in the
-     * {@link ACameraDevice_createCaptureSession }
-     * documentation are guaranteed to be supported.</p>
+     * <code>LIMITED</code>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#level-3-additional-guaranteed-configurations">tables</a>
+     * in the documentation are guaranteed to be supported.</p>
      * <p>The following additional capabilities are guaranteed to be supported:</p>
      * <ul>
      * <li><code>YUV_REPROCESSING</code> capability (ACAMERA_REQUEST_AVAILABLE_CAPABILITIES contains
diff --git a/camera/tests/fuzzer/camera_Parameters_fuzzer.cpp b/camera/tests/fuzzer/camera_Parameters_fuzzer.cpp
index 07efc20..e59f76c 100644
--- a/camera/tests/fuzzer/camera_Parameters_fuzzer.cpp
+++ b/camera/tests/fuzzer/camera_Parameters_fuzzer.cpp
@@ -16,6 +16,7 @@
 
 #include <CameraParameters.h>
 #include <CameraParameters2.h>
+#include <camera/StringUtils.h>
 #include <fcntl.h>
 #include <fuzzer/FuzzedDataProvider.h>
 #include <utils/String16.h>
@@ -24,6 +25,8 @@
 using namespace std;
 using namespace android;
 
+constexpr int8_t kMaxBytes = 20;
+
 string kValidFormats[] = {
         CameraParameters::PIXEL_FORMAT_YUV422SP,      CameraParameters::PIXEL_FORMAT_YUV420SP,
         CameraParameters::PIXEL_FORMAT_YUV422I,       CameraParameters::PIXEL_FORMAT_YUV420P,
@@ -34,26 +37,22 @@
 class CameraParametersFuzzer {
   public:
     void process(const uint8_t* data, size_t size);
-    ~CameraParametersFuzzer() {
-        delete mCameraParameters;
-        delete mCameraParameters2;
-    }
 
   private:
     void invokeCameraParameters();
     template <class type>
-    void initCameraParameters(type** obj);
+    void initCameraParameters(unique_ptr<type>& obj);
     template <class type>
-    void cameraParametersCommon(type* obj);
-    CameraParameters* mCameraParameters = nullptr;
-    CameraParameters2* mCameraParameters2 = nullptr;
+    void callCameraParametersAPIs(unique_ptr<type>& obj);
+    unique_ptr<CameraParameters> mCameraParameters;
+    unique_ptr<CameraParameters2> mCameraParameters2;
     FuzzedDataProvider* mFDP = nullptr;
 };
 
 template <class type>
-void CameraParametersFuzzer::initCameraParameters(type** obj) {
+void CameraParametersFuzzer::initCameraParameters(unique_ptr<type>& obj) {
     if (mFDP->ConsumeBool()) {
-        *obj = new type();
+        obj = make_unique<type>();
     } else {
         string params;
         if (mFDP->ConsumeBool()) {
@@ -61,94 +60,176 @@
             int32_t height = mFDP->ConsumeIntegral<int32_t>();
             int32_t minFps = mFDP->ConsumeIntegral<int32_t>();
             int32_t maxFps = mFDP->ConsumeIntegral<int32_t>();
-            params = CameraParameters::KEY_SUPPORTED_VIDEO_SIZES;
+            params = mFDP->ConsumeBool() ? mFDP->ConsumeRandomLengthString(kMaxBytes).c_str()
+                                         : CameraParameters::KEY_SUPPORTED_VIDEO_SIZES;
             params += '=' + to_string(width) + 'x' + to_string(height) + ';';
             if (mFDP->ConsumeBool()) {
-                params += CameraParameters::KEY_PREVIEW_FPS_RANGE;
+                params += mFDP->ConsumeBool() ? mFDP->ConsumeRandomLengthString(kMaxBytes).c_str()
+                                              : CameraParameters::KEY_PREVIEW_FPS_RANGE;
                 params += '=' + to_string(minFps) + ',' + to_string(maxFps) + ';';
             }
             if (mFDP->ConsumeBool()) {
-                params += CameraParameters::KEY_SUPPORTED_PICTURE_SIZES;
+                params += mFDP->ConsumeBool() ? mFDP->ConsumeRandomLengthString(kMaxBytes).c_str()
+                                              : CameraParameters::KEY_SUPPORTED_PICTURE_SIZES;
                 params += '=' + to_string(width) + 'x' + to_string(height) + ';';
             }
             if (mFDP->ConsumeBool()) {
-                params += CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS;
-                params += '=' + mFDP->PickValueInArray(kValidFormats) + ';';
+                params += mFDP->ConsumeBool() ? mFDP->ConsumeRandomLengthString(kMaxBytes).c_str()
+                                              : CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS;
+                params += '=' +
+                          (mFDP->ConsumeBool() ? mFDP->ConsumeRandomLengthString(kMaxBytes).c_str()
+                                               : mFDP->PickValueInArray(kValidFormats)) + ';';
             }
         } else {
-            params = mFDP->ConsumeRandomLengthString();
+            params = mFDP->ConsumeRandomLengthString(kMaxBytes);
         }
-        *obj = new type(toString8(params));
+        obj = make_unique<type>(toString8(params));
     }
 }
 
 template <class type>
-void CameraParametersFuzzer::cameraParametersCommon(type* obj) {
-    Vector<Size> supportedPreviewSizes;
-    obj->getSupportedPreviewSizes(supportedPreviewSizes);
-    int32_t previewWidth = mFDP->ConsumeIntegral<int32_t>();
-    int32_t previewHeight = mFDP->ConsumeIntegral<int32_t>();
-    obj->setPreviewSize(previewWidth, previewHeight);
-    obj->getPreviewSize(&previewWidth, &previewHeight);
-
+void CameraParametersFuzzer::callCameraParametersAPIs(unique_ptr<type>& obj) {
     Vector<Size> supportedVideoSizes;
-    obj->getSupportedVideoSizes(supportedVideoSizes);
-    if (supportedVideoSizes.size() != 0) {
-        int32_t videoWidth, videoHeight, preferredVideoWidth, preferredVideoHeight;
-        if (mFDP->ConsumeBool()) {
-            int32_t idx = mFDP->ConsumeIntegralInRange<int32_t>(0, supportedVideoSizes.size() - 1);
-            obj->setVideoSize(supportedVideoSizes[idx].width, supportedVideoSizes[idx].height);
-        } else {
-            videoWidth = mFDP->ConsumeIntegral<int32_t>();
-            videoHeight = mFDP->ConsumeIntegral<int32_t>();
-            obj->setVideoSize(videoWidth, videoHeight);
-        }
-        obj->getVideoSize(&videoWidth, &videoHeight);
-        obj->getPreferredPreviewSizeForVideo(&preferredVideoWidth, &preferredVideoHeight);
-    }
-
-    int32_t fps = mFDP->ConsumeIntegral<int32_t>();
-    obj->setPreviewFrameRate(fps);
-    obj->getPreviewFrameRate();
-    string previewFormat = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidFormats)
-                                               : mFDP->ConsumeRandomLengthString();
-    obj->setPreviewFormat(previewFormat.c_str());
-
-    int32_t pictureWidth = mFDP->ConsumeIntegral<int32_t>();
-    int32_t pictureHeight = mFDP->ConsumeIntegral<int32_t>();
-    Vector<Size> supportedPictureSizes;
-    obj->setPictureSize(pictureWidth, pictureHeight);
-    obj->getPictureSize(&pictureWidth, &pictureHeight);
-    obj->getSupportedPictureSizes(supportedPictureSizes);
-    string pictureFormat = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidFormats)
-                                               : mFDP->ConsumeRandomLengthString();
-    obj->setPictureFormat(pictureFormat.c_str());
-    obj->getPictureFormat();
-
-    if (mFDP->ConsumeBool()) {
-        obj->dump();
-    } else {
-        int32_t fd = open("/dev/null", O_CLOEXEC | O_RDWR | O_CREAT);
-        Vector<String16> args = {};
-        obj->dump(fd, args);
-        close(fd);
+    while (mFDP->remaining_bytes()) {
+        auto callCameraUtilsAPIs = mFDP->PickValueInArray<const std::function<void()>>({
+                [&]() {
+                    Vector<Size> supportedPreviewSizes;
+                    obj->getSupportedPreviewSizes(supportedPreviewSizes);
+                },
+                [&]() {
+                    int32_t previewWidth = mFDP->ConsumeIntegral<int32_t>();
+                    int32_t previewHeight = mFDP->ConsumeIntegral<int32_t>();
+                    obj->setPreviewSize(previewWidth, previewHeight);
+                },
+                [&]() {
+                    int32_t previewWidth, previewHeight;
+                    obj->getPreviewSize(&previewWidth, &previewHeight);
+                },
+                [&]() { obj->getSupportedVideoSizes(supportedVideoSizes); },
+                [&]() {
+                    int32_t videoWidth, videoHeight;
+                    if (supportedVideoSizes.size()) {
+                        int32_t idx = mFDP->ConsumeIntegralInRange<int32_t>(
+                                0, supportedVideoSizes.size() - 1);
+                        videoWidth = mFDP->ConsumeBool() ? supportedVideoSizes[idx].width
+                                                         : mFDP->ConsumeIntegral<int32_t>();
+                        videoHeight = mFDP->ConsumeBool() ? supportedVideoSizes[idx].height
+                                                          : mFDP->ConsumeIntegral<int32_t>();
+                        obj->setVideoSize(videoWidth, videoHeight);
+                    }
+                },
+                [&]() {
+                    int32_t videoWidth, videoHeight;
+                    obj->getVideoSize(&videoWidth, &videoHeight);
+                },
+                [&]() {
+                    int32_t preferredVideoWidth, preferredVideoHeight;
+                    obj->getPreferredPreviewSizeForVideo(&preferredVideoWidth,
+                                                         &preferredVideoHeight);
+                },
+                [&]() {
+                    int32_t fps = mFDP->ConsumeIntegral<int32_t>();
+                    obj->setPreviewFrameRate(fps);
+                },
+                [&]() { obj->getPreviewFrameRate(); },
+                [&]() {
+                    string previewFormat = mFDP->ConsumeBool()
+                                                   ? mFDP->PickValueInArray(kValidFormats)
+                                                   : mFDP->ConsumeRandomLengthString(kMaxBytes);
+                    obj->setPreviewFormat(previewFormat.c_str());
+                },
+                [&]() {
+                    int32_t pictureWidth = mFDP->ConsumeIntegral<int32_t>();
+                    int32_t pictureHeight = mFDP->ConsumeIntegral<int32_t>();
+                    obj->setPictureSize(pictureWidth, pictureHeight);
+                },
+                [&]() {
+                    int32_t pictureWidth, pictureHeight;
+                    obj->getPictureSize(&pictureWidth, &pictureHeight);
+                },
+                [&]() {
+                    Vector<Size> supportedPictureSizes;
+                    obj->getSupportedPictureSizes(supportedPictureSizes);
+                },
+                [&]() {
+                    string pictureFormat = mFDP->ConsumeBool()
+                                                   ? mFDP->PickValueInArray(kValidFormats)
+                                                   : mFDP->ConsumeRandomLengthString(kMaxBytes);
+                    obj->setPictureFormat(pictureFormat.c_str());
+                },
+                [&]() { obj->getPictureFormat(); },
+                [&]() {
+                    if (mFDP->ConsumeBool()) {
+                        obj->dump();
+                    } else {
+                        int32_t fd = open("/dev/null", O_CLOEXEC | O_RDWR | O_CREAT);
+                        Vector<String16> args = {};
+                        obj->dump(fd, args);
+                        close(fd);
+                    }
+                },
+                [&]() { obj->flatten(); },
+                [&]() {
+                    string key = mFDP->ConsumeRandomLengthString(kMaxBytes);
+                    float value = mFDP->ConsumeFloatingPoint<float>();
+                    obj->setFloat(key.c_str(), value);
+                },
+                [&]() {
+                    string key = mFDP->ConsumeRandomLengthString(kMaxBytes);
+                    obj->getFloat(key.c_str());
+                },
+                [&]() { obj->getPreviewFormat(); },
+                [&]() {
+                    string key = mFDP->ConsumeRandomLengthString(kMaxBytes);
+                    obj->remove(key.c_str());
+                },
+                [&]() {
+                    if (std::is_same_v<type, CameraParameters>) {
+                        string format = mFDP->ConsumeBool()
+                                                ? mFDP->ConsumeRandomLengthString(kMaxBytes)
+                                                : mFDP->PickValueInArray(kValidFormats);
+                        mCameraParameters->previewFormatToEnum(format.c_str());
+                    }
+                },
+                [&]() {
+                    if (std::is_same_v<type, CameraParameters>) {
+                        mCameraParameters->isEmpty();
+                    }
+                },
+                [&]() {
+                    if (std::is_same_v<type, CameraParameters>) {
+                        Vector<int32_t> formats;
+                        mCameraParameters->getSupportedPreviewFormats(formats);
+                    }
+                },
+                [&]() {
+                    if (std::is_same_v<type, CameraParameters2>) {
+                        string key1 = mFDP->ConsumeRandomLengthString(kMaxBytes);
+                        string key2 = mFDP->ConsumeRandomLengthString(kMaxBytes);
+                        int32_t order;
+                        mCameraParameters2->compareSetOrder(key1.c_str(), key2.c_str(), &order);
+                    }
+                },
+                [&]() {
+                    if (std::is_same_v<type, CameraParameters2>) {
+                        int32_t minFps = mFDP->ConsumeIntegral<int32_t>();
+                        int32_t maxFps = mFDP->ConsumeIntegral<int32_t>();
+                        mCameraParameters2->setPreviewFpsRange(minFps, maxFps);
+                    }
+                },
+        });
+        callCameraUtilsAPIs();
     }
 }
 
 void CameraParametersFuzzer::invokeCameraParameters() {
-    initCameraParameters<CameraParameters>(&mCameraParameters);
-    cameraParametersCommon<CameraParameters>(mCameraParameters);
-    initCameraParameters<CameraParameters2>(&mCameraParameters2);
-    cameraParametersCommon<CameraParameters2>(mCameraParameters2);
-
-    int32_t minFPS, maxFPS;
-    mCameraParameters->getPreviewFpsRange(&minFPS, &maxFPS);
-    string format = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidFormats)
-                                        : mFDP->ConsumeRandomLengthString();
-    mCameraParameters->previewFormatToEnum(format.c_str());
-    mCameraParameters->isEmpty();
-    Vector<int32_t> formats;
-    mCameraParameters->getSupportedPreviewFormats(formats);
+    if (mFDP->ConsumeBool()) {
+        initCameraParameters<CameraParameters>(mCameraParameters);
+        callCameraParametersAPIs(mCameraParameters);
+    } else {
+        initCameraParameters<CameraParameters2>(mCameraParameters2);
+        callCameraParametersAPIs(mCameraParameters2);
+    }
 }
 
 void CameraParametersFuzzer::process(const uint8_t* data, size_t size) {
diff --git a/camera/tests/fuzzer/camera_c2OutputConfiguration_fuzzer.cpp b/camera/tests/fuzzer/camera_c2OutputConfiguration_fuzzer.cpp
index 2fe9a94..7046075 100644
--- a/camera/tests/fuzzer/camera_c2OutputConfiguration_fuzzer.cpp
+++ b/camera/tests/fuzzer/camera_c2OutputConfiguration_fuzzer.cpp
@@ -26,85 +26,122 @@
 using namespace android;
 using namespace android::hardware::camera2::params;
 
+constexpr int8_t kMaxLoopIterations = 100;
 constexpr int32_t kSizeMin = 0;
 constexpr int32_t kSizeMax = 1000;
 
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-    FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+class C2OutputConfigurationFuzzer {
+  public:
+    void process(const uint8_t* data, size_t size);
 
-    OutputConfiguration* outputConfiguration = nullptr;
+  private:
+    void invokeC2OutputConfigFuzzer();
+    unique_ptr<OutputConfiguration> getC2OutputConfig();
+    sp<IGraphicBufferProducer> createIGraphicBufferProducer();
+    FuzzedDataProvider* mFDP = nullptr;
+};
 
-    if (fdp.ConsumeBool()) {
-        outputConfiguration = new OutputConfiguration();
+sp<IGraphicBufferProducer> C2OutputConfigurationFuzzer::createIGraphicBufferProducer() {
+    sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
+    sp<SurfaceControl> surfaceControl = composerClient->createSurface(
+            static_cast<String8>(mFDP->ConsumeRandomLengthString(kMaxBytes).c_str()) /* name */,
+            mFDP->ConsumeIntegral<uint32_t>() /* width */,
+            mFDP->ConsumeIntegral<uint32_t>() /* height */,
+            mFDP->ConsumeIntegral<int32_t>() /* format */,
+            mFDP->ConsumeIntegral<int32_t>() /* flags */);
+    if (surfaceControl) {
+        sp<Surface> surface = surfaceControl->getSurface();
+        return surface->getIGraphicBufferProducer();
     } else {
-        int32_t rotation = fdp.ConsumeIntegral<int32_t>();
-        string physicalCameraId = fdp.ConsumeRandomLengthString();
-        int32_t surfaceSetID = fdp.ConsumeIntegral<int32_t>();
-        bool isShared = fdp.ConsumeBool();
-
-        if (fdp.ConsumeBool()) {
-            sp<IGraphicBufferProducer> iGBP = nullptr;
-            sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
-            sp<SurfaceControl> surfaceControl = composerClient->createSurface(
-                    static_cast<String8>(fdp.ConsumeRandomLengthString().c_str()) /* name */,
-                    fdp.ConsumeIntegral<uint32_t>() /* width */,
-                    fdp.ConsumeIntegral<uint32_t>() /* height */,
-                    fdp.ConsumeIntegral<int32_t>() /* format */,
-                    fdp.ConsumeIntegral<int32_t>() /* flags */);
-            if (surfaceControl) {
-                sp<Surface> surface = surfaceControl->getSurface();
-                iGBP = surface->getIGraphicBufferProducer();
-            }
-            outputConfiguration = new OutputConfiguration(iGBP, rotation, physicalCameraId,
-                                                          surfaceSetID, isShared);
-            iGBP.clear();
-            composerClient.clear();
-            surfaceControl.clear();
-        } else {
-            size_t iGBPSize = fdp.ConsumeIntegralInRange<size_t>(kSizeMin, kSizeMax);
-            vector<sp<IGraphicBufferProducer>> iGBPs;
-            for (size_t idx = 0; idx < iGBPSize; ++idx) {
-                sp<IGraphicBufferProducer> iGBP = nullptr;
-                sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
-                sp<SurfaceControl> surfaceControl = composerClient->createSurface(
-                        static_cast<String8>(fdp.ConsumeRandomLengthString().c_str()) /* name */,
-                        fdp.ConsumeIntegral<uint32_t>() /* width */,
-                        fdp.ConsumeIntegral<uint32_t>() /* height */,
-                        fdp.ConsumeIntegral<int32_t>() /* format */,
-                        fdp.ConsumeIntegral<int32_t>() /* flags */);
-                if (surfaceControl) {
-                    sp<Surface> surface = surfaceControl->getSurface();
-                    iGBP = surface->getIGraphicBufferProducer();
-                    iGBPs.push_back(iGBP);
-                }
-                iGBP.clear();
-                composerClient.clear();
-                surfaceControl.clear();
-            }
-            outputConfiguration = new OutputConfiguration(iGBPs, rotation, physicalCameraId,
-                                                          surfaceSetID, isShared);
-        }
+        sp<IGraphicBufferProducer> gbp;
+        return gbp;
     }
+}
 
-    outputConfiguration->getRotation();
-    outputConfiguration->getSurfaceSetID();
-    outputConfiguration->getSurfaceType();
-    outputConfiguration->getWidth();
-    outputConfiguration->getHeight();
-    outputConfiguration->isDeferred();
-    outputConfiguration->isShared();
-    outputConfiguration->getPhysicalCameraId();
+unique_ptr<OutputConfiguration> C2OutputConfigurationFuzzer::getC2OutputConfig() {
+    unique_ptr<OutputConfiguration> outputConfiguration = nullptr;
+    auto selectOutputConfigurationConstructor =
+            mFDP->PickValueInArray<const std::function<void()>>({
+                    [&]() { outputConfiguration = make_unique<OutputConfiguration>(); },
 
-    OutputConfiguration outputConfiguration2;
-    outputConfiguration->gbpsEqual(outputConfiguration2);
-    outputConfiguration->sensorPixelModesUsedEqual(outputConfiguration2);
-    outputConfiguration->gbpsLessThan(outputConfiguration2);
-    outputConfiguration->sensorPixelModesUsedLessThan(outputConfiguration2);
-    outputConfiguration->getGraphicBufferProducers();
-    sp<IGraphicBufferProducer> gbp;
-    outputConfiguration->addGraphicProducer(gbp);
-    invokeReadWriteNullParcel<OutputConfiguration>(outputConfiguration);
-    invokeReadWriteParcel<OutputConfiguration>(outputConfiguration);
-    delete outputConfiguration;
+                    [&]() {
+                        int32_t rotation = mFDP->ConsumeIntegral<int32_t>();
+                        string physicalCameraId = mFDP->ConsumeRandomLengthString(kMaxBytes);
+                        int32_t surfaceSetID = mFDP->ConsumeIntegral<int32_t>();
+                        bool isShared = mFDP->ConsumeBool();
+                        sp<IGraphicBufferProducer> iGBP = createIGraphicBufferProducer();
+                        outputConfiguration = make_unique<OutputConfiguration>(
+                                iGBP, rotation, physicalCameraId, surfaceSetID, isShared);
+                    },
+
+                    [&]() {
+                        int32_t rotation = mFDP->ConsumeIntegral<int32_t>();
+                        string physicalCameraId = mFDP->ConsumeRandomLengthString(kMaxBytes);
+                        int32_t surfaceSetID = mFDP->ConsumeIntegral<int32_t>();
+                        bool isShared = mFDP->ConsumeBool();
+                        size_t iGBPSize = mFDP->ConsumeIntegralInRange<size_t>(kSizeMin, kSizeMax);
+                        vector<sp<IGraphicBufferProducer>> iGBPs;
+                        for (size_t idx = 0; idx < iGBPSize; ++idx) {
+                            sp<IGraphicBufferProducer> iGBP = createIGraphicBufferProducer();
+                            iGBPs.push_back(iGBP);
+                        }
+                        outputConfiguration = make_unique<OutputConfiguration>(
+                                iGBPs, rotation, physicalCameraId, surfaceSetID, isShared);
+                    },
+            });
+    selectOutputConfigurationConstructor();
+    return outputConfiguration;
+}
+
+void C2OutputConfigurationFuzzer::invokeC2OutputConfigFuzzer() {
+    unique_ptr<OutputConfiguration> outputConfiguration = getC2OutputConfig();
+    int8_t count = kMaxLoopIterations;
+    while (--count > 0) {
+    unique_ptr<OutputConfiguration> outputConfiguration2 = getC2OutputConfig();
+        auto callC2OutputConfAPIs = mFDP->PickValueInArray<const std::function<void()>>({
+                [&]() { outputConfiguration->getRotation(); },
+                [&]() { outputConfiguration->getSurfaceSetID(); },
+                [&]() { outputConfiguration->getSurfaceType(); },
+                [&]() { outputConfiguration->getWidth(); },
+                [&]() { outputConfiguration->getHeight(); },
+                [&]() { outputConfiguration->isDeferred(); },
+                [&]() { outputConfiguration->isShared(); },
+                [&]() { outputConfiguration->getPhysicalCameraId(); },
+                [&]() { outputConfiguration->gbpsEqual(*outputConfiguration2); },
+                [&]() { outputConfiguration->sensorPixelModesUsedEqual(*outputConfiguration2); },
+                [&]() { outputConfiguration->gbpsLessThan(*outputConfiguration2); },
+                [&]() { outputConfiguration->sensorPixelModesUsedLessThan(*outputConfiguration2); },
+                [&]() { outputConfiguration->getGraphicBufferProducers(); },
+                [&]() {
+                    sp<IGraphicBufferProducer> gbp = createIGraphicBufferProducer();
+                    outputConfiguration->addGraphicProducer(gbp);
+                },
+                [&]() { outputConfiguration->isMultiResolution(); },
+                [&]() { outputConfiguration->getColorSpace(); },
+                [&]() { outputConfiguration->getStreamUseCase(); },
+                [&]() { outputConfiguration->getTimestampBase(); },
+                [&]() { outputConfiguration->getMirrorMode(); },
+                [&]() { outputConfiguration->useReadoutTimestamp(); },
+        });
+        callC2OutputConfAPIs();
+    }
+    // Not keeping invokeReadWrite() APIs in while loop to avoid possible OOM.
+    invokeReadWriteNullParcel<OutputConfiguration>(outputConfiguration.get());
+    if (mFDP->ConsumeBool()) {
+        invokeReadWriteParcel<OutputConfiguration>(outputConfiguration.get());
+    } else {
+        invokeNewReadWriteParcel<OutputConfiguration>(outputConfiguration.get(), *mFDP);
+    }
+}
+
+void C2OutputConfigurationFuzzer::process(const uint8_t* data, size_t size) {
+    mFDP = new FuzzedDataProvider(data, size);
+    invokeC2OutputConfigFuzzer();
+    delete mFDP;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    C2OutputConfigurationFuzzer c2OutputConfigurationFuzzer;
+    c2OutputConfigurationFuzzer.process(data, size);
     return 0;
 }
diff --git a/media/audio/aconfig/Android.bp b/media/audio/aconfig/Android.bp
index a7d8c4a..08840e4 100644
--- a/media/audio/aconfig/Android.bp
+++ b/media/audio/aconfig/Android.bp
@@ -43,6 +43,18 @@
     name: "com.android.media.audio-aconfig-cc",
     aconfig_declarations: "com.android.media.audio-aconfig",
     defaults: ["audio-aconfig-cc-defaults"],
+    double_loadable: true,
+    host_supported: true,
+    product_available: true,
+    vendor_available: true,
+    // TODO(b/316909431) native_bridge_supported: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media",
+        "com.android.media.swcodec",
+        "com.android.btservices",
+    ],
+    min_sdk_version: "29",
 }
 
 cc_aconfig_library {
diff --git a/media/audio/aconfig/audio.aconfig b/media/audio/aconfig/audio.aconfig
index 73cb8ca..388e5e0 100644
--- a/media/audio/aconfig/audio.aconfig
+++ b/media/audio/aconfig/audio.aconfig
@@ -42,3 +42,10 @@
     description: "Enable spatializer offload"
     bug: "307842941"
 }
+
+flag {
+    name: "stereo_spatialization"
+    namespace: "media_audio"
+    description: "Enable stereo channel mask for spatialization."
+    bug: "303920722"
+}
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 60b814e..1a6c7f1 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -28,7 +28,6 @@
 
 #include "media/AidlConversionCppNdk.h"
 
-#include <media/ShmemCompat.h>
 #include <media/stagefright/foundation/MediaDefs.h>
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/media/audioaidlconversion/Android.bp b/media/audioaidlconversion/Android.bp
index d3a5755..07c59c7 100644
--- a/media/audioaidlconversion/Android.bp
+++ b/media/audioaidlconversion/Android.bp
@@ -56,6 +56,19 @@
 }
 
 cc_defaults {
+    name: "audio_aidl_conversion_common_default_cpp",
+    shared_libs: [
+        "libbinder",
+        "libshmemcompat",
+        "shared-file-region-aidl-cpp",
+        "framework-permission-aidl-cpp",
+    ],
+    export_shared_lib_headers: [
+        "shared-file-region-aidl-cpp",
+    ],
+}
+
+cc_defaults {
     name: "audio_aidl_conversion_common_default",
     export_include_dirs: ["include"],
     host_supported: true,
@@ -67,17 +80,12 @@
     ],
     shared_libs: [
         "libbase",
-        "libbinder",
         "liblog",
-        "libshmemcompat",
         "libstagefright_foundation",
         "libutils",
-        "shared-file-region-aidl-cpp",
-        "framework-permission-aidl-cpp",
     ],
     export_shared_lib_headers: [
         "libbase",
-        "shared-file-region-aidl-cpp",
     ],
     cflags: [
         "-Wall",
@@ -113,6 +121,7 @@
     ],
     defaults: [
         "audio_aidl_conversion_common_default",
+        "audio_aidl_conversion_common_default_cpp",
         "latest_android_media_audio_common_types_cpp_export_shared",
     ],
     min_sdk_version: "29",
@@ -223,6 +232,7 @@
     ],
     defaults: [
         "audio_aidl_conversion_common_default",
+        "audio_aidl_conversion_common_default_cpp",
         "audio_aidl_conversion_common_util_default",
         "latest_android_media_audio_common_types_cpp_shared",
         "latest_android_media_audio_common_types_ndk_shared",
diff --git a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
index 656d76a..53f529e 100644
--- a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
@@ -30,7 +30,6 @@
 #include <utility>
 
 #include <android-base/expected.h>
-#include <binder/Status.h>
 
 #if defined(BACKEND_NDK_IMPL)
 #include <android/binder_auto_utils.h>
@@ -40,6 +39,7 @@
 namespace aidl {
 #else
 #include <binder/Enums.h>
+#include <binder/Status.h>
 #endif  // BACKEND_NDK_IMPL
 namespace android {
 
@@ -374,6 +374,30 @@
  * Note: for EX_TRANSACTION_FAILED and EX_SERVICE_SPECIFIC a more detailed error code
  * can be found from transactionError() or serviceSpecificErrorCode().
  */
+#if defined(BACKEND_NDK_IMPL)
+static inline ::android::status_t statusTFromExceptionCode(binder_exception_t exception) {
+    switch (exception) {
+        case EX_NONE:
+            return ::android::OK;
+        case EX_SECURITY:  // Java SecurityException, rethrows locally in Java
+            return ::android::PERMISSION_DENIED;
+        case EX_BAD_PARCELABLE:  // Java BadParcelableException, rethrows in Java
+        case EX_ILLEGAL_ARGUMENT:  // Java IllegalArgumentException, rethrows in Java
+        case EX_NULL_POINTER:  // Java NullPointerException, rethrows in Java
+            return ::android::BAD_VALUE;
+        case EX_ILLEGAL_STATE:  // Java IllegalStateException, rethrows in Java
+        case EX_UNSUPPORTED_OPERATION:  // Java UnsupportedOperationException, rethrows
+            return ::android::INVALID_OPERATION;
+        case EX_PARCELABLE:  // Java bootclass loader (not standard exception), rethrows
+        case EX_NETWORK_MAIN_THREAD:  // Java NetworkOnMainThreadException, rethrows
+        case EX_TRANSACTION_FAILED: // Native - see error code
+        case EX_SERVICE_SPECIFIC:   // Java ServiceSpecificException,
+                                            // rethrows in Java with integer error code
+            return ::android::UNKNOWN_ERROR;
+    }
+    return ::android::UNKNOWN_ERROR;
+}
+#else
 static inline ::android::status_t statusTFromExceptionCode(int32_t exceptionCode) {
     using namespace ::android::binder;
     switch (exceptionCode) {
@@ -398,6 +422,7 @@
     }
     return ::android::UNKNOWN_ERROR;
 }
+#endif  // BACKEND_NDK_IMPL
 
 /**
  * Return the equivalent Android ::android::status_t from a binder status.
@@ -410,6 +435,7 @@
  *
  * return_type method(type0 param0, ...)
  */
+#if !defined(BACKEND_NDK_IMPL)
 static inline ::android::status_t statusTFromBinderStatus(const ::android::binder::Status &status) {
     return status.isOk() ? ::android::OK // check ::android::OK,
         : status.serviceSpecificErrorCode() // service-side error, not standard Java exception
@@ -418,6 +444,7 @@
         ?: statusTFromExceptionCode(status.exceptionCode()); // a service-side error with a
                                                     // standard Java exception (fromExceptionCode)
 }
+#endif
 
 #if defined(BACKEND_NDK_IMPL)
 static inline ::android::status_t statusTFromBinderStatus(const ::ndk::ScopedAStatus &status) {
@@ -443,6 +470,7 @@
  * This is used for methods not returning an explicit status_t,
  * where Java callers expect an exception, not an integer return value.
  */
+#if !defined(BACKEND_NDK_IMPL)
 static inline ::android::binder::Status binderStatusFromStatusT(
         ::android::status_t status, const char *optionalMessage = nullptr) {
     const char * const emptyIfNull = optionalMessage == nullptr ? "" : optionalMessage;
@@ -470,6 +498,7 @@
     // throw a ServiceSpecificException.
     return Status::fromServiceSpecificError(status, emptyIfNull);
 }
+#endif
 
 } // namespace aidl_utils
 
diff --git a/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
index 60727b4..f78243e 100644
--- a/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
+++ b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+#define LOG_TAG "AidlConversionNdkTests"
 #include <iostream>
 #include <type_traits>
 
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index ce9fc39..c7c04c5 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -90,8 +90,8 @@
 
         std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
         CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator), C2_OK);
-        mLinearPool = std::make_shared<C2PooledBlockPool>(
-                mLinearAllocator, mBlockPoolId++, getBufferPoolVer());
+        mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++,
+                                                          getBufferPoolVer());
         ASSERT_NE(mLinearPool, nullptr);
 
         std::vector<std::unique_ptr<C2Param>> queried;
@@ -336,7 +336,9 @@
             ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout";
         }
         int64_t timestamp = (*Info)[frameID].timestamp;
-        flags = ((*Info)[frameID].flags == FLAG_CONFIG_DATA) ? C2FrameData::FLAG_CODEC_CONFIG : 0;
+        flags = ((*Info)[frameID].vtsFlags & (1 << VTS_BIT_FLAG_CSD_FRAME))
+                        ? C2FrameData::FLAG_CODEC_CONFIG
+                        : 0;
         if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1))))
             flags |= C2FrameData::FLAG_END_OF_STREAM;
 
@@ -531,14 +533,10 @@
 
     // request EOS for thumbnail
     // signal EOS flag with last frame
-    size_t i = -1;
-    uint32_t flags;
-    do {
-        i++;
-        flags = 0;
-        if (Info[i].flags) flags = 1u << (Info[i].flags - 1);
-
-    } while (!(flags & SYNC_FRAME));
+    size_t i;
+    for (i = 0; i < Info.size(); i++) {
+        if (Info[i].vtsFlags & (1 << VTS_BIT_FLAG_SYNC_FRAME)) break;
+    }
     std::ifstream eleStream;
     eleStream.open(mInputFile, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
@@ -643,14 +641,11 @@
     mFlushedIndices.clear();
     int index = numFramesFlushed;
     bool keyFrame = false;
-    uint32_t flags = 0;
     while (index < (int)Info.size()) {
-        if (Info[index].flags) flags = 1u << (Info[index].flags - 1);
-        if ((flags & SYNC_FRAME) == SYNC_FRAME) {
+        if (Info[index].vtsFlags & (1 << VTS_BIT_FLAG_SYNC_FRAME)) {
             keyFrame = true;
             break;
         }
-        flags = 0;
         eleStream.ignore(Info[index].bytesCount);
         index++;
     }
@@ -684,24 +679,24 @@
     int bytesCount = 0;
     uint32_t frameId = 0;
     uint32_t flags = 0;
+    uint32_t vtsFlags = 0;
     uint32_t timestamp = 0;
     bool codecConfig = false;
     // This test introduces empty CSD after every 20th frame
     // and empty input frames at an interval of 5 frames.
     while (1) {
         if (!(frameId % 5)) {
-            if (!(frameId % 20))
-                flags = 32;
-            else
-                flags = 0;
+            vtsFlags = !(frameId % 20) ? (1 << VTS_BIT_FLAG_CSD_FRAME) : 0;
             bytesCount = 0;
         } else {
             if (!(eleInfo >> bytesCount)) break;
             eleInfo >> flags;
+            vtsFlags = mapInfoFlagstoVtsFlags(flags);
+            ASSERT_NE(vtsFlags, 0xFF) << "unrecognized flag entry in info file: " << mInfoFile;
             eleInfo >> timestamp;
-            codecConfig = flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+            codecConfig = (vtsFlags & (1 << VTS_BIT_FLAG_CSD_FRAME)) != 0;
         }
-        Info.push_back({bytesCount, flags, timestamp});
+        Info.push_back({bytesCount, vtsFlags, timestamp});
         frameId++;
     }
     eleInfo.close();
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
index f36bc41..a72f7bd 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
@@ -233,18 +233,24 @@
     int32_t numCsds = 0;
     int32_t bytesCount = 0;
     uint32_t flags = 0;
+    uint32_t vtsFlags = 0;
     uint32_t timestamp = 0;
     while (1) {
         if (!(eleInfo >> bytesCount)) break;
         eleInfo >> flags;
+        vtsFlags = mapInfoFlagstoVtsFlags(flags);
+        if (vtsFlags == 0xFF) {
+            ALOGE("unrecognized flag entry in info file %s", info.c_str());
+            return -1;
+        }
         eleInfo >> timestamp;
-        bool codecConfig = flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+        bool codecConfig = (vtsFlags & (1 << VTS_BIT_FLAG_CSD_FRAME)) != 0 ;
         if (codecConfig) numCsds++;
-        bool nonDisplayFrame = ((flags & FLAG_NON_DISPLAY_FRAME) != 0);
+        bool nonDisplayFrame = (vtsFlags & (1 << VTS_BIT_FLAG_NO_SHOW_FRAME)) != 0;
         if (timestampDevTest && !codecConfig && !nonDisplayFrame) {
             timestampUslist->push_back(timestamp);
         }
-        frameInfo->push_back({bytesCount, flags, timestamp});
+        frameInfo->push_back({bytesCount, vtsFlags, timestamp});
     }
     ALOGV("numCsds : %d", numCsds);
     eleInfo.close();
@@ -273,3 +279,11 @@
     ASSERT_EQ(flushedIndices.empty(), true);
     flushedWork.clear();
 }
+
+int mapInfoFlagstoVtsFlags(int infoFlags) {
+    if (infoFlags == 0) return 0;
+    else if (infoFlags == 0x1) return (1 << VTS_BIT_FLAG_SYNC_FRAME);
+    else if (infoFlags == 0x10) return (1 << VTS_BIT_FLAG_NO_SHOW_FRAME);
+    else if (infoFlags == 0x20) return (1 << VTS_BIT_FLAG_CSD_FRAME);
+    return 0xFF;
+}
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
index 48e80a4..eda7b99 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
@@ -29,9 +29,6 @@
 #include <chrono>
 #include <fstream>
 
-#define FLAG_NON_DISPLAY_FRAME (1 << 4)
-#define FLAG_CONFIG_DATA (1 << 5)
-
 #define MAX_RETRY 20
 #define TIME_OUT 400ms
 #define MAX_INPUT_BUFFERS 8
@@ -53,9 +50,15 @@
 // Component name prefix
 extern std::string sComponentNamePrefix;
 
+enum c2_vts_flags_t {
+    VTS_BIT_FLAG_SYNC_FRAME = 1,
+    VTS_BIT_FLAG_NO_SHOW_FRAME = 2,
+    VTS_BIT_FLAG_CSD_FRAME = 3,
+};
+
 struct FrameInfo {
     int bytesCount;
-    uint32_t flags;
+    uint32_t vtsFlags;
     int64_t timestamp;
 };
 
@@ -165,4 +168,7 @@
 void verifyFlushOutput(std::list<std::unique_ptr<C2Work>>& flushedWork,
                        std::list<std::unique_ptr<C2Work>>& workQueue,
                        std::list<uint64_t>& flushedIndices, std::mutex& queueLock);
+
+int mapInfoFlagstoVtsFlags(int infoFlags);
+
 #endif  // MEDIA_C2_HIDL_TEST_COMMON_H
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 2cf0d6e..fdb28f4 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -120,8 +120,8 @@
 
         std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
         CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator), C2_OK);
-        mLinearPool = std::make_shared<C2PooledBlockPool>(
-                mLinearAllocator, mBlockPoolId++, getBufferPoolVer());
+        mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++,
+                                                          getBufferPoolVer());
         ASSERT_NE(mLinearPool, nullptr);
 
         std::vector<std::unique_ptr<C2Param>> queried;
@@ -463,7 +463,9 @@
         }
         int64_t timestamp = (*Info)[frameID].timestamp;
 
-        flags = ((*Info)[frameID].flags == FLAG_CONFIG_DATA) ? C2FrameData::FLAG_CODEC_CONFIG : 0;
+        flags = ((*Info)[frameID].vtsFlags & (1 << VTS_BIT_FLAG_CSD_FRAME))
+                        ? C2FrameData::FLAG_CODEC_CONFIG
+                        : 0;
         if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1))))
             flags |= C2FrameData::FLAG_END_OF_STREAM;
 
@@ -711,17 +713,19 @@
         ASSERT_EQ(eleInfo.is_open(), true) << mInputFile << " - file not found";
         int bytesCount = 0;
         uint32_t flags = 0;
+        uint32_t vtsFlags = 0;
         uint32_t timestamp = 0;
         uint32_t timestampMax = 0;
         while (1) {
             if (!(eleInfo >> bytesCount)) break;
             eleInfo >> flags;
+            vtsFlags = mapInfoFlagstoVtsFlags(flags);
+            ASSERT_NE(vtsFlags, 0xFF) << "unrecognized flag entry in info file: " << mInfoFile;
             eleInfo >> timestamp;
             timestamp += timestampOffset;
-            Info.push_back({bytesCount, flags, timestamp});
-            bool codecConfig =
-                    flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
-            bool nonDisplayFrame = ((flags & FLAG_NON_DISPLAY_FRAME) != 0);
+            Info.push_back({bytesCount, vtsFlags, timestamp});
+            bool codecConfig = (vtsFlags & (1 << VTS_BIT_FLAG_CSD_FRAME)) != 0;
+            bool nonDisplayFrame = (vtsFlags & (1 << VTS_BIT_FLAG_NO_SHOW_FRAME)) != 0;
 
             {
                 ULock l(mQueueLock);
@@ -795,20 +799,15 @@
     int32_t numCsds = populateInfoVector(mInfoFile, &Info, mTimestampDevTest, &mTimestampUslist);
     ASSERT_GE(numCsds, 0) << "Error in parsing input info file: " << mInfoFile;
 
-    uint32_t flags = 0;
     for (size_t i = 0; i < MAX_ITERATIONS; i++) {
         ASSERT_EQ(mComponent->start(), C2_OK);
 
         // request EOS for thumbnail
         // signal EOS flag with last frame
         size_t j = -1;
-        do {
-            j++;
-            flags = 0;
-            if (Info[j].flags) flags = 1u << (Info[j].flags - 1);
-
-        } while (!(flags & SYNC_FRAME));
-
+        for (j = 0; j < Info.size(); j++) {
+            if (Info[j].vtsFlags & (1 << VTS_BIT_FLAG_SYNC_FRAME)) break;
+        }
         std::ifstream eleStream;
         eleStream.open(mInputFile, std::ifstream::binary);
         ASSERT_EQ(eleStream.is_open(), true);
@@ -908,14 +907,11 @@
     // Seek to next key frame and start decoding till the end
     int index = numFramesFlushed;
     bool keyFrame = false;
-    uint32_t flags = 0;
     while (index < (int)Info.size()) {
-        if (Info[index].flags) flags = 1u << (Info[index].flags - 1);
-        if ((flags & SYNC_FRAME) == SYNC_FRAME) {
+        if (Info[index].vtsFlags & (1 << VTS_BIT_FLAG_SYNC_FRAME)) {
             keyFrame = true;
             break;
         }
-        flags = 0;
         eleStream.ignore(Info[index].bytesCount);
         index++;
     }
@@ -949,24 +945,24 @@
     int bytesCount = 0;
     uint32_t frameId = 0;
     uint32_t flags = 0;
+    uint32_t vtsFlags = 0;
     uint32_t timestamp = 0;
     bool codecConfig = false;
     // This test introduces empty CSD after every 20th frame
     // and empty input frames at an interval of 5 frames.
     while (1) {
         if (!(frameId % 5)) {
-            if (!(frameId % 20))
-                flags = 32;
-            else
-                flags = 0;
+            vtsFlags = !(frameId % 20) ? (1 << VTS_BIT_FLAG_CSD_FRAME) : 0;
             bytesCount = 0;
         } else {
             if (!(eleInfo >> bytesCount)) break;
             eleInfo >> flags;
+            vtsFlags = mapInfoFlagstoVtsFlags(flags);
+            ASSERT_NE(vtsFlags, 0xFF) << "unrecognized flag entry in info file: " << mInfoFile;
             eleInfo >> timestamp;
-            codecConfig = flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+            codecConfig = (vtsFlags & (1 << VTS_BIT_FLAG_CSD_FRAME)) != 0;
         }
-        Info.push_back({bytesCount, flags, timestamp});
+        Info.push_back({bytesCount, vtsFlags, timestamp});
         frameId++;
     }
     eleInfo.close();
@@ -1046,12 +1042,9 @@
     }
 
     int offset = framesToDecode;
-    uint32_t flags = 0;
     while (1) {
         while (offset < (int)Info.size()) {
-            flags = 0;
-            if (Info[offset].flags) flags = 1u << (Info[offset].flags - 1);
-            if (flags & SYNC_FRAME) {
+            if (Info[offset].vtsFlags & (1 << VTS_BIT_FLAG_SYNC_FRAME)) {
                 keyFrame = true;
                 break;
             }
diff --git a/media/libaaudio/src/binding/AudioEndpointParcelable.h b/media/libaaudio/src/binding/AudioEndpointParcelable.h
index 722dd14..12cc42e 100644
--- a/media/libaaudio/src/binding/AudioEndpointParcelable.h
+++ b/media/libaaudio/src/binding/AudioEndpointParcelable.h
@@ -53,7 +53,7 @@
     int32_t addFileDescriptor(const android::base::unique_fd& fd, int32_t sizeInBytes);
 
     /**
-     * Close current data file descriptor. The duplicated file descriptor will be close.
+     * Close current data file descriptor. The duplicated file descriptor will be closed.
      */
     void closeDataFileDescriptor();
 
diff --git a/media/libaaudio/src/client/AudioEndpoint.h b/media/libaaudio/src/client/AudioEndpoint.h
index 2c23e1d..b117572 100644
--- a/media/libaaudio/src/client/AudioEndpoint.h
+++ b/media/libaaudio/src/client/AudioEndpoint.h
@@ -107,7 +107,7 @@
      */
     void eraseDataMemory();
 
-    void freeDataQueue();
+    void freeDataQueue() { mDataQueue.reset(); }
 
     void dump() const;
 
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index f431da8..52925d9 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -399,6 +399,12 @@
     uint8_t buffer[getDeviceBufferCapacity() * getBytesPerFrame()];
     android::fifo_frames_t fullFramesAvailable = mAudioEndpoint->read(buffer,
             getDeviceBufferCapacity());
+    // Before releasing the data queue, update the frames read and written.
+    getFramesRead();
+    getFramesWritten();
+    // Call freeDataQueue() here because the following call to
+    // closeDataFileDescriptor() will invalidate the pointers used by the data queue.
+    mAudioEndpoint->freeDataQueue();
     mEndPointParcelable.closeDataFileDescriptor();
     aaudio_result_t result = mServiceInterface.exitStandby(
             mServiceStreamHandleInfo, endpointParcelable);
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
index d9b75da..68c9156 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
@@ -273,7 +273,8 @@
 
 int64_t AudioStreamInternalCapture::getFramesRead() {
     if (mAudioEndpoint) {
-        mLastFramesRead = mAudioEndpoint->getDataReadCounter() + mFramesOffsetFromService;
+        mLastFramesRead = std::max(mLastFramesRead,
+                                   mAudioEndpoint->getDataReadCounter() + mFramesOffsetFromService);
     }
     return mLastFramesRead;
 }
@@ -295,8 +296,10 @@
         if ((result != mCallbackFrames)) {
             ALOGE("callbackLoop: read() returned %d", result);
             if (result >= 0) {
-                // Only read some of the frames requested. Must have timed out.
-                result = AAUDIO_ERROR_TIMEOUT;
+                // Only read some of the frames requested. The stream can be disconnected
+                // or timed out.
+                processCommands();
+                result = isDisconnected() ? AAUDIO_ERROR_DISCONNECTED : AAUDIO_ERROR_TIMEOUT;
             }
             maybeCallErrorCallback(result);
             break;
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index 3badb0b..5bac2ca 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -329,8 +329,9 @@
 
 int64_t AudioStreamInternalPlay::getFramesWritten() {
     if (mAudioEndpoint) {
-        mLastFramesWritten = mAudioEndpoint->getDataWriteCounter()
-                             + mFramesOffsetFromService;
+        mLastFramesWritten = std::max(
+                mLastFramesWritten,
+                mAudioEndpoint->getDataWriteCounter() + mFramesOffsetFromService);
     }
     return mLastFramesWritten;
 }
@@ -353,8 +354,10 @@
             result = write(mCallbackBuffer.get(), mCallbackFrames, timeoutNanos);
             if ((result != mCallbackFrames)) {
                 if (result >= 0) {
-                    // Only wrote some of the frames requested. Must have timed out.
-                    result = AAUDIO_ERROR_TIMEOUT;
+                    // Only wrote some of the frames requested. The stream can be disconnected
+                    // or timed out.
+                    processCommands();
+                    result = isDisconnected() ? AAUDIO_ERROR_DISCONNECTED : AAUDIO_ERROR_TIMEOUT;
                 }
                 maybeCallErrorCallback(result);
                 break;
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index 1129ced..d59afef 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -241,3 +241,10 @@
         "libaaudio_internal",
     ],
 }
+
+cc_binary {
+    name: "test_idle_disconnected_shared_stream",
+    defaults: ["libaaudio_tests_defaults"],
+    srcs: ["test_idle_disconnected_shared_stream.cpp"],
+    shared_libs: ["libaaudio"],
+}
diff --git a/media/libaaudio/tests/test_idle_disconnected_shared_stream.cpp b/media/libaaudio/tests/test_idle_disconnected_shared_stream.cpp
new file mode 100644
index 0000000..2e24b6b
--- /dev/null
+++ b/media/libaaudio/tests/test_idle_disconnected_shared_stream.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// When receive disconnect event, ignore it and leave the shared stream at OPEN
+// state. It should be possible to open another shared stream and start it.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <aaudio/AAudio.h>
+#include <aaudio/AAudioTesting.h>
+
+static constexpr unsigned int ONE_SECOND = 1e6;
+static constexpr unsigned int WAIT_TIME_MS = 10 * ONE_SECOND;
+#define MMAP_POLICY              AAUDIO_POLICY_ALWAYS
+
+AAudioStream* openStream() {
+    AAudioStreamBuilder *aaudioBuilder = nullptr;
+    aaudio_result_t result = AAudio_createStreamBuilder(&aaudioBuilder);
+    if (result != AAUDIO_OK) {
+        printf("Failed to create stream builder, result=%d, %s\n",
+               result, AAudio_convertResultToText(result));
+        return nullptr;
+    }
+    AAudioStreamBuilder_setSharingMode(aaudioBuilder, AAUDIO_SHARING_MODE_SHARED);
+    AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+    AAudioStream* aaudioStream;
+    result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
+    if (result != AAUDIO_OK) {
+        printf("ERROR could not open AAudio stream, %d %s\n",
+               result, AAudio_convertResultToText(result));
+    }
+    AAudioStreamBuilder_delete(aaudioBuilder);
+    return aaudioStream;
+}
+
+aaudio_result_t testNoCloseSharedStreamAfterRoutingChanged(bool stopFirstStream) {
+    aaudio_result_t result = AAUDIO_OK;
+    printf("Please connect external device that supports MMAP playback, will wait 10 seconds\n");
+    usleep(WAIT_TIME_MS);
+
+    // Open first shared stream
+    printf("Open first shared stream\n");
+    AAudioStream* firstStream = openStream();
+    if (firstStream == nullptr) {
+        return 1;
+    }
+    result = AAudioStream_requestStart(firstStream);
+    if (result != AAUDIO_OK) {
+        return result;
+    }
+
+    if (stopFirstStream) {
+        printf("Stop first shared stream\n");
+        result = AAudioStream_requestStop(firstStream);
+        if (result != AAUDIO_OK) {
+            return result;
+        }
+        printf("Wait to make sure the stream is stopped\n");
+        usleep(ONE_SECOND * 3);
+    }
+
+    printf("Please disconnect and reconnect the external device, will wait 10 second\n");
+    usleep(WAIT_TIME_MS);
+
+    // Open second stream after the first shared stream was reconnected
+    printf("Open second shared stream\n");
+    AAudioStream* secondStream = openStream();
+    if (secondStream == nullptr) {
+        result = 1;
+        goto exit;
+    }
+
+    // Starting second stream should be successful
+    printf("Start second shared stream\n");
+    result = AAudioStream_requestStart(secondStream);
+    if (result != AAUDIO_OK) {
+        printf("ERROR could not start second stream, %d %s\n",
+               result, AAudio_convertResultToText(result));
+    }
+
+exit:
+    // Close all streams
+    AAudioStream_close(firstStream);
+    AAudioStream_close(secondStream);
+    return result;
+}
+
+int main(int argc, char **argv) {
+    (void) argc; // unused
+    (void) argv; // unused
+
+    aaudio_policy_t originalPolicy = AAudio_getMMapPolicy();
+    AAudio_setMMapPolicy(MMAP_POLICY);
+
+    printf("Run first test. The first stream is started when routing changed.\n");
+    aaudio_result_t result = testNoCloseSharedStreamAfterRoutingChanged(false /*stopFirstStream*/);
+
+    if (result != AAUDIO_OK) {
+        goto exit;
+    }
+
+    printf("First test passed\n");
+    printf("----------------------------------------------------------------\n");
+    printf("Run second test. The first stream is stopped when routing changed.\n");
+    if (testNoCloseSharedStreamAfterRoutingChanged(true /*stopFirstStream*/) == AAUDIO_OK) {
+        printf("Second test passed\n");
+    }
+
+exit:
+    AAudio_setMMapPolicy(originalPolicy);
+
+    return result != AAUDIO_OK ? EXIT_FAILURE : EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 658bf63..51a679b 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -217,6 +217,7 @@
     ],
     defaults: [
         "audio_aidl_conversion_common_default",
+        "audio_aidl_conversion_common_default_cpp",
         "latest_android_media_audio_common_types_cpp_export_shared",
     ],
 }
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 6a6557c..86fa63f 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -451,6 +451,7 @@
     }
     *config = VALUE_OR_RETURN_STATUS(
             ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
+    if (mixPortConfig.id == 0) return BAD_VALUE;  // HAL suggests a different config.
     ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
     args.portConfigId = mixPortConfig.id;
     const bool isOffload = isBitPositionFlagSet(
@@ -523,6 +524,7 @@
     }
     *config = VALUE_OR_RETURN_STATUS(
             ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
+    if (mixPortConfig.id == 0) return BAD_VALUE;  // HAL suggests a different config.
     ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
     args.portConfigId = mixPortConfig.id;
     RecordTrackMetadata aidlTrackMetadata{
@@ -707,8 +709,7 @@
                     *config, isInput, 0 /*portId*/));
     AudioPortConfig portConfig;
     std::lock_guard l(mLock);
-    return mMapper.findOrCreatePortConfig(
-            requestedPortConfig, std::set<int32_t>(), &portConfig);
+    return mMapper.setPortConfig(requestedPortConfig, std::set<int32_t>(), &portConfig);
 }
 
 MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
@@ -780,7 +781,7 @@
     Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
     {
         std::lock_guard l(mLock);
-        RETURN_STATUS_IF_ERROR(mMapper.findOrCreatePortConfig(
+        RETURN_STATUS_IF_ERROR(mMapper.setPortConfig(
                     requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
     }
     auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
index a8f9f7e..96a3e60 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -24,7 +24,6 @@
 
 #include <aidl/android/hardware/audio/core/IModule.h>
 #include <android/binder_manager.h>
-#include <binder/IServiceManager.h>
 #include <media/AidlConversionNdkCpp.h>
 #include <media/AidlConversionUtil.h>
 #include <utils/Log.h>
@@ -119,23 +118,9 @@
     if (pids == nullptr) {
         return BAD_VALUE;
     }
-    // The functionality for retrieving debug infos of services is not exposed via the NDK.
-    sp<IServiceManager> sm = defaultServiceManager();
-    if (sm == nullptr) {
-        return NO_INIT;
-    }
-    std::set<pid_t> pidsSet;
-    const auto moduleServiceName = std::string(IModule::descriptor) + "/";
-    auto debugInfos = sm->getServiceDebugInfo();
-    for (const auto& info : debugInfos) {
-        if (info.pid > 0 &&
-                info.name.size() > moduleServiceName.size() && // '>' as there must be instance name
-                info.name.substr(0, moduleServiceName.size()) == moduleServiceName) {
-            pidsSet.insert(info.pid);
-        }
-    }
-    *pids = {pidsSet.begin(), pidsSet.end()};
-    return NO_ERROR;
+    // Retrieval of HAL pids requires "list services" permission which is not granted
+    // to the audio server. This job is performed by AudioService (in Java) instead.
+    return PERMISSION_DENIED;
 }
 
 status_t DevicesFactoryHalAidl::setCallbackOnce(sp<DevicesFactoryHalCallback> callback) {
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index aee42a9..182d68a 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -131,6 +131,7 @@
 }
 
 ndk::ScopedAStatus EffectProxy::close() {
+    command(CommandId::STOP);
     return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
         return effect->close();
     });
diff --git a/media/libaudiohal/impl/Hal2AidlMapper.cpp b/media/libaudiohal/impl/Hal2AidlMapper.cpp
index 47fcd27..413a1f8 100644
--- a/media/libaudiohal/impl/Hal2AidlMapper.cpp
+++ b/media/libaudiohal/impl/Hal2AidlMapper.cpp
@@ -30,11 +30,13 @@
 using aidl::android::aidl_utils::statusTFromBinderStatus;
 using aidl::android::media::audio::common::AudioChannelLayout;
 using aidl::android::media::audio::common::AudioConfig;
+using aidl::android::media::audio::common::AudioConfigBase;
 using aidl::android::media::audio::common::AudioDevice;
 using aidl::android::media::audio::common::AudioDeviceAddress;
 using aidl::android::media::audio::common::AudioDeviceDescription;
 using aidl::android::media::audio::common::AudioDeviceType;
 using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
 using aidl::android::media::audio::common::AudioInputFlags;
 using aidl::android::media::audio::common::AudioIoFlags;
 using aidl::android::media::audio::common::AudioOutputFlags;
@@ -64,10 +66,11 @@
             portConfig.format.value() == config.base.format;
 }
 
-void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
+AudioConfig* setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
     config->base.sampleRate = portConfig.sampleRate.value().value;
     config->base.channelMask = portConfig.channelMask.value();
     config->base.format = portConfig.format.value();
+    return config;
 }
 
 void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
@@ -142,8 +145,11 @@
             std::vector<int32_t>* ids, std::set<int32_t>* portIds) -> status_t {
         for (const auto& s : configs) {
             AudioPortConfig portConfig;
-            RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
+            RETURN_STATUS_IF_ERROR(setPortConfig(
                             s, destinationPortIds, &portConfig, cleanups));
+            LOG_ALWAYS_FATAL_IF(portConfig.id == 0,
+                    "fillPortConfigs: initial config: %s, port config: %s",
+                    s.toString().c_str(), portConfig.toString().c_str());
             ids->push_back(portConfig.id);
             if (portIds != nullptr) {
                 portIds->insert(portConfig.portId);
@@ -189,30 +195,23 @@
 }
 
 status_t Hal2AidlMapper::createOrUpdatePortConfig(
-        const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result, bool* created) {
-    AudioPortConfig appliedPortConfig;
+        const AudioPortConfig& requestedPortConfig, AudioPortConfig* result, bool* created) {
     bool applied = false;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
-                            requestedPortConfig, &appliedPortConfig, &applied)));
+                            requestedPortConfig, result, &applied)));
     if (!applied) {
-        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
-                                appliedPortConfig, &appliedPortConfig, &applied)));
-        if (!applied) {
-            ALOGE("%s: module %s did not apply suggested config %s",
-                    __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
-            return NO_INIT;
-        }
+        result->id = 0;
+        *created = false;
+        return OK;
     }
 
-    int32_t id = appliedPortConfig.id;
+    int32_t id = result->id;
     if (requestedPortConfig.id != 0 && requestedPortConfig.id != id) {
         LOG_ALWAYS_FATAL("%s: requested port config id %d changed to %d", __func__,
                 requestedPortConfig.id, id);
     }
 
-    auto [it, inserted] = mPortConfigs.insert_or_assign(std::move(id),
-            std::move(appliedPortConfig));
-    *result = it;
+    auto [_, inserted] = mPortConfigs.insert_or_assign(id, *result);
     *created = inserted;
     return OK;
 }
@@ -258,11 +257,10 @@
     return OK;
 }
 
-status_t Hal2AidlMapper::findOrCreatePortConfig(
+status_t Hal2AidlMapper::findOrCreateDevicePortConfig(
         const AudioDevice& device, const AudioConfig* config, AudioPortConfig* portConfig,
         bool* created) {
-    auto portConfigIt = findPortConfig(device);
-    if (portConfigIt == mPortConfigs.end()) {
+    if (auto portConfigIt = findPortConfig(device); portConfigIt == mPortConfigs.end()) {
         auto portsIt = findPort(device);
         if (portsIt == mPorts.end()) {
             ALOGE("%s: device port for device %s is not found in the module %s",
@@ -274,24 +272,40 @@
         if (config != nullptr) {
             setPortConfigFromConfig(&requestedPortConfig, *config);
         }
-        RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
-                created));
+        AudioPortConfig suggestedOrAppliedPortConfig;
+        RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig,
+                        &suggestedOrAppliedPortConfig, created));
+        if (suggestedOrAppliedPortConfig.id == 0) {
+            // Try again with the suggested config
+            suggestedOrAppliedPortConfig.id = requestedPortConfig.id;
+            AudioPortConfig appliedPortConfig;
+            RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(suggestedOrAppliedPortConfig,
+                            &appliedPortConfig, created));
+            if (appliedPortConfig.id == 0) {
+                ALOGE("%s: module %s did not apply suggested config %s", __func__,
+                        mInstance.c_str(), suggestedOrAppliedPortConfig.toString().c_str());
+                return NO_INIT;
+            }
+            *portConfig = appliedPortConfig;
+        } else {
+            *portConfig = suggestedOrAppliedPortConfig;
+        }
     } else {
+        *portConfig = portConfigIt->second;
         *created = false;
     }
-    *portConfig = portConfigIt->second;
     return OK;
 }
 
-status_t Hal2AidlMapper::findOrCreatePortConfig(
+status_t Hal2AidlMapper::findOrCreateMixPortConfig(
         const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
         AudioSource source, const std::set<int32_t>& destinationPortIds,
         AudioPortConfig* portConfig, bool* created) {
     // These flags get removed one by one in this order when retrying port finding.
     static const std::vector<AudioInputFlags> kOptionalInputFlags{
         AudioInputFlags::FAST, AudioInputFlags::RAW, AudioInputFlags::VOIP_TX };
-    auto portConfigIt = findPortConfig(config, flags, ioHandle);
-    if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
+    if (auto portConfigIt = findPortConfig(config, flags, ioHandle);
+            portConfigIt == mPortConfigs.end() && flags.has_value()) {
         auto optionalInputFlagsIt = kOptionalInputFlags.begin();
         AudioIoFlags matchFlags = flags.value();
         auto portsIt = findPort(config, matchFlags, destinationPortIds);
@@ -319,14 +333,14 @@
         AudioPortConfig requestedPortConfig;
         requestedPortConfig.portId = portsIt->first;
         setPortConfigFromConfig(&requestedPortConfig, config);
+        requestedPortConfig.flags = portsIt->second.flags;
         requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
         if (matchFlags.getTag() == AudioIoFlags::Tag::input
                 && source != AudioSource::SYS_RESERVED_INVALID) {
             requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
                     AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
         }
-        RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
-                created));
+        return createOrUpdatePortConfig(requestedPortConfig, portConfig, created);
     } else if (portConfigIt == mPortConfigs.end() && !flags.has_value()) {
         ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
                 "and was not created as flags are not specified",
@@ -343,13 +357,12 @@
         }
 
         if (requestedPortConfig != portConfigIt->second) {
-            RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
-                    created));
+            return createOrUpdatePortConfig(requestedPortConfig, portConfig, created);
         } else {
+            *portConfig = portConfigIt->second;
             *created = false;
         }
     }
-    *portConfig = portConfigIt->second;
     return OK;
 }
 
@@ -371,11 +384,11 @@
                 AudioPortMixExtUseCase::Tag::source ?
                 requestedPortConfig.ext.get<Tag::mix>().usecase.
                 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
-        return findOrCreatePortConfig(config, requestedPortConfig.flags,
+        return findOrCreateMixPortConfig(config, requestedPortConfig.flags,
                 requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
                 portConfig, created);
     } else if (requestedPortConfig.ext.getTag() == Tag::device) {
-        return findOrCreatePortConfig(
+        return findOrCreateDevicePortConfig(
                 requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
                 portConfig, created);
     }
@@ -384,18 +397,6 @@
     return BAD_VALUE;
 }
 
-status_t Hal2AidlMapper::findOrCreatePortConfig(
-        const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
-        AudioPortConfig* portConfig, Cleanups* cleanups) {
-    bool created = false;
-    RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
-                    requestedPortConfig, destinationPortIds, portConfig, &created));
-    if (created && cleanups != nullptr) {
-        cleanups->add(&Hal2AidlMapper::resetPortConfig, portConfig->id);
-    }
-    return OK;
-}
-
 status_t Hal2AidlMapper::findPortConfig(const AudioDevice& device, AudioPortConfig* portConfig) {
     if (auto it = findPortConfig(device); it != mPortConfigs.end()) {
         *portConfig = it->second;
@@ -675,21 +676,56 @@
             config->toString().c_str(), mixPortConfig->toString().c_str());
     resetUnusedPatchesAndPortConfigs();
     const bool isInput = flags.getTag() == AudioIoFlags::Tag::input;
+    const AudioConfig initialConfig = *config;
     // Find / create AudioPortConfigs for the device port and the mix port,
     // then find / create a patch between them, and open a stream on the mix port.
     AudioPortConfig devicePortConfig;
     bool created = false;
-    RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(device, config,
-                                                  &devicePortConfig, &created));
+    RETURN_STATUS_IF_ERROR(findOrCreateDevicePortConfig(device, config,
+                    &devicePortConfig, &created));
+    LOG_ALWAYS_FATAL_IF(devicePortConfig.id == 0);
     if (created) {
         cleanups->add(&Hal2AidlMapper::resetPortConfig, devicePortConfig.id);
     }
-    RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*config, flags, ioHandle, source,
+    RETURN_STATUS_IF_ERROR(findOrCreateMixPortConfig(*config, flags, ioHandle, source,
                     std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
     if (created) {
         cleanups->add(&Hal2AidlMapper::resetPortConfig, mixPortConfig->id);
     }
     setConfigFromPortConfig(config, *mixPortConfig);
+    bool retryWithSuggestedConfig = false;   // By default, let the framework to retry.
+    if (mixPortConfig->id == 0 && config->base == AudioConfigBase{}) {
+        // The HAL proposes a default config, can retry here.
+        retryWithSuggestedConfig = true;
+    } else if (isInput && config->base != initialConfig.base) {
+        // If the resulting config is different, we must stop and provide the config to the
+        // framework so that it can retry.
+        mixPortConfig->id = 0;
+    } else if (!isInput && mixPortConfig->id == 0 &&
+                    (initialConfig.base.format.type == AudioFormatType::PCM ||
+                            !isBitPositionFlagSet(flags.get<AudioIoFlags::output>(),
+                                    AudioOutputFlags::DIRECT) ||
+                            isBitPositionFlagSet(flags.get<AudioIoFlags::output>(),
+                                    AudioOutputFlags::COMPRESS_OFFLOAD))) {
+        // The framework does not retry opening non-direct PCM and IEC61937 outputs, need to retry
+        // here (see 'AudioHwDevice::openOutputStream').
+        retryWithSuggestedConfig = true;
+    }
+    if (mixPortConfig->id == 0 && retryWithSuggestedConfig) {
+        ALOGD("%s: retrying to find/create a mix port config using config %s", __func__,
+                config->toString().c_str());
+        RETURN_STATUS_IF_ERROR(findOrCreateMixPortConfig(*config, flags, ioHandle, source,
+                        std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
+        if (created) {
+            cleanups->add(&Hal2AidlMapper::resetPortConfig, mixPortConfig->id);
+        }
+        setConfigFromPortConfig(config, *mixPortConfig);
+    }
+    if (mixPortConfig->id == 0) {
+        ALOGD("%p %s: returning suggested config for the stream: %s", this, __func__,
+                config->toString().c_str());
+        return OK;
+    }
     if (isInput) {
         RETURN_STATUS_IF_ERROR(findOrCreatePatch(
                         {devicePortConfig.id}, {mixPortConfig->id}, patch, &created));
@@ -706,6 +742,18 @@
     return OK;
 }
 
+status_t Hal2AidlMapper::setPortConfig(
+        const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
+        AudioPortConfig* portConfig, Cleanups* cleanups) {
+    bool created = false;
+    RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
+                    requestedPortConfig, destinationPortIds, portConfig, &created));
+    if (created && cleanups != nullptr) {
+        cleanups->add(&Hal2AidlMapper::resetPortConfig, portConfig->id);
+    }
+    return OK;
+}
+
 status_t Hal2AidlMapper::releaseAudioPatch(int32_t patchId) {
     return releaseAudioPatches({patchId});
 }
diff --git a/media/libaudiohal/impl/Hal2AidlMapper.h b/media/libaudiohal/impl/Hal2AidlMapper.h
index 70a2bd7..ee55b22 100644
--- a/media/libaudiohal/impl/Hal2AidlMapper.h
+++ b/media/libaudiohal/impl/Hal2AidlMapper.h
@@ -36,6 +36,11 @@
 // structures directly. Mapper does the job of translating the "legacy" way of identifying ports
 // and port configs (by device addresses and I/O handles) into AIDL IDs. Once the framework will
 // be updated to provide these IDs directly to libaudiohal, the need for the mapper will cease.
+//
+// Note that unlike DeviceHalInterface, which sometimes allows a method to return an error,
+// but still consider some of the outputs to be valid (for example, in 'open{Input|Output}Stream'),
+// 'Hal2AidlMapper' follows the Binder convention. It means that if a method returns an error,
+// the outputs may not be initialized at all and should not be considered by the caller.
 class Hal2AidlMapper {
   public:
     using Cleanups = Cleanups<Hal2AidlMapper>;
@@ -49,27 +54,6 @@
             const std::vector<::aidl::android::media::audio::common::AudioPortConfig>& sources,
             const std::vector<::aidl::android::media::audio::common::AudioPortConfig>& sinks,
             int32_t* patchId, Cleanups* cleanups);
-    status_t findOrCreatePortConfig(
-            const ::aidl::android::media::audio::common::AudioDevice& device,
-            const ::aidl::android::media::audio::common::AudioConfig* config,
-            ::aidl::android::media::audio::common::AudioPortConfig* portConfig,
-            bool* created);
-    status_t findOrCreatePortConfig(
-            const ::aidl::android::media::audio::common::AudioConfig& config,
-            const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
-            int32_t ioHandle,
-            ::aidl::android::media::audio::common::AudioSource source,
-            const std::set<int32_t>& destinationPortIds,
-            ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
-    status_t findOrCreatePortConfig(
-        const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
-        const std::set<int32_t>& destinationPortIds,
-        ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
-    status_t findOrCreatePortConfig(
-        const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
-        const std::set<int32_t>& destinationPortIds,
-        ::aidl::android::media::audio::common::AudioPortConfig* portConfig,
-        Cleanups* cleanups = nullptr);
     status_t findPortConfig(
             const ::aidl::android::media::audio::common::AudioDevice& device,
             ::aidl::android::media::audio::common::AudioPortConfig* portConfig);
@@ -88,6 +72,8 @@
         return ::aidl::android::convertContainer(mRoutes, routes, converter);
     }
     status_t initialize();
+    // If the resulting 'mixPortConfig->id' is 0, that means the stream was not created,
+    // and 'config' is a suggested config.
     status_t prepareToOpenStream(
         int32_t ioHandle,
         const ::aidl::android::media::audio::common::AudioDevice& device,
@@ -97,6 +83,11 @@
         ::aidl::android::media::audio::common::AudioConfig* config,
         ::aidl::android::media::audio::common::AudioPortConfig* mixPortConfig,
         ::aidl::android::hardware::audio::core::AudioPatch* patch);
+    status_t setPortConfig(
+        const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
+        const std::set<int32_t>& destinationPortIds,
+        ::aidl::android::media::audio::common::AudioPortConfig* portConfig,
+        Cleanups* cleanups = nullptr);
     status_t releaseAudioPatch(int32_t patchId);
     void resetUnusedPatchesAndPortConfigs();
     status_t setDevicePortConnectedState(
@@ -128,9 +119,11 @@
             const ::aidl::android::media::audio::common::AudioPort& p);
     bool audioDeviceMatches(const ::aidl::android::media::audio::common::AudioDevice& device,
             const ::aidl::android::media::audio::common::AudioPortConfig& p);
+    // If the 'result->id' is 0, that means, the config was not created/updated,
+    // and the 'result' is a suggestion from the HAL.
     status_t createOrUpdatePortConfig(
             const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
-            PortConfigs::iterator* result, bool *created);
+            ::aidl::android::media::audio::common::AudioPortConfig* result, bool *created);
     void eraseConnectedPort(int32_t portId);
     status_t findOrCreatePatch(
         const std::set<int32_t>& sourcePortConfigIds,
@@ -139,6 +132,24 @@
     status_t findOrCreatePatch(
         const ::aidl::android::hardware::audio::core::AudioPatch& requestedPatch,
         ::aidl::android::hardware::audio::core::AudioPatch* patch, bool* created);
+    status_t findOrCreateDevicePortConfig(
+            const ::aidl::android::media::audio::common::AudioDevice& device,
+            const ::aidl::android::media::audio::common::AudioConfig* config,
+            ::aidl::android::media::audio::common::AudioPortConfig* portConfig,
+            bool* created);
+    // If the resulting 'portConfig->id' is 0, that means the config was not created,
+    // and 'portConfig' is a suggested config.
+    status_t findOrCreateMixPortConfig(
+            const ::aidl::android::media::audio::common::AudioConfig& config,
+            const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
+            int32_t ioHandle,
+            ::aidl::android::media::audio::common::AudioSource source,
+            const std::set<int32_t>& destinationPortIds,
+            ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
+    status_t findOrCreatePortConfig(
+        const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
+        const std::set<int32_t>& destinationPortIds,
+        ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
     Patches::iterator findPatch(const std::set<int32_t>& sourcePortConfigIds,
             const std::set<int32_t>& sinkPortConfigIds);
     Ports::iterator findPort(const ::aidl::android::media::audio::common::AudioDevice& device);
diff --git a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
index adff110..1204a3b 100644
--- a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
+++ b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
@@ -201,6 +201,9 @@
     ndk::ScopedAStatus getAAudioHardwareBurstMinUsec(int32_t*) override {
         return ndk::ScopedAStatus::ok();
     }
+    ndk::ScopedAStatus prepareToDisconnectExternalDevice(int32_t) override {
+        return ndk::ScopedAStatus::ok();
+    }
 
     bool mIsScreenTurnedOn = false;
     ScreenRotation mScreenRotation = ScreenRotation::DEG_0;
diff --git a/media/libeffects/loudness/dsp/core/dynamic_range_compression.cpp b/media/libeffects/loudness/dsp/core/dynamic_range_compression.cpp
index 578f58a..33f6779 100644
--- a/media/libeffects/loudness/dsp/core/dynamic_range_compression.cpp
+++ b/media/libeffects/loudness/dsp/core/dynamic_range_compression.cpp
@@ -89,8 +89,7 @@
   } else {
     state_ = alpha_release_ * state_ + (1.0f - alpha_release_) * cv;
   }
-  compressor_gain_ *=
-      math::ExpApproximationViaTaylorExpansionOrder5(state_ - prev_state);
+  compressor_gain_ *= expf(state_ - prev_state);
   x *= compressor_gain_;
   if (x > kFixedPointLimit) {
     return kFixedPointLimit;
@@ -118,8 +117,7 @@
   } else {
     state_ = alpha_release_ * state_ + (1.0f - alpha_release_) * cv;
   }
-  compressor_gain_ *=
-      math::ExpApproximationViaTaylorExpansionOrder5(state_ - prev_state);
+  compressor_gain_ *= expf(state_ - prev_state);
   *x1 *= compressor_gain_;
   if (*x1 > kFixedPointLimit) {
     *x1 = kFixedPointLimit;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index a625893..bb49b5a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1977,6 +1977,8 @@
         if (rate > 0) {
             format->setFloat("operating-rate", rate * mPlaybackSettings.mSpeed);
         }
+
+        format->setInt32("android._video-scaling", mVideoScalingMode);
     }
 
     Mutex::Autolock autoLock(mDecoderLock);
diff --git a/media/module/extractors/mp4/ItemTable.cpp b/media/module/extractors/mp4/ItemTable.cpp
index cf3df62..c6586fc 100644
--- a/media/module/extractors/mp4/ItemTable.cpp
+++ b/media/module/extractors/mp4/ItemTable.cpp
@@ -1501,9 +1501,9 @@
                     info.isExif(), (long long)offset, (long long)size);
             if ((info.isExif() && size > 4) || (info.isXmp() && size > 0)) {
                 ExternalMetaItem metaItem = {
-                        .isExif = info.isExif(),
                         .offset = offset,
                         .size = size,
+                        .isExif = info.isExif(),
                 };
                 mItemIdToMetaMap.add(info.itemId, metaItem);
             }
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index 559927a..b3707c8 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -522,7 +522,7 @@
         return AMEDIA_ERROR_UNKNOWN;
     }
 
-    [=] {
+    [this, &track] {
         int64_t duration;
         int32_t samplerate;
         // Only for audio track.
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 42e9078..a2b1c5e 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -427,6 +427,9 @@
 }
 
 void MtpDataPacket::putString(const uint16_t* string) {
+    if (string == NULL) {
+        return;
+    }
     int count = 0;
     for (int i = 0; i <= MTP_STRING_MAX_CHARACTER_NUMBER; i++) {
         if (string[i])
diff --git a/media/utils/MethodStatistics.cpp b/media/utils/MethodStatistics.cpp
index 086757b..80f0fc4 100644
--- a/media/utils/MethodStatistics.cpp
+++ b/media/utils/MethodStatistics.cpp
@@ -20,6 +20,8 @@
 
 // Repository for MethodStatistics Objects
 
+// It's important to have the HAL class name defined with suffix "Hidl/Aidl" because
+// TimerThread::isRequestFromHal use this string to match binder call to/from hal.
 std::shared_ptr<std::vector<std::string>>
 getStatisticsClassesForModule(std::string_view moduleName) {
     static const std::map<std::string, std::shared_ptr<std::vector<std::string>>,
@@ -34,6 +36,15 @@
                 "StreamOutHalHidl",
               })
         },
+        {
+            METHOD_STATISTICS_MODULE_NAME_AUDIO_AIDL,
+            std::shared_ptr<std::vector<std::string>>(
+                new std::vector<std::string>{
+                "DeviceHalAidl",
+                "EffectHalAidl",
+                "StreamHalAidl",
+              })
+        },
     };
     auto it = m.find(moduleName);
     if (it == m.end()) return {};
@@ -61,6 +72,9 @@
             addClassesToMap(
                     getStatisticsClassesForModule(METHOD_STATISTICS_MODULE_NAME_AUDIO_HIDL),
                     m);
+            addClassesToMap(
+                    getStatisticsClassesForModule(METHOD_STATISTICS_MODULE_NAME_AUDIO_AIDL),
+                    m);
             return m;
         }();
 
diff --git a/media/utils/TimerThread.cpp b/media/utils/TimerThread.cpp
index ad27af3..1c94691 100644
--- a/media/utils/TimerThread.cpp
+++ b/media/utils/TimerThread.cpp
@@ -129,11 +129,16 @@
 //
 /* static */
 bool TimerThread::isRequestFromHal(const std::shared_ptr<const Request>& request) {
-    const size_t hidlPos = request->tag.asStringView().find("Hidl");
-    if (hidlPos == std::string::npos) return false;
-    // should be a separator afterwards Hidl which indicates the string was in the class.
-    const size_t separatorPos = request->tag.asStringView().find("::", hidlPos);
-    return separatorPos != std::string::npos;
+    for (const auto& s : {"Hidl", "Aidl"}) {
+        const auto& tagSV = request->tag.asStringView();
+        const size_t halStrPos = tagSV.find(s);
+        // should be a separator afterwards Hidl/Aidl which indicates the string was in the class.
+        if (halStrPos != std::string::npos && tagSV.find("::", halStrPos) != std::string::npos) {
+            return true;
+        }
+    }
+
+    return false;
 }
 
 struct TimerThread::SnapshotAnalysis TimerThread::getSnapshotAnalysis(size_t retiredCount) const {
diff --git a/media/utils/include/mediautils/MethodStatistics.h b/media/utils/include/mediautils/MethodStatistics.h
index c8b36d8..2543dfa 100644
--- a/media/utils/include/mediautils/MethodStatistics.h
+++ b/media/utils/include/mediautils/MethodStatistics.h
@@ -124,6 +124,7 @@
 // Managed Statistics support.
 // Supported Modules
 #define METHOD_STATISTICS_MODULE_NAME_AUDIO_HIDL "AudioHidl"
+#define METHOD_STATISTICS_MODULE_NAME_AUDIO_AIDL "AudioAidl"
 
 // Returns a vector of class names for the module, or a nullptr if module not found.
 std::shared_ptr<std::vector<std::string>>
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 9420bf1..cb342ee 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -875,12 +875,15 @@
             dprintf(fd, "\nIEffect binder call profile:\n");
             write(fd, timeCheckStats.c_str(), timeCheckStats.size());
 
-            // Automatically fetch HIDL statistics.
-            std::shared_ptr<std::vector<std::string>> hidlClassNames =
-                    mediautils::getStatisticsClassesForModule(
-                            METHOD_STATISTICS_MODULE_NAME_AUDIO_HIDL);
-            if (hidlClassNames) {
-                for (const auto& className : *hidlClassNames) {
+            // Automatically fetch HIDL or AIDL statistics.
+            const std::string_view halType = (mDevicesFactoryHal->getHalVersion().getType() ==
+                                      AudioHalVersionInfo::Type::HIDL)
+                                             ? METHOD_STATISTICS_MODULE_NAME_AUDIO_HIDL
+                                             : METHOD_STATISTICS_MODULE_NAME_AUDIO_AIDL;
+            const std::shared_ptr<std::vector<std::string>> halClassNames =
+                    mediautils::getStatisticsClassesForModule(halType);
+            if (halClassNames) {
+                for (const auto& className : *halClassNames) {
                     auto stats = mediautils::getStatisticsForClass(className);
                     if (stats) {
                         timeCheckStats = stats->dump();
@@ -3222,41 +3225,19 @@
         return 0;
     }
 
-    audio_config_t halconfig = *config;
-    sp<DeviceHalInterface> inHwHal = inHwDev->hwDevice();
-    sp<StreamInHalInterface> inStream;
-    status_t status = inHwHal->openInputStream(
-            *input, devices, &halconfig, flags, address, source,
-            outputDevice, outputDeviceAddress, &inStream);
-    ALOGV("openInput_l() openInputStream returned input %p, devices %#x, SamplingRate %d"
-           ", Format %#x, Channels %#x, flags %#x, status %d addr %s",
-            inStream.get(),
+    AudioStreamIn *inputStream = nullptr;
+    status_t status = inHwDev->openInputStream(
+            &inputStream,
+            *input,
             devices,
-            halconfig.sample_rate,
-            halconfig.format,
-            halconfig.channel_mask,
             flags,
-            status, address);
+            config,
+            address,
+            source,
+            outputDevice,
+            outputDeviceAddress.c_str());
 
-    // If the input could not be opened with the requested parameters and we can handle the
-    // conversion internally, try to open again with the proposed parameters.
-    if (status == BAD_VALUE &&
-        audio_is_linear_pcm(config->format) &&
-        audio_is_linear_pcm(halconfig.format) &&
-        (halconfig.sample_rate <= AUDIO_RESAMPLER_DOWN_RATIO_MAX * config->sample_rate) &&
-        (audio_channel_count_from_in_mask(halconfig.channel_mask) <= FCC_LIMIT) &&
-        (audio_channel_count_from_in_mask(config->channel_mask) <= FCC_LIMIT)) {
-        // FIXME describe the change proposed by HAL (save old values so we can log them here)
-        ALOGV("openInput_l() reopening with proposed sampling rate and channel mask");
-        inStream.clear();
-        status = inHwHal->openInputStream(
-                *input, devices, &halconfig, flags, address, source,
-                outputDevice, outputDeviceAddress, &inStream);
-        // FIXME log this new status; HAL should not propose any further changes
-    }
-
-    if (status == NO_ERROR && inStream != 0) {
-        AudioStreamIn *inputStream = new AudioStreamIn(inHwDev, inStream, flags);
+    if (status == NO_ERROR) {
         if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
             const sp<IAfMmapCaptureThread> thread =
                     IAfMmapCaptureThread::create(this, *input, inHwDev, inputStream, mSystemReady);
diff --git a/services/audioflinger/IAfThread.h b/services/audioflinger/IAfThread.h
index 7084be9..46a67e8 100644
--- a/services/audioflinger/IAfThread.h
+++ b/services/audioflinger/IAfThread.h
@@ -386,6 +386,12 @@
             const effect_uuid_t* type, bool suspend, audio_session_t sessionId)
             REQUIRES(mutex()) = 0;
 
+    // Wait while the Thread is busy.  This is done to ensure that
+    // the Thread is not busy releasing the Tracks, during which the Thread mutex
+    // may be temporarily unlocked.  Some Track methods will use this method to
+    // avoid races.
+    virtual void waitWhileThreadBusy_l(audio_utils::unique_lock& ul)
+            REQUIRES(mutex()) = 0;
     // Dynamic cast to derived interface
     virtual sp<IAfDirectOutputThread> asIAfDirectOutputThread() { return nullptr; }
     virtual sp<IAfDuplicatingThread> asIAfDuplicatingThread() { return nullptr; }
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 4a1948c..b4cb805 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -23,6 +23,7 @@
 #include <audio_utils/mutex.h>
 #include <audio_utils/LinearMap.h>
 #include <binder/AppOpsManager.h>
+#include <utils/RWLock.h>
 
 namespace android {
 
@@ -352,6 +353,7 @@
     // Must hold thread lock to access tee patches
     template <class F>
     void                forEachTeePatchTrack_l(F f) {
+        RWLock::AutoRLock readLock(mTeePatchesRWLock);
         for (auto& tp : mTeePatches) { f(tp.patchTrack); }
     };
 
@@ -387,6 +389,7 @@
     audio_output_flags_t mFlags;
     TeePatches mTeePatches;
     std::optional<TeePatches> mTeePatchesToUpdate;
+    RWLock              mTeePatchesRWLock;
     const float         mSpeed;
     const bool          mIsSpatialized;
     const bool          mIsBitPerfect;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 18bb173..4d699b2 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2849,6 +2849,8 @@
         // effectively get the latency it requested.
         if (track->isExternalTrack()) {
             IAfTrackBase::track_state state = track->state();
+            // Because the track is not on the ActiveTracks,
+            // at this point, only the TrackHandle will be adding the track.
             mutex().unlock();
             status = AudioSystem::startOutput(track->portId());
             mutex().lock();
@@ -2929,7 +2931,12 @@
 
         track->setResetDone(false);
         track->resetPresentationComplete();
+
+        // Do not release the ThreadBase mutex after the track is added to mActiveTracks unless
+        // all key changes are complete.  It is possible that the threadLoop will begin
+        // processing the added track immediately after the ThreadBase mutex is released.
         mActiveTracks.add(track);
+
         if (chain != 0) {
             ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(),
                     track->sessionId());
@@ -4704,8 +4711,12 @@
 void PlaybackThread::removeTracks_l(const Vector<sp<IAfTrack>>& tracksToRemove)
 NO_THREAD_SAFETY_ANALYSIS  // release and re-acquire mutex()
 {
+    if (tracksToRemove.empty()) return;
+
+    // Block all incoming TrackHandle requests until we are finished with the release.
+    setThreadBusy_l(true);
+
     for (const auto& track : tracksToRemove) {
-        mActiveTracks.remove(track);
         ALOGV("%s(%d): removing track on session %d", __func__, track->id(), track->sessionId());
         sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
         if (chain != 0) {
@@ -4713,17 +4724,16 @@
                     __func__, track->id(), chain.get(), track->sessionId());
             chain->decActiveTrackCnt();
         }
+
         // If an external client track, inform APM we're no longer active, and remove if needed.
-        // We do this under lock so that the state is consistent if the Track is destroyed.
+        // Since the track is active, we do it here instead of TrackBase::destroy().
         if (track->isExternalTrack()) {
+            mutex().unlock();
             AudioSystem::stopOutput(track->portId());
             if (track->isTerminated()) {
                 AudioSystem::releaseOutput(track->portId());
             }
-        }
-        if (track->isTerminated()) {
-            // remove from our tracks vector
-            removeTrack_l(track);
+            mutex().lock();
         }
         if (mHapticChannelCount > 0 &&
                 ((track->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
@@ -4740,7 +4750,24 @@
                 chain->setHapticIntensity_l(track->id(), os::HapticScale::MUTE);
             }
         }
+
+        // Under lock, the track is removed from the active tracks list.
+        //
+        // Once the track is no longer active, the TrackHandle may directly
+        // modify it as the threadLoop() is no longer responsible for its maintenance.
+        // Do not modify the track from threadLoop after the mutex is unlocked
+        // if it is not active.
+        mActiveTracks.remove(track);
+
+        if (track->isTerminated()) {
+            // remove from our tracks vector
+            removeTrack_l(track);
+        }
     }
+
+    // Allow incoming TrackHandle requests.  We still hold the mutex,
+    // so pending TrackHandle requests will occur after we unlock it.
+    setThreadBusy_l(false);
 }
 
 status_t PlaybackThread::getTimestamp_l(AudioTimestamp& timestamp)
@@ -9579,10 +9606,24 @@
 
 void RecordThread::readInputParameters_l()
 {
-    status_t result = mInput->stream->getAudioProperties(&mSampleRate, &mChannelMask, &mHALFormat);
-    LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving audio properties from HAL: %d", result);
-    mFormat = mHALFormat;
+    const audio_config_base_t audioConfig = mInput->getAudioProperties();
+    mSampleRate = audioConfig.sample_rate;
+    mChannelMask = audioConfig.channel_mask;
+    if (!audio_is_input_channel(mChannelMask)) {
+        LOG_ALWAYS_FATAL("Channel mask %#x not valid for input", mChannelMask);
+    }
+
     mChannelCount = audio_channel_count_from_in_mask(mChannelMask);
+
+    // Get actual HAL format.
+    status_t result = mInput->stream->getAudioProperties(nullptr, nullptr, &mHALFormat);
+    LOG_ALWAYS_FATAL_IF(result != OK, "Error when retrieving input stream format: %d", result);
+    // Get format from the shim, which will be different than the HAL format
+    // if recording compressed audio from IEC61937 wrapped sources.
+    mFormat = audioConfig.format;
+    if (!audio_is_valid_format(mFormat)) {
+        LOG_ALWAYS_FATAL("Format %#x not valid for input", mFormat);
+    }
     if (audio_is_linear_pcm(mFormat)) {
         LOG_ALWAYS_FATAL_IF(mChannelCount > FCC_LIMIT, "HAL channel count %d > %d",
                 mChannelCount, FCC_LIMIT);
@@ -9590,8 +9631,7 @@
         // Can have more that FCC_LIMIT channels in encoded streams.
         ALOGI("HAL format %#x is not linear pcm", mFormat);
     }
-    result = mInput->stream->getFrameSize(&mFrameSize);
-    LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving frame size from HAL: %d", result);
+    mFrameSize = mInput->getFrameSize();
     LOG_ALWAYS_FATAL_IF(mFrameSize <= 0, "Error frame size was %zu but must be greater than zero",
             mFrameSize);
     result = mInput->stream->getBufferSize(&mBufferSize);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index ea994a5..8491e43 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -599,6 +599,35 @@
                 // check if some effects must be suspended when an effect chain is added
     void checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain) REQUIRES(mutex());
 
+    /**
+     * waitWhileThreadBusy_l() serves as a mutex gate, which does not allow
+     * progress beyond the method while the PlaybackThread is busy (see setThreadBusy_l()).
+     * During the wait, the ThreadBase_Mutex is temporarily unlocked.
+     *
+     * This implementation uses a condition variable.  Alternative methods to gate
+     * the thread may use a second mutex (i.e. entry based on scoped_lock(mutex, gating_mutex)),
+     * but those have less flexibility and more lock order issues.
+     *
+     * Current usage by Track::destroy(), Track::start(), Track::stop(), Track::pause(),
+     * and Track::flush() block this way, and the primary caller is through TrackHandle
+     * with no other mutexes held.
+     *
+     * Special tracks like PatchTrack and OutputTrack may also hold the another thread's
+     * ThreadBase_Mutex during this time.  No other mutex is held.
+     */
+
+    void waitWhileThreadBusy_l(audio_utils::unique_lock& ul) final REQUIRES(mutex()) {
+        // the wait returns immediately if the predicate is satisfied.
+        mThreadBusyCv.wait(ul, [&]{ return mThreadBusy == false;});
+    }
+
+    void setThreadBusy_l(bool busy) REQUIRES(mutex()) {
+        if (busy == mThreadBusy) return;
+        mThreadBusy = busy;
+        if (busy == true) return;  // no need to wake threads if we become busy.
+        mThreadBusyCv.notify_all();
+    }
+
                 // sends the metadata of the active tracks to the HAL
                 struct MetadataUpdate {
                     std::vector<playback_track_metadata_v7_t> playbackMetadataUpdate;
@@ -641,6 +670,13 @@
                 ThreadMetrics           mThreadMetrics;
                 const bool              mIsOut;
 
+    // mThreadBusy is checked under the ThreadBase_Mutex to ensure that
+    // TrackHandle operations do not proceed while the ThreadBase is busy
+    // with the track.  mThreadBusy is only true if the track is active.
+    //
+    bool mThreadBusy = false; // GUARDED_BY(ThreadBase_Mutex) but read in lambda.
+    audio_utils::condition_variable mThreadBusyCv;
+
                 // updated by PlaybackThread::readOutputParameters_l() or
                 // RecordThread::readInputParameters_l()
                 uint32_t                mSampleRate;
@@ -839,7 +875,7 @@
 
                 SimpleLog mLocalLog;  // locked internally
 
-private:
+    private:
     void dumpBase_l(int fd, const Vector<String16>& args) REQUIRES(mutex());
     void dumpEffectChains_l(int fd, const Vector<String16>& args) REQUIRES(mutex());
 };
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index fe582eb..4e82173 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -890,12 +890,17 @@
         bool wasActive = false;
         const sp<IAfThreadBase> thread = mThread.promote();
         if (thread != 0) {
-            audio_utils::lock_guard _l(thread->mutex());
+            audio_utils::unique_lock ul(thread->mutex());
+            thread->waitWhileThreadBusy_l(ul);
+
             auto* const playbackThread = thread->asIAfPlaybackThread().get();
             wasActive = playbackThread->destroyTrack_l(this);
             forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
         }
         if (isExternalTrack() && !wasActive) {
+            // If the track is not active, the TrackHandle is responsible for
+            // releasing the port id, not the ThreadBase::threadLoop().
+            // At this point, there is no concurrency issue as the track is going away.
             AudioSystem::releaseOutput(mPortId);
         }
     }
@@ -1079,7 +1084,13 @@
         // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
         // does not allow 0 frame size request contrary to getNextBuffer
     }
-    for (auto& teePatch : mTeePatches) {
+    TeePatches teePatches;
+    if (mTeePatchesRWLock.tryReadLock() == NO_ERROR) {
+        // Cache a copy of tee patches in case it is updated while using.
+        teePatches = mTeePatches;
+        mTeePatchesRWLock.unlock();
+    }
+    for (auto& teePatch : teePatches) {
         IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
         const size_t framesWritten = patchRecord->writeFrames(
                 sourceBuffer.i8, frameCount, mFrameSize);
@@ -1092,7 +1103,7 @@
     using namespace std::chrono_literals;
     // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
     ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
-             spent.count(), mTeePatches.size());
+             spent.count(), teePatches.size());
 }
 
 // ExtendedAudioBufferProvider interface
@@ -1181,7 +1192,9 @@
                 return PERMISSION_DENIED;
             }
         }
-        audio_utils::lock_guard _lth(thread->mutex());
+        audio_utils::unique_lock ul(thread->mutex());
+        thread->waitWhileThreadBusy_l(ul);
+
         track_state state = mState;
         // here the track could be either new, or restarted
         // in both cases "unstop" the track
@@ -1306,7 +1319,9 @@
     ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
     const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        audio_utils::lock_guard _l(thread->mutex());
+        audio_utils::unique_lock ul(thread->mutex());
+        thread->waitWhileThreadBusy_l(ul);
+
         track_state state = mState;
         if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
             // If the track is not active (PAUSED and buffers full), flush buffers
@@ -1341,7 +1356,9 @@
     ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
     const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        audio_utils::lock_guard _l(thread->mutex());
+        audio_utils::unique_lock ul(thread->mutex());
+        thread->waitWhileThreadBusy_l(ul);
+
         auto* const playbackThread = thread->asIAfPlaybackThread().get();
         switch (mState) {
         case STOPPING_1:
@@ -1378,7 +1395,9 @@
     ALOGV("%s(%d)", __func__, mId);
     const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        audio_utils::lock_guard _l(thread->mutex());
+        audio_utils::unique_lock ul(thread->mutex());
+        thread->waitWhileThreadBusy_l(ul);
+
         auto* const playbackThread = thread->asIAfPlaybackThread().get();
 
         // Flush the ring buffer now if the track is not active in the PlaybackThread.
@@ -1616,7 +1635,10 @@
 void Track::updateTeePatches_l() {
     if (mTeePatchesToUpdate.has_value()) {
         forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
-        mTeePatches = mTeePatchesToUpdate.value();
+        {
+            RWLock::AutoWLock writeLock(mTeePatchesRWLock);
+            mTeePatches = std::move(mTeePatchesToUpdate.value());
+        }
         if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
                 mState == TrackBase::STOPPING_1) {
             forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); });
diff --git a/services/audioflinger/datapath/Android.bp b/services/audioflinger/datapath/Android.bp
index ee98aef..4235f14 100644
--- a/services/audioflinger/datapath/Android.bp
+++ b/services/audioflinger/datapath/Android.bp
@@ -43,11 +43,14 @@
 
     srcs: [
         "AudioHwDevice.cpp",
+        "AudioStreamIn.cpp",
         "AudioStreamOut.cpp",
+        "SpdifStreamIn.cpp",
         "SpdifStreamOut.cpp",
     ],
 
     header_libs: [
+        "libaudioclient_headers",
         "libaudiohal_headers",
         "liberror_headers",
     ],
diff --git a/services/audioflinger/datapath/AudioHwDevice.cpp b/services/audioflinger/datapath/AudioHwDevice.cpp
index 67e9991..95e9ecc 100644
--- a/services/audioflinger/datapath/AudioHwDevice.cpp
+++ b/services/audioflinger/datapath/AudioHwDevice.cpp
@@ -1,19 +1,19 @@
 /*
-**
-** Copyright 2007, 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.
-*/
+ *
+ * Copyright 2007, 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 "AudioHwDevice"
 //#define LOG_NDEBUG 0
@@ -21,10 +21,13 @@
 #include <system/audio.h>
 #include <utils/Log.h>
 
+#include <audio_utils/spdif/SPDIFDecoder.h>
 #include <audio_utils/spdif/SPDIFEncoder.h>
+#include <media/AudioResamplerPublic.h>
 
 #include "AudioHwDevice.h"
 #include "AudioStreamOut.h"
+#include "SpdifStreamIn.h"
 #include "SpdifStreamOut.h"
 
 namespace android {
@@ -47,12 +50,8 @@
     auto outputStream = new AudioStreamOut(this, flags);
 
     // Try to open the HAL first using the current format.
-    ALOGV("openOutputStream(), try "
-            " sampleRate %d, Format %#x, "
-            "channelMask %#x",
-            config->sample_rate,
-            config->format,
-            config->channel_mask);
+    ALOGV("openOutputStream(), try sampleRate %d, format %#x, channelMask %#x", config->sample_rate,
+            config->format, config->channel_mask);
     status_t status = outputStream->open(handle, deviceType, config, address);
 
     if (status != NO_ERROR) {
@@ -62,13 +61,8 @@
         // FIXME Look at any modification to the config.
         // The HAL might modify the config to suggest a wrapped format.
         // Log this so we can see what the HALs are doing.
-        ALOGI("openOutputStream(), HAL returned"
-            " sampleRate %d, Format %#x, "
-            "channelMask %#x, status %d",
-            config->sample_rate,
-            config->format,
-            config->channel_mask,
-            status);
+        ALOGI("openOutputStream(), HAL returned sampleRate %d, format %#x, channelMask %#x,"
+                " status %d", config->sample_rate, config->format, config->channel_mask, status);
 
         // If the data is encoded then try again using wrapped PCM.
         const bool wrapperNeeded = !audio_has_proportional_frames(originalConfig.format)
@@ -96,6 +90,79 @@
     return status;
 }
 
+status_t AudioHwDevice::openInputStream(
+        AudioStreamIn **ppStreamIn,
+        audio_io_handle_t handle,
+        audio_devices_t deviceType,
+        audio_input_flags_t flags,
+        struct audio_config *config,
+        const char *address,
+        audio_source_t source,
+        audio_devices_t outputDevice,
+        const char *outputDeviceAddress) {
+
+    struct audio_config originalConfig = *config;
+    auto inputStream = new AudioStreamIn(this, flags);
+
+    // Try to open the HAL first using the current format.
+    ALOGV("openInputStream(), try sampleRate %d, format %#x, channelMask %#x", config->sample_rate,
+            config->format, config->channel_mask);
+    status_t status = inputStream->open(handle, deviceType, config, address, source, outputDevice,
+                                        outputDeviceAddress);
+
+    // If the input could not be opened with the requested parameters and we can handle the
+    // conversion internally, try to open again with the proposed parameters.
+    if (status == BAD_VALUE &&
+        audio_is_linear_pcm(originalConfig.format) &&
+        audio_is_linear_pcm(config->format) &&
+        (config->sample_rate <= AUDIO_RESAMPLER_DOWN_RATIO_MAX * config->sample_rate) &&
+        (audio_channel_count_from_in_mask(config->channel_mask) <= FCC_LIMIT) &&
+        (audio_channel_count_from_in_mask(originalConfig.channel_mask) <= FCC_LIMIT)) {
+        // FIXME describe the change proposed by HAL (save old values so we can log them here)
+        ALOGV("openInputStream() reopening with proposed sampling rate and channel mask");
+        status = inputStream->open(handle, deviceType, config, address, source,
+                outputDevice, outputDeviceAddress);
+        // FIXME log this new status; HAL should not propose any further changes
+        if (status != NO_ERROR) {
+            delete inputStream;
+            inputStream = nullptr;
+        }
+    } else if (status != NO_ERROR) {
+        delete inputStream;
+        inputStream = nullptr;
+
+        // FIXME Look at any modification to the config.
+        // The HAL might modify the config to suggest a wrapped format.
+        // Log this so we can see what the HALs are doing.
+        ALOGI("openInputStream(), HAL returned sampleRate %d, format %#x, channelMask %#x,"
+                " status %d", config->sample_rate, config->format, config->channel_mask, status);
+
+        // If the data is encoded then try again using wrapped PCM.
+        const bool unwrapperNeeded = !audio_has_proportional_frames(originalConfig.format)
+                && ((flags & AUDIO_INPUT_FLAG_DIRECT) != 0);
+
+        if (unwrapperNeeded) {
+            if (SPDIFDecoder::isFormatSupported(originalConfig.format)) {
+                inputStream = new SpdifStreamIn(this, flags, originalConfig.format);
+                status = inputStream->open(handle, deviceType, &originalConfig, address, source,
+                        outputDevice, outputDeviceAddress);
+                if (status != NO_ERROR) {
+                    ALOGE("ERROR - openInputStream(), SPDIF open returned %d",
+                        status);
+                    delete inputStream;
+                    inputStream = nullptr;
+                }
+            } else {
+                ALOGE("ERROR - openInputStream(), SPDIFDecoder does not support format 0x%08x",
+                    originalConfig.format);
+            }
+        }
+    }
+
+    *ppStreamIn = inputStream;
+    return status;
+}
+
 bool AudioHwDevice::supportsAudioPatches() const {
     bool result;
     return mHwDevice->supportsAudioPatches(&result) == OK ? result : false;
diff --git a/services/audioflinger/datapath/AudioHwDevice.h b/services/audioflinger/datapath/AudioHwDevice.h
index cfb6fbd..80c1473 100644
--- a/services/audioflinger/datapath/AudioHwDevice.h
+++ b/services/audioflinger/datapath/AudioHwDevice.h
@@ -1,22 +1,21 @@
 /*
-**
-** Copyright 2007, 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.
-*/
+ *
+ * Copyright 2007, 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_HW_DEVICE_H
-#define ANDROID_AUDIO_HW_DEVICE_H
+#pragma once
 
 #include <stdint.h>
 #include <stdlib.h>
@@ -30,6 +29,7 @@
 
 namespace android {
 
+class AudioStreamIn;
 class AudioStreamOut;
 
 class AudioHwDevice {
@@ -89,6 +89,17 @@
             struct audio_config *config,
             const char *address);
 
+    status_t openInputStream(
+            AudioStreamIn **ppStreamIn,
+            audio_io_handle_t handle,
+            audio_devices_t deviceType,
+            audio_input_flags_t flags,
+            struct audio_config *config,
+            const char *address,
+            audio_source_t source,
+            audio_devices_t outputDevice,
+            const char *outputDeviceAddress);
+
     [[nodiscard]] bool supportsAudioPatches() const;
 
     [[nodiscard]] status_t getAudioPort(struct audio_port_v7 *port) const;
@@ -112,5 +123,3 @@
 };
 
 } // namespace android
-
-#endif // ANDROID_AUDIO_HW_DEVICE_H
diff --git a/services/audioflinger/datapath/AudioStreamIn.cpp b/services/audioflinger/datapath/AudioStreamIn.cpp
new file mode 100644
index 0000000..24f3bb9
--- /dev/null
+++ b/services/audioflinger/datapath/AudioStreamIn.cpp
@@ -0,0 +1,137 @@
+/*
+ *
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioFlinger"
+//#define LOG_NDEBUG 0
+#include "AudioStreamIn.h"
+
+#include <media/audiohal/DeviceHalInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
+#include <system/audio.h>
+#include <utils/Log.h>
+
+#include "AudioHwDevice.h"
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+AudioStreamIn::AudioStreamIn(AudioHwDevice *dev, audio_input_flags_t flags)
+        : audioHwDev(dev)
+        , flags(flags)
+{
+}
+
+// This must be defined here together with the HAL includes above and
+// not solely in the header.
+AudioStreamIn::~AudioStreamIn() = default;
+
+sp<DeviceHalInterface> AudioStreamIn::hwDev() const
+{
+    return audioHwDev->hwDevice();
+}
+
+status_t AudioStreamIn::getCapturePosition(int64_t* frames, int64_t* time)
+{
+    if (stream == nullptr) {
+        return NO_INIT;
+    }
+
+    int64_t halPosition = 0;
+    const status_t status = stream->getCapturePosition(&halPosition, time);
+    if (status != NO_ERROR) {
+        return status;
+    }
+
+    // Adjust for standby using HAL rate frames.
+    // Only apply this correction if the HAL is getting PCM frames.
+    if (mHalFormatHasProportionalFrames) {
+        const uint64_t adjustedPosition = (halPosition <= mFramesReadAtStandby) ?
+                0 : (halPosition - mFramesReadAtStandby);
+        // Scale from HAL sample rate to application rate.
+        *frames = adjustedPosition / mRateMultiplier;
+    } else {
+        // For compressed formats.
+        *frames = halPosition;
+    }
+
+    return status;
+}
+
+status_t AudioStreamIn::open(
+        audio_io_handle_t handle,
+        audio_devices_t deviceType,
+        struct audio_config *config,
+        const char *address,
+        audio_source_t source,
+        audio_devices_t outputDevice,
+        const char *outputDeviceAddress)
+{
+    sp<StreamInHalInterface> inStream;
+
+    int status = hwDev()->openInputStream(
+            handle,
+            deviceType,
+            config,
+            flags,
+            address,
+            source,
+            outputDevice,
+            outputDeviceAddress,
+            &inStream);
+    ALOGV("AudioStreamIn::open(), HAL returned stream %p, sampleRate %d, format %#x,"
+            " channelMask %#x, status %d", inStream.get(), config->sample_rate, config->format,
+            config->channel_mask, status);
+
+    if (status == NO_ERROR) {
+        stream = inStream;
+        mHalFormatHasProportionalFrames = audio_has_proportional_frames(config->format);
+        status = stream->getFrameSize(&mHalFrameSize);
+        LOG_ALWAYS_FATAL_IF(status != OK, "Error retrieving frame size from HAL: %d", status);
+        LOG_ALWAYS_FATAL_IF(mHalFrameSize == 0, "Error frame size was %zu but must be greater than"
+                " zero", mHalFrameSize);
+    }
+
+    return status;
+}
+
+audio_config_base_t AudioStreamIn::getAudioProperties() const
+{
+    audio_config_base_t result = AUDIO_CONFIG_BASE_INITIALIZER;
+    if (stream->getAudioProperties(&result) != OK) {
+        result.sample_rate = 0;
+        result.channel_mask = AUDIO_CHANNEL_INVALID;
+        result.format = AUDIO_FORMAT_INVALID;
+    }
+    return result;
+}
+
+status_t AudioStreamIn::standby()
+{
+    mFramesReadAtStandby = mFramesRead;
+    return stream->standby();
+}
+
+status_t AudioStreamIn::read(void* buffer, size_t bytes, size_t* read)
+{
+    const status_t result = stream->read(buffer, bytes, read);
+    if (result == OK && *read > 0 && mHalFrameSize > 0) {
+        mFramesRead += *read / mHalFrameSize;
+    }
+    return result;
+}
+
+} // namespace android
diff --git a/services/audioflinger/datapath/AudioStreamIn.h b/services/audioflinger/datapath/AudioStreamIn.h
index 604a4e4..6d1c6a7 100644
--- a/services/audioflinger/datapath/AudioStreamIn.h
+++ b/services/audioflinger/datapath/AudioStreamIn.h
@@ -31,30 +31,57 @@
     virtual status_t standby() = 0;
 };
 
-// AudioStreamIn is immutable, so its fields are const.
-// The methods must not be const to match StreamHalInterface signature.
-
-struct AudioStreamIn : public Source {
+/**
+ * Managed access to a HAL input stream.
+ */
+class AudioStreamIn : public Source {
+public:
     const AudioHwDevice* const audioHwDev;
-    const sp<StreamInHalInterface> stream;
+    sp<StreamInHalInterface> stream;
     const audio_input_flags_t flags;
 
-    AudioStreamIn(
-            const AudioHwDevice* dev, const sp<StreamInHalInterface>& in,
-            audio_input_flags_t flags)
-        : audioHwDev(dev), stream(in), flags(flags) {}
+    [[nodiscard]] sp<DeviceHalInterface> hwDev() const;
 
-    status_t read(void* buffer, size_t bytes, size_t* read) final {
-        return stream->read(buffer, bytes, read);
-    }
+    AudioStreamIn(AudioHwDevice *dev, audio_input_flags_t flags);
 
-    status_t getCapturePosition(int64_t* frames, int64_t* time) final {
-        return stream->getCapturePosition(frames, time);
-    }
+    virtual status_t open(
+            audio_io_handle_t handle,
+            audio_devices_t deviceType,
+            struct audio_config *config,
+            const char *address,
+            audio_source_t source,
+            audio_devices_t outputDevice,
+            const char *outputDeviceAddress);
 
-    status_t standby() final { return stream->standby(); }
+    ~AudioStreamIn() override;
 
-    sp<DeviceHalInterface> hwDev() const { return audioHwDev->hwDevice(); }
+    status_t getCapturePosition(int64_t* frames, int64_t* time) override;
+
+    status_t read(void* buffer, size_t bytes, size_t* read) override;
+
+    /**
+     * @return frame size from the perspective of the application and the AudioFlinger.
+     */
+    [[nodiscard]] virtual size_t getFrameSize() const { return mHalFrameSize; }
+
+    /**
+     * @return audio stream configuration: channel mask, format, sample rate:
+     *   - channel mask from the perspective of the application and the AudioFlinger,
+     *     The HAL is in stereo mode when playing multi-channel compressed audio over HDMI;
+     *   - format from the perspective of the application and the AudioFlinger;
+     *   - sample rate from the perspective of the application and the AudioFlinger,
+     *     The HAL may be running at a higher sample rate if, for example, playing wrapped EAC3.
+     */
+    [[nodiscard]] virtual audio_config_base_t getAudioProperties() const;
+
+    status_t standby() override;
+
+protected:
+    uint64_t mFramesRead = 0;
+    int64_t mFramesReadAtStandby = 0;
+    int mRateMultiplier = 1;
+    bool mHalFormatHasProportionalFrames = false;
+    size_t mHalFrameSize = 0;
 };
 
 }  // namespace android
diff --git a/services/audioflinger/datapath/AudioStreamOut.cpp b/services/audioflinger/datapath/AudioStreamOut.cpp
index 6fa82e5..1830d15 100644
--- a/services/audioflinger/datapath/AudioStreamOut.cpp
+++ b/services/audioflinger/datapath/AudioStreamOut.cpp
@@ -1,30 +1,31 @@
 /*
-**
-** Copyright 2015, 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.
-*/
+ *
+ * Copyright 2015, 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 "AudioFlinger"
 //#define LOG_NDEBUG 0
 
+#include "AudioStreamOut.h"
+
 #include <media/audiohal/DeviceHalInterface.h>
 #include <media/audiohal/StreamHalInterface.h>
 #include <system/audio.h>
 #include <utils/Log.h>
 
 #include "AudioHwDevice.h"
-#include "AudioStreamOut.h"
 
 namespace android {
 
@@ -132,14 +133,9 @@
             config,
             address,
             &outStream);
-    ALOGV("AudioStreamOut::open(), HAL returned "
-            " stream %p, sampleRate %d, Format %#x, "
-            "channelMask %#x, status %d",
-            outStream.get(),
-            config->sample_rate,
-            config->format,
-            config->channel_mask,
-            status);
+    ALOGV("AudioStreamOut::open(), HAL returned stream %p, sampleRate %d, format %#x,"
+            " channelMask %#x, status %d", outStream.get(), config->sample_rate, config->format,
+            config->channel_mask, status);
 
     // Some HALs may not recognize AUDIO_FORMAT_IEC61937. But if we declare
     // it as PCM then it will probably work.
@@ -162,7 +158,7 @@
         mHalFormatHasProportionalFrames = audio_has_proportional_frames(config->format);
         status = stream->getFrameSize(&mHalFrameSize);
         LOG_ALWAYS_FATAL_IF(status != OK, "Error retrieving frame size from HAL: %d", status);
-        LOG_ALWAYS_FATAL_IF(mHalFrameSize <= 0, "Error frame size was %zu but must be greater than"
+        LOG_ALWAYS_FATAL_IF(mHalFrameSize == 0, "Error frame size was %zu but must be greater than"
                 " zero", mHalFrameSize);
 
     }
diff --git a/services/audioflinger/datapath/AudioStreamOut.h b/services/audioflinger/datapath/AudioStreamOut.h
index ce00f8c..ea41bba 100644
--- a/services/audioflinger/datapath/AudioStreamOut.h
+++ b/services/audioflinger/datapath/AudioStreamOut.h
@@ -1,27 +1,28 @@
 /*
-**
-** Copyright 2015, 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.
-*/
+ *
+ * Copyright 2015, 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_STREAM_OUT_H
-#define ANDROID_AUDIO_STREAM_OUT_H
+#pragma once
 
 #include <stdint.h>
 #include <sys/types.h>
 
 #include <system/audio.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
 
 namespace android {
 
@@ -34,9 +35,6 @@
  */
 class AudioStreamOut {
 public:
-// AudioStreamOut is immutable, so its fields are const.
-// For emphasis, we could also make all pointers to them be "const *",
-// but that would clutter the code unnecessarily.
     AudioHwDevice * const audioHwDev;
     sp<StreamOutHalInterface> stream;
     const audio_output_flags_t flags;
@@ -101,15 +99,13 @@
     virtual void presentationComplete() { mExpectRetrograde = true; }
 
 protected:
-    uint64_t             mFramesWritten = 0; // reset by flush
-    uint64_t             mFramesWrittenAtStandby = 0;
-    uint64_t             mRenderPosition = 0; // reset by flush, standby, or presentation complete
-    int                  mRateMultiplier = 1;
-    bool                 mHalFormatHasProportionalFrames = false;
-    size_t               mHalFrameSize = 0;
-    bool                 mExpectRetrograde = false; // see presentationComplete
+    uint64_t mFramesWritten = 0; // reset by flush
+    uint64_t mFramesWrittenAtStandby = 0;
+    uint64_t mRenderPosition = 0; // reset by flush, standby, or presentation complete
+    int mRateMultiplier = 1;
+    bool mHalFormatHasProportionalFrames = false;
+    size_t mHalFrameSize = 0;
+    bool mExpectRetrograde = false; // see presentationComplete
 };
 
 } // namespace android
-
-#endif // ANDROID_AUDIO_STREAM_OUT_H
diff --git a/services/audioflinger/datapath/SpdifStreamIn.cpp b/services/audioflinger/datapath/SpdifStreamIn.cpp
new file mode 100644
index 0000000..98ce712
--- /dev/null
+++ b/services/audioflinger/datapath/SpdifStreamIn.cpp
@@ -0,0 +1,128 @@
+/*
+ *
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioFlinger"
+//#define LOG_NDEBUG 0
+#include "Configuration.h"
+#include <system/audio.h>
+#include <utils/Log.h>
+
+#include <audio_utils/spdif/SPDIFDecoder.h>
+
+#include "AudioHwDevice.h"
+#include "SpdifStreamIn.h"
+
+namespace android {
+
+/**
+ * If the HAL is generating IEC61937 data and AudioFlinger expects elementary stream then we need to
+ * extract the data using an SPDIF decoder.
+ */
+SpdifStreamIn::SpdifStreamIn(AudioHwDevice *dev,
+            audio_input_flags_t flags,
+            audio_format_t format)
+        : AudioStreamIn(dev, flags)
+        , mSpdifDecoder(this, format)
+{
+}
+
+status_t SpdifStreamIn::open(
+        audio_io_handle_t handle,
+        audio_devices_t devices,
+        struct audio_config *config,
+        const char *address,
+        audio_source_t source,
+        audio_devices_t outputDevice,
+        const char* outputDeviceAddress)
+{
+    struct audio_config customConfig = *config;
+
+    mApplicationConfig.format = config->format;
+    mApplicationConfig.sample_rate = config->sample_rate;
+    mApplicationConfig.channel_mask = config->channel_mask;
+
+    mRateMultiplier = spdif_rate_multiplier(config->format);
+    if (mRateMultiplier <= 0) {
+        ALOGE("ERROR SpdifStreamIn::open() unrecognized format 0x%08X\n", config->format);
+        return BAD_VALUE;
+    }
+    customConfig.sample_rate = config->sample_rate * mRateMultiplier;
+    customConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+    customConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
+
+    // Always print this because otherwise it could be very confusing if the
+    // HAL and AudioFlinger are using different formats.
+    // Print before open() because HAL may modify customConfig.
+    ALOGI("SpdifStreamIn::open() AudioFlinger requested sampleRate %d, format %#x, channelMask %#x",
+            config->sample_rate, config->format, config->channel_mask);
+    ALOGI("SpdifStreamIn::open() HAL configured for sampleRate %d, format %#x, channelMask %#x",
+            customConfig.sample_rate, customConfig.format, customConfig.channel_mask);
+
+    const status_t status = AudioStreamIn::open(
+            handle,
+            devices,
+            &customConfig,
+            address,
+            source,
+            outputDevice,
+            outputDeviceAddress);
+
+    ALOGI("SpdifStreamIn::open() status = %d", status);
+
+#ifdef TEE_SINK
+    if (status == OK) {
+        // Don't use PCM 16-bit format to avoid WAV encoding IEC61937 data.
+        mTee.set(customConfig.sample_rate,
+                audio_channel_count_from_in_mask(customConfig.channel_mask),
+                AUDIO_FORMAT_IEC61937, NBAIO_Tee::TEE_FLAG_INPUT_THREAD);
+        mTee.setId(std::string("_") + std::to_string(handle) + "_C");
+    }
+#endif
+
+    return status;
+}
+
+int SpdifStreamIn::standby()
+{
+    mSpdifDecoder.reset();
+    return AudioStreamIn::standby();
+}
+
+status_t SpdifStreamIn::readDataBurst(void* buffer, size_t bytes, size_t* read)
+{
+    status_t status = AudioStreamIn::read(buffer, bytes, read);
+
+#ifdef TEE_SINK
+    if (*read > 0) {
+        mTee.write(reinterpret_cast<const char *>(buffer), *read / AudioStreamIn::getFrameSize());
+    }
+#endif
+    return status;
+}
+
+status_t SpdifStreamIn::read(void* buffer, size_t numBytes, size_t* read)
+{
+    // Read from SPDIF extractor. It will call back to readDataBurst().
+    const auto bytesRead = mSpdifDecoder.read(buffer, numBytes);
+    if (bytesRead >= 0) {
+        *read = bytesRead;
+        return OK;
+    }
+    return NOT_ENOUGH_DATA;
+}
+
+} // namespace android
diff --git a/services/audioflinger/datapath/SpdifStreamIn.h b/services/audioflinger/datapath/SpdifStreamIn.h
new file mode 100644
index 0000000..78832ee
--- /dev/null
+++ b/services/audioflinger/datapath/SpdifStreamIn.h
@@ -0,0 +1,134 @@
+/*
+ *
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <system/audio.h>
+
+#include "AudioStreamIn.h"
+
+#include <audio_utils/spdif/SPDIFDecoder.h>
+#include <afutils/NBAIO_Tee.h>
+
+namespace android {
+
+/**
+ * Stream that is a PCM data burst in the HAL but looks like an encoded stream
+ * to the AudioFlinger. Wraps encoded data in an SPDIF wrapper per IEC61973-3.
+ */
+class SpdifStreamIn : public AudioStreamIn {
+public:
+
+    SpdifStreamIn(AudioHwDevice *dev, audio_input_flags_t flags,
+            audio_format_t format);
+
+    status_t open(
+            audio_io_handle_t handle,
+            audio_devices_t devices,
+            struct audio_config *config,
+            const char *address,
+            audio_source_t source,
+            audio_devices_t outputDevice,
+            const char* outputDeviceAddress) override;
+
+    /**
+    * Read audio buffer from driver. If at least one frame was read successfully prior to the error,
+    * it is suggested that the driver return that successful (short) byte count
+    * and then return an error in the subsequent call.
+    *
+    * If set_callback() has previously been called to enable non-blocking mode
+    * the write() is not allowed to block. It must write only the number of
+    * bytes that currently fit in the driver/hardware buffer and then return
+    * this byte count. If this is less than the requested write size the
+    * callback function must be called when more space is available in the
+    * driver/hardware buffer.
+    */
+    status_t read(void* buffer, size_t bytes, size_t* read) override;
+
+    /**
+     * @return frame size from the perspective of the application and the AudioFlinger.
+     */
+    [[nodiscard]] size_t getFrameSize() const override { return sizeof(int8_t); }
+
+    /**
+     * @return audio_config_base_t from the perspective of the application and the AudioFlinger.
+     */
+    [[nodiscard]] audio_config_base_t getAudioProperties() const override {
+        return mApplicationConfig;
+    }
+
+    /**
+     * @return format from the perspective of the application and the AudioFlinger.
+     */
+    [[nodiscard]] virtual audio_format_t getFormat() const { return mApplicationConfig.format; }
+
+    /**
+     * The HAL may be running at a higher sample rate if, for example, reading wrapped EAC3.
+     * @return sample rate from the perspective of the application and the AudioFlinger.
+     */
+    [[nodiscard]] virtual uint32_t getSampleRate() const { return mApplicationConfig.sample_rate; }
+
+    /**
+     * The HAL is in stereo mode when reading multi-channel compressed audio.
+     * @return channel mask from the perspective of the application and the AudioFlinger.
+     */
+    [[nodiscard]] virtual audio_channel_mask_t getChannelMask() const {
+        return mApplicationConfig.channel_mask;
+    }
+
+    status_t standby() override;
+
+private:
+
+    class MySPDIFDecoder : public SPDIFDecoder
+    {
+    public:
+        MySPDIFDecoder(SpdifStreamIn *spdifStreamIn, audio_format_t format)
+          :  SPDIFDecoder(format)
+          , mSpdifStreamIn(spdifStreamIn)
+        {
+        }
+
+        ssize_t readInput(void* buffer, size_t bytes) override
+        {
+            size_t bytesRead = 0;
+            const auto result = mSpdifStreamIn->readDataBurst(buffer, bytes, &bytesRead);
+            if (result < 0) {
+                return result;
+            }
+            return bytesRead;
+        }
+
+    protected:
+        SpdifStreamIn * const mSpdifStreamIn;
+    };
+
+    MySPDIFDecoder mSpdifDecoder;
+    audio_config_base_t mApplicationConfig = AUDIO_CONFIG_BASE_INITIALIZER;
+
+    status_t readDataBurst(void* data, size_t bytes, size_t* read);
+
+#ifdef TEE_SINK
+    NBAIO_Tee mTee;
+#endif
+
+};
+
+} // namespace android
diff --git a/services/audioflinger/datapath/SpdifStreamOut.cpp b/services/audioflinger/datapath/SpdifStreamOut.cpp
index 0c6a5a1..65a4eec 100644
--- a/services/audioflinger/datapath/SpdifStreamOut.cpp
+++ b/services/audioflinger/datapath/SpdifStreamOut.cpp
@@ -1,19 +1,19 @@
 /*
-**
-** Copyright 2015, 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.
-*/
+ *
+ * Copyright 2015, 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 "AudioFlinger"
 //#define LOG_NDEBUG 0
@@ -42,10 +42,10 @@
 }
 
 status_t SpdifStreamOut::open(
-                              audio_io_handle_t handle,
-                              audio_devices_t devices,
-                              struct audio_config *config,
-                              const char *address)
+        audio_io_handle_t handle,
+        audio_devices_t devices,
+        struct audio_config *config,
+        const char *address)
 {
     struct audio_config customConfig = *config;
 
@@ -53,22 +53,10 @@
     mApplicationConfig.sample_rate = config->sample_rate;
     mApplicationConfig.channel_mask = config->channel_mask;
 
-    // Some data bursts run at a higher sample rate.
-    // TODO Move this into the audio_utils as a static method.
-    switch(config->format) {
-        case AUDIO_FORMAT_E_AC3:
-        case AUDIO_FORMAT_E_AC3_JOC:
-            mRateMultiplier = 4;
-            break;
-        case AUDIO_FORMAT_AC3:
-        case AUDIO_FORMAT_DTS:
-        case AUDIO_FORMAT_DTS_HD:
-            mRateMultiplier = 1;
-            break;
-        default:
-            ALOGE("ERROR SpdifStreamOut::open() unrecognized format 0x%08X\n",
-                config->format);
-            return BAD_VALUE;
+    mRateMultiplier = spdif_rate_multiplier(config->format);
+    if (mRateMultiplier <= 0) {
+        ALOGE("ERROR SpdifStreamOut::open() unrecognized format 0x%08X\n", config->format);
+        return BAD_VALUE;
     }
     customConfig.sample_rate = config->sample_rate * mRateMultiplier;
 
@@ -78,16 +66,10 @@
     // Always print this because otherwise it could be very confusing if the
     // HAL and AudioFlinger are using different formats.
     // Print before open() because HAL may modify customConfig.
-    ALOGI("SpdifStreamOut::open() AudioFlinger requested"
-            " sampleRate %d, format %#x, channelMask %#x",
-            config->sample_rate,
-            config->format,
-            config->channel_mask);
-    ALOGI("SpdifStreamOut::open() HAL configured for"
-            " sampleRate %d, format %#x, channelMask %#x",
-            customConfig.sample_rate,
-            customConfig.format,
-            customConfig.channel_mask);
+    ALOGI("SpdifStreamOut::open() AudioFlinger requested sampleRate %d, format %#x,"
+            " channelMask %#x", config->sample_rate, config->format, config->channel_mask);
+    ALOGI("SpdifStreamOut::open() HAL configured for sampleRate %d, format %#x, channelMask %#x",
+            customConfig.sample_rate, customConfig.format, customConfig.channel_mask);
 
     const status_t status = AudioStreamOut::open(
             handle,
diff --git a/services/audioflinger/datapath/SpdifStreamOut.h b/services/audioflinger/datapath/SpdifStreamOut.h
index 56d57f6..c6d27ba 100644
--- a/services/audioflinger/datapath/SpdifStreamOut.h
+++ b/services/audioflinger/datapath/SpdifStreamOut.h
@@ -1,22 +1,21 @@
 /*
-**
-** Copyright 2015, 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.
-*/
+ *
+ * Copyright 2015, 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_SPDIF_STREAM_OUT_H
-#define ANDROID_SPDIF_STREAM_OUT_H
+#pragma once
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -40,8 +39,6 @@
     SpdifStreamOut(AudioHwDevice *dev, audio_output_flags_t flags,
             audio_format_t format);
 
-    ~SpdifStreamOut() override = default;
-
     status_t open(
             audio_io_handle_t handle,
             audio_devices_t devices,
@@ -116,10 +113,10 @@
         SpdifStreamOut * const mSpdifStreamOut;
     };
 
-    MySPDIFEncoder       mSpdifEncoder;
-    audio_config_base_t  mApplicationConfig = AUDIO_CONFIG_BASE_INITIALIZER;
+    MySPDIFEncoder mSpdifEncoder;
+    audio_config_base_t mApplicationConfig = AUDIO_CONFIG_BASE_INITIALIZER;
 
-    ssize_t  writeDataBurst(const void* data, size_t bytes);
+    ssize_t writeDataBurst(const void* data, size_t bytes);
 
 #ifdef TEE_SINK
     NBAIO_Tee mTee;
@@ -128,5 +125,3 @@
 };
 
 } // namespace android
-
-#endif // ANDROID_SPDIF_STREAM_OUT_H
diff --git a/services/audioflinger/datapath/ThreadMetrics.h b/services/audioflinger/datapath/ThreadMetrics.h
index c643a57..4eb8aa0 100644
--- a/services/audioflinger/datapath/ThreadMetrics.h
+++ b/services/audioflinger/datapath/ThreadMetrics.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_THREADMETRICS_H
-#define ANDROID_AUDIO_THREADMETRICS_H
+#pragma once
 
 #include <media/MediaMetricsItem.h>
 
@@ -210,5 +209,3 @@
 };
 
 } // namespace android
-
-#endif // ANDROID_AUDIO_THREADMETRICS_H
diff --git a/services/audioflinger/datapath/TrackMetrics.h b/services/audioflinger/datapath/TrackMetrics.h
index 2b44acb..ad5d3db 100644
--- a/services/audioflinger/datapath/TrackMetrics.h
+++ b/services/audioflinger/datapath/TrackMetrics.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_TRACKMETRICS_H
-#define ANDROID_AUDIO_TRACKMETRICS_H
+#pragma once
 
 #include <binder/IActivityManager.h>
 #include <binder/IPCThreadState.h>
@@ -306,5 +305,3 @@
 };
 
 } // namespace android
-
-#endif // ANDROID_AUDIO_TRACKMETRICS_H
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 13b70e5..7c70877 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -364,7 +364,7 @@
 
     void dump(String8 *dst, int spaces, const char* extraInfo = nullptr) const override;
     virtual DeviceVector devices() const;
-    void setDevices(const DeviceVector &devices) { mDevices = devices; }
+    void setDevices(const DeviceVector &devices);
     bool sharesHwModuleWith(const sp<SwAudioOutputDescriptor>& outputDesc);
     virtual DeviceVector supportedDevices() const;
     virtual bool devicesSupportEncodedFormats(const DeviceTypeSet& deviceTypes);
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 6c130fd..c502fc2 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -93,6 +93,8 @@
 
     void setEncapsulationInfoFromHal(AudioPolicyClientInterface *clientInterface);
 
+    void setPreferredConfig(const audio_config_base_t * preferredConfig);
+
     void dump(String8 *dst, int spaces, bool verbose = true) const;
 
 private:
@@ -107,6 +109,7 @@
     audio_format_t      mCurrentEncodedFormat;
     bool                mIsDynamic = false;
     std::string         mDeclaredAddress; // Original device address
+    std::optional<audio_config_base_t> mPreferredConfig;
 };
 
 class DeviceVector : public SortedVector<sp<DeviceDescriptor> >
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index cf20260..d206637 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -89,10 +89,12 @@
     status_t addProfile(const sp<IOProfile> &profile);
 
     status_t addOutputProfile(const std::string& name, const audio_config_t *config,
-            audio_devices_t device, const String8& address);
+            audio_devices_t device, const String8& address,
+            audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE);
     status_t removeOutputProfile(const std::string& name);
     status_t addInputProfile(const std::string& name, const audio_config_t *config,
-            audio_devices_t device, const String8& address);
+            audio_devices_t device, const String8& address,
+            audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE);
     status_t removeInputProfile(const std::string& name);
 
     audio_module_handle_t getHandle() const { return mHandle; }
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index d027564..6537a00 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -778,6 +778,19 @@
     }
 }
 
+void SwAudioOutputDescriptor::setDevices(const android::DeviceVector &devices) {
+    if ((mFlags & AUDIO_OUTPUT_FLAG_BIT_PERFECT) == AUDIO_OUTPUT_FLAG_BIT_PERFECT) {
+        for (auto device : mDevices) {
+            device->setPreferredConfig(nullptr);
+        }
+        auto config = getConfig();
+        for (auto device : devices) {
+            device->setPreferredConfig(&config);
+        }
+    }
+    mDevices = devices;
+}
+
 // HwAudioOutputDescriptor implementation
 HwAudioOutputDescriptor::HwAudioOutputDescriptor(const sp<SourceClientDescriptor>& source,
                                                  AudioPolicyClientInterface *clientInterface)
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index fe25693..9f7b8fc 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -132,6 +132,20 @@
 {
     DeviceDescriptorBase::toAudioPortConfig(dstConfig, srcConfig);
     dstConfig->ext.device.hw_module = getModuleHandle();
+    if (mPreferredConfig.has_value()) {
+        if (mPreferredConfig->format != AUDIO_FORMAT_DEFAULT) {
+            dstConfig->config_mask |= AUDIO_PORT_CONFIG_FORMAT;
+            dstConfig->format = mPreferredConfig->format;
+        }
+        if (mPreferredConfig->sample_rate != 0) {
+            dstConfig->config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
+            dstConfig->sample_rate = mPreferredConfig->sample_rate;
+        }
+        if (mPreferredConfig->channel_mask != AUDIO_CHANNEL_NONE) {
+            dstConfig->config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
+            dstConfig->channel_mask = mPreferredConfig->channel_mask;
+        }
+    }
 }
 
 void DeviceDescriptor::toAudioPort(struct audio_port *port) const
@@ -183,6 +197,14 @@
     }
 }
 
+void DeviceDescriptor::setPreferredConfig(const audio_config_base_t* preferredConfig) {
+    if (preferredConfig == nullptr) {
+        mPreferredConfig.reset();
+    } else {
+        mPreferredConfig = *preferredConfig;
+    }
+}
+
 void DeviceDescriptor::dump(String8 *dst, int spaces, bool verbose) const
 {
     String8 extraInfo;
@@ -193,6 +215,13 @@
     std::string descBaseDumpStr;
     DeviceDescriptorBase::dump(&descBaseDumpStr, spaces, extraInfo.c_str(), verbose);
     dst->append(descBaseDumpStr.c_str());
+
+    if (mPreferredConfig.has_value()) {
+        dst->append(base::StringPrintf(
+                "%*sPreferred Config: format=%#x, channelMask=%#x, sampleRate=%u\n",
+                spaces, "", mPreferredConfig.value().format, mPreferredConfig.value().channel_mask,
+                mPreferredConfig.value().sample_rate).c_str());
+    }
 }
 
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index cb45f54..6696b45 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -59,12 +59,13 @@
 }
 
 status_t HwModule::addOutputProfile(const std::string& name, const audio_config_t *config,
-                                    audio_devices_t device, const String8& address)
+                                    audio_devices_t device, const String8& address,
+                                    audio_output_flags_t flags)
 {
     sp<IOProfile> profile = new OutputProfile(name);
-
     profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
                                               config->sample_rate));
+    profile->setFlags(flags);
 
     sp<DeviceDescriptor> devDesc =
             new DeviceDescriptor(device, getTagForDevice(device), address.c_str());
@@ -128,11 +129,13 @@
 }
 
 status_t HwModule::addInputProfile(const std::string& name, const audio_config_t *config,
-                                   audio_devices_t device, const String8& address)
+                                   audio_devices_t device, const String8& address,
+                                   audio_input_flags_t flags)
 {
     sp<IOProfile> profile = new InputProfile(name);
     profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
                                               config->sample_rate));
+    profile->setFlags(flags);
 
     sp<DeviceDescriptor> devDesc =
             new DeviceDescriptor(device, getTagForDevice(device), address.c_str());
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
index a1785da..b4f71ae 100644
--- a/services/audiopolicy/managerdefault/Android.bp
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -22,6 +22,7 @@
     export_include_dirs: ["."],
 
     shared_libs: [
+        "com.android.media.audio-aconfig-cc",
         "libaudiofoundation",
         "libaudiopolicycomponents",
         "libcutils",
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 135548f..2e13178 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -41,6 +41,7 @@
 
 #include <Serializer.h>
 #include <android/media/audio/common/AudioPort.h>
+#include <com_android_media_audio.h>
 #include <cutils/bitops.h>
 #include <cutils/properties.h>
 #include <media/AudioParameter.h>
@@ -3673,9 +3674,13 @@
             outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
             inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
             rSubmixModule->addOutputProfile(address.c_str(), &outputConfig,
-                    AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
+                    AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address,
+                    audio_is_linear_pcm(outputConfig.format)
+                        ? AUDIO_OUTPUT_FLAG_NONE : AUDIO_OUTPUT_FLAG_DIRECT);
             rSubmixModule->addInputProfile(address.c_str(), &inputConfig,
-                    AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
+                    AUDIO_DEVICE_IN_REMOTE_SUBMIX, address,
+                    audio_is_linear_pcm(inputConfig.format)
+                        ? AUDIO_INPUT_FLAG_NONE : AUDIO_INPUT_FLAG_DIRECT);
 
             if ((res = setDeviceConnectionStateInt(deviceTypeToMakeAvailable,
                     AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
@@ -4444,8 +4449,8 @@
             if (!mAvailableOutputDevices.containsAtLeastOne(curProfile->getSupportedDevices())) {
                 continue;
             }
-            if ((curProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
-                        != AUDIO_OUTPUT_FLAG_NONE) {
+            if (offloadPossible && ((curProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
+                        != AUDIO_OUTPUT_FLAG_NONE)) {
                 if ((directMode & AUDIO_DIRECT_OFFLOAD_GAPLESS_SUPPORTED)
                         != AUDIO_DIRECT_NOT_SUPPORTED) {
                     // Already reports offload gapless supported. No need to report offload support.
@@ -5966,7 +5971,11 @@
     // some positional channel masks and PCM format
 
     if (config != nullptr && *config != AUDIO_CONFIG_INITIALIZER) {
-        if (!audio_is_channel_mask_spatialized(config->channel_mask)) {
+        const bool channel_mask_spatialized =
+                com_android_media_audio_stereo_spatialization()
+                ? audio_channel_mask_contains_stereo(config->channel_mask)
+                : audio_is_channel_mask_spatialized(config->channel_mask);
+        if (!channel_mask_spatialized) {
             return false;
         }
         if (!audio_is_linear_pcm(config->format)) {
@@ -6747,6 +6756,12 @@
         closingOutput->stop();
     }
     closingOutput->close();
+    if ((closingOutput->getFlags().output & AUDIO_OUTPUT_FLAG_BIT_PERFECT)
+            == AUDIO_OUTPUT_FLAG_BIT_PERFECT) {
+        for (const auto device : closingOutput->devices()) {
+            device->setPreferredConfig(nullptr);
+        }
+    }
 
     removeOutput(output);
     mPreviousOutputs = mOutputs;
@@ -8361,6 +8376,12 @@
         ALOGE("%s failed to open output %d", __func__, status);
         return nullptr;
     }
+    if ((flags & AUDIO_OUTPUT_FLAG_BIT_PERFECT) == AUDIO_OUTPUT_FLAG_BIT_PERFECT) {
+        auto portConfig = desc->getConfig();
+        for (const auto& device : devices) {
+            device->setPreferredConfig(&portConfig);
+        }
+    }
 
     // Here is where the out_set_parameters() for card & device gets called
     sp<DeviceDescriptor> device = devices.getDeviceForOpening();
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 7584632..6de71a3 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -164,6 +164,8 @@
     status_t status = af->openInput(request, &response);
     if (status == OK) {
         *input = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_module_handle_t(response.input));
+        *config = VALUE_OR_RETURN_STATUS(
+                aidl2legacy_AudioConfig_audio_config_t(response.config, true /*isInput*/));
     }
     return status;
 }
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 85b7ad9..42f7899 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -101,7 +101,7 @@
     audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
                                     AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     ssize_t index = mInputSources.indexOfKey(aliasSource);
     if (index < 0) {
         ALOGV("addInputEffects(): no processing needs to be attached to this source");
@@ -156,7 +156,7 @@
 {
     status_t status = NO_ERROR;
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     ssize_t index = mInputSessions.indexOfKey(audioSession);
     if (index < 0) {
         return status;
@@ -179,7 +179,7 @@
 {
     status_t status = NO_ERROR;
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     size_t index;
     for (index = 0; index < mInputSessions.size(); index++) {
         if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
@@ -212,7 +212,7 @@
 {
     status_t status = NO_ERROR;
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     size_t index;
     for (index = 0; index < mOutputSessions.size(); index++) {
         if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
@@ -245,7 +245,7 @@
 {
     status_t status = NO_ERROR;
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     // create audio processors according to stream
     // FIXME: should we have specific post processing settings for internal streams?
     // default to media for now.
@@ -309,7 +309,7 @@
     (void) output; // argument not used for now
     (void) stream; // argument not used for now
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     ssize_t index = mOutputSessions.indexOfKey(audioSession);
     if (index < 0) {
         ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
@@ -370,7 +370,7 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
 
     // Find the EffectDescVector for the given source type, or create a new one if necessary.
     ssize_t index = mInputSources.indexOfKey(source);
@@ -435,7 +435,7 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
 
     // Find the EffectDescVector for the given stream type, or create a new one if necessary.
     ssize_t index = mOutputStreams.indexOfKey(stream);
@@ -475,7 +475,7 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
 
     // Check each source type.
     size_t numSources = mInputSources.size();
@@ -506,7 +506,7 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
 
     // Check each stream type.
     size_t numStreams = mOutputStreams.size();
@@ -948,7 +948,7 @@
     loadProcessingChain(processings->postprocess, mOutputStreams);
 
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         loadDeviceProcessingChain(processings->deviceprocess, mDeviceEffects);
     }
 
@@ -985,7 +985,7 @@
 
 void AudioPolicyEffects::initDefaultDeviceEffects()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     for (const auto& deviceEffectsIter : mDeviceEffects) {
         const auto& deviceEffects =  deviceEffectsIter.second;
         for (const auto& effectDesc : deviceEffects->mEffectDescriptors->mEffects) {
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index e17df48..7f41f09 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -23,6 +23,7 @@
 #include <future>
 
 #include <android-base/thread_annotations.h>
+#include <audio_utils/mutex.h>
 #include <cutils/misc.h>
 #include <media/AudioEffect.h>
 #include <media/audiohal/EffectsFactoryHalInterface.h>
@@ -59,7 +60,7 @@
     virtual ~AudioPolicyEffects();
 
     // NOTE: methods on AudioPolicyEffects should never be called with the AudioPolicyService
-    // main mutex (mLock) held as they will indirectly call back into AudioPolicyService when
+    // main mutex (mMutex) held as they will indirectly call back into AudioPolicyService when
     // managing audio effects.
 
     // Return a list of effect descriptors for default input effects
@@ -204,7 +205,7 @@
         void setProcessorEnabled(bool enabled);
 
         const audio_session_t mSessionId;
-        // AudioPolicyManager keeps mLock, no need for lock on reference count here
+        // AudioPolicyManager keeps mMutex, no need for lock on reference count here
         int mRefCount;
         Vector< sp<AudioEffect> >mEffects;
     };
@@ -263,9 +264,9 @@
                          size_t *totSize);
 
     // protects access to mInputSources, mInputSessions, mOutputStreams, mOutputSessions
-    // never hold AudioPolicyService::mLock when calling AudioPolicyEffects methods as
+    // never hold AudioPolicyService::mMutex when calling AudioPolicyEffects methods as
     // those can call back into AudioPolicyService methods and try to acquire the mutex
-    Mutex mLock;
+    mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kAudioPolicyEffects_Mutex};
     // Automatic input effects are configured per audio_source_t
     KeyedVector< audio_source_t, EffectDescVector* > mInputSources;
     // Automatic input effects are unique for audio_io_handle_t
@@ -279,7 +280,7 @@
     /**
      * @brief mDeviceEffects map of device effects indexed by the device address
      */
-    std::map<std::string, std::unique_ptr<DeviceEffects>> mDeviceEffects GUARDED_BY(mLock);
+    std::map<std::string, std::unique_ptr<DeviceEffects>> mDeviceEffects GUARDED_BY(mMutex);
 
     /**
      * Device Effect initialization must be asynchronous: the audio_policy service parses and init
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 509b673..6e1ecec 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -114,7 +114,7 @@
 void AudioPolicyService::doOnNewAudioModulesAvailable()
 {
     if (mAudioPolicyManager == NULL) return;
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     mAudioPolicyManager->onNewAudioModulesAvailable();
 }
@@ -140,7 +140,7 @@
     }
 
     ALOGV("setDeviceConnectionState()");
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     status_t status = mAudioPolicyManager->setDeviceConnectionState(
             state, port, encodedFormat);
@@ -162,7 +162,7 @@
                         AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
         return Status::ok();
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
             legacy2aidl_audio_policy_dev_state_t_AudioPolicyDeviceState(
@@ -190,7 +190,7 @@
     }
 
     ALOGV("handleDeviceConfigChange()");
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     status_t status =  mAudioPolicyManager->handleDeviceConfigChange(
             device, address.c_str(), deviceNameAidl.c_str(), encodedFormat);
@@ -221,7 +221,7 @@
     // acquire lock before calling setMode() so that setMode() + setPhoneState() are an atomic
     // operation from policy manager standpoint (no other operation (e.g track start or stop)
     // can be interleaved).
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     // TODO: check if it is more appropriate to do it in platform specific policy manager
 
     // Audio HAL mode conversion for call redirect modes
@@ -242,7 +242,7 @@
 }
 
 Status AudioPolicyService::getPhoneState(AudioMode* _aidl_return) {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_mode_t_AudioMode(mPhoneState));
     return Status::ok();
 }
@@ -270,7 +270,7 @@
         return binderStatusFromStatusT(BAD_VALUE);
     }
     ALOGV("setForceUse()");
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     mAudioPolicyManager->setForceUse(usage, config);
     onCheckSpatializer_l();
@@ -312,7 +312,7 @@
         return binderStatusFromStatusT(NO_INIT);
     }
     ALOGV("getOutput()");
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
             legacy2aidl_audio_io_handle_t_int32_t(mAudioPolicyManager->getOutput(stream)));
@@ -352,7 +352,7 @@
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(validateUsage(attr, attributionSource)));
 
     ALOGV("%s()", __func__);
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
 
     if (!mPackageManager.allowPlaybackCapture(VALUE_OR_RETURN_BINDER_STATUS(
         aidl2legacy_int32_t_uid_t(attributionSource.uid)))) {
@@ -458,7 +458,7 @@
                                                      sp<AudioPolicyEffects>& effects,
                                                      const char *context)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     const ssize_t index = mAudioPlaybackClients.indexOfKey(portId);
     if (index < 0) {
         ALOGE("%s AudioTrack client not found for portId %d", context, portId);
@@ -489,7 +489,7 @@
             ALOGW("Failed to add effects on session %d", client->session);
         }
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     status_t status = mAudioPolicyManager->startOutput(portId);
     if (status == NO_ERROR) {
@@ -531,7 +531,7 @@
             ALOGW("Failed to release effects on session %d", client->session);
         }
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     status_t status = mAudioPolicyManager->stopOutput(portId);
     if (status == NO_ERROR) {
@@ -567,7 +567,7 @@
         audioPolicyEffects->releaseOutputSessionEffects(
             client->io, client->stream, client->session);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if (client != nullptr && client->active) {
         onUpdateActiveSpatializerTracks_l();
     }
@@ -691,7 +691,7 @@
         status_t status;
         AudioPolicyInterface::input_type_t inputType;
 
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         {
             AutoCallerClear acc;
             // the audio_in_acoustics_t parameter is ignored by get_input()
@@ -794,7 +794,7 @@
     }
     sp<AudioRecordClient> client;
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
 
         ssize_t index = mAudioRecordClients.indexOfKey(portId);
         if (index < 0) {
@@ -817,7 +817,7 @@
         return binderStatusFromStatusT(PERMISSION_DENIED);
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
 
     ALOGW_IF(client->silenced, "startInput on silenced input for port %d, uid %d. Unsilencing.",
             portIdAidl,
@@ -937,7 +937,7 @@
         return binderStatusFromStatusT(NO_INIT);
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
 
     ssize_t index = mAudioRecordClients.indexOfKey(portId);
     if (index < 0) {
@@ -967,7 +967,7 @@
     sp<AudioPolicyEffects>audioPolicyEffects;
     sp<AudioRecordClient> client;
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         audioPolicyEffects = mAudioPolicyEffects;
         ssize_t index = mAudioRecordClients.indexOfKey(portId);
         if (index < 0) {
@@ -995,7 +995,7 @@
         }
     }
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         AutoCallerClear acc;
         mAudioPolicyManager->releaseInput(portId);
     }
@@ -1019,7 +1019,7 @@
     if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return binderStatusFromStatusT(BAD_VALUE);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     mAudioPolicyManager->initStreamVolume(stream, indexMin, indexMax);
     return binderStatusFromStatusT(NO_ERROR);
@@ -1043,7 +1043,7 @@
     if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return binderStatusFromStatusT(BAD_VALUE);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     return binderStatusFromStatusT(mAudioPolicyManager->setStreamVolumeIndex(stream,
                                                                              index,
@@ -1065,7 +1065,7 @@
     if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return binderStatusFromStatusT(BAD_VALUE);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             mAudioPolicyManager->getStreamVolumeIndex(stream, &index, device)));
@@ -1090,7 +1090,7 @@
     if (!settingsAllowed()) {
         return binderStatusFromStatusT(PERMISSION_DENIED);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     return binderStatusFromStatusT(
             mAudioPolicyManager->setVolumeIndexForAttributes(attributes, index, device));
@@ -1110,7 +1110,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             mAudioPolicyManager->getVolumeIndexForAttributes(attributes, index, device)));
@@ -1129,7 +1129,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             mAudioPolicyManager->getMinVolumeIndexForAttributes(attributes, index)));
@@ -1148,7 +1148,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             mAudioPolicyManager->getMaxVolumeIndexForAttributes(attributes, index)));
@@ -1190,7 +1190,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             mAudioPolicyManager->getDevicesForAttributes(aa, &devices, forVolume)));
@@ -1210,7 +1210,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
             legacy2aidl_audio_io_handle_t_int32_t(mAudioPolicyManager->getOutputForEffect(&desc)));
@@ -1235,7 +1235,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     return binderStatusFromStatusT(
             mAudioPolicyManager->registerEffect(&desc, io, strategy, session, id));
@@ -1247,7 +1247,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     return binderStatusFromStatusT(mAudioPolicyManager->unregisterEffect(id));
 }
@@ -1258,7 +1258,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     return binderStatusFromStatusT(mAudioPolicyManager->setEffectEnabled(id, enabled));
 }
@@ -1277,7 +1277,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     return binderStatusFromStatusT(mAudioPolicyManager->moveEffectsToIo(ids, io));
 }
@@ -1295,7 +1295,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     *_aidl_return = mAudioPolicyManager->isStreamActive(stream, inPastMs);
     return Status::ok();
@@ -1315,7 +1315,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     *_aidl_return = mAudioPolicyManager->isStreamActiveRemotely(stream, inPastMs);
     return Status::ok();
@@ -1327,7 +1327,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     *_aidl_return = mAudioPolicyManager->isSourceActive(source);
     return Status::ok();
@@ -1339,7 +1339,7 @@
         return NO_INIT;
     }
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         audioPolicyEffects = mAudioPolicyEffects;
     }
     if (audioPolicyEffects == 0) {
@@ -1463,7 +1463,7 @@
             convertRange(systemUsagesAidl.begin(), systemUsagesAidl.begin() + size,
                          std::back_inserter(systemUsages), aidl2legacy_AudioUsage_audio_usage_t)));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if(!modifyAudioRoutingAllowed()) {
         return binderStatusFromStatusT(PERMISSION_DENIED);
     }
@@ -1483,7 +1483,7 @@
     audio_flags_mask_t capturePolicy = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_flags_mask_t_mask(capturePolicyAidl));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if (mAudioPolicyManager == NULL) {
         ALOGV("%s() mAudioPolicyManager == NULL", __func__);
         return binderStatusFromStatusT(NO_INIT);
@@ -1500,7 +1500,7 @@
         ALOGV("mAudioPolicyManager == NULL");
         return binderStatusFromStatusT(AUDIO_OFFLOAD_NOT_SUPPORTED);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_offload_mode_t_AudioOffloadMode(
             mAudioPolicyManager->getOffloadSupport(info)));
@@ -1525,7 +1525,7 @@
 
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(validateUsage(attributes)));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     *_aidl_return = mAudioPolicyManager->isDirectOutputSupported(config, attributes);
     return Status::ok();
 }
@@ -1561,7 +1561,7 @@
     std::unique_ptr<audio_port_v7[]> ports(new audio_port_v7[num_ports]);
     unsigned int generation;
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
@@ -1589,7 +1589,7 @@
 
 Status AudioPolicyService::listDeclaredDevicePorts(media::AudioPortRole role,
                                                     std::vector<media::AudioPortFw>* _aidl_return) {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
@@ -1601,7 +1601,7 @@
 Status AudioPolicyService::getAudioPort(int portId,
                                         media::AudioPortFw* _aidl_return) {
     audio_port_v7 port{ .id = portId };
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
@@ -1628,7 +1628,7 @@
             aidl2legacy_int32_t_audio_port_handle_t(handleAidl));
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(AudioValidator::validateAudioPatch(patch)));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if(!modifyAudioRoutingAllowed()) {
         return binderStatusFromStatusT(PERMISSION_DENIED);
     }
@@ -1647,7 +1647,7 @@
 {
     audio_patch_handle_t handle = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_patch_handle_t(handleAidl));
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if(!modifyAudioRoutingAllowed()) {
         return binderStatusFromStatusT(PERMISSION_DENIED);
     }
@@ -1672,7 +1672,7 @@
     std::unique_ptr<audio_patch[]> patches(new audio_patch[num_patches]);
     unsigned int generation;
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
@@ -1710,7 +1710,7 @@
     RETURN_IF_BINDER_ERROR(
             binderStatusFromStatusT(AudioValidator::validateAudioPortConfig(config)));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if(!modifyAudioRoutingAllowed()) {
         return binderStatusFromStatusT(PERMISSION_DENIED);
     }
@@ -1728,7 +1728,7 @@
     audio_devices_t device;
 
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         if (mAudioPolicyManager == NULL) {
             return binderStatusFromStatusT(NO_INIT);
         }
@@ -1750,7 +1750,7 @@
 {
     audio_session_t session = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_session_t(sessionAidl));
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
@@ -1769,7 +1769,7 @@
             convertRange(mixesAidl.begin(), mixesAidl.begin() + size, std::back_inserter(mixes),
                          aidl2legacy_AudioMix)));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
 
     // loopback|render only need a MediaProjection (checked in caller AudioService.java)
     bool needModifyAudioRouting = std::any_of(mixes.begin(), mixes.end(), [](auto& mix) {
@@ -1812,7 +1812,7 @@
 
 Status AudioPolicyService::updatePolicyMixes(
         const ::std::vector<::android::media::AudioMixUpdate>& updates) {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     for (const auto& update : updates) {
         AudioMix mix = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_AudioMix(update.audioMix));
         std::vector<AudioMixMatchCriterion> newCriteria =
@@ -1834,7 +1834,7 @@
             convertContainer<AudioDeviceTypeAddrVector>(devicesAidl,
                                                         aidl2legacy_AudioDeviceTypeAddress));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if(!modifyAudioRoutingAllowed()) {
         return binderStatusFromStatusT(PERMISSION_DENIED);
     }
@@ -1848,7 +1848,7 @@
 Status AudioPolicyService::removeUidDeviceAffinities(int32_t uidAidl) {
     uid_t uid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(uidAidl));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if(!modifyAudioRoutingAllowed()) {
         return binderStatusFromStatusT(PERMISSION_DENIED);
     }
@@ -1867,7 +1867,7 @@
             convertContainer<AudioDeviceTypeAddrVector>(devicesAidl,
                                                         aidl2legacy_AudioDeviceTypeAddress));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if(!modifyAudioRoutingAllowed()) {
         return binderStatusFromStatusT(PERMISSION_DENIED);
     }
@@ -1881,7 +1881,7 @@
 Status AudioPolicyService::removeUserIdDeviceAffinities(int32_t userIdAidl) {
     int userId = VALUE_OR_RETURN_BINDER_STATUS(convertReinterpret<int>(userIdAidl));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if(!modifyAudioRoutingAllowed()) {
         return binderStatusFromStatusT(PERMISSION_DENIED);
     }
@@ -1905,7 +1905,7 @@
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             AudioValidator::validateAudioAttributes(attributes, "68953950")));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
@@ -1926,7 +1926,7 @@
     audio_port_handle_t portId = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_port_handle_t(portIdAidl));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
@@ -1942,7 +1942,7 @@
     if (!settingsAllowed()) {
         return binderStatusFromStatusT(PERMISSION_DENIED);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     return binderStatusFromStatusT(mAudioPolicyManager->setMasterMono(mono));
 }
@@ -1952,7 +1952,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     return binderStatusFromStatusT(mAudioPolicyManager->getMasterMono(_aidl_return));
 }
@@ -1970,7 +1970,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     *_aidl_return = mAudioPolicyManager->getStreamVolumeDB(stream, index, device);
     return Status::ok();
@@ -1991,7 +1991,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             mAudioPolicyManager->getSurroundFormats(&numSurroundFormats, surroundFormats.get(),
@@ -2022,7 +2022,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             mAudioPolicyManager->getReportedSurroundFormats(
@@ -2044,7 +2044,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     audio_devices_t device = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioDeviceDescription_audio_devices_t(deviceAidl));
@@ -2064,7 +2064,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     return binderStatusFromStatusT(
             mAudioPolicyManager->setSurroundFormatEnabled(audioFormat, enabled));
@@ -2087,7 +2087,7 @@
     std::vector<uid_t> uids;
     RETURN_IF_BINDER_ERROR(convertInt32VectorToUidVectorWithLimit(uidsAidl, uids));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     mUidPolicy->setAssistantUids(uids);
     return Status::ok();
 }
@@ -2097,7 +2097,7 @@
     std::vector<uid_t> activeUids;
     RETURN_IF_BINDER_ERROR(convertInt32VectorToUidVectorWithLimit(activeUidsAidl, activeUids));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     mUidPolicy->setActiveAssistantUids(activeUids);
     return Status::ok();
 }
@@ -2107,7 +2107,7 @@
     std::vector<uid_t> uids;
     RETURN_IF_BINDER_ERROR(convertInt32VectorToUidVectorWithLimit(uidsAidl, uids));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     mUidPolicy->setA11yUids(uids);
     return Status::ok();
 }
@@ -2115,7 +2115,7 @@
 Status AudioPolicyService::setCurrentImeUid(int32_t uidAidl)
 {
     uid_t uid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(uidAidl));
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     mUidPolicy->setCurrentImeUid(uid);
     return Status::ok();
 }
@@ -2125,7 +2125,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     *_aidl_return = mAudioPolicyManager->isHapticPlaybackSupported();
     return Status::ok();
@@ -2136,7 +2136,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     *_aidl_return = mAudioPolicyManager->isUltrasoundSupported();
     return Status::ok();
@@ -2147,7 +2147,7 @@
     if (mAudioPolicyManager == nullptr) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     *_aidl_return = mAudioPolicyManager->isHotwordStreamSupported(lookbackAudio);
     return Status::ok();
@@ -2160,7 +2160,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     RETURN_IF_BINDER_ERROR(
             binderStatusFromStatusT(mAudioPolicyManager->listAudioProductStrategies(strategies)));
     *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
@@ -2180,7 +2180,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             mAudioPolicyManager->getProductStrategyFromAudioAttributes(
                     aa, productStrategy, fallbackOnDefault)));
@@ -2195,7 +2195,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     RETURN_IF_BINDER_ERROR(
             binderStatusFromStatusT(mAudioPolicyManager->listAudioVolumeGroups(groups)));
     *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
@@ -2214,7 +2214,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     RETURN_IF_BINDER_ERROR(
             binderStatusFromStatusT(
                     mAudioPolicyManager->getVolumeGroupFromAudioAttributes(
@@ -2225,7 +2225,7 @@
 
 Status AudioPolicyService::setRttEnabled(bool enabled)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     mUidPolicy->setRttEnabled(enabled);
     return Status::ok();
 }
@@ -2235,7 +2235,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     *_aidl_return = mAudioPolicyManager->isCallScreenModeSupported();
     return Status::ok();
@@ -2256,7 +2256,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     status_t status = mAudioPolicyManager->setDevicesRoleForStrategy(strategy, role, devices);
     if (status == NO_ERROR) {
        onCheckSpatializer_l();
@@ -2279,7 +2279,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     status_t status = mAudioPolicyManager->removeDevicesRoleForStrategy(strategy, role, devices);
     if (status == NO_ERROR) {
        onCheckSpatializer_l();
@@ -2296,7 +2296,7 @@
    if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     status_t status = mAudioPolicyManager->clearDevicesRoleForStrategy(strategy, role);
     if (status == NO_ERROR) {
        onCheckSpatializer_l();
@@ -2317,7 +2317,7 @@
     if (mAudioPolicyManager == NULL) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             mAudioPolicyManager->getDevicesForRoleAndStrategy(strategy, role, devices)));
     *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
@@ -2347,7 +2347,7 @@
     if (mAudioPolicyManager == nullptr) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     return binderStatusFromStatusT(
             mAudioPolicyManager->setDevicesRoleForCapturePreset(audioSource, role, devices));
 }
@@ -2367,7 +2367,7 @@
     if (mAudioPolicyManager == nullptr) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     return binderStatusFromStatusT(
             mAudioPolicyManager->addDevicesRoleForCapturePreset(audioSource, role, devices));
 }
@@ -2387,7 +2387,7 @@
    if (mAudioPolicyManager == nullptr) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     return binderStatusFromStatusT(
             mAudioPolicyManager->removeDevicesRoleForCapturePreset(audioSource, role, devices));
 }
@@ -2402,7 +2402,7 @@
     if (mAudioPolicyManager == nullptr) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     return binderStatusFromStatusT(
             mAudioPolicyManager->clearDevicesRoleForCapturePreset(audioSource, role));
 }
@@ -2420,7 +2420,7 @@
     if (mAudioPolicyManager == nullptr) {
         return binderStatusFromStatusT(NO_INIT);
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             mAudioPolicyManager->getDevicesForRoleAndCapturePreset(audioSource, role, devices)));
     *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
@@ -2467,7 +2467,7 @@
             convertContainer<AudioDeviceTypeAddrVector>(devicesAidl,
                                                         aidl2legacy_AudioDeviceTypeAddress));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     *_aidl_return = mAudioPolicyManager->canBeSpatialized(&attr, &config, devices);
     return Status::ok();
 }
@@ -2486,7 +2486,7 @@
             aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     audio_config_t config = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioConfig_audio_config_t(configAidl, false /*isInput*/));
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     *_aidl_return = static_cast<media::AudioDirectMode>(
             VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_direct_mode_t_int32_t_mask(
                     mAudioPolicyManager->getDirectPlaybackSupport(&attr, &config))));
@@ -2503,7 +2503,7 @@
             aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     AudioProfileVector audioProfiles;
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             mAudioPolicyManager->getDirectProfilesForAttributes(&attr, audioProfiles)));
     *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
@@ -2523,7 +2523,7 @@
             aidl2legacy_int32_t_audio_port_handle_t(portIdAidl));
 
     std::vector<audio_mixer_attributes_t> mixerAttrs;
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     RETURN_IF_BINDER_ERROR(
             binderStatusFromStatusT(mAudioPolicyManager->getSupportedMixerAttributes(
                     portId, mixerAttrs)));
@@ -2551,7 +2551,7 @@
     audio_port_handle_t portId = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_port_handle_t(portIdAidl));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     return binderStatusFromStatusT(
             mAudioPolicyManager->setPreferredMixerAttributes(&attr, portId, uid, &mixerAttr));
 }
@@ -2569,7 +2569,7 @@
     audio_port_handle_t portId = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_port_handle_t(portIdAidl));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     audio_mixer_attributes_t mixerAttr = AUDIO_MIXER_ATTRIBUTES_INITIALIZER;
     RETURN_IF_BINDER_ERROR(
             binderStatusFromStatusT(mAudioPolicyManager->getPreferredMixerAttributes(
@@ -2593,7 +2593,7 @@
     audio_port_handle_t portId = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_port_handle_t(portIdAidl));
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     return binderStatusFromStatusT(
             mAudioPolicyManager->clearPreferredMixerAttributes(&attr, portId, uid));
 }
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 5d3788d..835a617 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -265,7 +265,7 @@
             .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
             .record(); });
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
 
         // start audio commands thread
         mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
@@ -284,7 +284,7 @@
     sp<UidPolicy> uidPolicy = new UidPolicy(this);
     sp<SensorPrivacyPolicy> sensorPrivacyPolicy = new SensorPrivacyPolicy(this);
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         mAudioPolicyEffects = audioPolicyEffects;
         mUidPolicy = uidPolicy;
         mSensorPrivacyPolicy = sensorPrivacyPolicy;
@@ -294,16 +294,16 @@
 
     // Create spatializer if supported
     if (mAudioPolicyManager != nullptr) {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         const audio_attributes_t attr = attributes_initializer(AUDIO_USAGE_MEDIA);
         AudioDeviceTypeAddrVector devices;
         bool hasSpatializer = mAudioPolicyManager->canBeSpatialized(&attr, nullptr, devices);
         if (hasSpatializer) {
             // Unlock as Spatializer::create() will use the callback and acquire the
             // AudioPolicyService_Mutex.
-            mLock.unlock();
+            mMutex.unlock();
             mSpatializer = Spatializer::create(this, effectsFactoryHal);
-            mLock.lock();
+            mMutex.lock();
         }
         if (mSpatializer == nullptr) {
             // No spatializer created, signal the reason: NO_INIT a failure, OK means intended.
@@ -356,7 +356,7 @@
         ALOGW("%s got NULL client", __FUNCTION__);
         return Status::ok();
     }
-    Mutex::Autolock _l(mNotificationClientsLock);
+    audio_utils::lock_guard _l(mNotificationClientsMutex);
 
     uid_t uid = IPCThreadState::self()->getCallingUid();
     pid_t pid = IPCThreadState::self()->getCallingPid();
@@ -379,7 +379,7 @@
 
 Status AudioPolicyService::setAudioPortCallbacksEnabled(bool enabled)
 {
-    Mutex::Autolock _l(mNotificationClientsLock);
+    audio_utils::lock_guard _l(mNotificationClientsMutex);
 
     uid_t uid = IPCThreadState::self()->getCallingUid();
     pid_t pid = IPCThreadState::self()->getCallingPid();
@@ -394,7 +394,7 @@
 
 Status AudioPolicyService::setAudioVolumeGroupCallbacksEnabled(bool enabled)
 {
-    Mutex::Autolock _l(mNotificationClientsLock);
+    audio_utils::lock_guard _l(mNotificationClientsMutex);
 
     uid_t uid = IPCThreadState::self()->getCallingUid();
     pid_t pid = IPCThreadState::self()->getCallingPid();
@@ -412,7 +412,7 @@
 {
     bool hasSameUid = false;
     {
-        Mutex::Autolock _l(mNotificationClientsLock);
+        audio_utils::lock_guard _l(mNotificationClientsMutex);
         int64_t token = ((int64_t)uid<<32) | pid;
         mNotificationClients.removeItem(token);
         for (size_t i = 0; i < mNotificationClients.size(); i++) {
@@ -423,7 +423,7 @@
         }
     }
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         if (mAudioPolicyManager && !hasSameUid) {
             // called from binder death notification: no need to clear caller identity
             mAudioPolicyManager->releaseResourcesForUid(uid);
@@ -438,7 +438,7 @@
 
 void AudioPolicyService::doOnAudioPortListUpdate()
 {
-    Mutex::Autolock _l(mNotificationClientsLock);
+    audio_utils::lock_guard _l(mNotificationClientsMutex);
     for (size_t i = 0; i < mNotificationClients.size(); i++) {
         mNotificationClients.valueAt(i)->onAudioPortListUpdate();
     }
@@ -451,7 +451,7 @@
 
 void AudioPolicyService::doOnAudioPatchListUpdate()
 {
-    Mutex::Autolock _l(mNotificationClientsLock);
+    audio_utils::lock_guard _l(mNotificationClientsMutex);
     for (size_t i = 0; i < mNotificationClients.size(); i++) {
         mNotificationClients.valueAt(i)->onAudioPatchListUpdate();
     }
@@ -464,7 +464,7 @@
 
 void AudioPolicyService::doOnAudioVolumeGroupChanged(volume_group_t group, int flags)
 {
-    Mutex::Autolock _l(mNotificationClientsLock);
+    audio_utils::lock_guard _l(mNotificationClientsMutex);
     for (size_t i = 0; i < mNotificationClients.size(); i++) {
         mNotificationClients.valueAt(i)->onAudioVolumeGroupChanged(group, flags);
     }
@@ -479,7 +479,7 @@
 
 void AudioPolicyService::doOnDynamicPolicyMixStateUpdate(const String8& regId, int32_t state)
 {
-    Mutex::Autolock _l(mNotificationClientsLock);
+    audio_utils::lock_guard _l(mNotificationClientsMutex);
     for (size_t i = 0; i < mNotificationClients.size(); i++) {
         mNotificationClients.valueAt(i)->onDynamicPolicyMixStateUpdate(regId, state);
     }
@@ -509,7 +509,7 @@
                                                   audio_patch_handle_t patchHandle,
                                                   audio_source_t source)
 {
-    Mutex::Autolock _l(mNotificationClientsLock);
+    audio_utils::lock_guard _l(mNotificationClientsMutex);
     for (size_t i = 0; i < mNotificationClients.size(); i++) {
         mNotificationClients.valueAt(i)->onRecordingConfigurationUpdate(event, clientInfo,
                 clientConfig, clientEffects, deviceConfig, effects, patchHandle, source);
@@ -523,7 +523,7 @@
 
 void AudioPolicyService::doOnRoutingUpdated()
 {
-  Mutex::Autolock _l(mNotificationClientsLock);
+  audio_utils::lock_guard _l(mNotificationClientsMutex);
     for (size_t i = 0; i < mNotificationClients.size(); i++) {
         mNotificationClients.valueAt(i)->onRoutingUpdated();
     }
@@ -536,7 +536,7 @@
 
 void AudioPolicyService::doOnVolumeRangeInitRequest()
 {
-    Mutex::Autolock _l(mNotificationClientsLock);
+    audio_utils::lock_guard _l(mNotificationClientsMutex);
     for (size_t i = 0; i < mNotificationClients.size(); i++) {
         mNotificationClients.valueAt(i)->onVolumeRangeInitRequest();
     }
@@ -544,7 +544,7 @@
 
 void AudioPolicyService::onCheckSpatializer()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     onCheckSpatializer_l();
 }
 
@@ -568,7 +568,7 @@
             const audio_attributes_t attr = attributes_initializer(AUDIO_USAGE_MEDIA);
             audio_config_base_t config = mSpatializer->getAudioInConfig();
 
-            Mutex::Autolock _l(mLock);
+            audio_utils::lock_guard _l(mMutex);
             status_t status =
                     mAudioPolicyManager->getSpatializerOutput(&config, &attr, &newOutput);
             ALOGV("%s currentOutput %d newOutput %d channel_mask %#x",
@@ -577,13 +577,13 @@
                 return;
             }
             size_t numActiveTracks = countActiveClientsOnOutput_l(newOutput);
-            mLock.unlock();
+            mMutex.unlock();
             // It is OK to call detachOutput() is none is already attached.
             mSpatializer->detachOutput();
             if (status == NO_ERROR && newOutput != AUDIO_IO_HANDLE_NONE) {
                 status = mSpatializer->attachOutput(newOutput, numActiveTracks);
             }
-            mLock.lock();
+            mMutex.lock();
             if (status != NO_ERROR) {
                 mAudioPolicyManager->releaseSpatializerOutput(newOutput);
             }
@@ -592,7 +592,7 @@
             audio_io_handle_t output = mSpatializer->detachOutput();
 
             if (output != AUDIO_IO_HANDLE_NONE) {
-                Mutex::Autolock _l(mLock);
+                audio_utils::lock_guard _l(mMutex);
                 mAudioPolicyManager->releaseSpatializerOutput(output);
             }
         }
@@ -627,7 +627,7 @@
     audio_io_handle_t output = mSpatializer->getOutput();
     size_t activeClients;
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         activeClients = countActiveClientsOnOutput_l(output);
     }
     mSpatializer->updateActiveTracks(activeClients);
@@ -783,12 +783,8 @@
             IPCThreadState::self()->getCallingPid());
 }
 
-static bool dumpTryLock(Mutex& mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
-{
-    return mutex.timedLock(kDumpLockTimeoutNs) == NO_ERROR;
-}
-
-static void dumpReleaseLock(Mutex& mutex, bool locked) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
+static void dumpReleaseLock(audio_utils::mutex& mutex, bool locked)
+        RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
 {
     if (locked) mutex.unlock();
 }
@@ -825,7 +821,7 @@
 
 void AudioPolicyService::updateUidStates()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     updateUidStates_l();
 }
 
@@ -1027,7 +1023,7 @@
         bool isTopOrLatestAssistant = latestActiveAssistant == nullptr ? false :
             current->attributionSource.uid == latestActiveAssistant->attributionSource.uid;
 
-        auto canCaptureIfInCallOrCommunication = [&](const auto &recordClient) REQUIRES(mLock) {
+        auto canCaptureIfInCallOrCommunication = [&](const auto &recordClient) REQUIRES(mMutex) {
             uid_t recordUid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(
                 recordClient->attributionSource.uid));
             bool canCaptureCall = recordClient->canCaptureOutput;
@@ -1205,11 +1201,12 @@
 }
 
 status_t AudioPolicyService::dump(int fd, const Vector<String16>& args __unused)
+NO_THREAD_SAFETY_ANALYSIS  // update for trylock.
 {
     if (!dumpAllowed()) {
         dumpPermissionDenial(fd);
     } else {
-        const bool locked = dumpTryLock(mLock);
+        const bool locked = mMutex.try_lock(kDumpLockTimeoutNs);
         if (!locked) {
             String8 result(kDeadlockedString);
             write(fd, result.c_str(), result.size());
@@ -1238,7 +1235,7 @@
 
         mPackageManager.dump(fd);
 
-        dumpReleaseLock(mLock, locked);
+        dumpReleaseLock(mMutex, locked);
 
         if (mSpatializer != nullptr) {
             std::string dumpString = mSpatializer->toString(1 /* level */);
@@ -1483,7 +1480,7 @@
 
     sp<UidPolicy> uidPolicy;
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         uidPolicy = mUidPolicy;
     }
     if (uidPolicy) {
@@ -1512,7 +1509,7 @@
 
     sp<UidPolicy> uidPolicy;
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         uidPolicy = mUidPolicy;
     }
     if (uidPolicy) {
@@ -1541,7 +1538,7 @@
 
     sp<UidPolicy> uidPolicy;
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         uidPolicy = mUidPolicy;
     }
     if (uidPolicy) {
@@ -1579,7 +1576,7 @@
             ActivityManager::PROCESS_STATE_UNKNOWN,
             String16("audioserver"));
     if (!res) {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         mObserverRegistered = true;
     } else {
         ALOGE("UidPolicy::registerSelf linkToDeath failed: %d", res);
@@ -1591,12 +1588,12 @@
 void AudioPolicyService::UidPolicy::unregisterSelf() {
     mAm.unlinkToDeath(this);
     mAm.unregisterUidObserver(this);
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     mObserverRegistered = false;
 }
 
 void AudioPolicyService::UidPolicy::binderDied(__unused const wp<IBinder> &who) {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     mCachedUids.clear();
     mObserverRegistered = false;
 }
@@ -1604,7 +1601,7 @@
 void AudioPolicyService::UidPolicy::checkRegistered() {
     bool needToReregister = false;
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         needToReregister = !mObserverRegistered;
     }
     if (needToReregister) {
@@ -1617,7 +1614,7 @@
     if (isServiceUid(uid)) return true;
     checkRegistered();
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         auto overrideIter = mOverrideUids.find(uid);
         if (overrideIter != mOverrideUids.end()) {
             return overrideIter->second.first;
@@ -1632,7 +1629,7 @@
     ActivityManager am;
     bool active = am.isUidActive(uid, String16("audioserver"));
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         mCachedUids.insert(std::pair<uid_t,
                            std::pair<bool, int>>(uid, std::pair<bool, int>(active,
                                                       ActivityManager::PROCESS_STATE_UNKNOWN)));
@@ -1646,7 +1643,7 @@
     }
     checkRegistered();
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         auto overrideIter = mOverrideUids.find(uid);
         if (overrideIter != mOverrideUids.end()) {
             if (overrideIter->second.first) {
@@ -1681,7 +1678,7 @@
         state = am.getUidProcessState(uid, String16("audioserver"));
     }
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         mCachedUids.insert(std::pair<uid_t,
                            std::pair<bool, int>>(uid, std::pair<bool, int>(active, state)));
     }
@@ -1736,7 +1733,7 @@
     bool wasActive = isUidActive(uid);
     int previousState = getUidState(uid);
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         updateUidLocked(uids, uid, active, state, insert);
     }
     if (wasActive != isUidActive(uid) || state != previousState) {
@@ -1771,7 +1768,7 @@
 }
 
 bool AudioPolicyService::UidPolicy::isA11yOnTop() {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mMutex);
     for (const auto &uid : mCachedUids) {
         if (!isA11yUid(uid.first)) {
             continue;
@@ -1902,7 +1899,7 @@
 {
     nsecs_t waitTime = -1;
 
-    mLock.lock();
+    audio_utils::unique_lock ul(mMutex);
     while (!exitPending())
     {
         sp<AudioPolicyService> svc;
@@ -1923,27 +1920,27 @@
                     VolumeData *data = (VolumeData *)command->mParam.get();
                     ALOGV("AudioCommandThread() processing set volume stream %d, \
                             volume %f, output %d", data->mStream, data->mVolume, data->mIO);
-                    mLock.unlock();
+                    ul.unlock();
                     command->mStatus = AudioSystem::setStreamVolume(data->mStream,
                                                                     data->mVolume,
                                                                     data->mIO);
-                    mLock.lock();
+                    ul.lock();
                     }break;
                 case SET_PARAMETERS: {
                     ParametersData *data = (ParametersData *)command->mParam.get();
                     ALOGV("AudioCommandThread() processing set parameters string %s, io %d",
                             data->mKeyValuePairs.c_str(), data->mIO);
-                    mLock.unlock();
+                    ul.unlock();
                     command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
-                    mLock.lock();
+                    ul.lock();
                     }break;
                 case SET_VOICE_VOLUME: {
                     VoiceVolumeData *data = (VoiceVolumeData *)command->mParam.get();
                     ALOGV("AudioCommandThread() processing set voice volume volume %f",
                             data->mVolume);
-                    mLock.unlock();
+                    ul.unlock();
                     command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
-                    mLock.lock();
+                    ul.lock();
                     }break;
                 case STOP_OUTPUT: {
                     StopOutputData *data = (StopOutputData *)command->mParam.get();
@@ -1953,9 +1950,9 @@
                     if (svc == 0) {
                         break;
                     }
-                    mLock.unlock();
+                    ul.unlock();
                     svc->doStopOutput(data->mPortId);
-                    mLock.lock();
+                    ul.lock();
                     }break;
                 case RELEASE_OUTPUT: {
                     ReleaseOutputData *data = (ReleaseOutputData *)command->mParam.get();
@@ -1965,9 +1962,9 @@
                     if (svc == 0) {
                         break;
                     }
-                    mLock.unlock();
+                    ul.unlock();
                     svc->doReleaseOutput(data->mPortId);
-                    mLock.lock();
+                    ul.lock();
                     }break;
                 case CREATE_AUDIO_PATCH: {
                     CreateAudioPatchData *data = (CreateAudioPatchData *)command->mParam.get();
@@ -1976,9 +1973,9 @@
                     if (af == 0) {
                         command->mStatus = PERMISSION_DENIED;
                     } else {
-                        mLock.unlock();
+                        ul.unlock();
                         command->mStatus = af->createAudioPatch(&data->mPatch, &data->mHandle);
-                        mLock.lock();
+                        ul.lock();
                     }
                     } break;
                 case RELEASE_AUDIO_PATCH: {
@@ -1988,9 +1985,9 @@
                     if (af == 0) {
                         command->mStatus = PERMISSION_DENIED;
                     } else {
-                        mLock.unlock();
+                        ul.unlock();
                         command->mStatus = af->releaseAudioPatch(data->mHandle);
-                        mLock.lock();
+                        ul.lock();
                     }
                     } break;
                 case UPDATE_AUDIOPORT_LIST: {
@@ -1999,9 +1996,9 @@
                     if (svc == 0) {
                         break;
                     }
-                    mLock.unlock();
+                    ul.unlock();
                     svc->doOnAudioPortListUpdate();
-                    mLock.lock();
+                    ul.lock();
                     }break;
                 case UPDATE_AUDIOPATCH_LIST: {
                     ALOGV("AudioCommandThread() processing update audio patch list");
@@ -2009,9 +2006,9 @@
                     if (svc == 0) {
                         break;
                     }
-                    mLock.unlock();
+                    ul.unlock();
                     svc->doOnAudioPatchListUpdate();
-                    mLock.lock();
+                    ul.lock();
                     }break;
                 case CHANGED_AUDIOVOLUMEGROUP: {
                     AudioVolumeGroupData *data =
@@ -2021,9 +2018,9 @@
                     if (svc == 0) {
                         break;
                     }
-                    mLock.unlock();
+                    ul.unlock();
                     svc->doOnAudioVolumeGroupChanged(data->mGroup, data->mFlags);
-                    mLock.lock();
+                    ul.lock();
                     }break;
                 case SET_AUDIOPORT_CONFIG: {
                     SetAudioPortConfigData *data = (SetAudioPortConfigData *)command->mParam.get();
@@ -2032,9 +2029,9 @@
                     if (af == 0) {
                         command->mStatus = PERMISSION_DENIED;
                     } else {
-                        mLock.unlock();
+                        ul.unlock();
                         command->mStatus = af->setAudioPortConfig(&data->mConfig);
-                        mLock.lock();
+                        ul.lock();
                     }
                     } break;
                 case DYN_POLICY_MIX_STATE_UPDATE: {
@@ -2046,9 +2043,9 @@
                     if (svc == 0) {
                         break;
                     }
-                    mLock.unlock();
+                    ul.unlock();
                     svc->doOnDynamicPolicyMixStateUpdate(data->mRegId, data->mState);
-                    mLock.lock();
+                    ul.lock();
                     } break;
                 case RECORDING_CONFIGURATION_UPDATE: {
                     RecordingConfigurationUpdateData *data =
@@ -2058,21 +2055,21 @@
                     if (svc == 0) {
                         break;
                     }
-                    mLock.unlock();
+                    ul.unlock();
                     svc->doOnRecordingConfigurationUpdate(data->mEvent, &data->mClientInfo,
                             &data->mClientConfig, data->mClientEffects,
                             &data->mDeviceConfig, data->mEffects,
                             data->mPatchHandle, data->mSource);
-                    mLock.lock();
+                    ul.lock();
                     } break;
                 case SET_EFFECT_SUSPENDED: {
                     SetEffectSuspendedData *data = (SetEffectSuspendedData *)command->mParam.get();
                     ALOGV("AudioCommandThread() processing set effect suspended");
                     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
                     if (af != 0) {
-                        mLock.unlock();
+                        ul.unlock();
                         af->setEffectSuspended(data->mEffectId, data->mSessionId, data->mSuspended);
-                        mLock.lock();
+                        ul.lock();
                     }
                     } break;
                 case AUDIO_MODULES_UPDATE: {
@@ -2081,9 +2078,9 @@
                     if (svc == 0) {
                         break;
                     }
-                    mLock.unlock();
+                    ul.unlock();
                     svc->doOnNewAudioModulesAvailable();
-                    mLock.lock();
+                    ul.lock();
                     } break;
                 case ROUTING_UPDATED: {
                     ALOGV("AudioCommandThread() processing routing update");
@@ -2091,9 +2088,9 @@
                     if (svc == 0) {
                         break;
                     }
-                    mLock.unlock();
+                    ul.unlock();
                     svc->doOnRoutingUpdated();
-                    mLock.lock();
+                    ul.lock();
                     } break;
 
                 case UPDATE_UID_STATES: {
@@ -2102,9 +2099,9 @@
                     if (svc == 0) {
                         break;
                     }
-                    mLock.unlock();
+                    ul.unlock();
                     svc->updateUidStates();
-                    mLock.lock();
+                    ul.lock();
                     } break;
 
                 case CHECK_SPATIALIZER_OUTPUT: {
@@ -2113,9 +2110,9 @@
                     if (svc == 0) {
                         break;
                     }
-                    mLock.unlock();
+                    ul.unlock();
                     svc->doOnCheckSpatializer();
-                    mLock.lock();
+                    ul.lock();
                     } break;
 
                 case UPDATE_ACTIVE_SPATIALIZER_TRACKS: {
@@ -2124,9 +2121,9 @@
                     if (svc == 0) {
                         break;
                     }
-                    mLock.unlock();
+                    ul.unlock();
                     svc->doOnUpdateActiveSpatializerTracks();
-                    mLock.lock();
+                    ul.lock();
                     } break;
 
                 case VOL_RANGE_INIT_REQUEST: {
@@ -2135,28 +2132,28 @@
                     if (svc == 0) {
                         break;
                     }
-                    mLock.unlock();
+                    ul.unlock();
                     svc->doOnVolumeRangeInitRequest();
-                    mLock.lock();
+                    ul.lock();
                     } break;
 
                 default:
                     ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
                 }
                 {
-                    Mutex::Autolock _l(command->mLock);
+                    audio_utils::lock_guard _l(command->mMutex);
                     if (command->mWaitStatus) {
                         command->mWaitStatus = false;
-                        command->mCond.signal();
+                        command->mCond.notify_one();
                     }
                 }
                 waitTime = -1;
-                // release mLock before releasing strong reference on the service as
+                // release ul before releasing strong reference on the service as
                 // AudioPolicyService destructor calls AudioCommandThread::exit() which
-                // acquires mLock.
-                mLock.unlock();
+                // acquires ul.
+                ul.unlock();
                 svc.clear();
-                mLock.lock();
+                ul.lock();
             } else {
                 waitTime = mAudioCommands[0]->mTime - curTime;
                 break;
@@ -2174,9 +2171,10 @@
         if (!exitPending()) {
             ALOGV("AudioCommandThread() going to sleep");
             if (waitTime == -1) {
-                mWaitWorkCV.wait(mLock);
+                mWaitWorkCV.wait(ul);
             } else {
-                mWaitWorkCV.waitRelative(mLock, waitTime);
+                // discard return value.
+                mWaitWorkCV.wait_for(ul, std::chrono::nanoseconds(waitTime));
             }
         }
     }
@@ -2184,17 +2182,17 @@
     if (!mAudioCommands.isEmpty()) {
         release_wake_lock(mName.c_str());
     }
-    mLock.unlock();
     return false;
 }
 
 status_t AudioPolicyService::AudioCommandThread::dump(int fd)
+NO_THREAD_SAFETY_ANALYSIS  // trylock
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
     String8 result;
 
-    const bool locked = dumpTryLock(mLock);
+    const bool locked = mMutex.try_lock(kDumpLockTimeoutNs);
     if (!locked) {
         String8 result2(kCmdDeadlockedString);
         write(fd, result2.c_str(), result2.size());
@@ -2217,7 +2215,7 @@
 
     write(fd, result.c_str(), result.size());
 
-    dumpReleaseLock(mLock, locked);
+    dumpReleaseLock(mMutex, locked);
 
     return NO_ERROR;
 }
@@ -2475,14 +2473,15 @@
 status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
 {
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         insertCommand_l(command, delayMs);
-        mWaitWorkCV.signal();
+        mWaitWorkCV.notify_one();
     }
-    Mutex::Autolock _l(command->mLock);
+    audio_utils::unique_lock ul(command->mMutex);
     while (command->mWaitStatus) {
         nsecs_t timeOutNs = kAudioCommandTimeoutNs + milliseconds(delayMs);
-        if (command->mCond.waitRelative(command->mLock, timeOutNs) != NO_ERROR) {
+        if (command->mCond.wait_for(
+                    ul, std::chrono::nanoseconds(timeOutNs)) == std::cv_status::timeout) {
             command->mStatus = TIMED_OUT;
             command->mWaitStatus = false;
         }
@@ -2490,7 +2489,7 @@
     return command->mStatus;
 }
 
-// insertCommand_l() must be called with mLock held
+// insertCommand_l() must be called with mMutex held
 void AudioPolicyService::AudioCommandThread::insertCommand_l(sp<AudioCommand>& command, int delayMs)
 {
     ssize_t i;  // not size_t because i will count down to -1
@@ -2678,9 +2677,9 @@
 {
     ALOGV("AudioCommandThread::exit");
     {
-        AutoMutex _l(mLock);
+        audio_utils::lock_guard _l(mMutex);
         requestExit();
-        mWaitWorkCV.signal();
+        mWaitWorkCV.notify_one();
     }
     // Note that we can call it from the thread loop if all other references have been released
     // but it will safely return WOULD_BLOCK in this case
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index aaf0b1b..9a8a056 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -20,6 +20,7 @@
 #include <android/media/BnAudioPolicyService.h>
 #include <android/media/GetSpatializerResponse.h>
 #include <android-base/thread_annotations.h>
+#include <audio_utils/mutex.h>
 #include <cutils/misc.h>
 #include <cutils/config_utils.h>
 #include <cutils/compiler.h>
@@ -387,10 +388,10 @@
      * by audio policy manager and attach/detach the spatializer effect accordingly.
      */
     void onCheckSpatializer() override;
-    void onCheckSpatializer_l() REQUIRES(mLock);
+    void onCheckSpatializer_l() REQUIRES(mMutex);
     void doOnCheckSpatializer();
 
-    void onUpdateActiveSpatializerTracks_l() REQUIRES(mLock);
+    void onUpdateActiveSpatializerTracks_l() REQUIRES(mMutex);
     void doOnUpdateActiveSpatializerTracks();
 
 
@@ -402,14 +403,14 @@
                         AudioPolicyService() ANDROID_API;
     virtual             ~AudioPolicyService();
 
-            status_t dumpInternals(int fd) REQUIRES(mLock);
+    status_t dumpInternals(int fd) REQUIRES(mMutex);
 
     // Handles binder shell commands
     virtual status_t shellCommand(int in, int out, int err, Vector<String16>& args);
 
 
     // Sets whether the given UID records only silence
-    virtual void setAppState_l(sp<AudioRecordClient> client, app_state_t state) REQUIRES(mLock);
+    virtual void setAppState_l(sp<AudioRecordClient> client, app_state_t state) REQUIRES(mMutex);
 
     // Overrides the UID state as if it is idle
     status_t handleSetUidState(Vector<String16>& args, int err);
@@ -435,9 +436,9 @@
                            const AttributionSourceState& attributionSource);
 
     void updateUidStates();
-    void updateUidStates_l() REQUIRES(mLock);
+    void updateUidStates_l() REQUIRES(mMutex);
 
-    void silenceAllRecordings_l() REQUIRES(mLock);
+    void silenceAllRecordings_l() REQUIRES(mMutex);
 
     static bool isVirtualSource(audio_source_t source);
 
@@ -510,11 +511,11 @@
         void checkRegistered();
 
         wp<AudioPolicyService> mService;
-        Mutex mLock;
+        audio_utils::mutex mMutex{audio_utils::MutexOrder::kUidPolicy_Mutex};
         ActivityManager mAm;
         bool mObserverRegistered = false;
-        std::unordered_map<uid_t, std::pair<bool, int>> mOverrideUids GUARDED_BY(mLock);
-        std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids GUARDED_BY(mLock);
+        std::unordered_map<uid_t, std::pair<bool, int>> mOverrideUids GUARDED_BY(mMutex);
+        std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids GUARDED_BY(mMutex);
         std::vector<uid_t> mAssistantUids;
         std::vector<uid_t> mActiveAssistantUids;
         std::vector<uid_t> mA11yUids;
@@ -641,8 +642,8 @@
 
             int mCommand;   // SET_VOLUME, SET_PARAMETERS...
             nsecs_t mTime;  // time stamp
-            Mutex mLock;    // mutex associated to mCond
-            Condition mCond; // condition for status return
+            audio_utils::mutex mMutex{audio_utils::MutexOrder::kAudioCommand_Mutex};
+            audio_utils::condition_variable mCond; // condition for status return
             status_t mStatus; // command status
             bool mWaitStatus; // true if caller is waiting for status
             sp<AudioCommandData> mParam;     // command specific parameter data
@@ -730,8 +731,8 @@
             bool mSuspended;
         };
 
-        Mutex   mLock;
-        Condition mWaitWorkCV;
+        mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kCommandThread_Mutex};
+        audio_utils::condition_variable mWaitWorkCV;
         Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands
         sp<AudioCommand> mLastCommand;      // last processed command (used by dump)
         String8 mName;                      // string used by wake lock fo delayed commands
@@ -996,12 +997,12 @@
      * @return the number of active tracks.
      */
     size_t countActiveClientsOnOutput_l(
-        audio_io_handle_t output, bool spatializedOnly = true) REQUIRES(mLock);
+            audio_io_handle_t output, bool spatializedOnly = true) REQUIRES(mMutex);
 
-    mutable Mutex mLock;    // prevents concurrent access to AudioPolicy manager functions changing
-                            // device connection state  or routing
-    // Note: lock acquisition order is always mLock > mEffectsLock:
-    // mLock protects AudioPolicyManager methods that can call into audio flinger
+    mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kAudioPolicyService_Mutex};
+    // prevents concurrent access to AudioPolicy manager functions changing
+    // device connection state or routing.
+    // mMutex protects AudioPolicyManager methods that can call into audio flinger
     // and possibly back in to audio policy service and acquire mEffectsLock.
     sp<AudioCommandThread> mAudioCommandThread;     // audio commands thread
     sp<AudioCommandThread> mOutputCommandThread;    // process stop and release output
@@ -1009,29 +1010,30 @@
     AudioPolicyClient *mAudioPolicyClient;
     std::vector<audio_usage_t> mSupportedSystemUsages;
 
-    Mutex mNotificationClientsLock;
+    mutable audio_utils::mutex mNotificationClientsMutex{
+            audio_utils::MutexOrder::kAudioPolicyService_NotificationClientsMutex};
     DefaultKeyedVector<int64_t, sp<NotificationClient>> mNotificationClients
-        GUARDED_BY(mNotificationClientsLock);
+            GUARDED_BY(mNotificationClientsMutex);
     // Manage all effects configured in audio_effects.conf
-    // never hold AudioPolicyService::mLock when calling AudioPolicyEffects methods as
+    // never hold AudioPolicyService::mMutex when calling AudioPolicyEffects methods as
     // those can call back into AudioPolicyService methods and try to acquire the mutex
-    sp<AudioPolicyEffects> mAudioPolicyEffects GUARDED_BY(mLock);
-    audio_mode_t mPhoneState GUARDED_BY(mLock);
-    uid_t mPhoneStateOwnerUid GUARDED_BY(mLock);
+    sp<AudioPolicyEffects> mAudioPolicyEffects GUARDED_BY(mMutex);
+    audio_mode_t mPhoneState GUARDED_BY(mMutex);
+    uid_t mPhoneStateOwnerUid GUARDED_BY(mMutex);
 
-    sp<UidPolicy> mUidPolicy GUARDED_BY(mLock);
-    sp<SensorPrivacyPolicy> mSensorPrivacyPolicy GUARDED_BY(mLock);
+    sp<UidPolicy> mUidPolicy GUARDED_BY(mMutex);
+    sp<SensorPrivacyPolicy> mSensorPrivacyPolicy GUARDED_BY(mMutex);
 
     DefaultKeyedVector<audio_port_handle_t, sp<AudioRecordClient>> mAudioRecordClients
-        GUARDED_BY(mLock);
+            GUARDED_BY(mMutex);
     DefaultKeyedVector<audio_port_handle_t, sp<AudioPlaybackClient>> mAudioPlaybackClients
-        GUARDED_BY(mLock);
+            GUARDED_BY(mMutex);
 
     MediaPackageManager mPackageManager; // To check allowPlaybackCapture
 
     CaptureStateNotifier mCaptureStateNotifier;
 
-    // created in onFirstRef() and never cleared: does not need to be guarded by mLock
+    // created in onFirstRef() and never cleared: does not need to be guarded by mMutex
     sp<Spatializer> mSpatializer;
 
     void *mLibraryHandle = nullptr;
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 90418a5..ca3e0e0 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -229,7 +229,7 @@
         return;
     }
     auto latencyModesStrs = android::sysprop::BluetoothProperties::dsa_transport_preference();
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     // First load preferred low latency modes ordered from the property
     for (auto str : latencyModesStrs) {
         if (!str.has_value()) continue;
@@ -394,7 +394,11 @@
         return status;
     }
     for (const auto channelMask : channelMasks) {
-        if (!audio_is_channel_mask_spatialized(channelMask)) {
+        const bool channel_mask_spatialized =
+                com_android_media_audio_stereo_spatialization()
+                ? audio_channel_mask_contains_stereo(channelMask)
+                : audio_is_channel_mask_spatialized(channelMask);
+        if (!channel_mask_spatialized) {
             ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
             continue;
         }
@@ -461,7 +465,7 @@
 
 /** Gets the channel mask, sampling rate and format set for the spatializer input. */
 audio_config_base_t Spatializer::getAudioInConfig() const {
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
     // For now use highest supported channel count
     config.channel_mask = getMaxChannelMask(mChannelMasks, FCC_LIMIT);
@@ -470,7 +474,7 @@
 
 status_t Spatializer::registerCallback(
         const sp<media::INativeSpatializerCallback>& callback) {
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     if (callback == nullptr) {
         return BAD_VALUE;
     }
@@ -498,7 +502,7 @@
 // IBinder::DeathRecipient
 void Spatializer::binderDied(__unused const wp<IBinder> &who) {
     {
-        std::lock_guard lock(mLock);
+        audio_utils::lock_guard lock(mMutex);
         mLevel = Spatialization::Level::NONE;
         mSpatializerCallback.clear();
     }
@@ -527,7 +531,7 @@
     sp<media::INativeSpatializerCallback> callback;
     bool levelChanged = false;
     {
-        std::lock_guard lock(mLock);
+        audio_utils::lock_guard lock(mMutex);
         levelChanged = mLevel != level;
         mLevel = level;
         callback = mSpatializerCallback;
@@ -551,7 +555,7 @@
     if (level == nullptr) {
         return binderStatusFromStatusT(BAD_VALUE);
     }
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     *level = mLevel;
     ALOGV("%s level %d", __func__, (int)*level);
     return Status::ok();
@@ -562,14 +566,14 @@
     if (supports == nullptr) {
         return binderStatusFromStatusT(BAD_VALUE);
     }
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     *supports = mSupportsHeadTracking;
     return Status::ok();
 }
 
 Status Spatializer::getSupportedHeadTrackingModes(
         std::vector<HeadTracking::Mode>* modes) {
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     ALOGV("%s", __func__);
     if (modes == nullptr) {
         return binderStatusFromStatusT(BAD_VALUE);
@@ -585,7 +589,7 @@
         return binderStatusFromStatusT(INVALID_OPERATION);
     }
     mLocalLog.log("%s with %s", __func__, ToString(mode).c_str());
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     switch (mode) {
         case HeadTracking::Mode::OTHER:
             return binderStatusFromStatusT(BAD_VALUE);
@@ -610,7 +614,7 @@
     if (mode == nullptr) {
         return binderStatusFromStatusT(BAD_VALUE);
     }
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     *mode = mActualHeadTrackingMode;
     ALOGV("%s mode %d", __func__, (int)*mode);
     return Status::ok();
@@ -620,7 +624,7 @@
     if (!mSupportsHeadTracking) {
         return binderStatusFromStatusT(INVALID_OPERATION);
     }
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     if (mPoseController != nullptr) {
         mPoseController->recenter();
     }
@@ -637,7 +641,7 @@
         ALOGW("Invalid screenToStage vector.");
         return binderStatusFromStatusT(BAD_VALUE);
     }
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     if (mPoseController != nullptr) {
         mLocalLog.log("%s with screenToStage %s", __func__,
                 media::VectorRecorder::toString<float>(screenToStage).c_str());
@@ -650,7 +654,7 @@
     ALOGV("%s", __func__);
     bool levelChanged = false;
     {
-        std::lock_guard lock(mLock);
+        audio_utils::lock_guard lock(mMutex);
         if (mSpatializerCallback == nullptr) {
             return binderStatusFromStatusT(INVALID_OPERATION);
         }
@@ -674,7 +678,7 @@
     if (!mSupportsHeadTracking) {
         return binderStatusFromStatusT(INVALID_OPERATION);
     }
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     if (mHeadSensor != sensorHandle) {
         mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
         mHeadSensor = sensorHandle;
@@ -689,7 +693,7 @@
     if (!mSupportsHeadTracking) {
         return binderStatusFromStatusT(INVALID_OPERATION);
     }
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     if (mScreenSensor != sensorHandle) {
         mLocalLog.log("%s with 0x%08x", __func__, sensorHandle);
         mScreenSensor = sensorHandle;
@@ -708,7 +712,7 @@
     // It is possible due to numerical inaccuracies to exceed the boundaries of 0 to 2 * M_PI.
     ALOGI_IF(angle != physicalToLogicalAngle,
             "%s: clamping %f to %f", __func__, physicalToLogicalAngle, angle);
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     mDisplayOrientation = angle;
     if (mPoseController != nullptr) {
         // This turns on the rate-limiter.
@@ -728,7 +732,7 @@
     // It is possible due to numerical inaccuracies to exceed the boundaries of 0 to 2 * M_PI.
     ALOGI_IF(angle != hingeAngle,
             "%s: clamping %f to %f", __func__, hingeAngle, angle);
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     mHingeAngle = angle;
     if (mEngine != nullptr) {
         setEffectParameter_l(SPATIALIZER_PARAM_HINGE_ANGLE, std::vector<float>{angle});
@@ -739,7 +743,7 @@
 Status Spatializer::setFoldState(bool folded) {
     ALOGV("%s foldState %d", __func__, (int)folded);
     mLocalLog.log("%s with %d", __func__, (int)folded);
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     mFoldedState = folded;
     if (mEngine != nullptr) {
         // we don't suppress multiple calls with the same folded state - that's
@@ -761,7 +765,7 @@
 Status Spatializer::registerHeadTrackingCallback(
         const sp<media::ISpatializerHeadTrackingCallback>& callback) {
     ALOGV("%s callback %p", __func__, callback.get());
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     if (!mSupportsHeadTracking) {
         return binderStatusFromStatusT(INVALID_OPERATION);
     }
@@ -771,7 +775,7 @@
 
 Status Spatializer::setParameter(int key, const std::vector<unsigned char>& value) {
     ALOGV("%s key %d", __func__, key);
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     status_t status = INVALID_OPERATION;
     if (mEngine != nullptr) {
         status = setEffectParameter_l(key, value);
@@ -785,7 +789,7 @@
     if (value == nullptr) {
         return binderStatusFromStatusT(BAD_VALUE);
     }
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     status_t status = INVALID_OPERATION;
     if (mEngine != nullptr) {
         ALOGV("%s key %d mEngine %p", __func__, key, mEngine.get());
@@ -799,7 +803,7 @@
     if (output == nullptr) {
         binderStatusFromStatusT(BAD_VALUE);
     }
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     *output = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_io_handle_t_int32_t(mOutput));
     ALOGV("%s got output %d", __func__, *output);
     return Status::ok();
@@ -837,7 +841,7 @@
     ALOGV("%s", __func__);
     sp<media::ISpatializerHeadTrackingCallback> callback;
     {
-        std::lock_guard lock(mLock);
+        audio_utils::lock_guard lock(mMutex);
         callback = mHeadTrackingCallback;
         if (mEngine != nullptr) {
             setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
@@ -865,7 +869,7 @@
     sp<media::ISpatializerHeadTrackingCallback> callback;
     HeadTracking::Mode spatializerMode;
     {
-        std::lock_guard lock(mLock);
+        audio_utils::lock_guard lock(mMutex);
         if (!mSupportsHeadTracking) {
             spatializerMode = HeadTracking::Mode::DISABLED;
         } else {
@@ -932,7 +936,7 @@
     sp<media::INativeSpatializerCallback> callback;
 
     {
-        std::lock_guard lock(mLock);
+        audio_utils::lock_guard lock(mMutex);
         ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
         mLocalLog.log("%s with output %d tracks %zu (mOutput %d)", __func__, (int)output,
                       numActiveTracks, (int)mOutput);
@@ -998,7 +1002,7 @@
     sp<media::INativeSpatializerCallback> callback;
 
     {
-        std::lock_guard lock(mLock);
+        audio_utils::lock_guard lock(mMutex);
         mLocalLog.log("%s with output %d tracks %zu", __func__, (int)mOutput, mNumActiveTracks);
         ALOGV("%s mOutput %d", __func__, (int)mOutput);
         if (mOutput == AUDIO_IO_HANDLE_NONE) {
@@ -1032,7 +1036,7 @@
 
 void Spatializer::onSupportedLatencyModesChangedMsg(
         audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes) {
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     ALOGV("%s output %d mOutput %d num modes %zu",
             __func__, (int)output, (int)mOutput, modes.size());
     if (output == mOutput) {
@@ -1043,7 +1047,7 @@
 }
 
 void Spatializer::updateActiveTracks(size_t numActiveTracks) {
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     if (mNumActiveTracks != numActiveTracks) {
         mLocalLog.log("%s from %zu to %zu", __func__, mNumActiveTracks, numActiveTracks);
         mNumActiveTracks = numActiveTracks;
@@ -1174,7 +1178,7 @@
 
 void Spatializer::calculateHeadPose() {
     ALOGV("%s", __func__);
-    std::lock_guard lock(mLock);
+    audio_utils::lock_guard lock(mMutex);
     if (mPoseController != nullptr) {
         mPoseController->calculateAsync();
     }
@@ -1193,7 +1197,7 @@
     bool needUnlock = false;
 
     prefixSpace += ' ';
-    if (!mLock.try_lock()) {
+    if (!mMutex.try_lock()) {
         // dumpsys even try_lock failed, information dump can be useful although may not accurate
         ss.append(prefixSpace).append("try_lock failed, dumpsys below maybe INACCURATE!\n");
     } else {
@@ -1239,6 +1243,10 @@
     base::StringAppendF(&ss, "%sDisplayOrientation: %f\n", prefixSpace.c_str(),
                         mDisplayOrientation);
 
+    // 4. Show flag or property state.
+    base::StringAppendF(&ss, "%sStereo Spatialization: %s\n", prefixSpace.c_str(),
+            com_android_media_audio_stereo_spatialization() ? "true" : "false");
+
     ss.append(prefixSpace + "CommandLog:\n");
     ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);
 
@@ -1258,7 +1266,7 @@
     }
 
     if (needUnlock) {
-        mLock.unlock();
+        mMutex.unlock();
     }
     return ss;
 }
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index 123517e..24788dc 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -23,6 +23,7 @@
 #include <android/media/audio/common/AudioLatencyMode.h>
 #include <android/media/audio/common/HeadTracking.h>
 #include <android/media/audio/common/Spatialization.h>
+#include <audio_utils/mutex.h>
 #include <audio_utils/SimpleLog.h>
 #include <math.h>
 #include <media/AudioEffect.h>
@@ -148,7 +149,7 @@
 
     /** Level getter for use by local classes. */
     media::audio::common::Spatialization::Level getLevel() const {
-        std::lock_guard lock(mLock);
+        audio_utils::lock_guard lock(mMutex);
         return mLevel;
     }
 
@@ -161,7 +162,7 @@
      */
     audio_io_handle_t detachOutput();
     /** Returns the output stream the spatializer is attached to. */
-    audio_io_handle_t getOutput() const { std::lock_guard lock(mLock); return mOutput; }
+    audio_io_handle_t getOutput() const { audio_utils::lock_guard lock(mMutex); return mOutput; }
 
     void updateActiveTracks(size_t numActiveTracks);
 
@@ -261,7 +262,7 @@
      *  according to values vector size.
      */
     template<typename T>
-    status_t setEffectParameter_l(uint32_t type, const std::vector<T>& values) REQUIRES(mLock) {
+    status_t setEffectParameter_l(uint32_t type, const std::vector<T>& values) REQUIRES(mMutex) {
         static_assert(sizeof(T) <= sizeof(uint32_t), "The size of T must less than 32 bits");
 
         uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1 + values.size()];
@@ -286,7 +287,7 @@
      * The variant is for compound parameters with two values of different base types
      */
     template<typename P1, typename P2>
-    status_t setEffectParameter_l(uint32_t type, const P1 val1, const P2 val2) REQUIRES(mLock) {
+    status_t setEffectParameter_l(uint32_t type, const P1 val1, const P2 val2) REQUIRES(mMutex) {
         static_assert(sizeof(P1) <= sizeof(uint32_t), "The size of P1 must less than 32 bits");
         static_assert(sizeof(P2) <= sizeof(uint32_t), "The size of P2 must less than 32 bits");
 
@@ -314,7 +315,7 @@
      * by specifying values vector size.
      */
     template<typename T>
-    status_t getEffectParameter_l(uint32_t type, std::vector<T> *values) REQUIRES(mLock) {
+    status_t getEffectParameter_l(uint32_t type, std::vector<T> *values) REQUIRES(mMutex) {
         static_assert(sizeof(T) <= sizeof(uint32_t), "The size of T must less than 32 bits");
 
         uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1 + values->size()];
@@ -345,7 +346,7 @@
      * The variant is for compound parameters with two values of different base types
      */
     template<typename P1, typename P2>
-    status_t getEffectParameter_l(uint32_t type, P1 *val1, P2 *val2) REQUIRES(mLock) {
+    status_t getEffectParameter_l(uint32_t type, P1 *val1, P2 *val2) REQUIRES(mMutex) {
         static_assert(sizeof(P1) <= sizeof(uint32_t), "The size of P1 must less than 32 bits");
         static_assert(sizeof(P2) <= sizeof(uint32_t), "The size of P2 must less than 32 bits");
 
@@ -375,25 +376,25 @@
      * spatializer state and playback activity and configures the pose controller
      * accordingly.
      */
-    void checkSensorsState_l() REQUIRES(mLock);
+    void checkSensorsState_l() REQUIRES(mMutex);
 
     /**
      * Checks if the head pose controller should be created or destroyed according
      * to desired head tracking mode.
      */
-    void checkPoseController_l() REQUIRES(mLock);
+    void checkPoseController_l() REQUIRES(mMutex);
 
     /**
      * Checks if the spatializer effect should be enabled based on
      * playback activity and requested level.
      */
-    void checkEngineState_l() REQUIRES(mLock);
+    void checkEngineState_l() REQUIRES(mMutex);
 
     /**
      * Reset head tracking mode and recenter pose in engine: Called when the head tracking
      * is disabled.
      */
-    void resetEngineHeadPose_l() REQUIRES(mLock);
+    void resetEngineHeadPose_l() REQUIRES(mMutex);
 
     /** Read bluetooth.core.le.dsa_transport_preference property and populate the ordered list of
      * preferred low latency modes in mOrderedLowLatencyModes.
@@ -406,7 +407,7 @@
      * Note: Because MODE_FREE is not in mOrderedLowLatencyModes, it will always be at
      * the end of the list.
      */
-    void sortSupportedLatencyModes_l() REQUIRES(mLock);
+    void sortSupportedLatencyModes_l() REQUIRES(mMutex);
 
     /**
      * Called after enabling head tracking in the spatializer engine to indicate which
@@ -415,14 +416,14 @@
      * When the connection mode is direct to the sensor, the sensor ID is also communicated
      * to the spatializer engine.
      */
-    void setEngineHeadtrackingConnectionMode_l() REQUIRES(mLock);
+    void setEngineHeadtrackingConnectionMode_l() REQUIRES(mMutex);
 
     /**
      * Select the desired head tracking connection mode for the spatializer engine among the list
      * stored in mSupportedHeadtrackingConnectionModes at init time.
      * Also returns the desired low latency mode according to selected connection mode.
      */
-    audio_latency_mode_t selectHeadtrackingConnectionMode_l() REQUIRES(mLock);
+    audio_latency_mode_t selectHeadtrackingConnectionMode_l() REQUIRES(mMutex);
 
     /** Effect engine descriptor */
     const effect_descriptor_t mEngineDescriptor;
@@ -435,48 +436,48 @@
     const std::string mMetricsId = kDefaultMetricsId;
 
     /** Mutex protecting internal state */
-    mutable std::mutex mLock;
+    mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kSpatializer_Mutex};
 
     /** Client AudioEffect for the engine */
-    sp<AudioEffect> mEngine GUARDED_BY(mLock);
+    sp<AudioEffect> mEngine GUARDED_BY(mMutex);
     /** Output stream the spatializer mixer thread is attached to */
-    audio_io_handle_t mOutput GUARDED_BY(mLock) = AUDIO_IO_HANDLE_NONE;
+    audio_io_handle_t mOutput GUARDED_BY(mMutex) = AUDIO_IO_HANDLE_NONE;
 
     /** Callback interface to the client (AudioService) controlling this`Spatializer */
-    sp<media::INativeSpatializerCallback> mSpatializerCallback GUARDED_BY(mLock);
+    sp<media::INativeSpatializerCallback> mSpatializerCallback GUARDED_BY(mMutex);
 
     /** Callback interface for head tracking */
-    sp<media::ISpatializerHeadTrackingCallback> mHeadTrackingCallback GUARDED_BY(mLock);
+    sp<media::ISpatializerHeadTrackingCallback> mHeadTrackingCallback GUARDED_BY(mMutex);
 
     /** Requested spatialization level */
-    media::audio::common::Spatialization::Level mLevel GUARDED_BY(mLock) =
+    media::audio::common::Spatialization::Level mLevel GUARDED_BY(mMutex) =
             media::audio::common::Spatialization::Level::NONE;
 
     /** Control logic for head-tracking, etc. */
-    std::shared_ptr<SpatializerPoseController> mPoseController GUARDED_BY(mLock);
+    std::shared_ptr<SpatializerPoseController> mPoseController GUARDED_BY(mMutex);
 
     /** Last requested head tracking mode */
-    media::HeadTrackingMode mDesiredHeadTrackingMode GUARDED_BY(mLock)
+    media::HeadTrackingMode mDesiredHeadTrackingMode GUARDED_BY(mMutex)
             = media::HeadTrackingMode::STATIC;
 
     /** Last-reported actual head-tracking mode. */
-    media::audio::common::HeadTracking::Mode mActualHeadTrackingMode GUARDED_BY(mLock)
+    media::audio::common::HeadTracking::Mode mActualHeadTrackingMode GUARDED_BY(mMutex)
             = media::audio::common::HeadTracking::Mode::DISABLED;
 
     /** Selected Head pose sensor */
-    int32_t mHeadSensor GUARDED_BY(mLock) = SpatializerPoseController::INVALID_SENSOR;
+    int32_t mHeadSensor GUARDED_BY(mMutex) = SpatializerPoseController::INVALID_SENSOR;
 
     /** Selected Screen pose sensor */
-    int32_t mScreenSensor GUARDED_BY(mLock) = SpatializerPoseController::INVALID_SENSOR;
+    int32_t mScreenSensor GUARDED_BY(mMutex) = SpatializerPoseController::INVALID_SENSOR;
 
     /** Last display orientation received */
-    float mDisplayOrientation GUARDED_BY(mLock) = 0.f;  // aligned to natural up orientation.
+    float mDisplayOrientation GUARDED_BY(mMutex) = 0.f;  // aligned to natural up orientation.
 
     /** Last folded state */
-    bool mFoldedState GUARDED_BY(mLock) = false;  // foldable: true means folded.
+    bool mFoldedState GUARDED_BY(mMutex) = false;  // foldable: true means folded.
 
     /** Last hinge angle */
-    float mHingeAngle GUARDED_BY(mLock) = 0.f;  // foldable: 0.f is closed, M_PI flat open.
+    float mHingeAngle GUARDED_BY(mMutex) = 0.f;  // foldable: 0.f is closed, M_PI flat open.
 
     std::vector<media::audio::common::Spatialization::Level> mLevels;
     std::vector<media::audio::common::HeadTracking::Mode> mHeadTrackingModes;
@@ -497,8 +498,8 @@
     sp<ALooper> mLooper;
     sp<EngineCallbackHandler> mHandler;
 
-    size_t mNumActiveTracks GUARDED_BY(mLock) = 0;
-    std::vector<audio_latency_mode_t> mSupportedLatencyModes GUARDED_BY(mLock);
+    size_t mNumActiveTracks GUARDED_BY(mMutex) = 0;
+    std::vector<audio_latency_mode_t> mSupportedLatencyModes GUARDED_BY(mMutex);
     /** preference order for low latency modes according to persist.bluetooth.hid.transport */
     std::vector<audio_latency_mode_t> mOrderedLowLatencyModes;
     /** string to latency mode map used to parse bluetooth.core.le.dsa_transport_preference */
@@ -514,10 +515,10 @@
      * Dump to local log with max/average pose angle every mPoseRecordThreshold.
      */
     // Record one log line per second (up to mMaxLocalLogLine) to capture most recent sensor data.
-    media::VectorRecorder mPoseRecorder GUARDED_BY(mLock) {
+    media::VectorRecorder mPoseRecorder GUARDED_BY(mMutex) {
         6 /* vectorSize */, std::chrono::seconds(1), mMaxLocalLogLine, { 3 } /* delimiterIdx */};
     // Record one log line per minute (up to mMaxLocalLogLine) to capture durable sensor data.
-    media::VectorRecorder mPoseDurableRecorder  GUARDED_BY(mLock) {
+    media::VectorRecorder mPoseDurableRecorder GUARDED_BY(mMutex) {
         6 /* vectorSize */, std::chrono::minutes(1), mMaxLocalLogLine, { 3 } /* delimiterIdx */};
 };  // Spatializer
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 6acf0b6..3f43af5 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -123,6 +123,10 @@
     android_atomic_write(level, &gLogLevel);
 }
 
+int32_t format_as(CameraService::StatusInternal s) {
+  return fmt::underlying(s);
+}
+
 // ----------------------------------------------------------------------------
 
 static const std::string sDumpPermission("android.permission.DUMP");
@@ -510,8 +514,8 @@
     }
 
     if (newStatus == StatusInternal::NOT_PRESENT) {
-        logDeviceRemoved(cameraId, fmt::sprintf("Device status changed from %d to %d", oldStatus,
-                newStatus));
+        logDeviceRemoved(cameraId, fmt::format("Device status changed from {} to {}",
+                oldStatus, newStatus));
 
         // Set the device status to NOT_PRESENT, clients will no longer be able to connect
         // to this device until the status changes
@@ -537,8 +541,8 @@
         removeStates(cameraId);
     } else {
         if (oldStatus == StatusInternal::NOT_PRESENT) {
-            logDeviceAdded(cameraId, fmt::sprintf("Device status changed from %d to %d", oldStatus,
-                    newStatus));
+            logDeviceAdded(cameraId, fmt::format("Device status changed from {} to {}",
+                    oldStatus, newStatus));
         }
         updateStatus(newStatus, cameraId);
     }
@@ -578,9 +582,9 @@
     if (updated) {
         std::string idCombo = id + " : " + physicalId;
         if (newStatus == StatusInternal::PRESENT) {
-            logDeviceAdded(idCombo, fmt::sprintf("Device status changed to %d", newStatus));
+            logDeviceAdded(idCombo, fmt::format("Device status changed to {}", newStatus));
         } else {
-            logDeviceRemoved(idCombo, fmt::sprintf("Device status changed to %d", newStatus));
+            logDeviceRemoved(idCombo, fmt::format("Device status changed to {}", newStatus));
         }
         // Avoid calling getSystemCameraKind() with mStatusListenerLock held (b/141756275)
         SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 7dc0b91..1487013 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -693,6 +693,8 @@
         UNKNOWN = static_cast<int32_t>(hardware::ICameraServiceListener::STATUS_UNKNOWN)
     };
 
+    friend int32_t format_as(StatusInternal s);
+
     /**
      * Container class for the state of each logical camera device, including: ID, status, and
      * dependencies on other devices.  The mapping of camera ID -> state saved in mCameraStates
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 7443788..3488629 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -1063,7 +1063,7 @@
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
                 "Camera %s: Error creating output stream (%d x %d, fmt %x, dataSpace %x): %s (%d)",
                 mCameraIdStr.c_str(), streamInfo.width, streamInfo.height, streamInfo.format,
-                streamInfo.dataSpace, strerror(-err), err);
+                static_cast<int>(streamInfo.dataSpace), strerror(-err), err);
     } else {
         int i = 0;
         for (auto& binder : binders) {
@@ -1160,7 +1160,8 @@
     if (err != OK) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
                 "Camera %s: Error creating output stream (%d x %d, fmt %x, dataSpace %x): %s (%d)",
-                mCameraIdStr.c_str(), width, height, format, dataSpace, strerror(-err), err);
+                mCameraIdStr.c_str(), width, height, format, static_cast<int>(dataSpace),
+                strerror(-err), err);
     } else {
         // Can not add streamId to mStreamMap here, as the surface is deferred. Add it to
         // a separate list to track. Once the deferred surface is set, this id will be
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 107cc19..28b2d78 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -3590,6 +3590,7 @@
     for (size_t i = 0; i < mNextRequests.size(); i++) {
         auto& nextRequest = mNextRequests.editItemAt(i);
         sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
+        captureRequest->mTestPatternChanged = overrideTestPattern(captureRequest);
         // Do not override rotate&crop for stream configurations that include
         // SurfaceViews(HW_COMPOSER) output, unless mOverrideToPortrait is set.
         // The display rotation there will be compensated by NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY
@@ -3748,7 +3749,6 @@
         bool triggersMixedIn = (triggerCount > 0 || mPrevTriggers > 0);
         mPrevTriggers = triggerCount;
 
-        bool testPatternChanged = overrideTestPattern(captureRequest);
         bool settingsOverrideChanged = overrideSettingsOverride(captureRequest);
 
         // If the request is the same as last, or we had triggers now or last time or
@@ -3757,7 +3757,7 @@
                 (mPrevRequest != captureRequest || triggersMixedIn ||
                          captureRequest->mRotateAndCropChanged ||
                          captureRequest->mAutoframingChanged ||
-                         testPatternChanged || settingsOverrideChanged ||
+                         captureRequest->mTestPatternChanged || settingsOverrideChanged ||
                          (flags::inject_session_params() && mForceNewRequestAfterReconfigure)) &&
                 // Request settings are all the same within one batch, so only treat the first
                 // request in a batch as new
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 25f841a..e32a36f 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -655,6 +655,8 @@
         bool                                mAutoframingAuto;
         // Indicates that the auto framing value within 'mSettingsList' was modified
         bool                                mAutoframingChanged = false;
+        // Indicates that the camera test pattern setting is modified
+        bool                                mTestPatternChanged = false;
 
         // Whether this capture request has its zoom ratio set to 1.0x before
         // the framework overrides it for camera HAL consumption.
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index c59138c..152687e 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -84,10 +84,10 @@
     status_t res = getEndpointUsage(&consumerUsage);
     if (res != OK) consumerUsage = 0;
 
-    lines << fmt::sprintf("      State: %d\n", mState);
+    lines << fmt::sprintf("      State: %d\n", static_cast<int>(mState));
     lines << fmt::sprintf("      Dims: %d x %d, format 0x%x, dataspace 0x%x\n",
             camera_stream::width, camera_stream::height,
-            camera_stream::format, camera_stream::data_space);
+            camera_stream::format, static_cast<int>(camera_stream::data_space));
     lines << fmt::sprintf("      Max size: %zu\n", mMaxSize);
     lines << fmt::sprintf("      Combined usage: 0x%" PRIx64 ", max HAL buffers: %d\n",
             mUsage | consumerUsage, camera_stream::max_buffers);
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index 3be8e15..11ef9b7 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -623,7 +623,7 @@
     if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
         if (dataSpace != streamInfo.dataSpace) {
             std::string msg = fmt::sprintf("Camera %s:Surface dataSpace doesn't match: %d vs %d",
-                    logicalCameraId.c_str(), dataSpace, streamInfo.dataSpace);
+                    logicalCameraId.c_str(), static_cast<int>(dataSpace), static_cast<int>(streamInfo.dataSpace));
             ALOGE("%s: %s", __FUNCTION__, msg.c_str());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
         }
@@ -1133,7 +1133,7 @@
 }
 
 void filterParameters(const CameraMetadata& src, const CameraMetadata& deviceInfo,
-        int vendorTagId, CameraMetadata& dst) {
+        metadata_vendor_id_t vendorTagId, CameraMetadata& dst) {
     const CameraMetadata params(src);
     camera_metadata_ro_entry_t availableSessionKeys = deviceInfo.find(
             ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index 29e3eca..5b2ea5c 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -177,7 +177,7 @@
         aidl::android::hardware::camera::device::RequestTemplate* tempId /*out*/);
 
 void filterParameters(const CameraMetadata& src, const CameraMetadata& deviceInfo,
-        int vendorTagId, CameraMetadata& dst);
+        metadata_vendor_id_t vendorTagId, CameraMetadata& dst);
 
 constexpr int32_t MAX_SURFACES_PER_STREAM = 4;
 
diff --git a/services/camera/virtualcamera/TEST_MAPPING b/services/camera/virtualcamera/TEST_MAPPING
index 66c5e52..25fca73 100644
--- a/services/camera/virtualcamera/TEST_MAPPING
+++ b/services/camera/virtualcamera/TEST_MAPPING
@@ -2,9 +2,7 @@
   "presubmit" : [
     {
       "name": "virtual_camera_tests"
-    }
-  ],
-  "postsubmit": [
+    },
     {
       "name": "CtsVirtualDevicesCameraTestCases",
       "options": [
diff --git a/services/camera/virtualcamera/VirtualCameraDevice.cc b/services/camera/virtualcamera/VirtualCameraDevice.cc
index ec72ee3..84f721b 100644
--- a/services/camera/virtualcamera/VirtualCameraDevice.cc
+++ b/services/camera/virtualcamera/VirtualCameraDevice.cc
@@ -119,9 +119,10 @@
     const std::vector<SupportedStreamConfiguration>& supportedInputConfig) {
   if (!std::all_of(supportedInputConfig.begin(), supportedInputConfig.end(),
                    [](const SupportedStreamConfiguration& config) {
-                     return config.pixelFormat == Format::YUV_420_888;
+                     return isFormatSupportedForInput(
+                         config.width, config.height, config.pixelFormat);
                    })) {
-    ALOGE("%s: input configuration contains unsupported pixel format", __func__);
+    ALOGE("%s: input configuration contains unsupported format", __func__);
     return std::nullopt;
   }
 
@@ -322,7 +323,7 @@
   ALOGV("%s", __func__);
 
   *_aidl_return = ndk::SharedRefBase::make<VirtualCameraSession>(
-      *this, in_callback, mVirtualCameraClientCallback);
+      sharedFromThis(), in_callback, mVirtualCameraClientCallback);
 
   return ndk::ScopedAStatus::ok();
 };
@@ -367,6 +368,13 @@
   return std::string(kDevicePathPrefix) + std::to_string(mCameraId);
 }
 
+std::shared_ptr<VirtualCameraDevice> VirtualCameraDevice::sharedFromThis() {
+  // SharedRefBase which BnCameraDevice inherits from breaks
+  // std::enable_shared_from_this. This is recommended replacement for
+  // shared_from_this() per documentation in binder_interface_utils.h.
+  return ref<VirtualCameraDevice>();
+}
+
 }  // namespace virtualcamera
 }  // namespace companion
 }  // namespace android
diff --git a/services/camera/virtualcamera/VirtualCameraDevice.h b/services/camera/virtualcamera/VirtualCameraDevice.h
index ee7a3a7..402de6c 100644
--- a/services/camera/virtualcamera/VirtualCameraDevice.h
+++ b/services/camera/virtualcamera/VirtualCameraDevice.h
@@ -98,6 +98,8 @@
   uint32_t getCameraId() const { return mCameraId; }
 
  private:
+  std::shared_ptr<VirtualCameraDevice> sharedFromThis();
+
   const uint32_t mCameraId;
   const std::shared_ptr<
       ::aidl::android::companion::virtualcamera::IVirtualCameraCallback>
diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.cc b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
index 8621160..79c91ef 100644
--- a/services/camera/virtualcamera/VirtualCameraRenderThread.cc
+++ b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
@@ -19,6 +19,7 @@
 
 #include <chrono>
 #include <cstddef>
+#include <cstdint>
 #include <future>
 #include <memory>
 #include <mutex>
@@ -38,6 +39,7 @@
 #include "android-base/thread_annotations.h"
 #include "android/binder_auto_utils.h"
 #include "android/hardware_buffer.h"
+#include "ui/GraphicBuffer.h"
 #include "util/EglFramebuffer.h"
 #include "util/JpegUtil.h"
 #include "util/MetadataBuilder.h"
@@ -109,6 +111,45 @@
   return msg;
 }
 
+std::shared_ptr<EglFrameBuffer> allocateTemporaryFramebuffer(
+    EGLDisplay eglDisplay, const uint width, const int height) {
+  const AHardwareBuffer_Desc desc{
+      .width = static_cast<uint32_t>(width),
+      .height = static_cast<uint32_t>(height),
+      .layers = 1,
+      .format = AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420,
+      .usage = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
+               AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
+      .rfu0 = 0,
+      .rfu1 = 0};
+
+  AHardwareBuffer* hwBufferPtr;
+  int status = AHardwareBuffer_allocate(&desc, &hwBufferPtr);
+  if (status != NO_ERROR) {
+    ALOGE(
+        "%s: Failed to allocate hardware buffer for temporary framebuffer: %d",
+        __func__, status);
+    return nullptr;
+  }
+
+  return std::make_shared<EglFrameBuffer>(
+      eglDisplay,
+      std::shared_ptr<AHardwareBuffer>(hwBufferPtr, AHardwareBuffer_release));
+}
+
+bool isYuvFormat(const PixelFormat pixelFormat) {
+  switch (static_cast<android_pixel_format_t>(pixelFormat)) {
+    case HAL_PIXEL_FORMAT_YCBCR_422_I:
+    case HAL_PIXEL_FORMAT_YCBCR_422_SP:
+    case HAL_PIXEL_FORMAT_Y16:
+    case HAL_PIXEL_FORMAT_YV12:
+    case HAL_PIXEL_FORMAT_YCBCR_420_888:
+      return true;
+    default:
+      return false;
+  }
+}
+
 }  // namespace
 
 CaptureRequestBuffer::CaptureRequestBuffer(int streamId, int bufferId,
@@ -218,7 +259,10 @@
   ALOGV("Render thread starting");
 
   mEglDisplayContext = std::make_unique<EglDisplayContext>();
-  mEglTextureProgram = std::make_unique<EglTextureProgram>();
+  mEglTextureYuvProgram =
+      std::make_unique<EglTextureProgram>(EglTextureProgram::TextureFormat::YUV);
+  mEglTextureRgbProgram = std::make_unique<EglTextureProgram>(
+      EglTextureProgram::TextureFormat::RGBA);
   mEglSurfaceTexture = std::make_unique<EglSurfaceTexture>(mInputSurfaceWidth,
                                                            mInputSurfaceHeight);
   mInputSurfacePromise.set_value(mEglSurfaceTexture->getSurface());
@@ -371,6 +415,22 @@
     return cameraStatus(Status::INTERNAL_ERROR);
   }
 
+  // Let's create YUV framebuffer and render the surface into this.
+  // This will take care about rescaling as well as potential format conversion.
+  std::shared_ptr<EglFrameBuffer> framebuffer = allocateTemporaryFramebuffer(
+      mEglDisplayContext->getEglDisplay(), stream->width, stream->height);
+  if (framebuffer == nullptr) {
+    ALOGE("Failed to allocate temporary framebuffer for JPEG compression");
+    return cameraStatus(Status::INTERNAL_ERROR);
+  }
+
+  // Render into temporary framebuffer.
+  ndk::ScopedAStatus status = renderIntoEglFramebuffer(*framebuffer);
+  if (!status.isOk()) {
+    ALOGE("Failed to render input texture into temporary framebuffer");
+    return status;
+  }
+
   AHardwareBuffer_Planes planes_info;
 
   int32_t rawFence = fence != nullptr ? fence->get() : -1;
@@ -382,10 +442,21 @@
     return cameraStatus(Status::INTERNAL_ERROR);
   }
 
-  sp<GraphicBuffer> gBuffer = mEglSurfaceTexture->getCurrentBuffer();
+  std::shared_ptr<AHardwareBuffer> inHwBuffer = framebuffer->getHardwareBuffer();
+  GraphicBuffer* gBuffer = GraphicBuffer::fromAHardwareBuffer(inHwBuffer.get());
+
   bool compressionSuccess = true;
   if (gBuffer != nullptr) {
     android_ycbcr ycbcr;
+    if (gBuffer->getPixelFormat() != HAL_PIXEL_FORMAT_YCbCr_420_888) {
+      // This should never happen since we're allocating the temporary buffer
+      // with YUV420 layout above.
+      ALOGE("%s: Cannot compress non-YUV buffer (pixelFormat %d)", __func__,
+            gBuffer->getPixelFormat());
+      AHardwareBuffer_unlock(hwBuffer.get(), nullptr);
+      return cameraStatus(Status::INTERNAL_ERROR);
+    }
+
     status_t status =
         gBuffer->lockYCbCr(AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, &ycbcr);
     ALOGV("Locked buffers");
@@ -434,31 +505,7 @@
     return cameraStatus(Status::ILLEGAL_ARGUMENT);
   }
 
-  // Wait for fence to clear.
-  if (fence != nullptr && fence->isValid()) {
-    status_t ret = fence->wait(kAcquireFenceTimeout.count());
-    if (ret != 0) {
-      ALOGE(
-          "Timeout while waiting for the acquire fence for buffer %d"
-          " for streamId %d",
-          bufferId, streamId);
-      return cameraStatus(Status::INTERNAL_ERROR);
-    }
-  }
-
-  mEglDisplayContext->makeCurrent();
-  framebuffer->beforeDraw();
-
-  if (mEglSurfaceTexture->getCurrentBuffer() == nullptr) {
-    // If there's no current buffer, nothing was written to the surface and
-    // texture is not initialized yet. Let's render the framebuffer black
-    // instead of rendering the texture.
-    glClearColor(0.0f, 0.5f, 0.5f, 0.0f);
-    glClear(GL_COLOR_BUFFER_BIT);
-  } else {
-    mEglTextureProgram->draw(mEglSurfaceTexture->updateTexture());
-  }
-  framebuffer->afterDraw();
+  ndk::ScopedAStatus status = renderIntoEglFramebuffer(*framebuffer, fence);
 
   const std::chrono::nanoseconds after =
       std::chrono::duration_cast<std::chrono::nanoseconds>(
@@ -470,6 +517,43 @@
   return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus VirtualCameraRenderThread::renderIntoEglFramebuffer(
+    EglFrameBuffer& framebuffer, sp<Fence> fence) {
+  ALOGV("%s", __func__);
+  // Wait for fence to clear.
+  if (fence != nullptr && fence->isValid()) {
+    status_t ret = fence->wait(kAcquireFenceTimeout.count());
+    if (ret != 0) {
+      ALOGE("Timeout while waiting for the acquire fence for buffer");
+      return cameraStatus(Status::INTERNAL_ERROR);
+    }
+  }
+
+  mEglDisplayContext->makeCurrent();
+  framebuffer.beforeDraw();
+
+  sp<GraphicBuffer> textureBuffer = mEglSurfaceTexture->getCurrentBuffer();
+  if (textureBuffer == nullptr) {
+    // If there's no current buffer, nothing was written to the surface and
+    // texture is not initialized yet. Let's render the framebuffer black
+    // instead of rendering the texture.
+    glClearColor(0.0f, 0.5f, 0.5f, 0.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+  } else {
+    const bool renderSuccess =
+        isYuvFormat(static_cast<PixelFormat>(textureBuffer->getPixelFormat()))
+            ? mEglTextureYuvProgram->draw(mEglSurfaceTexture->updateTexture())
+            : mEglTextureRgbProgram->draw(mEglSurfaceTexture->updateTexture());
+    if (!renderSuccess) {
+      ALOGE("%s: Failed to render texture", __func__);
+      return cameraStatus(Status::INTERNAL_ERROR);
+    }
+  }
+  framebuffer.afterDraw();
+
+  return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace virtualcamera
 }  // namespace companion
 }  // namespace android
diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.h b/services/camera/virtualcamera/VirtualCameraRenderThread.h
index a4374e6..b3aaed8 100644
--- a/services/camera/virtualcamera/VirtualCameraRenderThread.h
+++ b/services/camera/virtualcamera/VirtualCameraRenderThread.h
@@ -24,7 +24,9 @@
 
 #include "VirtualCameraSessionContext.h"
 #include "aidl/android/hardware/camera/device/ICameraDeviceCallback.h"
+#include "android/binder_auto_utils.h"
 #include "util/EglDisplayContext.h"
+#include "util/EglFramebuffer.h"
 #include "util/EglProgram.h"
 #include "util/EglSurfaceTexture.h"
 
@@ -135,6 +137,13 @@
   ndk::ScopedAStatus renderIntoImageStreamBuffer(int streamId, int bufferId,
                                                  sp<Fence> fence = nullptr);
 
+  // Render current image into provided EglFramebuffer.
+  // If fence is specified, this function will block until the fence is cleared
+  // before writing to the buffer.
+  // Always called on the render thread.
+  ndk::ScopedAStatus renderIntoEglFramebuffer(EglFrameBuffer& framebuffer,
+                                              sp<Fence> fence = nullptr);
+
   // Camera callback
   const std::shared_ptr<
       ::aidl::android::hardware::camera::device::ICameraDeviceCallback>
@@ -156,7 +165,8 @@
 
   // EGL helpers - constructed and accessed only from rendering thread.
   std::unique_ptr<EglDisplayContext> mEglDisplayContext;
-  std::unique_ptr<EglTextureProgram> mEglTextureProgram;
+  std::unique_ptr<EglTextureProgram> mEglTextureYuvProgram;
+  std::unique_ptr<EglTextureProgram> mEglTextureRgbProgram;
   std::unique_ptr<EglSurfaceTexture> mEglSurfaceTexture;
 
   std::promise<sp<Surface>> mInputSurfacePromise;
diff --git a/services/camera/virtualcamera/VirtualCameraSession.cc b/services/camera/virtualcamera/VirtualCameraSession.cc
index 9e15871..47780d8 100644
--- a/services/camera/virtualcamera/VirtualCameraSession.cc
+++ b/services/camera/virtualcamera/VirtualCameraSession.cc
@@ -153,7 +153,7 @@
 }  // namespace
 
 VirtualCameraSession::VirtualCameraSession(
-    VirtualCameraDevice& cameraDevice,
+    std::shared_ptr<VirtualCameraDevice> cameraDevice,
     std::shared_ptr<ICameraDeviceCallback> cameraDeviceCallback,
     std::shared_ptr<IVirtualCameraCallback> virtualCameraClientCallback)
     : mCameraDevice(cameraDevice),
@@ -201,6 +201,12 @@
     return cameraStatus(Status::ILLEGAL_ARGUMENT);
   }
 
+  std::shared_ptr<VirtualCameraDevice> virtualCamera = mCameraDevice.lock();
+  if (virtualCamera == nullptr) {
+    ALOGW("%s: configure called on already unregistered camera", __func__);
+    return cameraStatus(Status::CAMERA_DISCONNECTED);
+  }
+
   mSessionContext.removeStreamsNotInStreamConfiguration(
       in_requestedConfiguration);
 
@@ -213,7 +219,7 @@
   int inputWidth;
   int inputHeight;
 
-  if (!mCameraDevice.isStreamCombinationSupported(in_requestedConfiguration)) {
+  if (!virtualCamera->isStreamCombinationSupported(in_requestedConfiguration)) {
     ALOGE("%s: Requested stream configuration is not supported", __func__);
     return cameraStatus(Status::ILLEGAL_ARGUMENT);
   }
diff --git a/services/camera/virtualcamera/VirtualCameraSession.h b/services/camera/virtualcamera/VirtualCameraSession.h
index 50962e5..82a7a34 100644
--- a/services/camera/virtualcamera/VirtualCameraSession.h
+++ b/services/camera/virtualcamera/VirtualCameraSession.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERASESSION_H
 #define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERASESSION_H
 
+#include <atomic>
 #include <memory>
 #include <set>
 
@@ -46,7 +47,7 @@
   // When virtualCameraClientCallback is null, the input surface will be filled
   // with test pattern.
   VirtualCameraSession(
-      VirtualCameraDevice& mCameraDevice,
+      std::shared_ptr<VirtualCameraDevice> mCameraDevice,
       std::shared_ptr<
           ::aidl::android::hardware::camera::device::ICameraDeviceCallback>
           cameraDeviceCallback,
@@ -116,7 +117,7 @@
       const ::aidl::android::hardware::camera::device::CaptureRequest& request)
       EXCLUDES(mLock);
 
-  VirtualCameraDevice& mCameraDevice;
+  std::weak_ptr<VirtualCameraDevice> mCameraDevice;
 
   mutable std::mutex mLock;
 
diff --git a/services/camera/virtualcamera/aidl/android/companion/virtualcamera/Format.aidl b/services/camera/virtualcamera/aidl/android/companion/virtualcamera/Format.aidl
index d9b90a6..b155147 100644
--- a/services/camera/virtualcamera/aidl/android/companion/virtualcamera/Format.aidl
+++ b/services/camera/virtualcamera/aidl/android/companion/virtualcamera/Format.aidl
@@ -24,5 +24,6 @@
 @Backing(type="int")
 enum Format {
     UNKNOWN = 0,
+    RGBA_8888 = 1,
     YUV_420_888 = 0x23,
 }
diff --git a/services/camera/virtualcamera/tests/EglUtilTest.cc b/services/camera/virtualcamera/tests/EglUtilTest.cc
index d0b7218..589e312 100644
--- a/services/camera/virtualcamera/tests/EglUtilTest.cc
+++ b/services/camera/virtualcamera/tests/EglUtilTest.cc
@@ -61,12 +61,24 @@
   EXPECT_TRUE(eglTestPatternProgram.isInitialized());
 }
 
-TEST_F(EglTest, EglTextureProgramSuccessfulInit) {
+TEST_F(EglTest, EglTextureProgramYuvSuccessfulInit) {
   if (!isGlExtensionSupported(kGlExtYuvTarget)) {
       GTEST_SKIP() << "Skipping test because of missing required GL extension " << kGlExtYuvTarget;
   }
 
-  EglTextureProgram eglTextureProgram;
+  EglTextureProgram eglTextureProgram(EglTextureProgram::TextureFormat::YUV);
+
+  // Verify the shaders compiled and linked successfully.
+  EXPECT_TRUE(eglTextureProgram.isInitialized());
+}
+
+TEST_F(EglTest, EglTextureProgramRgbaSuccessfulInit) {
+  if (!isGlExtensionSupported(kGlExtYuvTarget)) {
+      GTEST_SKIP() << "Skipping test because of missing required GL extension "
+                   << kGlExtYuvTarget;
+  }
+
+  EglTextureProgram eglTextureProgram(EglTextureProgram::TextureFormat::RGBA);
 
   // Verify the shaders compiled and linked successfully.
   EXPECT_TRUE(eglTextureProgram.isInitialized());
diff --git a/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc b/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc
index f4d5042..38261fb 100644
--- a/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc
+++ b/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc
@@ -153,7 +153,7 @@
       createConfiguration(kVgaWidth, kVgaHeight, Format::YUV_420_888);
 };
 
-TEST_F(VirtualCameraServiceTest, RegisterCameraSucceeds) {
+TEST_F(VirtualCameraServiceTest, RegisterCameraWithYuvInputSucceeds) {
   sp<BBinder> token = sp<BBinder>::make();
   ndk::SpAIBinder ndkToken(AIBinder_fromPlatformBinder(token));
   bool aidlRet;
@@ -167,6 +167,20 @@
   EXPECT_THAT(getCameraIds(), SizeIs(1));
 }
 
+TEST_F(VirtualCameraServiceTest, RegisterCameraWithRgbaInputSucceeds) {
+  sp<BBinder> token = sp<BBinder>::make();
+  ndk::SpAIBinder ndkToken(AIBinder_fromPlatformBinder(token));
+  bool aidlRet;
+
+  VirtualCameraConfiguration config =
+      createConfiguration(kVgaWidth, kVgaHeight, Format::RGBA_8888);
+
+  ASSERT_TRUE(mCameraService->registerCamera(ndkToken, config, &aidlRet).isOk());
+
+  EXPECT_TRUE(aidlRet);
+  EXPECT_THAT(getCameraIds(), SizeIs(1));
+}
+
 TEST_F(VirtualCameraServiceTest, RegisterCameraTwiceSecondReturnsFalse) {
   createCamera();
   bool aidlRet;
diff --git a/services/camera/virtualcamera/tests/VirtualCameraSessionTest.cc b/services/camera/virtualcamera/tests/VirtualCameraSessionTest.cc
index 9edfe77..30bd2b6 100644
--- a/services/camera/virtualcamera/tests/VirtualCameraSessionTest.cc
+++ b/services/camera/virtualcamera/tests/VirtualCameraSessionTest.cc
@@ -20,8 +20,8 @@
 #include "VirtualCameraDevice.h"
 #include "VirtualCameraSession.h"
 #include "aidl/android/companion/virtualcamera/BnVirtualCameraCallback.h"
-#include "aidl/android/companion/virtualcamera/IVirtualCameraCallback.h"
 #include "aidl/android/companion/virtualcamera/SupportedStreamConfiguration.h"
+#include "aidl/android/hardware/camera/common/Status.h"
 #include "aidl/android/hardware/camera/device/BnCameraDeviceCallback.h"
 #include "aidl/android/hardware/camera/device/StreamConfiguration.h"
 #include "aidl/android/hardware/graphics/common/PixelFormat.h"
@@ -44,6 +44,7 @@
 using ::aidl::android::companion::virtualcamera::BnVirtualCameraCallback;
 using ::aidl::android::companion::virtualcamera::Format;
 using ::aidl::android::companion::virtualcamera::SupportedStreamConfiguration;
+using ::aidl::android::hardware::camera::common::Status;
 using ::aidl::android::hardware::camera::device::BnCameraDeviceCallback;
 using ::aidl::android::hardware::camera::device::BufferRequest;
 using ::aidl::android::hardware::camera::device::BufferRequestStatus;
@@ -110,7 +111,7 @@
                                          .pixelFormat = Format::YUV_420_888}},
         mMockVirtualCameraClientCallback);
     mVirtualCameraSession = ndk::SharedRefBase::make<VirtualCameraSession>(
-        *mVirtualCameraDevice, mMockCameraDeviceCallback,
+        mVirtualCameraDevice, mMockCameraDeviceCallback,
         mMockVirtualCameraClientCallback);
 
     // Explicitly defining default actions below to prevent gmock from
@@ -223,6 +224,22 @@
   EXPECT_THAT(aidlReturn, Eq(requests.size()));
 }
 
+TEST_F(VirtualCameraSessionTest, configureAfterCameraRelease) {
+  StreamConfiguration streamConfiguration;
+  streamConfiguration.streams = {
+      createStream(kStreamId, kWidth, kHeight, PixelFormat::YCBCR_420_888)};
+  std::vector<HalStream> halStreams;
+
+  // Release virtual camera.
+  mVirtualCameraDevice.reset();
+
+  // Expect configuration attempt returns CAMERA_DISCONNECTED service specific code.
+  EXPECT_THAT(
+      mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams)
+          .getServiceSpecificError(),
+      Eq(static_cast<int32_t>(Status::CAMERA_DISCONNECTED)));
+}
+
 }  // namespace
 }  // namespace virtualcamera
 }  // namespace companion
diff --git a/services/camera/virtualcamera/util/EglFramebuffer.cc b/services/camera/virtualcamera/util/EglFramebuffer.cc
index acf0122..57b94d3 100644
--- a/services/camera/virtualcamera/util/EglFramebuffer.cc
+++ b/services/camera/virtualcamera/util/EglFramebuffer.cc
@@ -112,6 +112,10 @@
   return mHeight;
 }
 
+std::shared_ptr<AHardwareBuffer> EglFrameBuffer::getHardwareBuffer() {
+  return mHardwareBuffer;
+}
+
 }  // namespace virtualcamera
 }  // namespace companion
 }  // namespace android
diff --git a/services/camera/virtualcamera/util/EglFramebuffer.h b/services/camera/virtualcamera/util/EglFramebuffer.h
index 35f85e2..b39df6d 100644
--- a/services/camera/virtualcamera/util/EglFramebuffer.h
+++ b/services/camera/virtualcamera/util/EglFramebuffer.h
@@ -50,6 +50,9 @@
   // Return height of framebuffer (in pixels).
   int getHeight() const;
 
+  // Return underlying hardware buffer.
+  std::shared_ptr<AHardwareBuffer> getHardwareBuffer();
+
  private:
   // Keeping shared_ptr to hardware buffer instance here prevents it from being
   // freed while tied to EGL framebufer / EGL texture.
diff --git a/services/camera/virtualcamera/util/EglProgram.cc b/services/camera/virtualcamera/util/EglProgram.cc
index c468d39..510fd33 100644
--- a/services/camera/virtualcamera/util/EglProgram.cc
+++ b/services/camera/virtualcamera/util/EglProgram.cc
@@ -76,17 +76,29 @@
     vTextureCoord = aTextureCoord;
   })";
 
-constexpr char kExternalTextureFragmentShader[] = R"(#version 300 es
+constexpr char kExternalYuvTextureFragmentShader[] = R"(#version 300 es
     #extension GL_OES_EGL_image_external_essl3 : require
     #extension GL_EXT_YUV_target : require
     precision mediump float;
     in vec2 vTextureCoord;
-    out vec4 fragColor;
+    layout (yuv) out vec4 fragColor;
     uniform __samplerExternal2DY2YEXT uTexture;
     void main() {
       fragColor = texture(uTexture, vTextureCoord);
     })";
 
+constexpr char kExternalRgbaTextureFragmentShader[] = R"(#version 300 es
+    #extension GL_OES_EGL_image_external : require
+    #extension GL_EXT_YUV_target : require
+    precision mediump float;
+    in vec2 vTextureCoord;
+    layout (yuv) out vec4 fragColor;
+    uniform samplerExternalOES uTexture;
+    void main() {
+      vec4 rgbaColor = texture(uTexture, vTextureCoord);
+      fragColor = vec4(rgb_2_yuv(rgbaColor.xyz, itu_601_full_range), 0.0);
+    })";
+
 constexpr int kCoordsPerVertex = 3;
 constexpr std::array<float, 12> kSquareCoords{-1.f, 1.0f, 0.0f,  // top left
                                               -1.f, -1.f, 0.0f,  // bottom left
@@ -237,7 +249,7 @@
   return true;
 }
 
-EglTextureProgram::EglTextureProgram() {
+EglTextureProgram::EglTextureProgram(const TextureFormat textureFormat) {
   if (!isGlExtensionSupported(kGlExtYuvTarget)) {
     ALOGE(
         "Cannot initialize external texture program due to missing "
@@ -245,7 +257,10 @@
     return;
   }
 
-  if (initialize(kExternalTextureVertexShader, kExternalTextureFragmentShader)) {
+  const char* fragmentShaderSrc = textureFormat == TextureFormat::YUV
+                                      ? kExternalYuvTextureFragmentShader
+                                      : kExternalRgbaTextureFragmentShader;
+  if (initialize(kExternalTextureVertexShader, fragmentShaderSrc)) {
     ALOGV("Successfully initialized EGL shaders for external texture program.");
   } else {
     ALOGE("External texture EGL shader program initialization failed.");
diff --git a/services/camera/virtualcamera/util/EglProgram.h b/services/camera/virtualcamera/util/EglProgram.h
index 8e394e7..1b5f2cd 100644
--- a/services/camera/virtualcamera/util/EglProgram.h
+++ b/services/camera/virtualcamera/util/EglProgram.h
@@ -55,7 +55,9 @@
 // TODO(b/301023410) Add support for translation / cropping.
 class EglTextureProgram : public EglProgram {
  public:
-  EglTextureProgram();
+  enum class TextureFormat { RGBA, YUV };
+
+  EglTextureProgram(TextureFormat textureFormat = TextureFormat::YUV);
 
   bool draw(GLuint textureId);
 };
diff --git a/services/camera/virtualcamera/util/Util.cc b/services/camera/virtualcamera/util/Util.cc
index 11dc3a6..df771b1 100644
--- a/services/camera/virtualcamera/util/Util.cc
+++ b/services/camera/virtualcamera/util/Util.cc
@@ -18,20 +18,26 @@
 
 #include <unistd.h>
 
+#include <algorithm>
+#include <array>
+
 #include "jpeglib.h"
 
 namespace android {
 namespace companion {
 namespace virtualcamera {
 
+using ::aidl::android::companion::virtualcamera::Format;
+using ::aidl::android::hardware::common::NativeHandle;
+
 // Lower bound for maximal supported texture size is at least 2048x2048
 // but on most platforms will be more.
 // TODO(b/301023410) - Query actual max texture size.
 constexpr int kMaxTextureSize = 2048;
 constexpr int kLibJpegDctSize = DCTSIZE;
 
-using ::aidl::android::companion::virtualcamera::Format;
-using ::aidl::android::hardware::common::NativeHandle;
+constexpr std::array<Format, 2> kSupportedFormats{Format::YUV_420_888,
+                                                  Format::RGBA_8888};
 
 sp<Fence> importFence(const NativeHandle& aidlHandle) {
   if (aidlHandle.fds.size() != 1) {
@@ -41,11 +47,15 @@
   return sp<Fence>::make(::dup(aidlHandle.fds[0].get()));
 }
 
+bool isPixelFormatSupportedForInput(const Format format) {
+  return std::find(kSupportedFormats.begin(), kSupportedFormats.end(),
+                   format) != kSupportedFormats.end();
+}
+
 // Returns true if specified format is supported for virtual camera input.
 bool isFormatSupportedForInput(const int width, const int height,
                                const Format format) {
-  if (format != Format::YUV_420_888) {
-    // For now only YUV_420_888 is supported for input.
+  if (!isPixelFormatSupportedForInput(format)) {
     return false;
   }
 
diff --git a/services/camera/virtualcamera/util/Util.h b/services/camera/virtualcamera/util/Util.h
index b778321..a73c99b 100644
--- a/services/camera/virtualcamera/util/Util.h
+++ b/services/camera/virtualcamera/util/Util.h
@@ -43,6 +43,10 @@
 sp<Fence> importFence(
     const ::aidl::android::hardware::common::NativeHandle& handle);
 
+// Returns true if specified pixel format is supported for virtual camera input.
+bool isPixelFormatSupportedForInput(
+    ::aidl::android::companion::virtualcamera::Format format);
+
 // Returns true if specified format is supported for virtual camera input.
 bool isFormatSupportedForInput(
     int width, int height,
diff --git a/services/mediametrics/AudioPowerUsage.cpp b/services/mediametrics/AudioPowerUsage.cpp
index 630a436..7dc445b 100644
--- a/services/mediametrics/AudioPowerUsage.cpp
+++ b/services/mediametrics/AudioPowerUsage.cpp
@@ -549,7 +549,7 @@
 
     int slot = 1;
     std::stringstream ss;
-    ss << "AudioPowerUsage:\n";
+    ss << "AudioPowerUsage interval " << mIntervalHours << " hours:\n";
     for (const auto &item : mItems) {
         if (slot >= limit - 1) {
             ss << "-- AudioPowerUsage may be truncated!\n";
diff --git a/services/mediametrics/include/mediametricsservice/TimedAction.h b/services/mediametrics/include/mediametricsservice/TimedAction.h
index c7ef585..e5d7df0 100644
--- a/services/mediametrics/include/mediametricsservice/TimedAction.h
+++ b/services/mediametrics/include/mediametricsservice/TimedAction.h
@@ -25,6 +25,12 @@
 namespace android::mediametrics {
 
 class TimedAction {
+    // Use system_clock instead of steady_clock to include suspend time.
+    using TimerClock = class std::chrono::system_clock;
+
+    // Define granularity of wakeup to prevent delayed events if
+    // device is suspended.
+    static constexpr auto kWakeupInterval = std::chrono::minutes(15);
 public:
     TimedAction() : mThread{[this](){threadLoop();}} {}
 
@@ -35,7 +41,7 @@
     // TODO: return a handle for cancelling the action?
     template <typename T> // T is in units of std::chrono::duration.
     void postIn(const T& time, std::function<void()> f) {
-        postAt(std::chrono::steady_clock::now() + time, f);
+        postAt(TimerClock::now() + time, f);
     }
 
     template <typename T> // T is in units of std::chrono::time_point
@@ -75,16 +81,21 @@
     void threadLoop() NO_THREAD_SAFETY_ANALYSIS { // thread safety doesn't cover unique_lock
         std::unique_lock l(mLock);
         while (!mQuit) {
-            auto sleepUntilTime = std::chrono::time_point<std::chrono::steady_clock>::max();
+            auto sleepUntilTime = std::chrono::time_point<TimerClock>::max();
             if (!mMap.empty()) {
                 sleepUntilTime = mMap.begin()->first;
-                if (sleepUntilTime <= std::chrono::steady_clock::now()) {
+                const auto now = TimerClock::now();
+                if (sleepUntilTime <= now) {
                     auto node = mMap.extract(mMap.begin()); // removes from mMap.
                     l.unlock();
                     node.mapped()();
                     l.lock();
                     continue;
                 }
+                // Bionic uses CLOCK_MONOTONIC for its pthread_mutex regardless
+                // of REALTIME specification, use kWakeupInterval to ensure minimum
+                // granularity if suspended.
+                sleepUntilTime = std::min(sleepUntilTime, now + kWakeupInterval);
             }
             mCondition.wait_until(l, sleepUntilTime);
         }
@@ -93,7 +104,7 @@
     mutable std::mutex mLock;
     std::condition_variable mCondition GUARDED_BY(mLock);
     bool mQuit GUARDED_BY(mLock) = false;
-    std::multimap<std::chrono::time_point<std::chrono::steady_clock>, std::function<void()>>
+    std::multimap<std::chrono::time_point<TimerClock>, std::function<void()>>
             mMap GUARDED_BY(mLock); // multiple functions could execute at the same time.
 
     // needs to be initialized after the variables above, done in constructor initializer list.
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 4438b0a..6b48075 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -422,10 +422,17 @@
     ALOGD("%s() called with dev %d, old = %d", __func__, deviceId, getDeviceId());
     if (getDeviceId() != deviceId) {
         if (getDeviceId() != AUDIO_PORT_HANDLE_NONE) {
+            // When there is a routing changed, mmap stream should be disconnected. Set `mConnected`
+            // as false here so that there won't be a new stream connect to this endpoint.
+            mConnected.store(false);
             const android::sp<AAudioServiceEndpointMMAP> holdEndpoint(this);
             std::thread asyncTask([holdEndpoint, deviceId]() {
                 ALOGD("onRoutingChanged() asyncTask launched");
-                holdEndpoint->disconnectRegisteredStreams();
+                // When routing changed, the stream is disconnected and cannot be used except for
+                // closing. In that case, it should be safe to release all registered streams.
+                // This can help release service side resource in case the client doesn't close
+                // the stream after receiving disconnect event.
+                holdEndpoint->releaseRegisteredStreams();
                 holdEndpoint->setDeviceId(deviceId);
             });
             asyncTask.detach();
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index 1dd0c3a..5e1e594 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -219,9 +219,13 @@
 
 void AAudioServiceEndpointShared::handleDisconnectRegisteredStreamsAsync() {
     android::sp<AAudioServiceEndpointShared> holdEndpoint(this);
+    // When there is a routing changed, mmap stream should be disconnected. Set `mConnected`
+    // as false here so that there won't be a new stream connect to this endpoint.
+    mConnected.store(false);
     std::thread asyncTask([holdEndpoint]() {
-        // We do not need the returned vector.
-        holdEndpoint->disconnectRegisteredStreams();
+        // When handling disconnection, the service side has disconnected. In that case,
+        // it should be safe to release all registered streams.
+        holdEndpoint->releaseRegisteredStreams();
     });
     asyncTask.detach();
 }