Merge changes from topic "cherrypicker-L89600000960032981:N30900001359241375" into udc-dev

* changes:
  Skip setting the state for paused binder thread invocations in waitUntilStateThenRelock
  Revert "Add mInterfaceLock back to Camera3Device methods called by RequestThread."
diff --git a/media/audioaidlconversion/AidlConversionNdkCpp.cpp b/media/audioaidlconversion/AidlConversionNdkCpp.cpp
new file mode 100644
index 0000000..36f6128
--- /dev/null
+++ b/media/audioaidlconversion/AidlConversionNdkCpp.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.
+ */
+
+#include <algorithm>
+#include <type_traits>
+
+#define LOG_TAG "AidlConversionNdkCpp"
+#include <utils/Log.h>
+
+#include <android-base/expected.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_enums.h>
+#include <android/binder_parcel.h>
+#include <binder/Enums.h>
+#include <media/AidlConversionNdkCpp.h>
+#include <media/AidlConversionUtil.h>
+
+using aidl::android::aidl_utils::statusTFromBinderStatusT;
+
+namespace android {
+
+namespace {
+
+// cpp2ndk and ndk2cpp are universal converters which work for any type,
+// however they are not the most efficient way to convert due to extra
+// marshaling / unmarshaling step.
+
+template<typename NdkType, typename CppType>
+ConversionResult<NdkType> cpp2ndk(const CppType& cpp) {
+    Parcel cppParcel;
+    RETURN_IF_ERROR(cpp.writeToParcel(&cppParcel));
+    ::ndk::ScopedAParcel ndkParcel(AParcel_create());
+    const int32_t ndkParcelBegin = AParcel_getDataPosition(ndkParcel.get());
+    RETURN_IF_ERROR(statusTFromBinderStatusT(AParcel_unmarshal(
+                            ndkParcel.get(), cppParcel.data(), cppParcel.dataSize())));
+    RETURN_IF_ERROR(statusTFromBinderStatusT(AParcel_setDataPosition(
+                            ndkParcel.get(), ndkParcelBegin)));
+    NdkType ndk;
+    RETURN_IF_ERROR(statusTFromBinderStatusT(ndk.readFromParcel(ndkParcel.get())));
+    return ndk;
+}
+
+template<typename CppType, typename NdkType>
+ConversionResult<CppType> ndk2cpp(const NdkType& ndk) {
+    ::ndk::ScopedAParcel ndkParcel(AParcel_create());
+    RETURN_IF_ERROR(statusTFromBinderStatusT(ndk.writeToParcel(ndkParcel.get())));
+    const int32_t ndkParcelDataSize = AParcel_getDataSize(ndkParcel.get());
+    if (ndkParcelDataSize < 0) {
+        return base::unexpected(BAD_VALUE);
+    }
+    // Parcel does not expose its data in a mutable form, we have to use an intermediate buffer.
+    std::vector<uint8_t> parcelData(static_cast<size_t>(ndkParcelDataSize));
+    RETURN_IF_ERROR(statusTFromBinderStatusT(AParcel_marshal(
+                            ndkParcel.get(), parcelData.data(), 0, ndkParcelDataSize)));
+    Parcel cppParcel;
+    RETURN_IF_ERROR(cppParcel.setData(parcelData.data(), parcelData.size()));
+    CppType cpp;
+    RETURN_IF_ERROR(cpp.readFromParcel(&cppParcel));
+    return cpp;
+}
+
+// cpp2ndk_Enum and ndk2cpp_Enum are more efficient implementations specifically for enums.
+
+template<typename OutEnum, typename OutEnumRange, typename InEnum>
+        ConversionResult<OutEnum> convertEnum(const OutEnumRange& range, InEnum e) {
+    using InIntType = std::underlying_type_t<InEnum>;
+    static_assert(std::is_same_v<InIntType, std::underlying_type_t<OutEnum>>);
+
+    InIntType inEnumIndex = static_cast<InIntType>(e);
+    OutEnum outEnum = static_cast<OutEnum>(inEnumIndex);
+    if (std::find(range.begin(), range.end(), outEnum) == range.end()) {
+        return base::unexpected(BAD_VALUE);
+    }
+    return outEnum;
+}
+
+template<typename NdkEnum, typename CppEnum>
+        ConversionResult<NdkEnum> cpp2ndk_Enum(CppEnum cpp) {
+    return convertEnum<NdkEnum>(::ndk::enum_range<NdkEnum>(), cpp);
+}
+
+template<typename CppEnum, typename NdkEnum>
+        ConversionResult<CppEnum> ndk2cpp_Enum(NdkEnum ndk) {
+    return convertEnum<CppEnum>(enum_range<CppEnum>(), ndk);
+}
+
+}  // namespace
+
+#define GENERATE_CONVERTERS(packageName, className)                     \
+    ConversionResult<::aidl::packageName::className> cpp2ndk_##className( \
+            const ::packageName::className& cpp) {                      \
+        return cpp2ndk<::aidl::packageName::className>(cpp);            \
+    }                                                                   \
+    ConversionResult<::packageName::className> ndk2cpp_##className(     \
+            const ::aidl::packageName::className& ndk) {                \
+        return ndk2cpp<::packageName::className>(ndk);                  \
+    }
+
+#define GENERATE_ENUM_CONVERTERS(packageName, className)                \
+    ConversionResult<::aidl::packageName::className> cpp2ndk_##className( \
+            const ::packageName::className& cpp) {                      \
+        return cpp2ndk_Enum<::aidl::packageName::className>(cpp);       \
+    }                                                                   \
+    ConversionResult<::packageName::className> ndk2cpp_##className(     \
+            const ::aidl::packageName::className& ndk) {                \
+        return ndk2cpp_Enum<::packageName::className>(ndk);             \
+}
+
+GENERATE_CONVERTERS(android::media::audio::common, AudioFormatDescription);
+GENERATE_CONVERTERS(android::media::audio::common, AudioHalEngineConfig);
+GENERATE_CONVERTERS(android::media::audio::common, AudioMMapPolicyInfo);
+GENERATE_ENUM_CONVERTERS(android::media::audio::common, AudioMMapPolicyType);
+GENERATE_CONVERTERS(android::media::audio::common, AudioPort);
+
+}  // namespace android
diff --git a/media/audioaidlconversion/Android.bp b/media/audioaidlconversion/Android.bp
index 1ec4849..d3a5755 100644
--- a/media/audioaidlconversion/Android.bp
+++ b/media/audioaidlconversion/Android.bp
@@ -212,3 +212,27 @@
     ],
     min_sdk_version: "31", //AParcelableHolder has been introduced in 31
 }
+
+/**
+ * Conversions between the NDK and CPP backends for common types.
+ */
+cc_library {
+    name: "libaudio_aidl_conversion_common_ndk_cpp",
+    srcs: [
+        "AidlConversionNdkCpp.cpp",
+    ],
+    defaults: [
+        "audio_aidl_conversion_common_default",
+        "audio_aidl_conversion_common_util_default",
+        "latest_android_media_audio_common_types_cpp_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libbase",
+    ],
+    cflags: [
+        "-DBACKEND_CPP_NDK",
+    ],
+    min_sdk_version: "33", //AParcel_unmarshal has been introduced in 33
+}
diff --git a/media/audioaidlconversion/TEST_MAPPING b/media/audioaidlconversion/TEST_MAPPING
index a0c9759..903b88a 100644
--- a/media/audioaidlconversion/TEST_MAPPING
+++ b/media/audioaidlconversion/TEST_MAPPING
@@ -1,7 +1,8 @@
 {
   "presubmit": [
     {
-      "name": "audio_aidl_ndk_conversion_tests"
+      "name": "audio_aidl_ndk_conversion_tests",
+      "name": "audio_aidl_ndk_cpp_conversion_tests"
     }
   ]
 }
diff --git a/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h b/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h
new file mode 100644
index 0000000..09f1c22
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+/**
+ * Conversions between the NDK and CPP backends for common types.
+ */
+#include <aidl/android/media/audio/common/AudioFormatDescription.h>
+#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
+#include <aidl/android/media/audio/common/AudioMMapPolicyInfo.h>
+#include <aidl/android/media/audio/common/AudioMMapPolicyType.h>
+#include <aidl/android/media/audio/common/AudioPort.h>
+#include <android/media/audio/common/AudioFormatDescription.h>
+#include <android/media/audio/common/AudioHalEngineConfig.h>
+#include <android/media/audio/common/AudioMMapPolicyInfo.h>
+#include <android/media/audio/common/AudioMMapPolicyType.h>
+#include <android/media/audio/common/AudioPort.h>
+#include <media/AidlConversionUtil.h>
+
+namespace android {
+
+#define DECLARE_CONVERTERS(packageName, className)                       \
+    ConversionResult<::aidl::packageName::className>                    \
+    cpp2ndk_##className(const ::packageName::className& cpp);           \
+    ConversionResult<::packageName::className>                          \
+    ndk2cpp_##className(const ::aidl::packageName::className& ndk);
+
+DECLARE_CONVERTERS(android::media::audio::common, AudioFormatDescription);
+DECLARE_CONVERTERS(android::media::audio::common, AudioHalEngineConfig);
+DECLARE_CONVERTERS(android::media::audio::common, AudioMMapPolicyInfo);
+DECLARE_CONVERTERS(android::media::audio::common, AudioMMapPolicyType);
+DECLARE_CONVERTERS(android::media::audio::common, AudioPort);
+
+#undef DECLARE_CONVERTERS
+
+}  // namespace android
diff --git a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
index b179cbb..f49f681 100644
--- a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
@@ -389,6 +389,10 @@
         ?: statusTFromExceptionCode(status.getExceptionCode()); // a service-side error with a
                                                      // standard Java exception (fromExceptionCode)
 }
+
+static inline ::android::status_t statusTFromBinderStatusT(binder_status_t status) {
+    return statusTFromBinderStatus(::ndk::ScopedAStatus::fromStatus(status));
+}
 #endif
 
 /**
diff --git a/media/audioaidlconversion/tests/Android.bp b/media/audioaidlconversion/tests/Android.bp
index de7c8a2..88b2cc9 100644
--- a/media/audioaidlconversion/tests/Android.bp
+++ b/media/audioaidlconversion/tests/Android.bp
@@ -44,3 +44,27 @@
         "-DBACKEND_NDK",
     ],
 }
+
+cc_test {
+    name: "audio_aidl_ndk_cpp_conversion_tests",
+
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_static",
+        "latest_android_media_audio_common_types_ndk_static",
+        "libaudio_aidl_conversion_tests_defaults",
+    ],
+    srcs: ["audio_aidl_ndk_cpp_conversion_tests.cpp"],
+    shared_libs: [
+        "libbinder",
+        "libbinder_ndk",
+        "libcutils",
+        "liblog",
+        "libutils",
+    ],
+    static_libs: [
+        "libaudio_aidl_conversion_common_ndk_cpp",
+    ],
+    cflags: [
+        "-DBACKEND_CPP_NDK",
+    ],
+}
diff --git a/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp b/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp
new file mode 100644
index 0000000..735a14b
--- /dev/null
+++ b/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#include <iostream>
+#include <type_traits>
+
+#include <gtest/gtest.h>
+
+#include <media/AidlConversionNdkCpp.h>
+
+namespace {
+template<typename> struct mf_traits {};
+template<class T, class U> struct mf_traits<U T::*> {
+    using member_type = U;
+};
+}  // namespace
+
+// Provide value printers for types generated from AIDL
+// They need to be in the same namespace as the types we intend to print
+#define DEFINE_PRINTING_TEMPLATES()
+    template <typename P>                                                                         \
+    std::enable_if_t<std::is_function_v<typename mf_traits<decltype(&P::toString)>::member_type>, \
+            std::ostream&> operator<<(std::ostream& os, const P& p) {                             \
+        return os << p.toString();                                                                \
+    }                                                                                             \
+    template <typename E>                                                                         \
+    std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) { \
+        return os << toString(e);                                                                 \
+    }
+
+namespace aidl::android::media::audio::common {
+DEFINE_PRINTING_TEMPLATES();
+}  // namespace aidl::android::media::audio::common
+namespace android::hardware::audio::common {
+DEFINE_PRINTING_TEMPLATES();
+}  // namespace android::hardware::audio::common
+#undef DEFINE_PRINTING_TEMPLATES
+
+using namespace android;
+
+namespace {
+
+using namespace ::aidl::android::media::audio::common;
+
+AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
+    AudioFormatDescription result;
+    result.type = type;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
+    auto result = make_AudioFormatDescription(AudioFormatType::PCM);
+    result.pcm = pcm;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(const std::string& encoding) {
+    AudioFormatDescription result;
+    result.encoding = encoding;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType transport, const std::string& encoding) {
+    auto result = make_AudioFormatDescription(encoding);
+    result.pcm = transport;
+    return result;
+}
+
+AudioFormatDescription make_AFD_Default() {
+    return AudioFormatDescription{};
+}
+
+AudioFormatDescription make_AFD_Invalid() {
+    return make_AudioFormatDescription(AudioFormatType::SYS_RESERVED_INVALID);
+}
+
+AudioFormatDescription make_AFD_Pcm16Bit() {
+    return make_AudioFormatDescription(PcmType::INT_16_BIT);
+}
+
+AudioFormatDescription make_AFD_Bitstream() {
+    return make_AudioFormatDescription("example");
+}
+
+AudioFormatDescription make_AFD_Encap() {
+    return make_AudioFormatDescription(PcmType::INT_16_BIT, "example.encap");
+}
+
+AudioFormatDescription make_AFD_Encap_with_Enc() {
+    auto afd = make_AFD_Encap();
+    afd.encoding += "+example";
+    return afd;
+}
+
+}  // namespace
+
+// There is no reason to write test for every type which gets converted via parcelable
+// since the conversion code is all the same.
+
+class AudioFormatDescriptionRoundTripTest :
+        public testing::TestWithParam<::aidl::android::media::audio::common::AudioFormatDescription>
+{
+};
+TEST_P(AudioFormatDescriptionRoundTripTest, Ndk2Cpp2Ndk) {
+    const auto& initial = GetParam();
+    auto conv = ndk2cpp_AudioFormatDescription(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = cpp2ndk_AudioFormatDescription(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioFormatDescriptionRoundTrip, AudioFormatDescriptionRoundTripTest,
+        testing::Values(make_AFD_Invalid(), make_AFD_Default(), make_AFD_Pcm16Bit(),
+                make_AFD_Bitstream(), make_AFD_Encap(), make_AFD_Encap_with_Enc()));
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index 8aed623..77296a4 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -726,24 +726,6 @@
     }
 }
 
-void C2SoftGav1Dec::setError(const std::unique_ptr<C2Work> &work, c2_status_t error) {
-    mSignalledError = true;
-    work->result = error;
-    work->workletsProcessed = 1u;
-}
-
-bool C2SoftGav1Dec::allocTmpFrameBuffer(size_t size) {
-    if (size > mTmpFrameBufferSize) {
-        mTmpFrameBuffer = std::make_unique<uint16_t[]>(size);
-        if (mTmpFrameBuffer == nullptr) {
-            mTmpFrameBufferSize = 0;
-            return false;
-        }
-        mTmpFrameBufferSize = size;
-    }
-    return true;
-}
-
 bool C2SoftGav1Dec::outputBuffer(const std::shared_ptr<C2BlockPool> &pool,
                                  const std::unique_ptr<C2Work> &work) {
   if (!(work && pool)) return false;
@@ -790,6 +772,16 @@
   getHDRStaticParams(buffer, work);
   getHDR10PlusInfoData(buffer, work);
 
+  if (buffer->bitdepth == 10 &&
+      !(buffer->image_format == libgav1::kImageFormatYuv420 ||
+        buffer->image_format == libgav1::kImageFormatMonochrome400)) {
+    ALOGE("image_format %d not supported for 10bit", buffer->image_format);
+    mSignalledError = true;
+    work->workletsProcessed = 1u;
+    work->result = C2_CORRUPTED;
+    return false;
+  }
+
   const bool isMonochrome =
       buffer->image_format == libgav1::kImageFormatMonochrome400;
 
@@ -862,6 +854,9 @@
   uint8_t *dstY = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_Y]);
   uint8_t *dstU = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_U]);
   uint8_t *dstV = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_V]);
+  size_t srcYStride = buffer->stride[0];
+  size_t srcUStride = buffer->stride[1];
+  size_t srcVStride = buffer->stride[2];
 
   C2PlanarLayout layout = wView.layout();
   size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
@@ -872,88 +867,26 @@
     const uint16_t *srcY = (const uint16_t *)buffer->plane[0];
     const uint16_t *srcU = (const uint16_t *)buffer->plane[1];
     const uint16_t *srcV = (const uint16_t *)buffer->plane[2];
-    size_t srcYStride = buffer->stride[0] / 2;
-    size_t srcUStride = buffer->stride[1] / 2;
-    size_t srcVStride = buffer->stride[2] / 2;
 
     if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
         convertYUV420Planar16ToY410OrRGBA1010102(
-                (uint32_t *)dstY, srcY, srcU, srcV, srcYStride,
-                srcUStride, srcVStride,
+                (uint32_t *)dstY, srcY, srcU, srcV, srcYStride / 2,
+                srcUStride / 2, srcVStride / 2,
                 dstYStride / sizeof(uint32_t), mWidth, mHeight,
                 std::static_pointer_cast<const C2ColorAspectsStruct>(codedColorAspects));
     } else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
-        dstYStride /= 2;
-        dstUStride /= 2;
-        dstVStride /= 2;
-        if (buffer->image_format == libgav1::kImageFormatYuv444 ||
-            buffer->image_format == libgav1::kImageFormatYuv422) {
-            // TODO(https://crbug.com/libyuv/952): replace this block with libyuv::I410ToP010 and
-            // libyuv::I210ToP010 when they are available.
-            // Note it may be safe to alias dstY in I010ToP010, but the libyuv API doesn't make any
-            // guarantees.
-            const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
-            if (!allocTmpFrameBuffer(tmpSize)) {
-                ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
-                setError(work, C2_NO_MEMORY);
-                return false;
-            }
-            uint16_t *const tmpY = mTmpFrameBuffer.get();
-            uint16_t *const tmpU = tmpY + dstYStride * mHeight;
-            uint16_t *const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
-            if (buffer->image_format == libgav1::kImageFormatYuv444) {
-                libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
-                                   tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride,
-                                   mWidth, mHeight);
-            } else {
-                libyuv::I210ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
-                                   tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride,
-                                   mWidth, mHeight);
-            }
-            libyuv::I010ToP010(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstVStride,
-                               (uint16_t*)dstY, dstYStride, (uint16_t*)dstU, dstUStride,
-                               mWidth, mHeight);
-        } else {
-            convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
-                                        srcYStride, srcUStride, srcVStride, dstYStride,
-                                        dstUStride, mWidth, mHeight, isMonochrome);
-        }
+        convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
+                                    srcYStride / 2, srcUStride / 2, srcVStride / 2, dstYStride / 2,
+                                    dstUStride / 2, mWidth, mHeight, isMonochrome);
     } else {
-        if (buffer->image_format == libgav1::kImageFormatYuv444) {
-            // TODO(https://crbug.com/libyuv/950): replace this block with libyuv::I410ToI420 when
-            // it's available.
-            const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
-            if (!allocTmpFrameBuffer(tmpSize)) {
-                ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
-                setError(work, C2_NO_MEMORY);
-                return false;
-            }
-            uint16_t *const tmpY = mTmpFrameBuffer.get();
-            uint16_t *const tmpU = tmpY + dstYStride * mHeight;
-            uint16_t *const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
-            libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
-                               tmpY, dstYStride, tmpU, dstUStride, tmpV, dstVStride,
-                               mWidth, mHeight);
-            libyuv::I010ToI420(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride,
-                               dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
-                               mWidth, mHeight);
-        } else if (buffer->image_format == libgav1::kImageFormatYuv422) {
-            libyuv::I210ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
-                               dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
-                               mWidth, mHeight);
-        } else {
-            convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
-                                        srcUStride / 2, srcVStride / 2, dstYStride, dstUStride,
-                                        mWidth, mHeight, isMonochrome);
-        }
+        convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
+                                    srcUStride / 2, srcVStride / 2, dstYStride, dstUStride, mWidth,
+                                    mHeight, isMonochrome);
     }
   } else {
     const uint8_t *srcY = (const uint8_t *)buffer->plane[0];
     const uint8_t *srcU = (const uint8_t *)buffer->plane[1];
     const uint8_t *srcV = (const uint8_t *)buffer->plane[2];
-    size_t srcYStride = buffer->stride[0];
-    size_t srcUStride = buffer->stride[1];
-    size_t srcVStride = buffer->stride[2];
 
     if (buffer->image_format == libgav1::kImageFormatYuv444) {
         libyuv::I444ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h
index c3b27ea..f0e14d7 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.h
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.h
@@ -19,8 +19,6 @@
 
 #include <inttypes.h>
 
-#include <memory>
-
 #include <media/stagefright/foundation/ColorUtils.h>
 
 #include <SimpleC2Component.h>
@@ -62,9 +60,6 @@
   uint32_t mHeight;
   bool mSignalledOutputEos;
   bool mSignalledError;
-  // Used during 10-bit I444/I422 to 10-bit P010 & 8-bit I420 conversions.
-  std::unique_ptr<uint16_t[]> mTmpFrameBuffer;
-  size_t mTmpFrameBufferSize = 0;
 
   C2StreamHdrStaticMetadataInfo::output mHdrStaticMetadataInfo;
   std::unique_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfo = nullptr;
@@ -102,9 +97,6 @@
   void destroyDecoder();
   void finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
                   const std::shared_ptr<C2GraphicBlock>& block);
-  // Sets |work->result| and mSignalledError. Returns false.
-  void setError(const std::unique_ptr<C2Work> &work, c2_status_t error);
-  bool allocTmpFrameBuffer(size_t size);
   bool outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
                     const std::unique_ptr<C2Work>& work);
   c2_status_t drainInternal(uint32_t drainMode,
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index c606d6f..9297520 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -119,8 +119,8 @@
     { C2Color::PRIMARIES_BT601_525,    ColorAspects::PrimariesBT601_6_525 },
     { C2Color::PRIMARIES_GENERIC_FILM, ColorAspects::PrimariesGenericFilm },
     { C2Color::PRIMARIES_BT2020,       ColorAspects::PrimariesBT2020 },
-//    { C2Color::PRIMARIES_RP431,        ColorAspects::Primaries... },
-//    { C2Color::PRIMARIES_EG432,        ColorAspects::Primaries... },
+    { C2Color::PRIMARIES_RP431,        ColorAspects::PrimariesRP431 },
+    { C2Color::PRIMARIES_EG432,        ColorAspects::PrimariesEG432 },
 //    { C2Color::PRIMARIES_EBU3213,      ColorAspects::Primaries... },
     { C2Color::PRIMARIES_OTHER,        ColorAspects::PrimariesOther },
 };
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index fc8ba9e..67ee42e 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -132,10 +132,11 @@
             AAudioConvert_contentTypeToInternal(builder.getContentType());
     const audio_usage_t usage =
             AAudioConvert_usageToInternal(builder.getUsage());
-    const audio_flags_mask_t attributesFlags =
-        AAudioConvert_allowCapturePolicyToAudioFlagsMask(builder.getAllowedCapturePolicy(),
-                                                         builder.getSpatializationBehavior(),
-                                                         builder.isContentSpatialized());
+    const audio_flags_mask_t attributesFlags = AAudio_computeAudioFlagsMask(
+                                                            builder.getAllowedCapturePolicy(),
+                                                            builder.getSpatializationBehavior(),
+                                                            builder.isContentSpatialized(),
+                                                            flags);
 
     const audio_attributes_t attributes = {
             .content_type = contentType,
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 8920e53..e8324a8 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -255,10 +255,11 @@
     return (audio_source_t) preset; // same value
 }
 
-audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask(
+audio_flags_mask_t AAudio_computeAudioFlagsMask(
         aaudio_allowed_capture_policy_t policy,
         aaudio_spatialization_behavior_t spatializationBehavior,
-        bool isContentSpatialized) {
+        bool isContentSpatialized,
+        audio_output_flags_t outputFlags) {
     audio_flags_mask_t flagsMask = AUDIO_FLAG_NONE;
     switch (policy) {
         case AAUDIO_UNSPECIFIED:
@@ -295,6 +296,15 @@
         flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_CONTENT_SPATIALIZED);
     }
 
+    if ((outputFlags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
+        flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_HW_AV_SYNC);
+    }
+    if ((outputFlags & AUDIO_OUTPUT_FLAG_FAST) != 0) {
+        flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_LOW_LATENCY);
+    } else if ((outputFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) {
+        flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_DEEP_BUFFER);
+    }
+
     return flagsMask;
 }
 
diff --git a/media/libaaudio/src/utility/AAudioUtilities.h b/media/libaaudio/src/utility/AAudioUtilities.h
index d8e5b00..d44bbab 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.h
+++ b/media/libaaudio/src/utility/AAudioUtilities.h
@@ -94,10 +94,11 @@
  * That is done somewhere else.
  * @return internal audio flags mask
  */
-audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask(
+audio_flags_mask_t AAudio_computeAudioFlagsMask(
         aaudio_allowed_capture_policy_t policy,
         aaudio_spatialization_behavior_t spatializationBehavior,
-        bool isContentSpatialized);
+        bool isContentSpatialized,
+        audio_output_flags_t outputFlags);
 
 audio_flags_mask_t AAudioConvert_privacySensitiveToAudioFlagsMask(
         bool privacySensitive);
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 2bbfb76..d5bbb52 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -300,11 +300,14 @@
         "aidl/android/media/AudioPortRole.aidl",
         "aidl/android/media/AudioPortType.aidl",
         "aidl/android/media/AudioProfileSys.aidl",
+        "aidl/android/media/AudioRoute.aidl",
         "aidl/android/media/AudioTimestampInternal.aidl",
         "aidl/android/media/AudioUniqueIdUse.aidl",
         "aidl/android/media/AudioVibratorInfo.aidl",
+        "aidl/android/media/DeviceConnectedState.aidl",
         "aidl/android/media/EffectDescriptor.aidl",
         "aidl/android/media/TrackSecondaryOutputInfo.aidl",
+        "aidl/android/media/SurroundSoundConfig.aidl",
     ],
     imports: [
         "android.media.audio.common.types-V2",
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 620cdc2..4384f97 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -810,10 +810,10 @@
 }
 
 status_t AudioFlingerClientAdapter::setDeviceConnectedState(
-        const struct audio_port_v7 *port, bool connected) {
+        const struct audio_port_v7 *port, media::DeviceConnectedState state) {
     media::AudioPortFw aidlPort = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_port_v7_AudioPortFw(*port));
-    return statusTFromBinderStatus(mDelegate->setDeviceConnectedState(aidlPort, connected));
+    return statusTFromBinderStatus(mDelegate->setDeviceConnectedState(aidlPort, state));
 }
 
 status_t AudioFlingerClientAdapter::setSimulateDeviceConnections(bool enabled) {
@@ -1369,9 +1369,9 @@
 }
 
 Status AudioFlingerServerAdapter::setDeviceConnectedState(
-        const media::AudioPortFw& port, bool connected) {
+        const media::AudioPortFw& port, media::DeviceConnectedState state) {
     audio_port_v7 portLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPortFw_audio_port_v7(port));
-    return Status::fromStatusT(mDelegate->setDeviceConnectedState(&portLegacy, connected));
+    return Status::fromStatusT(mDelegate->setDeviceConnectedState(&portLegacy, state));
 }
 
 Status AudioFlingerServerAdapter::setSimulateDeviceConnections(bool enabled) {
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index f0b4d11..7c0ce57 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -1306,6 +1306,7 @@
         streamType = AUDIO_STREAM_DTMF;
     }
     attr = AudioSystem::streamTypeToAttributes(streamType);
+    attr.flags = AUDIO_FLAG_LOW_LATENCY;
 
     const size_t frameCount = mProcessSize;
     status_t status = mpAudioTrack->set(
@@ -1314,7 +1315,7 @@
             AUDIO_FORMAT_PCM_16_BIT,
             AUDIO_CHANNEL_OUT_MONO,
             frameCount,
-            AUDIO_OUTPUT_FLAG_FAST,
+            AUDIO_OUTPUT_FLAG_NONE,
             wp<AudioTrack::IAudioTrackCallback>::fromExisting(this),
             0,    // notificationFrames
             0,    // sharedBuffer
diff --git a/media/libaudioclient/aidl/android/media/AudioRoute.aidl b/media/libaudioclient/aidl/android/media/AudioRoute.aidl
new file mode 100644
index 0000000..5ee2161
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioRoute.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+/**
+ * TODO(b/280077672): This is a temporary copy of the stable
+ * android.hardware.audio.core.AudioRoute. Interfaces from the Core API do not
+ * support the CPP backend. This copy will be removed either by moving the
+ * AudioRoute from core to a.m.a.common or by switching the framework internal
+ * interfaces to the NDK backend.
+ * {@hide}
+ */
+parcelable AudioRoute {
+    /**
+     * The list of IDs of source audio ports ('AudioPort.id').
+     * There must be at least one source in a valid route and all IDs must be
+     * unique.
+     */
+    int[] sourcePortIds;
+    /** The ID of the sink audio port ('AudioPort.id'). */
+    int sinkPortId;
+    /** If set, only one source can be active, mixing is not supported. */
+    boolean isExclusive;
+}
diff --git a/media/libaudioclient/aidl/android/media/DeviceConnectedState.aidl b/media/libaudioclient/aidl/android/media/DeviceConnectedState.aidl
new file mode 100644
index 0000000..e401384
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/DeviceConnectedState.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+package android.media;
+
+/**
+ * {@hide}
+ */
+@Backing(type="int")
+enum DeviceConnectedState {
+    CONNECTED = 0,
+    DISCONNECTED = 1,
+    PREPARE_TO_DISCONNECT = 2,
+}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 4d9fef4..884cd30 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -27,6 +27,7 @@
 import android.media.CreateRecordResponse;
 import android.media.CreateTrackRequest;
 import android.media.CreateTrackResponse;
+import android.media.DeviceConnectedState;
 import android.media.OpenInputRequest;
 import android.media.OpenInputResponse;
 import android.media.OpenOutputRequest;
@@ -227,7 +228,7 @@
 
     int getAAudioHardwareBurstMinUsec();
 
-    void setDeviceConnectedState(in AudioPortFw devicePort, boolean connected);
+    void setDeviceConnectedState(in AudioPortFw devicePort, DeviceConnectedState state);
 
     // Used for tests only. Requires AIDL HAL to work.
     void setSimulateDeviceConnections(boolean enabled);
diff --git a/media/libaudioclient/aidl/android/media/ISoundDose.aidl b/media/libaudioclient/aidl/android/media/ISoundDose.aidl
index 0e2a5ab..6cb22ef 100644
--- a/media/libaudioclient/aidl/android/media/ISoundDose.aidl
+++ b/media/libaudioclient/aidl/android/media/ISoundDose.aidl
@@ -49,13 +49,11 @@
     oneway void updateAttenuation(float attenuationDB, int device);
 
     /**
-     * Disable the calculation of sound dose. This has the effect that no MEL
-     * values will be computed on the framework side. The MEL returned from
-     * the IHalSoundDoseCallbacks will be ignored.
-     * Should only be called once at startup if the AudioService does not
-     * support CSD.
+     * Enables/disables the calculation of sound dose. This has the effect that
+     * if disabled no MEL values will be computed on the framework side. The MEL
+     * returned from the IHalSoundDoseCallbacks will be ignored.
      */
-    oneway void disableCsd();
+    oneway void setCsdEnabled(boolean enabled);
 
     /* -------------------------- Test API methods --------------------------
     /** Get the currently used RS2 upper bound. */
diff --git a/media/libaudioclient/aidl/android/media/SurroundSoundConfig.aidl b/media/libaudioclient/aidl/android/media/SurroundSoundConfig.aidl
new file mode 100644
index 0000000..f83fdef
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/SurroundSoundConfig.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.media.audio.common.AudioFormatDescription;
+
+/**
+ * TODO(b/280077672): This is a temporary copy of the stable
+ * android.hardware.audio.core.SurroundSoundConfig parcelable.
+ * Interfaces from the Core API do not support the CPP backend. This copy will
+ * be removed either by moving the AudioRoute from core to a.m.a.common or by
+ * switching the framework internal interfaces to the NDK backend.
+ * {@hide}
+ */
+parcelable SurroundSoundConfig {
+    parcelable SurroundFormatFamily {
+        /**
+         * A primaryFormat shall get an entry in the Surround Settings dialog on TV
+         * devices. There must be a corresponding Java ENCODING_... constant
+         * defined in AudioFormat.java, and a display name defined in
+         * AudioFormat.toDisplayName.
+         */
+        AudioFormatDescription primaryFormat;
+        /**
+         * List of formats that shall be equivalent to the primaryFormat from the
+         * users' point of view and don't need a dedicated Surround Settings
+         * dialog entry.
+         */
+        AudioFormatDescription[] subFormats;
+    }
+    SurroundFormatFamily[] formatFamilies;
+}
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 1803862..6e28d51 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -361,7 +361,8 @@
 
     virtual int32_t getAAudioHardwareBurstMinUsec() = 0;
 
-    virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) = 0;
+    virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port,
+                                             media::DeviceConnectedState state) = 0;
 
     virtual status_t setSimulateDeviceConnections(bool enabled) = 0;
 
@@ -481,7 +482,8 @@
             std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) override;
     int32_t getAAudioMixerBurstCount() override;
     int32_t getAAudioHardwareBurstMinUsec() override;
-    status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) override;
+    status_t setDeviceConnectedState(const struct audio_port_v7 *port,
+                                     media::DeviceConnectedState state) override;
     status_t setSimulateDeviceConnections(bool enabled) override;
     status_t setRequestedLatencyMode(audio_io_handle_t output,
             audio_latency_mode_t mode) override;
@@ -711,7 +713,8 @@
             std::vector<media::audio::common::AudioMMapPolicyInfo> *_aidl_return) override;
     Status getAAudioMixerBurstCount(int32_t* _aidl_return) override;
     Status getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
-    Status setDeviceConnectedState(const media::AudioPortFw& port, bool connected) override;
+    Status setDeviceConnectedState(const media::AudioPortFw& port,
+                                   media::DeviceConnectedState state) override;
     Status setSimulateDeviceConnections(bool enabled) override;
     Status setRequestedLatencyMode(
             int output, media::audio::common::AudioLatencyMode mode) override;
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 1dbcb86..3c05b0b 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -74,6 +74,12 @@
 cc_library_headers {
     name: "libaudiohal_headers",
 
+    header_libs: [
+        "libeffectsconfig_headers",
+    ],
+
+    export_header_lib_headers: ["libeffectsconfig_headers"],
+
     export_include_dirs: ["include"],
 }
 
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 9dbb591..09e70eb 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -35,6 +35,7 @@
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "libaudiohal_deathhandler",
+        "libeffectsconfig",
         "libhidlbase",
         "libhidlmemory",
     ],
@@ -287,15 +288,17 @@
         "android.hardware.common.fmq-V1-ndk",
     ],
     shared_libs: [
-        "libbinder_ndk",
         "libaudio_aidl_conversion_common_cpp",
         "libaudio_aidl_conversion_common_ndk",
+        "libaudio_aidl_conversion_common_ndk_cpp",
         "libaudio_aidl_conversion_core_ndk",
         "libaudio_aidl_conversion_effect_ndk",
         "libaudioaidlcommon",
+        "libbinder_ndk",
     ],
     header_libs: [
         "libaudio_system_headers",
+        "libeffectsconfig_headers",
     ],
     cflags: [
         "-Wall",
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index aafe6e0..f993907 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -23,10 +23,9 @@
 #include <aidl/android/hardware/audio/core/BnStreamCallback.h>
 #include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
 #include <aidl/android/hardware/audio/core/StreamDescriptor.h>
-#include <android/binder_enums.h>
-#include <binder/Enums.h>
 #include <error/expected_utils.h>
 #include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdkCpp.h>
 #include <media/AidlConversionUtil.h>
 #include <mediautils/TimeCheck.h>
 #include <Utils.h>
@@ -96,77 +95,35 @@
     portConfig->format = config.base.format;
 }
 
-template<typename OutEnum, typename OutEnumRange, typename InEnum>
-ConversionResult<OutEnum> convertEnum(const OutEnumRange& range, InEnum e) {
-    using InIntType = std::underlying_type_t<InEnum>;
-    static_assert(std::is_same_v<InIntType, std::underlying_type_t<OutEnum>>);
-
-    InIntType inEnumIndex = static_cast<InIntType>(e);
-    OutEnum outEnum = static_cast<OutEnum>(inEnumIndex);
-    if (std::find(range.begin(), range.end(), outEnum) == range.end()) {
-        return ::android::base::unexpected(BAD_VALUE);
-    }
-    return outEnum;
-}
-
-template<typename NdkEnum, typename CppEnum>
-ConversionResult<NdkEnum> cpp2ndk_Enum(CppEnum e) {
-    return convertEnum<NdkEnum>(::ndk::enum_range<NdkEnum>(), e);
-}
-
-template<typename CppEnum, typename NdkEnum>
-ConversionResult<CppEnum> ndk2cpp_Enum(NdkEnum e) {
-    return convertEnum<CppEnum>(::android::enum_range<CppEnum>(), e);
-}
-
-ConversionResult<android::media::audio::common::AudioDeviceAddress>
-ndk2cpp_AudioDeviceAddress(const AudioDeviceAddress& ndk) {
-    using CppTag = android::media::audio::common::AudioDeviceAddress::Tag;
-    using NdkTag = AudioDeviceAddress::Tag;
-
-    CppTag cppTag = VALUE_OR_RETURN(ndk2cpp_Enum<CppTag>(ndk.getTag()));
-
-    switch (cppTag) {
-        case CppTag::id:
-            return android::media::audio::common::AudioDeviceAddress::make<CppTag::id>(
-                    ndk.get<NdkTag::id>());
-        case CppTag::mac:
-            return android::media::audio::common::AudioDeviceAddress::make<CppTag::mac>(
-                    ndk.get<NdkTag::mac>());
-        case CppTag::ipv4:
-            return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv4>(
-                    ndk.get<NdkTag::ipv4>());
-        case CppTag::ipv6:
-            return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv6>(
-                    ndk.get<NdkTag::ipv6>());
-        case CppTag::alsa:
-            return android::media::audio::common::AudioDeviceAddress::make<CppTag::alsa>(
-                    ndk.get<NdkTag::alsa>());
-    }
-
-    return ::android::base::unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::audio::common::AudioDevice> ndk2cpp_AudioDevice(const AudioDevice& ndk) {
-    media::audio::common::AudioDevice cpp;
-    cpp.type.type = VALUE_OR_RETURN(
-            ndk2cpp_Enum<media::audio::common::AudioDeviceType>(ndk.type.type));
-    cpp.type.connection = ndk.type.connection;
-    cpp.address = VALUE_OR_RETURN(ndk2cpp_AudioDeviceAddress(ndk.address));
-    return cpp;
-}
-
-ConversionResult<media::audio::common::AudioMMapPolicyInfo>
-ndk2cpp_AudioMMapPolicyInfo(const AudioMMapPolicyInfo& ndk) {
-    media::audio::common::AudioMMapPolicyInfo cpp;
-    cpp.device = VALUE_OR_RETURN(ndk2cpp_AudioDevice(ndk.device));
-    cpp.mmapPolicy = VALUE_OR_RETURN(
-            ndk2cpp_Enum<media::audio::common::AudioMMapPolicy>(ndk.mmapPolicy));
+// Note: these converters are for types defined in different AIDL files. Although these
+// AIDL files are copies of each other, however formally these are different types
+// thus we don't use a conversion via a parcelable.
+ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
+    media::AudioRoute cpp;
+    cpp.sourcePortIds.insert(
+            cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
+    cpp.sinkPortId = ndk.sinkPortId;
+    cpp.isExclusive = ndk.isExclusive;
     return cpp;
 }
 
 }  // namespace
 
+status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
+    auto convertAudioPortFromMap = [](const Ports::value_type& pair) {
+        return ndk2cpp_AudioPort(pair.second);
+    };
+    return ::aidl::android::convertRange(mPorts.begin(), mPorts.end(), ports->begin(),
+            convertAudioPortFromMap);
+}
+
+status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
+    *routes = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::convertContainer<std::vector<media::AudioRoute>>(
+                    mRoutes, ndk2cpp_AudioRoute));
+    return OK;
+}
+
 status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
     // Obsolete.
     return INVALID_OPERATION;
@@ -176,8 +133,7 @@
     TIME_CHECK();
     if (mModule == nullptr) return NO_INIT;
     std::vector<AudioPort> ports;
-    RETURN_STATUS_IF_ERROR(
-            statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
     ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
             __func__, mInstance.c_str());
     std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
@@ -204,6 +160,9 @@
     std::transform(portConfigs.begin(), portConfigs.end(),
             std::inserter(mPortConfigs, mPortConfigs.end()),
             [](const auto& p) { return std::make_pair(p.id, p); });
+    std::transform(mPortConfigs.begin(), mPortConfigs.end(),
+            std::inserter(mInitialPortConfigIds, mInitialPortConfigIds.end()),
+            [](const auto& pcPair) { return pcPair.first; });
     std::vector<AudioPatch> patches;
     RETURN_STATUS_IF_ERROR(
             statusTFromBinderStatus(mModule->getAudioPatches(&patches)));  // OK if empty
@@ -357,12 +316,14 @@
             this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
             aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
             aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
+    resetUnusedPatchesAndPortConfigs();
     const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
     // 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(aidlDevice, &devicePortConfig, &created));
+    RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, aidlConfig,
+                                                  &devicePortConfig, &created));
     if (created) {
         cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
     }
@@ -888,8 +849,8 @@
         media::audio::common::AudioMMapPolicyType policyType,
         std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
     TIME_CHECK();
-    AudioMMapPolicyType mmapPolicyType =
-            VALUE_OR_RETURN_STATUS(cpp2ndk_Enum<AudioMMapPolicyType>(policyType));
+    AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
+            cpp2ndk_AudioMMapPolicyType(policyType));
 
     std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
 
@@ -966,12 +927,32 @@
     return OK;
 }
 
+status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
+    // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
+    // Call `setConnectedState` instead.
+    // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
+    const status_t status = setConnectedState(port, false /*connected*/);
+    if (status == NO_ERROR) {
+        mDeviceDisconnectionNotified.insert(port->id);
+    }
+    return status;
+}
+
 status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
     TIME_CHECK();
     if (!mModule) return NO_INIT;
     if (port == nullptr) {
         return BAD_VALUE;
     }
+    if (!connected && mDeviceDisconnectionNotified.erase(port->id) > 0) {
+        // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
+        // and then call `setConnectedState`. However, there is no API for
+        // `prepareToDisconnectExternalDevice` yet. In that case, `setConnectedState` will be
+        // called when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if
+        // previous call is successful. Also remove the cache here to avoid a large cache after
+        // a long run.
+        return NO_ERROR;
+    }
     bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
             ::aidl::android::AudioPortDirection::INPUT;
     AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
@@ -1109,7 +1090,7 @@
     return OK;
 }
 
-status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
+status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device, const AudioConfig* config,
         AudioPortConfig* portConfig, bool* created) {
     auto portConfigIt = findPortConfig(device);
     if (portConfigIt == mPortConfigs.end()) {
@@ -1121,6 +1102,9 @@
         }
         AudioPortConfig requestedPortConfig;
         requestedPortConfig.portId = portsIt->first;
+        if (config != nullptr) {
+            setPortConfigFromConfig(&requestedPortConfig, *config);
+        }
         RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
                 created));
     } else {
@@ -1223,7 +1207,8 @@
                 portConfig, created);
     } else if (requestedPortConfig.ext.getTag() == Tag::device) {
         return findOrCreatePortConfig(
-                requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
+                requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
+                portConfig, created);
     }
     ALOGW("%s: unsupported audio port config: %s",
             __func__, requestedPortConfig.toString().c_str());
@@ -1252,7 +1237,6 @@
             [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
 }
 
-
 DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
             const AudioConfig& config, const AudioIoFlags& flags,
             const std::set<int32_t>& destinationPortIds) {
@@ -1265,10 +1249,20 @@
                         std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
                                 config.base.sampleRate) != prof.sampleRates.end());
     };
+    static const std::vector<AudioOutputFlags> kOptionalOutputFlags{AudioOutputFlags::BIT_PERFECT};
+    int optionalFlags = 0;
+    auto flagMatches = [&flags, &optionalFlags](const AudioIoFlags& portFlags) {
+        // Ports should be able to match if the optional flags are not requested.
+        return portFlags == flags ||
+               (portFlags.getTag() == AudioIoFlags::Tag::output &&
+                        AudioIoFlags::make<AudioIoFlags::Tag::output>(
+                                portFlags.get<AudioIoFlags::Tag::output>() &
+                                        ~optionalFlags) == flags);
+    };
     auto matcher = [&](const auto& pair) {
         const auto& p = pair.second;
         return p.ext.getTag() == AudioPortExt::Tag::mix &&
-                p.flags == flags &&
+                flagMatches(p.flags) &&
                 (destinationPortIds.empty() ||
                         std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
                                 [&](const int32_t destId) { return mRoutingMatrix.count(
@@ -1276,7 +1270,24 @@
                 (p.profiles.empty() ||
                         std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
                         p.profiles.end()); };
-    return std::find_if(mPorts.begin(), mPorts.end(), matcher);
+    auto result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
+    if (result == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::output) {
+        auto optionalOutputFlagsIt = kOptionalOutputFlags.begin();
+        while (result == mPorts.end() && optionalOutputFlagsIt != kOptionalOutputFlags.end()) {
+            if (isBitPositionFlagSet(
+                        flags.get<AudioIoFlags::Tag::output>(), *optionalOutputFlagsIt)) {
+                // If the flag is set by the request, it must be matched.
+                ++optionalOutputFlagsIt;
+                continue;
+            }
+            optionalFlags |= makeBitPositionFlagMask(*optionalOutputFlagsIt++);
+            result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
+            ALOGI("%s: port for config %s, flags %s was not found in the module %s, "
+                  "retried with excluding optional flags %#x", __func__, config.toString().c_str(),
+                    flags.toString().c_str(), mInstance.c_str(), optionalFlags);
+        }
+    }
+    return result;
 }
 
 DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
@@ -1358,18 +1369,20 @@
         for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
         for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
     }
+    for (int32_t id : mInitialPortConfigIds) {
+        portConfigIds.erase(id);
+    }
     for (int32_t id : portConfigIds) resetPortConfig(id);
 }
 
 status_t DeviceHalAidl::updateRoutes() {
     TIME_CHECK();
-    std::vector<AudioRoute> routes;
     RETURN_STATUS_IF_ERROR(
-            statusTFromBinderStatus(mModule->getAudioRoutes(&routes)));
-    ALOGW_IF(routes.empty(), "%s: module %s returned an empty list of audio routes",
+            statusTFromBinderStatus(mModule->getAudioRoutes(&mRoutes)));
+    ALOGW_IF(mRoutes.empty(), "%s: module %s returned an empty list of audio routes",
             __func__, mInstance.c_str());
     mRoutingMatrix.clear();
-    for (const auto& r : routes) {
+    for (const auto& r : mRoutes) {
         for (auto portId : r.sourcePortIds) {
             mRoutingMatrix.emplace(r.sinkPortId, portId);
             mRoutingMatrix.emplace(portId, r.sinkPortId);
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index e4d5ec6..f2c64de 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -69,6 +69,10 @@
 class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl,
                       public CallbackBroker, public MicrophoneInfoProvider {
   public:
+    status_t getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) override;
+
+    status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) override;
+
     // Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
     status_t getSupportedDevices(uint32_t *devices) override;
 
@@ -161,6 +165,8 @@
     status_t getSoundDoseInterface(const std::string& module,
                                    ::ndk::SpAIBinder* soundDoseBinder) override;
 
+    status_t prepareToDisconnectExternalDevice(const struct audio_port_v7 *port) override;
+
     status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override;
 
     status_t setSimulateDeviceConnections(bool enabled) override;
@@ -185,6 +191,7 @@
     using PortConfigs = std::map<int32_t /*port config ID*/,
             ::aidl::android::media::audio::common::AudioPortConfig>;
     using Ports = std::map<int32_t /*port ID*/, ::aidl::android::media::audio::common::AudioPort>;
+    using Routes = std::vector<::aidl::android::hardware::audio::core::AudioRoute>;
     // Answers the question "whether portID 'first' is reachable from portID 'second'?"
     // It's not a map because both portIDs are known. The matrix is symmetric.
     using RoutingMatrix = std::set<std::pair<int32_t, int32_t>>;
@@ -215,6 +222,7 @@
         ::aidl::android::hardware::audio::core::AudioPatch* patch, bool* created);
     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(
@@ -284,12 +292,15 @@
     int32_t mDefaultInputPortId = -1;
     int32_t mDefaultOutputPortId = -1;
     PortConfigs mPortConfigs;
+    std::set<int32_t> mInitialPortConfigIds;
     Patches mPatches;
+    Routes mRoutes;
     RoutingMatrix mRoutingMatrix;
     Streams mStreams;
     Microphones mMicrophones;
     std::mutex mLock;
     std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
+    std::set<audio_port_handle_t> mDeviceDisconnectionNotified;
 };
 
 } // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index e0b1afb..d67cbdc 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -104,6 +104,15 @@
     }
 }
 
+status_t DeviceHalHidl::getAudioPorts(
+        std::vector<media::audio::common::AudioPort> *ports __unused) {
+    return INVALID_OPERATION;
+}
+
+status_t DeviceHalHidl::getAudioRoutes(std::vector<media::AudioRoute> *routes __unused) {
+    return INVALID_OPERATION;
+}
+
 status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {
     // Obsolete.
     return INVALID_OPERATION;
@@ -430,6 +439,7 @@
 
 template <typename HalPort>
 status_t DeviceHalHidl::getAudioPortImpl(HalPort *port) {
+    using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioPort;
     if (mDevice == 0) return NO_INIT;
     AudioPort hidlPort;
     HidlUtils::audioPortFromHal(*port, &hidlPort);
@@ -472,6 +482,7 @@
 }
 
 status_t DeviceHalHidl::setAudioPortConfig(const struct audio_port_config *config) {
+    using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioPortConfig;
     TIME_CHECK();
     if (mDevice == 0) return NO_INIT;
     AudioPortConfig hidlConfig;
@@ -535,9 +546,29 @@
 }
 #endif
 
+status_t DeviceHalHidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
+    // For HIDL HAL, there is not API to call notify the HAL to prepare for device connected
+    // state changed. Call `setConnectedState` directly.
+    const status_t status = setConnectedState(port, false /*connected*/);
+    if (status == NO_ERROR) {
+        // Cache the port id so that it won't disconnect twice.
+        mDeviceDisconnectionNotified.insert(port->id);
+    }
+    return status;
+}
+
 status_t DeviceHalHidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
+    using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioPort;
     TIME_CHECK();
     if (mDevice == 0) return NO_INIT;
+    if (!connected && mDeviceDisconnectionNotified.erase(port->id) > 0) {
+        // For device disconnection, APM will first call `prepareToDisconnectExternalDevice` and
+        // then call `setConnectedState`. However, in HIDL HAL, there is no API for
+        // `prepareToDisconnectExternalDevice`. In that case, HIDL HAL will call `setConnectedState`
+        // when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if previous
+        // call is successful. Also remove the cache here to avoid a large cache after a long run.
+        return NO_ERROR;
+    }
 #if MAJOR_VERSION == 7 && MINOR_VERSION == 1
     if (supportsSetConnectedState7_1) {
         AudioPort hidlPort;
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index afaad51..7222f03 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -29,6 +29,10 @@
 class DeviceHalHidl : public DeviceHalInterface, public CoreConversionHelperHidl
 {
   public:
+    status_t getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) override;
+
+    status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) override;
+
     // Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
     status_t getSupportedDevices(uint32_t *devices) override;
 
@@ -138,6 +142,8 @@
     status_t getSoundDoseInterface(const std::string& module,
                                    ::ndk::SpAIBinder* soundDoseBinder) override;
 
+    status_t prepareToDisconnectExternalDevice(const struct audio_port_v7* port) override;
+
   private:
     friend class DevicesFactoryHalHidl;
     sp<::android::hardware::audio::CPP_VERSION::IDevice> mDevice;
@@ -146,6 +152,7 @@
     bool supportsSetConnectedState7_1 = true;
     class SoundDoseWrapper;
     const std::unique_ptr<SoundDoseWrapper> mSoundDoseWrapper;
+    std::set<audio_port_handle_t> mDeviceDisconnectionNotified;
 
     // Can not be constructed directly by clients.
     explicit DeviceHalHidl(const sp<::android::hardware::audio::CPP_VERSION::IDevice>& device);
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
index 2eaaf5d..8345cd2 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -14,26 +14,67 @@
  * limitations under the License.
  */
 
+#include <memory>
+
 #define LOG_TAG "DevicesFactoryHalAidl"
 //#define LOG_NDEBUG 0
 
 #include <aidl/android/hardware/audio/core/IModule.h>
 #include <android/binder_manager.h>
 #include <binder/IServiceManager.h>
-#include <memory>
+#include <media/AidlConversionNdkCpp.h>
+#include <media/AidlConversionUtil.h>
 #include <utils/Log.h>
 
 #include "DeviceHalAidl.h"
 #include "DevicesFactoryHalAidl.h"
 
-using namespace ::aidl::android::hardware::audio::core;
+using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::hardware::audio::core::IConfig;
+using aidl::android::hardware::audio::core::IModule;
+using aidl::android::hardware::audio::core::SurroundSoundConfig;
+using aidl::android::media::audio::common::AudioHalEngineConfig;
 using ::android::detail::AudioHalVersionInfo;
 
 namespace android {
 
-DevicesFactoryHalAidl::DevicesFactoryHalAidl(std::shared_ptr<IConfig> iconfig)
-    : mIConfig(std::move(iconfig)) {
-    ALOG_ASSERT(iconfig != nullptr, "Provided default IConfig service is NULL");
+namespace {
+
+ConversionResult<media::SurroundSoundConfig::SurroundFormatFamily>
+ndk2cpp_SurroundSoundConfigFormatFamily(const SurroundSoundConfig::SurroundFormatFamily& ndk) {
+    media::SurroundSoundConfig::SurroundFormatFamily cpp;
+    cpp.primaryFormat = VALUE_OR_RETURN(ndk2cpp_AudioFormatDescription(ndk.primaryFormat));
+    cpp.subFormats = VALUE_OR_RETURN(::aidl::android::convertContainer<std::vector<
+            media::audio::common::AudioFormatDescription>>(ndk.subFormats,
+                    ndk2cpp_AudioFormatDescription));
+    return cpp;
+}
+
+ConversionResult<media::SurroundSoundConfig>
+ndk2cpp_SurroundSoundConfig(const SurroundSoundConfig& ndk) {
+    media::SurroundSoundConfig cpp;
+    cpp.formatFamilies = VALUE_OR_RETURN(::aidl::android::convertContainer<std::vector<
+            media::SurroundSoundConfig::SurroundFormatFamily>>(ndk.formatFamilies,
+                    ndk2cpp_SurroundSoundConfigFormatFamily));
+    return cpp;
+}
+
+}  // namespace
+
+DevicesFactoryHalAidl::DevicesFactoryHalAidl(std::shared_ptr<IConfig> config)
+    : mConfig(std::move(config)) {
+}
+
+status_t DevicesFactoryHalAidl::getDeviceNames(std::vector<std::string> *names) {
+    if (names == nullptr) {
+        return BAD_VALUE;
+    }
+    AServiceManager_forEachDeclaredInstance(IModule::descriptor, static_cast<void*>(names),
+            [](const char* instance, void* context) {
+                if (strcmp(instance, "default") == 0) instance = "primary";
+                static_cast<decltype(names)>(context)->push_back(instance);
+            });
+    return OK;
 }
 
 // Opens a device with the specified name. To close the device, it is
@@ -43,19 +84,22 @@
         return BAD_VALUE;
     }
 
+    // FIXME: Remove this call and the check for the supported module names
+    // after implementing retrieval of module names on the framework side.
+    // Currently it is still using the legacy XML config.
+    std::vector<std::string> deviceNames;
+    if (status_t status = getDeviceNames(&deviceNames); status != OK) {
+        return status;
+    }
     std::shared_ptr<IModule> service;
-    // FIXME: Normally we will list available HAL modules and connect to them,
-    // however currently we still get the list of module names from the config.
-    // Since the example service does not have all modules, the SM will wait
-    // for the missing ones forever.
-    if (strcmp(name, "primary") == 0 || strcmp(name, "r_submix") == 0 || strcmp(name, "usb") == 0) {
+    if (std::find(deviceNames.begin(), deviceNames.end(), name) != deviceNames.end()) {
         if (strcmp(name, "primary") == 0) name = "default";
         auto serviceName = std::string(IModule::descriptor) + "/" + name;
         service = IModule::fromBinder(
                 ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
         ALOGE_IF(service == nullptr, "%s fromBinder %s failed", __func__, serviceName.c_str());
     }
-    // If the service is a nullptr, the device will not be really functional,
+    // If the service is a nullptr, the device object will not be really functional,
     // but will not crash either.
     *device = sp<DeviceHalAidl>::make(name, service);
     return OK;
@@ -97,18 +141,28 @@
 
 AudioHalVersionInfo DevicesFactoryHalAidl::getHalVersion() const {
     int32_t versionNumber = 0;
-    if (mIConfig != 0) {
-        if (ndk::ScopedAStatus status = mIConfig->getInterfaceVersion(&versionNumber);
-                !status.isOk()) {
-            ALOGE("%s getInterfaceVersion failed: %s", __func__, status.getDescription().c_str());
-        }
-    } else {
-        ALOGW("%s no IConfig instance", __func__);
+    if (ndk::ScopedAStatus status = mConfig->getInterfaceVersion(&versionNumber); !status.isOk()) {
+        ALOGE("%s getInterfaceVersion failed: %s", __func__, status.getDescription().c_str());
     }
     // AIDL does not have minor version, fill 0 for all versions
     return AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, versionNumber);
 }
 
+status_t DevicesFactoryHalAidl::getSurroundSoundConfig(media::SurroundSoundConfig *config) {
+    SurroundSoundConfig ndkConfig;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mConfig->getSurroundSoundConfig(&ndkConfig)));
+    *config = VALUE_OR_RETURN_STATUS(ndk2cpp_SurroundSoundConfig(ndkConfig));
+    return OK;
+}
+
+status_t DevicesFactoryHalAidl::getEngineConfig(
+        media::audio::common::AudioHalEngineConfig *config) {
+    AudioHalEngineConfig ndkConfig;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mConfig->getEngineConfig(&ndkConfig)));
+    *config = VALUE_OR_RETURN_STATUS(ndk2cpp_AudioHalEngineConfig(ndkConfig));
+    return OK;
+}
+
 // Main entry-point to the shared library.
 extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
     auto serviceName = std::string(IConfig::descriptor) + "/default";
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.h b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
index cb627bc..21957bc 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
@@ -26,7 +26,9 @@
 {
   public:
     explicit DevicesFactoryHalAidl(
-            std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> iConfig);
+            std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> config);
+
+    status_t getDeviceNames(std::vector<std::string> *names) override;
 
     // Opens a device with the specified name. To close the device, it is
     // necessary to release references to the returned object.
@@ -38,8 +40,12 @@
 
     android::detail::AudioHalVersionInfo getHalVersion() const override;
 
+    status_t getSurroundSoundConfig(media::SurroundSoundConfig *config) override;
+
+    status_t getEngineConfig(media::audio::common::AudioHalEngineConfig *config) override;
+
   private:
-    const std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> mIConfig;
+    const std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> mConfig;
     ~DevicesFactoryHalAidl() = default;
 };
 
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
index 9f06f83..eef60b5 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
@@ -106,6 +106,10 @@
 }
 #endif
 
+status_t DevicesFactoryHalHidl::getDeviceNames(std::vector<std::string> *names __unused) {
+    return INVALID_OPERATION;
+}
+
 status_t DevicesFactoryHalHidl::openDevice(const char *name, sp<DeviceHalInterface> *device) {
     auto factories = copyDeviceFactories();
     if (factories.empty()) return NO_INIT;
@@ -232,6 +236,16 @@
     return AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, MAJOR_VERSION, MINOR_VERSION);
 }
 
+status_t DevicesFactoryHalHidl::getSurroundSoundConfig(
+        media::SurroundSoundConfig *config __unused) {
+    return INVALID_OPERATION;
+}
+
+status_t DevicesFactoryHalHidl::getEngineConfig(
+        media::audio::common::AudioHalEngineConfig *config __unused) {
+    return INVALID_OPERATION;
+}
+
 // Main entry-point to the shared library.
 extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
     auto service = hardware::audio::CPP_VERSION::IDevicesFactory::getService();
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.h b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
index 5294728..3285af7 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
@@ -37,6 +37,8 @@
     explicit DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory);
     void onFirstRef() override;
 
+    status_t getDeviceNames(std::vector<std::string> *names) override;
+
     // Opens a device with the specified name. To close the device, it is
     // necessary to release references to the returned object.
     status_t openDevice(const char *name, sp<DeviceHalInterface> *device) override;
@@ -47,6 +49,10 @@
 
     android::detail::AudioHalVersionInfo getHalVersion() const override;
 
+    status_t getSurroundSoundConfig(media::SurroundSoundConfig *config) override;
+
+    status_t getEngineConfig(media::audio::common::AudioHalEngineConfig *config) override;
+
   private:
     friend class ServiceNotificationListener;
     void addDeviceFactory(sp<IDevicesFactory> factory, bool needToNotify);
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
index bc05aa0..0dcb8ee 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -23,6 +23,7 @@
 //#define LOG_NDEBUG 0
 
 #include <error/expected_utils.h>
+#include <aidl/android/media/audio/common/AudioStreamType.h>
 #include <android/binder_manager.h>
 #include <media/AidlConversionCppNdk.h>
 #include <media/AidlConversionEffect.h>
@@ -35,11 +36,13 @@
 #include "EffectsFactoryHalAidl.h"
 
 using ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid;
-using aidl::android::aidl_utils::statusTFromBinderStatus;
-using aidl::android::hardware::audio::effect::Descriptor;
-using aidl::android::hardware::audio::effect::IFactory;
-using aidl::android::media::audio::common::AudioUuid;
-using android::detail::AudioHalVersionInfo;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Descriptor;
+using ::aidl::android::hardware::audio::effect::IFactory;
+using ::aidl::android::hardware::audio::effect::Processing;
+using ::aidl::android::media::audio::common::AudioUuid;
+using ::android::base::unexpected;
+using ::android::detail::AudioHalVersionInfo;
 
 namespace android {
 namespace effect {
@@ -92,7 +95,8 @@
                        [](const Descriptor& desc) { return !desc.common.id.proxy.has_value(); });
           return list;
       }()),
-      mEffectCount(mNonProxyDescList.size() + mProxyDescList.size()) {
+      mEffectCount(mNonProxyDescList.size() + mProxyDescList.size()),
+      mEffectProcessings(nullptr /* TODO: add AIDL implementation */) {
     ALOG_ASSERT(mFactory != nullptr, "Provided IEffectsFactory service is NULL");
     ALOGI("%s with %zu nonProxyEffects and %zu proxyEffects", __func__, mNonProxyDescList.size(),
           mProxyDescList.size());
@@ -269,6 +273,19 @@
     return 0 != mUuidProxyMap.count(uuid);
 }
 
+std::shared_ptr<const effectsConfig::Processings> EffectsFactoryHalAidl::getProcessings() const {
+    return mEffectProcessings;
+}
+
+::android::error::Result<size_t> EffectsFactoryHalAidl::getSkippedElements() const {
+    if (!mEffectProcessings) {
+        return ::android::base::unexpected(BAD_VALUE);
+    }
+
+    // Only return 0 for AIDL, because the AIDL interface doesn't aware of configuration file
+    return 0;
+}
+
 } // namespace effect
 
 // When a shared library is built from a static library, even explicit
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
index debfacf..70a7012 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -62,6 +62,10 @@
 
     detail::AudioHalVersionInfo getHalVersion() const override;
 
+    std::shared_ptr<const effectsConfig::Processings> getProcessings() const override;
+
+    ::android::error::Result<size_t> getSkippedElements() const override;
+
   private:
     const std::shared_ptr<IFactory> mFactory;
     const detail::AudioHalVersionInfo mHalVersion;
@@ -77,6 +81,8 @@
     const std::vector<Descriptor> mNonProxyDescList;
     // total number of effects including proxy effects
     const size_t mEffectCount;
+    // Query result of pre and post processing from effect factory
+    const std::shared_ptr<const effectsConfig::Processings> mEffectProcessings;
 
     std::mutex mLock;
     uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0;  // Align with HIDL (0 is INVALID_ID)
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
index 172ebdf..210c4b5 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
@@ -33,10 +33,11 @@
 
 #include "android/media/AudioHalVersion.h"
 
+using ::android::base::unexpected;
 using ::android::detail::AudioHalVersionInfo;
+using ::android::hardware::Return;
 using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
 using ::android::hardware::audio::effect::CPP_VERSION::implementation::EffectUtils;
-using ::android::hardware::Return;
 
 namespace android {
 namespace effect {
@@ -78,9 +79,11 @@
 }
 
 EffectsFactoryHalHidl::EffectsFactoryHalHidl(sp<IEffectsFactory> effectsFactory)
-        : EffectConversionHelperHidl("EffectsFactory"), mCache(new EffectDescriptorCache) {
-    ALOG_ASSERT(effectsFactory != nullptr, "Provided IEffectsFactory service is NULL");
-    mEffectsFactory = std::move(effectsFactory);
+    : EffectConversionHelperHidl("EffectsFactory"),
+      mEffectsFactory(std::move(effectsFactory)),
+      mCache(new EffectDescriptorCache),
+      mParsingResult(effectsConfig::parse()) {
+    ALOG_ASSERT(mEffectsFactory != nullptr, "Provided IEffectsFactory service is NULL");
 }
 
 status_t EffectsFactoryHalHidl::queryNumberEffects(uint32_t *pNumEffects) {
@@ -228,6 +231,17 @@
     return AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, MAJOR_VERSION, MINOR_VERSION);
 }
 
+std::shared_ptr<const effectsConfig::Processings> EffectsFactoryHalHidl::getProcessings() const {
+    return mParsingResult.parsedConfig;
+}
+
+::android::error::Result<size_t> EffectsFactoryHalHidl::getSkippedElements() const {
+    if (!mParsingResult.parsedConfig) {
+        return ::android::base::unexpected(BAD_VALUE);
+    }
+    return mParsingResult.nbSkippedElement;
+}
+
 } // namespace effect
 
 // When a shared library is built from a static library, even explicit
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.h b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
index 9875154..4110ba3 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <memory>
+#include <vector>
 
 #include PATH(android/hardware/audio/effect/FILE_VERSION/IEffectsFactory.h)
 #include <media/audiohal/EffectsFactoryHalInterface.h>
@@ -62,9 +63,19 @@
 
     android::detail::AudioHalVersionInfo getHalVersion() const override;
 
+    std::shared_ptr<const effectsConfig::Processings> getProcessings() const override;
+
+    ::android::error::Result<size_t> getSkippedElements() const override;
+
   private:
-    sp<IEffectsFactory> mEffectsFactory;
-    std::unique_ptr<EffectDescriptorCache> mCache;
+    const sp<IEffectsFactory> mEffectsFactory;
+    const std::unique_ptr<EffectDescriptorCache> mCache;
+    /**
+     * Configuration file parser result, used by getProcessings() and getConfigParseResult().
+     * This struct holds the result of parsing a configuration file. The result includes the parsed
+     * configuration data, as well as any errors that occurred during parsing.
+     */
+    const effectsConfig::ParsingResult mParsingResult;
 };
 
 } // namespace effect
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 6c43591..eccdfe8 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -436,8 +436,7 @@
     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    return statusTFromBinderStatus(mStream->prepareToClose());
 }
 
 status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 192790c..2b0af49 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -979,9 +979,10 @@
 }
 
 status_t StreamOutHalHidl::exit() {
-    // FIXME this is using hard-coded strings but in the future, this functionality will be
-    //       converted to use audio HAL extensions required to support tunneling
-    return setParameters(String8("exiting=1"));
+    // Signal exiting to remote_submix HAL.
+    AudioParameter param;
+    param.addInt(String8(AudioParameter::keyExiting), 1);
+    return setParameters(param.toString());
 }
 
 StreamInHalHidl::StreamInHalHidl(
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
index 2d5af59..b4440ee 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
@@ -52,6 +52,7 @@
     Parameter aidlParam;
     switch (type) {
         case VISUALIZER_PARAM_CAPTURE_SIZE: {
+            mCaptureSize = value;
             aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, captureSamples, value);
             break;
         }
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index e8d8998..45f2922 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -19,6 +19,8 @@
 
 #include <android/media/audio/common/AudioMMapPolicyInfo.h>
 #include <android/media/audio/common/AudioMMapPolicyType.h>
+#include <android/media/audio/common/AudioPort.h>
+#include <android/media/AudioRoute.h>
 #include <error/Result.h>
 #include <media/audiohal/EffectHalInterface.h>
 #include <system/audio.h>
@@ -38,6 +40,10 @@
 class DeviceHalInterface : public virtual RefBase
 {
   public:
+    virtual status_t getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) = 0;
+
+    virtual status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) = 0;
+
     // Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
     virtual status_t getSupportedDevices(uint32_t *devices) = 0;
 
@@ -149,6 +155,8 @@
     virtual status_t getSoundDoseInterface(const std::string& module,
                                            ::ndk::SpAIBinder* soundDoseBinder) = 0;
 
+    virtual status_t prepareToDisconnectExternalDevice(const struct audio_port_v7* port) = 0;
+
   protected:
     // Subclasses can not be constructed directly by clients.
     DeviceHalInterface() {}
diff --git a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
index be3a723..8397e9b 100644
--- a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <android/media/audio/common/AudioHalEngineConfig.h>
+#include <android/media/SurroundSoundConfig.h>
 #include <media/audiohal/DeviceHalInterface.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -34,6 +36,8 @@
 class DevicesFactoryHalInterface : public RefBase
 {
   public:
+    virtual status_t getDeviceNames(std::vector<std::string> *names) = 0;
+
     // Opens a device with the specified name. To close the device, it is
     // necessary to release references to the returned object.
     virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device) = 0;
@@ -46,6 +50,10 @@
 
     virtual android::detail::AudioHalVersionInfo getHalVersion() const = 0;
 
+    virtual status_t getSurroundSoundConfig(media::SurroundSoundConfig *config) = 0;
+
+    virtual status_t getEngineConfig(media::audio::common::AudioHalEngineConfig *config) = 0;
+
     static sp<DevicesFactoryHalInterface> create();
 
   protected:
diff --git a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
index d740fe9..832df18 100644
--- a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
@@ -15,8 +15,10 @@
  */
 
 #pragma once
+#include <vector>
 
 #include <media/audiohal/EffectHalInterface.h>
+#include <media/EffectsConfig.h>
 #include <system/audio_effect.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -33,21 +35,24 @@
     virtual status_t queryNumberEffects(uint32_t *pNumEffects) = 0;
 
     // Returns a descriptor of the next available effect.
-    virtual status_t getDescriptor(uint32_t index,
-            effect_descriptor_t *pDescriptor) = 0;
+    virtual status_t getDescriptor(uint32_t index, effect_descriptor_t* pDescriptor) = 0;
 
-    virtual status_t getDescriptor(const effect_uuid_t *pEffectUuid,
-            effect_descriptor_t *pDescriptor) = 0;
+    virtual status_t getDescriptor(const effect_uuid_t* pEffectUuid,
+                                   effect_descriptor_t* pDescriptor) = 0;
 
     virtual status_t getDescriptors(const effect_uuid_t *pEffectType,
                                     std::vector<effect_descriptor_t> *descriptors) = 0;
 
+    virtual std::shared_ptr<const effectsConfig::Processings> getProcessings() const = 0;
+
+    // status_t if parser return error, skipped elements if parsing result is OK (always 0 for AIDL)
+    virtual error::Result<size_t> getSkippedElements() const = 0;
+
     // Creates an effect engine of the specified type.
     // To release the effect engine, it is necessary to release references
     // to the returned effect object.
-    virtual status_t createEffect(const effect_uuid_t *pEffectUuid,
-            int32_t sessionId, int32_t ioId, int32_t deviceId,
-            sp<EffectHalInterface> *effect) = 0;
+    virtual status_t createEffect(const effect_uuid_t* pEffectUuid, int32_t sessionId, int32_t ioId,
+                                  int32_t deviceId, sp<EffectHalInterface>* effect) = 0;
 
     virtual status_t dumpEffects(int fd) = 0;
 
diff --git a/media/libaudiousecasevalidation/UsecaseValidator.cpp b/media/libaudiousecasevalidation/UsecaseValidator.cpp
index 0e5a824..d62df3a 100644
--- a/media/libaudiousecasevalidation/UsecaseValidator.cpp
+++ b/media/libaudiousecasevalidation/UsecaseValidator.cpp
@@ -99,10 +99,8 @@
 
         audio_attributes_t attrRet = attributes;
 
-        // Check if attribute usage media or unknown has been set.
-        bool isUsageValid = this->isUsageValid(attributes);
-
-        if (isUsageValid && m_lookup.isGameStream(streamId)) {
+        if (isUsageValid(attributes.usage) && isContentTypeValid(attributes.content_type)
+                && areFlagsValid(attributes.flags) && m_lookup.isGameStream(streamId)) {
             ALOGI("%s update usage: %d to AUDIO_USAGE_GAME for output: %d pid: %d package: %s",
                     __func__, attributes.usage, streamId, attributionSource.pid,
                     attributionSource.packageName.value_or("").c_str());
@@ -117,9 +115,9 @@
     /**
      * Check if attribute usage valid.
      */
-    bool isUsageValid(const audio_attributes_t& attr) {
-        ALOGV("isUsageValid attr.usage: %d", attr.usage);
-        switch (attr.usage) {
+    bool isUsageValid(audio_usage_t usage) {
+        ALOGV("isUsageValid usage: %d", usage);
+        switch (usage) {
             case AUDIO_USAGE_MEDIA:
             case AUDIO_USAGE_UNKNOWN:
                 return true;
@@ -129,6 +127,27 @@
         return false;
     }
 
+    bool isContentTypeValid(audio_content_type_t contentType) {
+        ALOGV("isContentTypeValid contentType: %d", contentType);
+        switch (contentType) {
+            case AUDIO_CONTENT_TYPE_MUSIC:
+            case AUDIO_CONTENT_TYPE_MOVIE:
+            case AUDIO_CONTENT_TYPE_UNKNOWN:
+                return true;
+            default:
+                break;
+        }
+        return false;
+    }
+
+    bool areFlagsValid(audio_flags_mask_t flags) {
+        ALOGV("areFlagsValid flags: %#x", flags);
+        if ((flags & AUDIO_FLAG_LOW_LATENCY) != 0) {
+            return true;
+        }
+        return false;
+    }
+
  protected:
     UsecaseLookup m_lookup;
 };
diff --git a/media/libaudiousecasevalidation/tests/UsecaseValidator-test.cpp b/media/libaudiousecasevalidation/tests/UsecaseValidator-test.cpp
index d92c8ba..5768a9b 100644
--- a/media/libaudiousecasevalidation/tests/UsecaseValidator-test.cpp
+++ b/media/libaudiousecasevalidation/tests/UsecaseValidator-test.cpp
@@ -52,10 +52,8 @@
  */
 error::Result<audio_attributes_t> UsecaseValidatorTest::testStartClient(audio_io_handle_t streamId,
         audio_port_handle_t portId,
-        audio_usage_t usage) {
+        audio_attributes_t attributes) {
     content::AttributionSourceState attributionSource;
-    audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
-    attributes.usage = usage;
 
     return m_validator->startClient(streamId, portId, attributionSource, attributes, NULL);
 }
@@ -141,11 +139,14 @@
     mediaPortId = testCreatePortId(mediaStreamId);
     EXPECT_NE(mediaPortId, 0);
 
+    audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+    attributes.usage = AUDIO_USAGE_GAME;
     // Start client on game stream.
-    testStartClient(gameStreamId, gamePortId, AUDIO_USAGE_GAME);
+    testStartClient(gameStreamId, gamePortId, attributes);
 
+    attributes.usage = AUDIO_USAGE_MEDIA;
     // Start client on media stream.
-    testStartClient(mediaStreamId, mediaPortId, AUDIO_USAGE_MEDIA);
+    testStartClient(mediaStreamId, mediaPortId, attributes);
 
     // Unregister media stream before stopClient.
     EXPECT_EQ(m_validator->unregisterStream(gameStreamId), 0);
@@ -175,18 +176,23 @@
     voiceCommPortId = testCreatePortId(gameStreamId);
     EXPECT_NE(voiceCommPortId, 0);
 
+    audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
     // Verify attributes on game stream.
-    auto attr = testStartClient(gameStreamId, gamePortId, AUDIO_USAGE_GAME);
+    attributes.usage = AUDIO_USAGE_GAME;
+    auto attr = testStartClient(gameStreamId, gamePortId, attributes);
     EXPECT_EQ(attr.value().usage, AUDIO_USAGE_GAME);
 
-    attr = testStartClient(gameStreamId, voiceCommPortId, AUDIO_USAGE_VOICE_COMMUNICATION);
+    attributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
+    attr = testStartClient(gameStreamId, voiceCommPortId, attributes);
     EXPECT_EQ(attr.value().usage, AUDIO_USAGE_VOICE_COMMUNICATION);
 
     // Verify attributes on media stream.
-    attr = testStartClient(mediaStreamId, mediaPortId, AUDIO_USAGE_MEDIA);
+    attributes.usage = AUDIO_USAGE_MEDIA;
+    attr = testStartClient(mediaStreamId, mediaPortId, attributes);
     EXPECT_EQ(attr.value().usage, AUDIO_USAGE_MEDIA);
 
-    attr = testStartClient(mediaStreamId, unknownPortId, AUDIO_USAGE_UNKNOWN);
+    attributes.usage = AUDIO_USAGE_UNKNOWN;
+    attr = testStartClient(mediaStreamId, unknownPortId, attributes);
     EXPECT_EQ(attr.value().usage, AUDIO_USAGE_UNKNOWN);
 
     // Stop client on game and media stream.
@@ -215,16 +221,79 @@
     unknownPortId = testCreatePortId(gameStreamId);
     EXPECT_NE(unknownPortId, 0);
 
+    audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+    attributes.flags = AUDIO_FLAG_LOW_LATENCY;
     // Verify attributes on game stream.
-    auto attr = testStartClient(gameStreamId, mediaPortId, AUDIO_USAGE_MEDIA);
+    attributes.usage = AUDIO_USAGE_MEDIA;
+    auto attr = testStartClient(gameStreamId, mediaPortId, attributes);
     EXPECT_EQ(attr.value().usage, AUDIO_USAGE_GAME);
 
-    attr = testStartClient(gameStreamId, unknownPortId, AUDIO_USAGE_UNKNOWN);
+    attributes.usage = AUDIO_USAGE_UNKNOWN;
+    attr = testStartClient(gameStreamId, unknownPortId, attributes);
     EXPECT_EQ(attr.value().usage, AUDIO_USAGE_GAME);
 
     // Unregister game stream.
     EXPECT_EQ(m_validator->unregisterStream(gameStreamId), 0);
 }
 
+/**
+ * Verify attributes usage does not change for non low latency clients.
+ */
+TEST_F(UsecaseValidatorTest, testAttributesUsageUnChangedIfNotLowLatency) {
+    audio_io_handle_t gameStreamId;
+    audio_port_handle_t mediaPortId, unknownPortId;
+
+    // Register game and media stream.
+    gameStreamId = testRegisterStream(true);
+    EXPECT_NE(gameStreamId, 0);
+
+    // Assign portId.
+    mediaPortId = testCreatePortId(gameStreamId);
+    EXPECT_NE(mediaPortId, 0);
+    unknownPortId = testCreatePortId(gameStreamId);
+    EXPECT_NE(unknownPortId, 0);
+
+    audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+    // Verify attributes on game stream.
+    attributes.usage = AUDIO_USAGE_MEDIA;
+    auto attr = testStartClient(gameStreamId, mediaPortId, attributes);
+    EXPECT_EQ(attr.value().usage, AUDIO_USAGE_MEDIA);
+
+    attributes.usage = AUDIO_USAGE_UNKNOWN;
+    attr = testStartClient(gameStreamId, unknownPortId, attributes);
+    EXPECT_EQ(attr.value().usage, AUDIO_USAGE_UNKNOWN);
+
+    // Unregister game stream.
+    EXPECT_EQ(m_validator->unregisterStream(gameStreamId), 0);
+}
+
+/**
+ * Verify attributes usage does not change for content type speech.
+ */
+TEST_F(UsecaseValidatorTest, testAttributesUsageUnChangedIfSpeech) {
+    audio_io_handle_t gameStreamId;
+    audio_port_handle_t mediaPortId, unknownPortId;
+
+    // Register game and media stream.
+    gameStreamId = testRegisterStream(true);
+    EXPECT_NE(gameStreamId, 0);
+
+    // Assign portId.
+    mediaPortId = testCreatePortId(gameStreamId);
+    EXPECT_NE(mediaPortId, 0);
+    unknownPortId = testCreatePortId(gameStreamId);
+    EXPECT_NE(unknownPortId, 0);
+
+    audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+    // Verify attributes on game stream.
+    attributes.usage = AUDIO_USAGE_MEDIA;
+    attributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
+    auto attr = testStartClient(gameStreamId, mediaPortId, attributes);
+    EXPECT_EQ(attr.value().usage, AUDIO_USAGE_MEDIA);
+
+    // Unregister game stream.
+    EXPECT_EQ(m_validator->unregisterStream(gameStreamId), 0);
+}
+
 }  // namespace media
 }  // namespace android
diff --git a/media/libaudiousecasevalidation/tests/UsecaseValidator-test.h b/media/libaudiousecasevalidation/tests/UsecaseValidator-test.h
index 3159ab4..8cbd0f0 100644
--- a/media/libaudiousecasevalidation/tests/UsecaseValidator-test.h
+++ b/media/libaudiousecasevalidation/tests/UsecaseValidator-test.h
@@ -69,7 +69,7 @@
     audio_port_handle_t testCreatePortId(audio_io_handle_t streamId);
     error::Result<audio_attributes_t> testStartClient(audio_io_handle_t streamId,
                                                       audio_port_handle_t portId,
-                                                      audio_usage_t usage);
+                                                      audio_attributes_t attributes);
     error::Result<audio_attributes_t> testVerifyAudioAttributes(audio_io_handle_t streamId,
                                                                 audio_usage_t usage);
 
diff --git a/media/libeffects/config/Android.bp b/media/libeffects/config/Android.bp
index b02dcb6..293a9c2 100644
--- a/media/libeffects/config/Android.bp
+++ b/media/libeffects/config/Android.bp
@@ -27,8 +27,21 @@
         "libcutils",
     ],
 
-    header_libs: ["libaudio_system_headers"],
-    export_header_lib_headers: ["libaudio_system_headers"],
+    header_libs: [
+        "libaudio_system_headers",
+        "liberror_headers",
+    ],
+
+    export_header_lib_headers: [
+        "libaudio_system_headers",
+        "liberror_headers",
+    ],
+
+    export_include_dirs: ["include"],
+}
+
+cc_library_headers {
+    name: "libeffectsconfig_headers",
 
     export_include_dirs: ["include"],
 }
diff --git a/media/libeffects/config/include/media/EffectsConfig.h b/media/libeffects/config/include/media/EffectsConfig.h
index 57d4dd7..a9730e5 100644
--- a/media/libeffects/config/include/media/EffectsConfig.h
+++ b/media/libeffects/config/include/media/EffectsConfig.h
@@ -22,8 +22,10 @@
  * @see audio_effects_conf_V2_0.xsd for documentation on each structure
  */
 
+#include <error/Result.h>
 #include <system/audio_effect.h>
 
+#include <cstddef>
 #include <map>
 #include <memory>
 #include <string>
@@ -75,6 +77,12 @@
     std::string address;
 };
 
+struct Processings {
+    std::vector<InputStream> preprocess;
+    std::vector<OutputStream> postprocess;
+    std::vector<DeviceEffects> deviceprocess;
+};
+
 /** Parsed configuration.
  * Intended to be a transient structure only used for deserialization.
  * Note: Everything is copied in the configuration from the xml dom.
@@ -82,19 +90,16 @@
  *       consider keeping a private handle on the xml dom and replace all strings by dom pointers.
  *       Or even better, use SAX parsing to avoid the allocations all together.
  */
-struct Config {
+struct Config : public Processings {
     float version;
     Libraries libraries;
     Effects effects;
-    std::vector<OutputStream> postprocess;
-    std::vector<InputStream> preprocess;
-    std::vector<DeviceEffects> deviceprocess;
 };
 
 /** Result of `parse(const char*)` */
 struct ParsingResult {
     /** Parsed config, nullptr if the xml lib could not load the file */
-    std::unique_ptr<Config> parsedConfig;
+    std::shared_ptr<const Config> parsedConfig;
     size_t nbSkippedElement; //< Number of skipped invalid library, effect or processing chain
     const std::string configPath; //< Path to the loaded configuration
 };
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
index 1696233..3096659 100644
--- a/media/libeffects/config/src/EffectsConfig.cpp
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -286,7 +286,7 @@
         return {nullptr, 0, std::move(path)};
     }
 
-    auto config = std::make_unique<Config>();
+    auto config = std::make_shared<Config>();
     size_t nbSkippedElements = 0;
     auto registerFailure = [&nbSkippedElements](bool result) {
         nbSkippedElements += result ? 0 : 1;
diff --git a/media/libeffects/factory/Android.bp b/media/libeffects/factory/Android.bp
index 22838a3..d94093e 100644
--- a/media/libeffects/factory/Android.bp
+++ b/media/libeffects/factory/Android.bp
@@ -39,6 +39,7 @@
     header_libs: [
         "libaudioeffects",
         "libeffects_headers",
+        "liberror_headers",
     ],
     export_header_lib_headers: ["libeffects_headers"],
 }
@@ -56,7 +57,6 @@
         "-Werror",
     ],
 
-
     shared_libs: [
         "libeffectsconfig",
         "libeffects",
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
index b3371a3..3bc889c 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -85,9 +85,7 @@
 static const std::string kEqualizerEffectName = "EqualizerBundle";
 static const Descriptor kEqualizerDesc = {
         .common = {.id = {.type = getEffectTypeUuidEqualizer(),
-                          .uuid = getEffectImplUuidEqualizerBundle(),
-                          .proxy = getEffectImplUuidEqualizerProxy()},
-
+                          .uuid = getEffectImplUuidEqualizerBundle()},
                    .flags = {.type = Flags::Type::INSERT,
                              .insert = Flags::Insert::FIRST,
                              .volume = Flags::Volume::CTRL},
@@ -102,8 +100,7 @@
 static const std::string kBassBoostEffectName = "Dynamic Bass Boost";
 static const Descriptor kBassBoostDesc = {
         .common = {.id = {.type = getEffectTypeUuidBassBoost(),
-                          .uuid = getEffectImplUuidBassBoostBundle(),
-                          .proxy = getEffectImplUuidBassBoostProxy()},
+                          .uuid = getEffectImplUuidBassBoostBundle()},
                    .flags = {.type = Flags::Type::INSERT,
                              .insert = Flags::Insert::FIRST,
                              .volume = Flags::Volume::CTRL,
@@ -121,8 +118,7 @@
 
 static const Descriptor kVirtualizerDesc = {
         .common = {.id = {.type = getEffectTypeUuidVirtualizer(),
-                          .uuid = getEffectImplUuidVirtualizerBundle(),
-                          .proxy = getEffectImplUuidVirtualizerProxy()},
+                          .uuid = getEffectImplUuidVirtualizerBundle()},
                    .flags = {.type = Flags::Type::INSERT,
                              .insert = Flags::Insert::LAST,
                              .volume = Flags::Volume::CTRL,
@@ -139,8 +135,7 @@
 static const std::string kVolumeEffectName = "Volume";
 static const Descriptor kVolumeDesc = {
         .common = {.id = {.type = getEffectTypeUuidVolume(),
-                          .uuid = getEffectImplUuidVolumeBundle(),
-                          .proxy = std::nullopt},
+                          .uuid = getEffectImplUuidVolumeBundle()},
                    .flags = {.type = Flags::Type::INSERT,
                              .insert = Flags::Insert::LAST,
                              .volume = Flags::Volume::CTRL},
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
index 9a8156e..e25f9b7 100644
--- a/media/libmediahelper/AudioParameter.cpp
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -32,6 +32,8 @@
 const char * const AudioParameter::keyFrameCount = AUDIO_PARAMETER_STREAM_FRAME_COUNT;
 const char * const AudioParameter::keyInputSource = AUDIO_PARAMETER_STREAM_INPUT_SOURCE;
 const char * const AudioParameter::keyScreenState = AUDIO_PARAMETER_KEY_SCREEN_STATE;
+const char * const AudioParameter::keyClosing = AUDIO_PARAMETER_KEY_CLOSING;
+const char * const AudioParameter::keyExiting = AUDIO_PARAMETER_KEY_EXITING;
 const char * const AudioParameter::keyBtNrec = AUDIO_PARAMETER_KEY_BT_NREC;
 const char * const AudioParameter::keyHwAvSync = AUDIO_PARAMETER_HW_AV_SYNC;
 const char * const AudioParameter::keyPresentationId = AUDIO_PARAMETER_STREAM_PRESENTATION_ID;
diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h
index 41aff7c..6c34a4f 100644
--- a/media/libmediahelper/include/media/AudioParameter.h
+++ b/media/libmediahelper/include/media/AudioParameter.h
@@ -49,6 +49,12 @@
     static const char * const keyInputSource;
     static const char * const keyScreenState;
 
+    // TODO(b/73175392) consider improvement to AIDL StreamOut interface.
+    // keyClosing: "true" when AudioOutputDescriptor is closing.  Used by A2DP HAL.
+    // keyExiting: "1" on AudioFlinger Thread preExit.  Used by remote_submix and A2DP HAL.
+    static const char * const keyClosing;
+    static const char * const keyExiting;
+
     //  keyBtNrec: BT SCO Noise Reduction + Echo Cancellation parameters
     //  keyHwAvSync: get HW synchronization source identifier from a device
     //  keyMonoOutput: Enable mono audio playback
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index ec6a00a..569a25f 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -79,7 +79,6 @@
     },
 }
 
-// this library gets wrapped into libstagefright as well as modules
 cc_library_static {
     name: "libstagefright_mpeg2extractor",
     apex_available: [
@@ -242,6 +241,7 @@
         "CodecErrorLog.cpp",
         "CryptoAsync.cpp",
         "FrameDecoder.cpp",
+        "HevcUtils.cpp",
         "InterfaceUtils.cpp",
         "JPEGSource.cpp",
         "MPEG2TSWriter.cpp",
@@ -255,6 +255,7 @@
         "MediaCodecSource.cpp",
         "MediaExtractor.cpp",
         "MediaExtractorFactory.cpp",
+        "MediaSource.cpp",
         "MediaSync.cpp",
         "MediaTrack.cpp",
         "MediaMuxer.cpp",
@@ -268,6 +269,7 @@
         "StagefrightMediaScanner.cpp",
         "SurfaceUtils.cpp",
         "ThrottledSource.cpp",
+        "Utils.cpp",
         "VideoFrameSchedulerBase.cpp",
         "VideoFrameScheduler.cpp",
     ],
@@ -326,11 +328,6 @@
         "libmedia_ndkformatpriv",
     ],
 
-    // to get Utils, MediaSource, HevcUtils
-    whole_static_libs: [
-        "libstagefright_mpeg2extractor",
-    ],
-
     header_libs:[
         "libmediadrm_headers",
         "libnativeloader-headers",
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 09c5d64..080c3d0 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -118,15 +118,6 @@
 static const char *kCodecCaptureRate = "android.media.mediacodec.capture-rate";
 static const char *kCodecOperatingRate = "android.media.mediacodec.operating-rate";
 static const char *kCodecPriority = "android.media.mediacodec.priority";
-static const char *kCodecConfigColorStandard = "android.media.mediacodec.config-color-standard";
-static const char *kCodecConfigColorRange = "android.media.mediacodec.config-color-range";
-static const char *kCodecConfigColorTransfer = "android.media.mediacodec.config-color-transfer";
-static const char *kCodecParsedColorStandard = "android.media.mediacodec.parsed-color-standard";
-static const char *kCodecParsedColorRange = "android.media.mediacodec.parsed-color-range";
-static const char *kCodecParsedColorTransfer = "android.media.mediacodec.parsed-color-transfer";
-static const char *kCodecHDRStaticInfo = "android.media.mediacodec.hdr-static-info";
-static const char *kCodecHDR10PlusInfo = "android.media.mediacodec.hdr10-plus-info";
-static const char *kCodecHDRFormat = "android.media.mediacodec.hdr-format";
 
 // Min/Max QP before shaping
 static const char *kCodecOriginalVideoQPIMin = "android.media.mediacodec.original-video-qp-i-min";
@@ -175,6 +166,29 @@
 static const char *kCodecVideoInputBytes = "android.media.mediacodec.video.input.bytes";
 static const char *kCodecVideoInputFrames = "android.media.mediacodec.video.input.frames";
 static const char *kCodecVideoEncodedDurationUs = "android.media.mediacodec.vencode.durationUs";
+// HDR metrics
+static const char *kCodecConfigColorStandard = "android.media.mediacodec.config-color-standard";
+static const char *kCodecConfigColorRange = "android.media.mediacodec.config-color-range";
+static const char *kCodecConfigColorTransfer = "android.media.mediacodec.config-color-transfer";
+static const char *kCodecParsedColorStandard = "android.media.mediacodec.parsed-color-standard";
+static const char *kCodecParsedColorRange = "android.media.mediacodec.parsed-color-range";
+static const char *kCodecParsedColorTransfer = "android.media.mediacodec.parsed-color-transfer";
+static const char *kCodecHDRStaticInfo = "android.media.mediacodec.hdr-static-info";
+static const char *kCodecHDR10PlusInfo = "android.media.mediacodec.hdr10-plus-info";
+static const char *kCodecHDRFormat = "android.media.mediacodec.hdr-format";
+// array/sync/async/block modes
+static const char *kCodecArrayMode = "android.media.mediacodec.array-mode";
+static const char *kCodecOperationMode = "android.media.mediacodec.operation-mode";
+static const char *kCodecOutputSurface = "android.media.mediacodec.output-surface";
+// max size configured by the app
+static const char *kCodecAppMaxInputSize = "android.media.mediacodec.app-max-input-size";
+// max size actually used
+static const char *kCodecUsedMaxInputSize = "android.media.mediacodec.used-max-input-size";
+// max size suggested by the codec
+static const char *kCodecCodecMaxInputSize = "android.media.mediacodec.codec-max-input-size";
+static const char *kCodecFlushCount = "android.media.mediacodec.flush-count";
+static const char *kCodecSetSurfaceCount = "android.media.mediacodec.set-surface-count";
+static const char *kCodecResolutionChangeCount = "android.media.mediacodec.resolution-change-count";
 
 // the kCodecRecent* fields appear only in getMetrics() results
 static const char *kCodecRecentLatencyMax = "android.media.mediacodec.recent.max";      /* in us */
@@ -935,7 +949,6 @@
       mWidth(0),
       mHeight(0),
       mRotationDegrees(0),
-      mHdrInfoFlags(0),
       mDequeueInputTimeoutGeneration(0),
       mDequeueInputReplyID(0),
       mDequeueOutputTimeoutGeneration(0),
@@ -1043,6 +1056,14 @@
     }
 
     mLifetimeStartNs = systemTime(SYSTEM_TIME_MONOTONIC);
+    resetMetricsFields();
+}
+
+void MediaCodec::resetMetricsFields() {
+    mHdrInfoFlags = 0;
+
+    mApiUsageMetrics = ApiUsageMetrics();
+    mReliabilityContextMetrics = ReliabilityContextMetrics();
 }
 
 void MediaCodec::updateMediametrics() {
@@ -1053,6 +1074,28 @@
 
     Mutex::Autolock _lock(mMetricsLock);
 
+    mediametrics_setInt32(mMetricsHandle, kCodecArrayMode, mApiUsageMetrics.isArrayMode ? 1 : 0);
+    mApiUsageMetrics.operationMode = (mFlags & kFlagIsAsync) ?
+            ((mFlags & kFlagUseBlockModel) ? ApiUsageMetrics::kBlockMode
+                    : ApiUsageMetrics::kAsynchronousMode)
+            : ApiUsageMetrics::kSynchronousMode;
+    mediametrics_setInt32(mMetricsHandle, kCodecOperationMode, mApiUsageMetrics.operationMode);
+    mediametrics_setInt32(mMetricsHandle, kCodecOutputSurface,
+            mApiUsageMetrics.isUsingOutputSurface ? 1 : 0);
+
+    mediametrics_setInt32(mMetricsHandle, kCodecAppMaxInputSize,
+            mApiUsageMetrics.inputBufferSize.appMax);
+    mediametrics_setInt32(mMetricsHandle, kCodecUsedMaxInputSize,
+            mApiUsageMetrics.inputBufferSize.usedMax);
+    mediametrics_setInt32(mMetricsHandle, kCodecCodecMaxInputSize,
+            mApiUsageMetrics.inputBufferSize.codecMax);
+
+    mediametrics_setInt32(mMetricsHandle, kCodecFlushCount, mReliabilityContextMetrics.flushCount);
+    mediametrics_setInt32(mMetricsHandle, kCodecSetSurfaceCount,
+            mReliabilityContextMetrics.setOutputSurfaceCount);
+    mediametrics_setInt32(mMetricsHandle, kCodecResolutionChangeCount,
+            mReliabilityContextMetrics.resolutionChangeCount);
+
     if (mLatencyHist.getCount() != 0 ) {
         mediametrics_setInt64(mMetricsHandle, kCodecLatencyMax, mLatencyHist.getMax());
         mediametrics_setInt64(mMetricsHandle, kCodecLatencyMin, mLatencyHist.getMin());
@@ -1295,7 +1338,7 @@
 
     // update does its own mutex locking
     updateMediametrics();
-    mHdrInfoFlags = 0;
+    resetMetricsFields();
 
     // ensure mutex while we do our own work
     Mutex::Autolock _lock(mMetricsLock);
@@ -1967,6 +2010,10 @@
             if (format->findInt32("color-format", &colorFormat)) {
                 mediametrics_setInt32(nextMetricsHandle, kCodecColorFormat, colorFormat);
             }
+            int32_t appMaxInputSize = -1;
+            if (format->findInt32(KEY_MAX_INPUT_SIZE, &appMaxInputSize)) {
+                mApiUsageMetrics.inputBufferSize.appMax = appMaxInputSize;
+            }
             if (mDomain == DOMAIN_VIDEO) {
                 float frameRate = -1.0;
                 if (format->findFloat("frame-rate", &frameRate)) {
@@ -3768,6 +3815,10 @@
                             mediametrics_setInt32(mMetricsHandle, kCodecLevel, level);
                         }
                         updateHdrMetrics(true /* isConfig */);
+                        int32_t codecMaxInputSize = -1;
+                        if (mInputFormat->findInt32(KEY_MAX_INPUT_SIZE, &codecMaxInputSize)) {
+                            mApiUsageMetrics.inputBufferSize.codecMax = codecMaxInputSize;
+                        }
                         // bitrate and bitrate mode, encoder only
                         if (mFlags & kFlagIsEncoder) {
                             // encoder specific values
@@ -4168,6 +4219,7 @@
                         setState(STARTED);
                         mCodec->signalResume();
                     }
+                    mReliabilityContextMetrics.flushCount++;
 
                     postPendingRepliesAndDeferredMessages("kWhatFlushCompleted");
                     break;
@@ -4328,6 +4380,8 @@
                 handleSetSurface(NULL);
             }
 
+            mApiUsageMetrics.isUsingOutputSurface = true;
+
             uint32_t flags;
             CHECK(msg->findInt32("flags", (int32_t *)&flags));
             if (flags & CONFIGURE_FLAG_USE_BLOCK_MODEL ||
@@ -4468,6 +4522,7 @@
                                 (void)disconnectFromSurface();
                                 mSurface = surface;
                             }
+                            mReliabilityContextMetrics.setOutputSurfaceCount++;
                         }
                     }
                     break;
@@ -5005,6 +5060,8 @@
                 }
             }
 
+            mApiUsageMetrics.isArrayMode = true;
+
             (new AMessage)->postReply(replyID);
             break;
         }
@@ -5273,6 +5330,7 @@
         ClientConfigParcel clientConfig;
         initClientConfigParcel(clientConfig);
         mResourceManagerProxy->notifyClientConfigChanged(clientConfig);
+        mReliabilityContextMetrics.resolutionChangeCount++;
     }
 
     updateHdrMetrics(false /* isConfig */);
@@ -5708,6 +5766,10 @@
     if (err != OK) {
         return -EINVAL;
     }
+
+    int32_t usedMaxInputSize = mApiUsageMetrics.inputBufferSize.usedMax;
+    mApiUsageMetrics.inputBufferSize.usedMax = size > usedMaxInputSize ? size : usedMaxInputSize;
+
     if (hasCryptoOrDescrambler() && !c2Buffer && !memory) {
         AString *errorDetailMsg;
         CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index 9d2568e..f91a8b2 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -733,32 +733,36 @@
     const bool is10Bit = (mSrcFormat == COLOR_FormatYUVP010
             || mSrcFormat == OMX_COLOR_FormatYUV420Planar16);
 
-    switch (mSrcColorSpace.mStandard) {
-    case ColorUtils::kColorStandardBT601_525:
-    case ColorUtils::kColorStandardBT601_625:
+    ColorAspects::Primaries primaries;
+    ColorAspects::MatrixCoeffs matrix;
+    if (ColorUtils::unwrapColorAspectsFromColorStandard(
+            mSrcColorSpace.mStandard, &primaries, &matrix) != OK) {
+        matrix = ColorAspects::MatrixUnspecified;
+    }
+
+    switch (matrix) {
+    case ColorAspects::MatrixBT601_6:
+    case ColorAspects::MatrixBT470_6M:   // use 601 matrix as that is the closest for now
+    case ColorAspects::MatrixSMPTE240M:  // use 601 matrix as that is the closest for now
         return (isFullRange ? &BT601_FULL :
                 is10Bit ? &BT601_LTD_10BIT : &BT601_LIMITED);
 
-    case ColorUtils::kColorStandardBT709:
+    case ColorAspects::MatrixBT709_5:
         return (isFullRange ? &BT709_FULL :
                 is10Bit ? &BT709_LTD_10BIT : &BT709_LIMITED);
 
-    case ColorUtils::kColorStandardBT2020:
+    case ColorAspects::MatrixBT2020:
+    case ColorAspects::MatrixBT2020Constant: // use 2020 matrix as that is the closest for now
         return (isFullRange ? &BT2020_FULL :
                 is10Bit ? &BT2020_LTD_10BIT : &BT2020_LIMITED);
 
     default:
-        // for now use the default matrices for unhandled color spaces
-        // TODO: fail?
-        // return nullptr;
-        [[fallthrough]];
-
-    case ColorUtils::kColorStandardUnspecified:
-        if (isFullRange) {
-            return is10Bit ? &BT2020_FULL : &BT601_FULL;
+        // use BT.2020 for 10-bit and 601 for 8-bit by default
+        if (is10Bit) {
+            return isFullRange ? &BT2020_FULL : &BT2020_LTD_10BIT;
+        } else {
+            return isFullRange ? &BT601_FULL : &BT601_LIMITED;
         }
-        return is10Bit ? &BT2020_LTD_10BIT : &BT601_LIMITED;
-
     }
 }
 
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 1cc281b..3d4b6f8 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -453,6 +453,7 @@
     void initMediametrics();
     void updateMediametrics();
     void flushMediametrics();
+    void resetMetricsFields();
     void updateEphemeralMediametrics(mediametrics_handle_t item);
     void updateLowLatency(const sp<AMessage> &msg);
     void onGetMetrics(const sp<AMessage>& msg);
@@ -492,6 +493,28 @@
             const int32_t colorTransfer);
     bool profileSupport10Bits(const AString &mime, const int32_t profile);
 
+    struct ApiUsageMetrics {
+        bool isArrayMode;
+        enum OperationMode {
+            kUnknownMode = 0,
+            kSynchronousMode = 1,
+            kAsynchronousMode = 2,
+            kBlockMode = 3,
+        };
+        OperationMode operationMode;
+        bool isUsingOutputSurface;
+        struct InputBufferSize {
+            int32_t appMax;  // max size configured by the app
+            int32_t usedMax;  // max size actually used
+            int32_t codecMax;  // max size suggested by the codec
+        } inputBufferSize;
+    } mApiUsageMetrics;
+    struct ReliabilityContextMetrics {
+        int32_t flushCount;
+        int32_t setOutputSurfaceCount;
+        int32_t resolutionChangeCount;
+    } mReliabilityContextMetrics;
+
     // initial create parameters
     AString mInitName;
 
diff --git a/media/module/foundation/ColorUtils.cpp b/media/module/foundation/ColorUtils.cpp
index 6dc8157..12bffca 100644
--- a/media/module/foundation/ColorUtils.cpp
+++ b/media/module/foundation/ColorUtils.cpp
@@ -60,6 +60,10 @@
         { CU::kColorStandardBT470M,         { CA::PrimariesBT470_6M, CA::MatrixBT470_6M } },
         // NOTE: there is no close match to the matrix used by standard film, chose closest
         { CU::kColorStandardFilm,           { CA::PrimariesGenericFilm, CA::MatrixBT2020 } },
+        // DCI-P3 (in DataSpace that drives this standard) is actually Display P3
+        // ITU does not specify a matrix suitable for P3. The theoretical KR/KB numbers are
+        // 0.229 and 0.079. Assume BT.601 matrix as P3 is commonly used for JPEG with BT.601.
+        { CU::kColorStandardDisplay_P3,     { CA::PrimariesEG432, CA::MatrixBT601_6 } },
     }
 };
 
@@ -264,6 +268,8 @@
         { 8, ColorAspects::PrimariesGenericFilm },
         { 9, ColorAspects::PrimariesBT2020 },
         { 10, ColorAspects::PrimariesOther /* XYZ */ },
+        { 11, ColorAspects::PrimariesRP431 },
+        { 12, ColorAspects::PrimariesEG432 },
     }
 };
 
@@ -438,6 +444,9 @@
         { CU::kColorStandardBT2020,               CA::PrimariesBT2020 },
         { CU::kColorStandardBT601_525_Unadjusted, CA::PrimariesBT601_6_525 },
         { CU::kColorStandardBT601_625_Unadjusted, CA::PrimariesBT601_6_625 },
+        { CU::kColorStandardDisplay_P3,           CA::PrimariesEG432 },
+        // fall back DCI P3 primaries to Display P3
+        { CU::kColorStandardDisplay_P3,           CA::PrimariesRP431 },
     }
 };
 
@@ -469,7 +478,8 @@
         { CU::kColorStandardBT2020Constant,       GET_HAL_BITFIELD(STANDARD, BT2020_CONSTANT_LUMINANCE) },
         { CU::kColorStandardBT470M,               GET_HAL_BITFIELD(STANDARD, BT470M) },
         { CU::kColorStandardFilm,                 GET_HAL_BITFIELD(STANDARD, FILM) },
-        { CU::kColorStandardDCI_P3,               GET_HAL_BITFIELD(STANDARD, DCI_P3) },
+        // DCI-P3 (in DataSpace that drives this standard) is actually Display P3
+        { CU::kColorStandardDisplay_P3,           GET_HAL_BITFIELD(STANDARD, DCI_P3) },
     }
 };
 
diff --git a/media/module/foundation/include/media/stagefright/foundation/ColorUtils.h b/media/module/foundation/include/media/stagefright/foundation/ColorUtils.h
index 72c8074..f4e89bb 100644
--- a/media/module/foundation/include/media/stagefright/foundation/ColorUtils.h
+++ b/media/module/foundation/include/media/stagefright/foundation/ColorUtils.h
@@ -57,7 +57,8 @@
         kColorStandardBT2020Constant =       7, // not in SDK
         kColorStandardBT470M =               8, // not in SDK
         kColorStandardFilm =                 9, // not in SDK
-        kColorStandardDCI_P3 =               10, // not in SDK, new in Android 8.0
+        kColorStandardDisplay_P3 =           10, // not in SDK, new in Android 8.0
+        kColorStandardDCI_P3 = kColorStandardDisplay_P3, // legacy (incorrect) name for Display P3
 
         /* This marks a section of color-standard values that are not supported by graphics HAL,
            but track defined color primaries-matrix coefficient combinations in media.
@@ -211,7 +212,7 @@
         case ColorUtils::kColorStandardBT2020Constant:       return "BT2020Constant";
         case ColorUtils::kColorStandardBT470M:               return "BT470M";
         case ColorUtils::kColorStandardFilm:                 return "Film";
-        case ColorUtils::kColorStandardDCI_P3:               return "DCI_P3";
+        case ColorUtils::kColorStandardDisplay_P3:           return "Display_P3";
         default:                                             return def;
     }
 }
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 3c0f8f3..f69307b 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -485,14 +485,17 @@
     return mAAudioHwBurstMinMicros;
 }
 
-status_t AudioFlinger::setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) {
+status_t AudioFlinger::setDeviceConnectedState(const struct audio_port_v7 *port,
+                                               media::DeviceConnectedState state) {
     status_t final_result = NO_INIT;
     Mutex::Autolock _l(mLock);
     AutoMutex lock(mHardwareLock);
     mHardwareStatus = AUDIO_HW_SET_CONNECTED_STATE;
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
         sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
-        status_t result = dev->setConnectedState(port, connected);
+        status_t result = state == media::DeviceConnectedState::PREPARE_TO_DISCONNECT
+                ? dev->prepareToDisconnectExternalDevice(port)
+                : dev->setConnectedState(port, state == media::DeviceConnectedState::CONNECTED);
         // Same logic as with setParameter: it's a success if at least one
         // HAL module accepts the update.
         if (final_result != NO_ERROR) {
@@ -1236,21 +1239,20 @@
         output.portId = portId;
 
         if (lStatus == NO_ERROR) {
+            // no risk of deadlock because AudioFlinger::mLock is held
+            Mutex::Autolock _dl(thread->mLock);
             // Connect secondary outputs. Failure on a secondary output must not imped the primary
             // Any secondary output setup failure will lead to a desync between the AP and AF until
             // the track is destroyed.
             updateSecondaryOutputsForTrack_l(track.get(), thread, secondaryOutputs);
-        }
-
-        // move effect chain to this output thread if an effect on same session was waiting
-        // for a track to be created
-        if (lStatus == NO_ERROR && effectThread != NULL) {
-            // no risk of deadlock because AudioFlinger::mLock is held
-            Mutex::Autolock _dl(thread->mLock);
-            Mutex::Autolock _sl(effectThread->mLock);
-            if (moveEffectChain_l(sessionId, effectThread, thread) == NO_ERROR) {
-                effectThreadId = thread->id();
-                effectIds = thread->getEffectIds_l(sessionId);
+            // move effect chain to this output thread if an effect on same session was waiting
+            // for a track to be created
+            if (effectThread != nullptr) {
+                Mutex::Autolock _sl(effectThread->mLock);
+                if (moveEffectChain_l(sessionId, effectThread, thread) == NO_ERROR) {
+                    effectThreadId = thread->id();
+                    effectIds = thread->getEffectIds_l(sessionId);
+                }
             }
         }
 
@@ -1861,6 +1863,8 @@
         String8(AudioParameter::keyStreamSupportedFormats),
         String8(AudioParameter::keyStreamSupportedChannels),
         String8(AudioParameter::keyStreamSupportedSamplingRates),
+        String8(AudioParameter::keyClosing),
+        String8(AudioParameter::keyExiting),
     };
 
     if (isAudioServerUid(callingUid)) {
@@ -3950,7 +3954,7 @@
         patchTrack->setPeerProxy(patchRecord, true /* holdReference */);
         patchRecord->setPeerProxy(patchTrack, false /* holdReference */);
     }
-    track->setTeePatches(std::move(teePatches));
+    track->setTeePatchesToUpdate(std::move(teePatches));
 }
 
 sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 323ce0e..47fa74f 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -297,7 +297,8 @@
 
     virtual int32_t getAAudioHardwareBurstMinUsec();
 
-    virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected);
+    virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port,
+                                             media::DeviceConnectedState state);
 
     virtual status_t setSimulateDeviceConnections(bool enabled);
 
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 19e4151..f324408 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -3407,12 +3407,20 @@
     } else if (patch.isSoftware() || patch.thread().promote() != nullptr) {
         sp <ThreadBase> thread;
         if (audio_port_config_has_input_direction(port)) {
+            if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
+                ALOGI("%s don't create postprocessing effect on record thread", __func__);
+                return NAME_NOT_FOUND;
+            }
             if (patch.isSoftware()) {
                 thread = patch.mRecord.thread();
             } else {
                 thread = patch.thread().promote();
             }
         } else {
+            if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC) {
+                ALOGI("%s don't create preprocessing effect on playback thread", __func__);
+                return NAME_NOT_FOUND;
+            }
             if (patch.isSoftware()) {
                 thread = patch.mPlayback.thread();
             } else {
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index 496aedc..39f772b 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -81,7 +81,7 @@
 }
 
 bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
-    if (mSoundDoseManager->isCsdDisabled()) {
+    if (!mSoundDoseManager->isCsdEnabled()) {
         ALOGV("%s csd is disabled", __func__);
         return false;
     }
@@ -95,7 +95,6 @@
         // TODO(b/278265907): enable A2DP when we can distinguish A2DP headsets
         // case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
-        case AUDIO_DEVICE_OUT_HEARING_AID:
         case AUDIO_DEVICE_OUT_USB_HEADSET:
         case AUDIO_DEVICE_OUT_BLE_HEADSET:
         case AUDIO_DEVICE_OUT_BLE_BROADCAST:
@@ -107,7 +106,7 @@
 
 void AudioFlinger::MelReporter::updateMetadataForCsd(audio_io_handle_t streamHandle,
         const std::vector<playback_track_metadata_v7_t>& metadataVec) {
-    if (mSoundDoseManager->isCsdDisabled()) {
+    if (!mSoundDoseManager->isCsdEnabled()) {
         ALOGV("%s csd is disabled", __func__);
         return;
     }
@@ -143,14 +142,10 @@
 
 void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
         const PatchPanel::Patch& patch) {
-    if (mSoundDoseManager->isCsdDisabled()) {
+    if (!mSoundDoseManager->isCsdEnabled()) {
         ALOGV("%s csd is disabled", __func__);
         return;
     }
-    if (useHalSoundDoseInterface()) {
-        ALOGV("%s using HAL sound dose, ignore new patch", __func__);
-        return;
-    }
 
     ALOGV("%s: handle %d mHalHandle %d device sink %08x",
             __func__, handle, patch.mHalHandle,
@@ -199,7 +194,7 @@
         ALOGI("%s add stream %d that uses device %d for CSD, nr of streams: %d", __func__,
               patch.streamHandle, deviceHandle, mActiveDevices[deviceHandle]);
 
-        if (outputThread != nullptr) {
+        if (outputThread != nullptr && !useHalSoundDoseInterface_l()) {
             outputThread->startMelComputation_l(mSoundDoseManager->getOrCreateProcessorForDevice(
                 deviceHandle,
                 patch.streamHandle,
@@ -211,7 +206,7 @@
 }
 
 void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
-    if (mSoundDoseManager->isCsdDisabled()) {
+    if (!mSoundDoseManager->isCsdEnabled()) {
         ALOGV("%s csd is disabled", __func__);
         return;
     }
@@ -271,7 +266,7 @@
         }
     }
 
-    if (outputThread != nullptr) {
+    if (outputThread != nullptr && !useHalSoundDoseInterface_l()) {
         outputThread->stopMelComputation_l();
     }
 }
@@ -287,13 +282,8 @@
     return std::nullopt;
 }
 
-bool AudioFlinger::MelReporter::useHalSoundDoseInterface() {
-    bool useHalSoundDoseInterface = !mSoundDoseManager->forceUseFrameworkMel();
-    {
-        std::lock_guard _l(mLock);
-        useHalSoundDoseInterface &= mUseHalSoundDoseInterface;
-    }
-    return useHalSoundDoseInterface;
+bool AudioFlinger::MelReporter::useHalSoundDoseInterface_l() {
+    return !mSoundDoseManager->forceUseFrameworkMel() & mUseHalSoundDoseInterface;
 }
 
 std::string AudioFlinger::MelReporter::dump() {
diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h
index 81a307a..2bc33f2 100644
--- a/services/audioflinger/MelReporter.h
+++ b/services/audioflinger/MelReporter.h
@@ -98,7 +98,7 @@
     std::optional<audio_patch_handle_t>
     activePatchStreamHandle_l(audio_io_handle_t streamHandle) REQUIRES(mLock);
 
-    bool useHalSoundDoseInterface();
+    bool useHalSoundDoseInterface_l() REQUIRES(mLock);
 
     AudioFlinger& mAudioFlinger;  // does not own the object
 
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index ad191b0..0e1a3c9 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -186,7 +186,9 @@
             }
             sp<os::ExternalVibration> getExternalVibration() const { return mExternalVibration; }
 
-            void    setTeePatches(TeePatches teePatches);
+            // This function should be called with holding thread lock.
+            void    updateTeePatches();
+            void    setTeePatchesToUpdate(TeePatches teePatchesToUpdate);
 
     void tallyUnderrunFrames(size_t frames) override {
        if (isOut()) { // we expect this from output tracks only
@@ -369,6 +371,7 @@
     bool                mPauseHwPending = false; // direct/offload track request for thread pause
     audio_output_flags_t mFlags;
     TeePatches  mTeePatches;
+    std::optional<TeePatches> mTeePatchesToUpdate;
     const float         mSpeed;
     const bool          mIsSpatialized;
     const bool          mIsBitPerfect;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 2d33d3c..8d0c648 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4104,6 +4104,10 @@
 
             setHalLatencyMode_l();
 
+            for (const auto &track : mActiveTracks ) {
+                track->updateTeePatches();
+            }
+
             // signal actual start of output stream when the render position reported by the kernel
             // starts moving.
             if (!mStandby && !mHalStarted && mKernelPositionOnStandby !=
@@ -6243,12 +6247,12 @@
     if (status == NO_ERROR) {
         status = mOutput->stream->setParameters(keyValuePair);
         if (!mStandby && status == INVALID_OPERATION) {
+            ALOGW("%s: setParameters failed with keyValuePair %s, entering standby",
+                    __func__, keyValuePair.c_str());
             mOutput->standby();
-            if (!mStandby) {
-                mThreadMetrics.logEndInterval();
-                mThreadSnapshot.onEnd();
-                setStandby_l();
-            }
+            mThreadMetrics.logEndInterval();
+            mThreadSnapshot.onEnd();
+            setStandby_l();
             mBytesWritten = 0;
             status = mOutput->stream->setParameters(keyValuePair);
         }
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 6b5ddce..7d2c4db 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1491,15 +1491,24 @@
     *backInserter++ = metadata;
 }
 
-void AudioFlinger::PlaybackThread::Track::setTeePatches(TeePatches teePatches) {
-    forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
-    mTeePatches = std::move(teePatches);
-    if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
-            mState == TrackBase::STOPPING_1) {
-        forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
+void AudioFlinger::PlaybackThread::Track::updateTeePatches() {
+    if (mTeePatchesToUpdate.has_value()) {
+        forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
+        mTeePatches = mTeePatchesToUpdate.value();
+        if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
+                mState == TrackBase::STOPPING_1) {
+            forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
+        }
+        mTeePatchesToUpdate.reset();
     }
 }
 
+void AudioFlinger::PlaybackThread::Track::setTeePatchesToUpdate(TeePatches teePatchesToUpdate) {
+    ALOGW_IF(mTeePatchesToUpdate.has_value(),
+             "%s, existing tee patches to update will be ignored", __func__);
+    mTeePatchesToUpdate = std::move(teePatchesToUpdate);
+}
+
 // must be called with player thread lock held
 void AudioFlinger::PlaybackThread::Track::processMuteEvent_l(const sp<
     IAudioManager>& audioManager, mute_state_t muteState)
diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index 827f7d4..a114a38 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -50,7 +50,7 @@
         size_t channelCount, audio_format_t format) {
     std::lock_guard _l(mLock);
 
-    if (mHalSoundDose != nullptr && !mDisableCsd) {
+    if (mHalSoundDose != nullptr && mEnabledCsd) {
         ALOGD("%s: using HAL MEL computation, no MelProcessor needed.", __func__);
         return nullptr;
     }
@@ -216,7 +216,7 @@
     if (id == AUDIO_PORT_HANDLE_NONE) {
         ALOGI("%s: no mapped id for audio device with type %d and address %s",
                 __func__, in_audioDevice.type.type,
-                in_audioDevice.address.get<AudioDeviceAddress::id>().c_str());
+                in_audioDevice.address.toString().c_str());
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     soundDoseManager->onMomentaryExposure(in_currentDbA, id);
@@ -243,7 +243,7 @@
     if (id == AUDIO_PORT_HANDLE_NONE) {
         ALOGI("%s: no mapped id for audio device with type %d and address %s",
                 __func__, in_audioDevice.type.type,
-                in_audioDevice.address.get<AudioDeviceAddress::id>().c_str());
+                in_audioDevice.address.toString().c_str());
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     // TODO: introduce timestamp in onNewMelValues callback
@@ -290,11 +290,11 @@
     return binder::Status::ok();
 }
 
-binder::Status SoundDoseManager::SoundDose::disableCsd() {
+binder::Status SoundDoseManager::SoundDose::setCsdEnabled(bool enabled) {
     ALOGV("%s", __func__);
     auto soundDoseManager = mSoundDoseManager.promote();
     if (soundDoseManager != nullptr) {
-        soundDoseManager->disableCsd();
+        soundDoseManager->setCsdEnabled(enabled);
     }
     return binder::Status::ok();
 }
@@ -365,26 +365,27 @@
     }
 }
 
-void SoundDoseManager::disableCsd() {
+void SoundDoseManager::setCsdEnabled(bool enabled) {
     ALOGV("%s",  __func__);
 
     std::lock_guard _l(mLock);
-    mDisableCsd = true;
+    mEnabledCsd = enabled;
 
-    // Normally, there should be no active MelProcessors when this method is called
-    // We pause however every cached MelProcessor as a defensive mechanism to not
-    // have unnecessary processing
     for (auto& activeEntry : mActiveProcessors) {
         auto melProcessor = activeEntry.second.promote();
         if (melProcessor != nullptr) {
-            melProcessor->pause();
+            if (enabled) {
+                melProcessor->resume();
+            } else {
+                melProcessor->pause();
+            }
         }
     }
 }
 
-bool SoundDoseManager::isCsdDisabled() {
+bool SoundDoseManager::isCsdEnabled() {
     std::lock_guard _l(mLock);
-    return mDisableCsd;
+    return mEnabledCsd;
 }
 
 void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) {
@@ -411,7 +412,7 @@
 }
 
 bool SoundDoseManager::isSoundDoseHalSupported() const {
-    if (mDisableCsd) {
+    if (!mEnabledCsd) {
         return false;
     }
 
@@ -455,7 +456,7 @@
     float currentCsd;
     {
         std::lock_guard _l(mLock);
-        if (mDisableCsd) {
+        if (!mEnabledCsd) {
             return;
         }
 
@@ -496,7 +497,7 @@
 
     {
         std::lock_guard _l(mLock);
-        if (mDisableCsd) {
+        if (!mEnabledCsd) {
             return;
         }
     }
@@ -522,7 +523,7 @@
     std::string output;
     {
         std::lock_guard _l(mLock);
-        if (mDisableCsd) {
+        if (!mEnabledCsd) {
             base::StringAppendF(&output, "CSD is disabled");
             return output;
         }
diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h
index 5081ce4..6c02afb 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.h
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -101,8 +101,8 @@
     /** Clear all map entries with passed audio_port_handle_t. */
     void clearMapDeviceIdEntries(audio_port_handle_t deviceId);
 
-    /** Returns true if CSD is disabled. */
-    bool isCsdDisabled();
+    /** Returns true if CSD is enabled. */
+    bool isCsdEnabled();
 
     std::string dump() const;
 
@@ -137,7 +137,7 @@
                                 const std::vector<media::SoundDoseRecord>& records) override;
         binder::Status updateAttenuation(float attenuationDB, int device) override;
         binder::Status getOutputRs2UpperBound(float* value) override;
-        binder::Status disableCsd() override;
+        binder::Status setCsdEnabled(bool enabled) override;
 
         binder::Status getCsd(float* value) override;
         binder::Status forceUseFrameworkMel(bool useFrameworkMel) override;
@@ -170,7 +170,7 @@
     sp<media::ISoundDoseCallback> getSoundDoseCallback() const;
 
     void updateAttenuation(float attenuationDB, audio_devices_t deviceType);
-    void disableCsd();
+    void setCsdEnabled(bool enabled);
     void setUseFrameworkMel(bool useFrameworkMel);
     void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices);
     bool isSoundDoseHalSupported() const;
@@ -202,7 +202,7 @@
     bool mUseFrameworkMel GUARDED_BY(mLock) = true;
     bool mComputeCsdOnAllDevices GUARDED_BY(mLock) = false;
 
-    bool mDisableCsd GUARDED_BY(mLock) = false;
+    bool mEnabledCsd GUARDED_BY(mLock) = true;
 };
 
 }  // namespace android
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 3d1cf76..134d068 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_AUDIOPOLICY_INTERFACE_H
 #define ANDROID_AUDIOPOLICY_INTERFACE_H
 
+#include <android/media/DeviceConnectedState.h>
 #include <media/AudioCommonTypes.h>
 #include <media/AudioContainers.h>
 #include <media/AudioDeviceTypeAddr.h>
@@ -567,7 +568,8 @@
     virtual status_t updateSecondaryOutputs(
             const TrackSecondaryOutputsMap& trackSecondaryOutputs) = 0;
 
-    virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) = 0;
+    virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port,
+                                             media::DeviceConnectedState state) = 0;
 
     virtual status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) = 0;
 };
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index 92a5628..1d570b7 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -15,6 +15,7 @@
         "src/AudioInputDescriptor.cpp",
         "src/AudioOutputDescriptor.cpp",
         "src/AudioPatch.cpp",
+        "src/AudioPolicyConfig.cpp",
         "src/AudioPolicyMix.cpp",
         "src/AudioProfileVectorHelper.cpp",
         "src/AudioRoute.cpp",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index a62d3f0..b24fce8 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -16,62 +16,56 @@
 
 #pragma once
 
+#include <string>
 #include <unordered_map>
 #include <unordered_set>
+#include <vector>
 
-#include <AudioPatch.h>
 #include <DeviceDescriptor.h>
-#include <IOProfile.h>
 #include <HwModule.h>
-#include <PolicyAudioPort.h>
-#include <AudioInputDescriptor.h>
-#include <AudioOutputDescriptor.h>
-#include <AudioPolicyMix.h>
-#include <EffectDescriptor.h>
-#include <SoundTriggerSession.h>
-#include <media/AudioProfile.h>
+#include <error/Result.h>
+#include <utils/StrongPointer.h>
+#include <utils/RefBase.h>
 
 namespace android {
 
-// This class gathers together various bits of AudioPolicyManager
-// configuration, which are usually filled out as a result of parsing
-// the audio_policy_configuration.xml file.
+// This class gathers together various bits of AudioPolicyManager configuration. It can be filled
+// out either as a result of parsing the audio_policy_configuration.xml file, from the HAL data, or
+// to default fallback data.
 //
-// Note that AudioPolicyConfig doesn't own some of the data,
-// it simply proxies access to the fields of AudioPolicyManager
-// class. Be careful about the fields that are references,
-// e.g. 'mOutputDevices'. This also means that it's impossible
-// to implement "deep copying" of this class without re-designing it.
-class AudioPolicyConfig
+// The data in this class is immutable once loaded, this is why a pointer to a const is returned
+// from the factory methods. However, this does not prevent modifications of data bits that
+// are held inside collections, for example, individual modules, devices, etc.
+class AudioPolicyConfig : public RefBase
 {
 public:
-    AudioPolicyConfig(HwModuleCollection &hwModules,
-                      DeviceVector &outputDevices,
-                      DeviceVector &inputDevices,
-                      sp<DeviceDescriptor> &defaultOutputDevice)
-        : mHwModules(hwModules),
-          mOutputDevices(outputDevices),
-          mInputDevices(inputDevices),
-          mDefaultOutputDevice(defaultOutputDevice) {
-        clear();
-    }
+    // Surround formats, with an optional list of subformats that are equivalent from users' POV.
+    using SurroundFormats = std::unordered_map<audio_format_t, std::unordered_set<audio_format_t>>;
 
-    void clear() {
-        mSource = {};
-        mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
-        mHwModules.clear();
-        mOutputDevices.clear();
-        mInputDevices.clear();
-        mDefaultOutputDevice.clear();
-        mIsSpeakerDrcEnabled = false;
-        mIsCallScreenModeSupported = false;
-        mSurroundFormats.clear();
-    }
+    // The source used to indicate the default fallback configuration.
+    static const constexpr char* const kDefaultConfigSource = "AudioPolicyConfig::setDefault";
+
+    // Creates the default (fallback) configuration.
+    static sp<const AudioPolicyConfig> createDefault();
+    // Attempts to load the configuration from the XML file, falls back to default on failure.
+    // If the XML file path is not provided, uses `audio_get_audio_policy_config_file` function.
+    static sp<const AudioPolicyConfig> loadFromApmXmlConfigWithFallback(
+            const std::string& xmlFilePath = "");
+    // The factory method to use in APM tests which craft the configuration manually.
+    static sp<AudioPolicyConfig> createWritableForTests();
+    // The factory method to use in APM tests which use a custom XML file.
+    static error::Result<sp<AudioPolicyConfig>> loadFromCustomXmlConfigForTests(
+            const std::string& xmlFilePath);
+    // The factory method to use in VTS tests. If the 'configPath' is empty,
+    // it is determined automatically from the list of known config paths.
+    static error::Result<sp<AudioPolicyConfig>> loadFromCustomXmlConfigForVtsTests(
+            const std::string& configPath, const std::string& xmlFileName);
+
+    ~AudioPolicyConfig() = default;
 
     const std::string& getSource() const {
         return mSource;
     }
-
     void setSource(const std::string& file) {
         mSource = file;
     }
@@ -79,16 +73,24 @@
     const std::string& getEngineLibraryNameSuffix() const {
         return mEngineLibraryNameSuffix;
     }
-
     void setEngineLibraryNameSuffix(const std::string& suffix) {
         mEngineLibraryNameSuffix = suffix;
     }
 
+    const HwModuleCollection& getHwModules() const { return mHwModules; }
     void setHwModules(const HwModuleCollection &hwModules)
     {
         mHwModules = hwModules;
     }
 
+    const DeviceVector& getInputDevices() const
+    {
+        return mInputDevices;
+    }
+    const DeviceVector& getOutputDevices() const
+    {
+        return mOutputDevices;
+    }
     void addDevice(const sp<DeviceDescriptor> &device)
     {
         if (audio_is_output_device(device->type())) {
@@ -97,128 +99,70 @@
             mInputDevices.add(device);
         }
     }
-
     void addInputDevices(const DeviceVector &inputDevices)
     {
         mInputDevices.add(inputDevices);
     }
-
     void addOutputDevices(const DeviceVector &outputDevices)
     {
         mOutputDevices.add(outputDevices);
     }
 
-    bool isSpeakerDrcEnabled() const { return mIsSpeakerDrcEnabled; }
+    const sp<DeviceDescriptor>& getDefaultOutputDevice() const { return mDefaultOutputDevice; }
+    void setDefaultOutputDevice(const sp<DeviceDescriptor> &defaultDevice)
+    {
+        mDefaultOutputDevice = defaultDevice;
+    }
 
+    bool isSpeakerDrcEnabled() const { return mIsSpeakerDrcEnabled; }
     void setSpeakerDrcEnabled(bool isSpeakerDrcEnabled)
     {
         mIsSpeakerDrcEnabled = isSpeakerDrcEnabled;
     }
 
     bool isCallScreenModeSupported() const { return mIsCallScreenModeSupported; }
-
     void setCallScreenModeSupported(bool isCallScreenModeSupported)
     {
         mIsCallScreenModeSupported = isCallScreenModeSupported;
     }
 
-
-    const HwModuleCollection getHwModules() const { return mHwModules; }
-
-    const DeviceVector &getInputDevices() const
-    {
-        return mInputDevices;
-    }
-
-    const DeviceVector &getOutputDevices() const
-    {
-        return mOutputDevices;
-    }
-
-    void setDefaultOutputDevice(const sp<DeviceDescriptor> &defaultDevice)
-    {
-        mDefaultOutputDevice = defaultDevice;
-    }
-
-    const sp<DeviceDescriptor> &getDefaultOutputDevice() const { return mDefaultOutputDevice; }
-
-    void setDefault(void)
-    {
-        mSource = "AudioPolicyConfig::setDefault";
-        mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
-        mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
-        mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
-        sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
-        defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
-        sp<AudioProfile> micProfile = new AudioProfile(
-                AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000);
-        defaultInputDevice->addAudioProfile(micProfile);
-        mOutputDevices.add(mDefaultOutputDevice);
-        mInputDevices.add(defaultInputDevice);
-
-        sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/);
-        mHwModules.add(module);
-
-        sp<OutputProfile> outProfile = new OutputProfile("primary");
-        outProfile->addAudioProfile(
-                new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
-        outProfile->addSupportedDevice(mDefaultOutputDevice);
-        outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
-        module->addOutputProfile(outProfile);
-
-        sp<InputProfile> inProfile = new InputProfile("primary");
-        inProfile->addAudioProfile(micProfile);
-        inProfile->addSupportedDevice(defaultInputDevice);
-        module->addInputProfile(inProfile);
-
-        setDefaultSurroundFormats();
-    }
-
-    // Surround formats, with an optional list of subformats that are equivalent from users' POV.
-    using SurroundFormats = std::unordered_map<audio_format_t, std::unordered_set<audio_format_t>>;
-
     const SurroundFormats &getSurroundFormats() const
     {
         return mSurroundFormats;
     }
-
+    void setDefaultSurroundFormats();
     void setSurroundFormats(const SurroundFormats &surroundFormats)
     {
         mSurroundFormats = surroundFormats;
     }
-
-    void setDefaultSurroundFormats()
+    void setSurroundFormats(SurroundFormats &&surroundFormats)
     {
-        mSurroundFormats = {
-            {AUDIO_FORMAT_AC3, {}},
-            {AUDIO_FORMAT_E_AC3, {}},
-            {AUDIO_FORMAT_DTS, {}},
-            {AUDIO_FORMAT_DTS_HD, {}},
-            {AUDIO_FORMAT_DTS_HD_MA, {}},
-            {AUDIO_FORMAT_DTS_UHD, {}},
-            {AUDIO_FORMAT_DTS_UHD_P2, {}},
-            {AUDIO_FORMAT_AAC_LC, {
-                    AUDIO_FORMAT_AAC_HE_V1, AUDIO_FORMAT_AAC_HE_V2, AUDIO_FORMAT_AAC_ELD,
-                    AUDIO_FORMAT_AAC_XHE}},
-            {AUDIO_FORMAT_DOLBY_TRUEHD, {}},
-            {AUDIO_FORMAT_E_AC3_JOC, {}},
-            {AUDIO_FORMAT_AC4, {}}};
+        mSurroundFormats = std::move(surroundFormats);
     }
 
+    void setDefault();
+
 private:
+    friend class sp<AudioPolicyConfig>;
+
     static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
 
-    std::string mSource;
-    std::string mEngineLibraryNameSuffix;
-    HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
-    DeviceVector &mOutputDevices;
-    DeviceVector &mInputDevices;
-    sp<DeviceDescriptor> &mDefaultOutputDevice;
+    AudioPolicyConfig() = default;
+
+    void augmentData();
+    status_t loadFromXml(const std::string& xmlFilePath, bool forVts);
+
+    std::string mSource;  // Not kDefaultConfigSource. Empty source means an empty config.
+    std::string mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
+    HwModuleCollection mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
+    DeviceVector mOutputDevices;
+    DeviceVector mInputDevices;
+    sp<DeviceDescriptor> mDefaultOutputDevice;
     // TODO: remove when legacy conf file is removed. true on devices that use DRC on the
     // DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.
     // Note: remove also speaker_drc_enabled from global configuration of XML config file.
-    bool mIsSpeakerDrcEnabled;
-    bool mIsCallScreenModeSupported;
+    bool mIsSpeakerDrcEnabled = false;
+    bool mIsCallScreenModeSupported = false;
     SurroundFormats mSurroundFormats;
 };
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 7ee6566..09ca989 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -701,8 +701,10 @@
             }
         }
 
+        // TODO(b/73175392) consider improving the AIDL interface.
+        // Signal closing to A2DP HAL.
         AudioParameter param;
-        param.add(String8("closing"), String8("true"));
+        param.add(String8(AudioParameter::keyClosing), String8("true"));
         mClientInterface->setParameters(mIoHandle, param.toString());
 
         mClientInterface->closeOutput(mIoHandle);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
new file mode 100644
index 0000000..575a6c5
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM_Config"
+
+#include <AudioPolicyConfig.h>
+#include <IOProfile.h>
+#include <Serializer.h>
+#include <media/AudioProfile.h>
+#include <system/audio.h>
+#include <system/audio_config.h>
+#include <utils/Log.h>
+
+namespace android {
+
+// static
+sp<const AudioPolicyConfig> AudioPolicyConfig::createDefault() {
+    auto config = sp<AudioPolicyConfig>::make();
+    config->setDefault();
+    return config;
+}
+
+// static
+sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmXmlConfigWithFallback(
+        const std::string& xmlFilePath) {
+    const std::string filePath =
+            xmlFilePath.empty() ? audio_get_audio_policy_config_file() : xmlFilePath;
+    auto config = sp<AudioPolicyConfig>::make();
+    if (status_t status = config->loadFromXml(filePath, false /*forVts*/); status == NO_ERROR) {
+        return config;
+    } else {
+        return createDefault();
+    }
+}
+
+// static
+sp<AudioPolicyConfig> AudioPolicyConfig::createWritableForTests() {
+    return sp<AudioPolicyConfig>::make();
+}
+
+// static
+error::Result<sp<AudioPolicyConfig>> AudioPolicyConfig::loadFromCustomXmlConfigForTests(
+        const std::string& xmlFilePath) {
+    auto config = sp<AudioPolicyConfig>::make();
+    if (status_t status = config->loadFromXml(xmlFilePath, false /*forVts*/); status == NO_ERROR) {
+        return config;
+    } else {
+        return base::unexpected(status);
+    }
+}
+
+// static
+error::Result<sp<AudioPolicyConfig>> AudioPolicyConfig::loadFromCustomXmlConfigForVtsTests(
+        const std::string& configPath, const std::string& xmlFileName) {
+    auto filePath = configPath;
+    if (filePath.empty()) {
+        for (const auto& location : audio_get_configuration_paths()) {
+            std::string path = location + '/' + xmlFileName;
+            if (access(path.c_str(), F_OK) == 0) {
+                filePath = location;
+                break;
+            }
+        }
+    }
+    if (filePath.empty()) {
+        ALOGE("Did not find a config file \"%s\" among known config paths", xmlFileName.c_str());
+        return base::unexpected(BAD_VALUE);
+    }
+    auto config = sp<AudioPolicyConfig>::make();
+    if (status_t status = config->loadFromXml(filePath + "/" + xmlFileName, true /*forVts*/);
+            status == NO_ERROR) {
+        return config;
+    } else {
+        return base::unexpected(status);
+    }
+}
+
+void AudioPolicyConfig::augmentData() {
+    // If microphones address is empty, set it according to device type
+    for (size_t i = 0; i < mInputDevices.size(); i++) {
+        if (mInputDevices[i]->address().empty()) {
+            if (mInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
+                mInputDevices[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+            } else if (mInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
+                mInputDevices[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
+            }
+        }
+    }
+}
+
+status_t AudioPolicyConfig::loadFromXml(const std::string& xmlFilePath, bool forVts) {
+    if (xmlFilePath.empty()) {
+        ALOGE("Audio policy configuration file name is empty");
+        return BAD_VALUE;
+    }
+    status_t status = forVts ? deserializeAudioPolicyFileForVts(xmlFilePath.c_str(), this)
+            : deserializeAudioPolicyFile(xmlFilePath.c_str(), this);
+    if (status == NO_ERROR) {
+        mSource = xmlFilePath;
+        augmentData();
+    } else {
+        ALOGE("Could not load audio policy from the configuration file \"%s\": %d",
+                xmlFilePath.c_str(), status);
+    }
+    return status;
+}
+
+void AudioPolicyConfig::setDefault() {
+    mSource = kDefaultConfigSource;
+    mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
+
+    mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
+    mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
+    sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
+    defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
+    sp<AudioProfile> micProfile = new AudioProfile(
+            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000);
+    defaultInputDevice->addAudioProfile(micProfile);
+    mOutputDevices.add(mDefaultOutputDevice);
+    mInputDevices.add(defaultInputDevice);
+
+    sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/);
+    mHwModules.add(module);
+
+    sp<OutputProfile> outProfile = new OutputProfile("primary");
+    outProfile->addAudioProfile(
+            new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
+    outProfile->addSupportedDevice(mDefaultOutputDevice);
+    outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
+    module->addOutputProfile(outProfile);
+
+    sp<InputProfile> inProfile = new InputProfile("primary");
+    inProfile->addAudioProfile(micProfile);
+    inProfile->addSupportedDevice(defaultInputDevice);
+    module->addInputProfile(inProfile);
+
+    setDefaultSurroundFormats();
+    augmentData();
+}
+
+void AudioPolicyConfig::setDefaultSurroundFormats() {
+    mSurroundFormats = {
+        {AUDIO_FORMAT_AC3, {}},
+        {AUDIO_FORMAT_E_AC3, {}},
+        {AUDIO_FORMAT_DTS, {}},
+        {AUDIO_FORMAT_DTS_HD, {}},
+        {AUDIO_FORMAT_DTS_HD_MA, {}},
+        {AUDIO_FORMAT_DTS_UHD, {}},
+        {AUDIO_FORMAT_DTS_UHD_P2, {}},
+        {AUDIO_FORMAT_AAC_LC, {
+                AUDIO_FORMAT_AAC_HE_V1, AUDIO_FORMAT_AAC_HE_V2, AUDIO_FORMAT_AAC_ELD,
+                AUDIO_FORMAT_AAC_XHE}},
+        {AUDIO_FORMAT_DOLBY_TRUEHD, {}},
+        {AUDIO_FORMAT_E_AC3_JOC, {}},
+        {AUDIO_FORMAT_AC4, {}}};
+}
+
+} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index d446e96..1b48dc3 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -29,6 +29,7 @@
 #include <utils/StrongPointer.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
+#include "IOProfile.h"
 #include "Serializer.h"
 #include "TypeConverter.h"
 
@@ -907,7 +908,6 @@
 {
     PolicySerializer serializer;
     status_t status = serializer.deserialize(fileName, config);
-    if (status != OK) config->clear();
     return status;
 }
 
@@ -915,7 +915,6 @@
 {
     PolicySerializer serializer;
     status_t status = serializer.deserialize(fileName, config, true /*ignoreVendorExtensions*/);
-    if (status != OK) config->clear();
     return status;
 }
 
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index 7ff0301..bac51f5 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -113,7 +113,7 @@
     status_t getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
             AudioDeviceTypeAddrVector &devices) const override;
 
-    engineConfig::ParsingResult loadAudioPolicyEngineConfig();
+    engineConfig::ParsingResult loadAudioPolicyEngineConfig(const std::string& xmlFilePath = "");
 
     const ProductStrategyMap &getProductStrategies() const { return mProductStrategies; }
 
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 5769a97..7d6a308 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -115,7 +115,7 @@
     return PRODUCT_STRATEGY_NONE;
 }
 
-engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
+engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
 {
     auto loadVolumeConfig = [](auto &volumeGroups, auto &volumeConfig) {
         // Ensure name unicity to prevent duplicate
@@ -163,8 +163,9 @@
         return stat(path, &fileStat) == 0 && S_ISREG(fileStat.st_mode);
     };
 
-    auto result = fileExists(engineConfig::DEFAULT_PATH) ?
-            engineConfig::parse(engineConfig::DEFAULT_PATH) : engineConfig::ParsingResult{};
+    const std::string filePath = xmlFilePath.empty() ? engineConfig::DEFAULT_PATH : xmlFilePath;
+    auto result = fileExists(filePath.c_str()) ?
+            engineConfig::parse(filePath.c_str()) : engineConfig::ParsingResult{};
     if (result.parsedConfig == nullptr) {
         ALOGD("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
         engineConfig::Config config = gDefaultEngineConfig;
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index ea8fc41..dd7ac1a 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <string>
 #include <utility>
 
 #include <AudioPolicyManagerObserver.h>
@@ -46,6 +47,13 @@
 {
 public:
     /**
+     * Loads the engine configuration from the specified or the default config file.
+     * If loading failed, tries to fall back to some default configuration. If fallback
+     * is impossible, returns an error.
+     */
+    virtual status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") = 0;
+
+    /**
      * Checks if the engine was correctly initialized.
      *
      * @return NO_ERROR if initialization has been done correctly, error code otherwise..
diff --git a/services/audiopolicy/engineconfigurable/src/Collection.h b/services/audiopolicy/engineconfigurable/src/Collection.h
index 02b41cb..4640515 100644
--- a/services/audiopolicy/engineconfigurable/src/Collection.h
+++ b/services/audiopolicy/engineconfigurable/src/Collection.h
@@ -53,6 +53,10 @@
     {
         collectionSupported();
     }
+    ~Collection()
+    {
+        clear();
+    }
 
     /**
      * Add a policy element to the collection. Policy elements are streams, strategies, input
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index a7f92cd..dad663e 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -68,16 +68,15 @@
 
 Engine::Engine() : mPolicyParameterMgr(new ParameterManagerWrapper())
 {
-    status_t loadResult = loadAudioPolicyEngineConfig();
+}
+
+status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
+{
+    status_t loadResult = loadAudioPolicyEngineConfig(xmlFilePath);
     if (loadResult < 0) {
         ALOGE("Policy Engine configuration is invalid.");
     }
-}
-
-Engine::~Engine()
-{
-    mStreamCollection.clear();
-    mInputSourceCollection.clear();
+    return loadResult;
 }
 
 status_t Engine::initCheck()
@@ -194,9 +193,9 @@
     return EngineBase::setDeviceConnectionState(device, state);
 }
 
-status_t Engine::loadAudioPolicyEngineConfig()
+status_t Engine::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
 {
-    auto result = EngineBase::loadAudioPolicyEngineConfig();
+    auto result = EngineBase::loadAudioPolicyEngineConfig(xmlFilePath);
 
     // Custom XML Parsing
     auto loadCriteria= [this](const auto& configCriteria, const auto& configCriterionTypes) {
@@ -531,5 +530,3 @@
 
 } // namespace audio_policy
 } // namespace android
-
-
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 8ea8052..b964cd6 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -33,12 +33,17 @@
 {
 public:
     Engine();
-    virtual ~Engine();
+    virtual ~Engine() = default;
 
     template <class RequestedInterface>
     RequestedInterface *queryInterface();
 
     ///
+    /// from EngineInterface
+    ///
+    android::status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
+
+    ///
     /// from EngineBase
     ///
     android::status_t initCheck() override;
@@ -132,7 +137,7 @@
     template <typename Property, typename Key>
     bool setPropertyForKey(const Property &property, const Key &key);
 
-    status_t loadAudioPolicyEngineConfig();
+    status_t loadAudioPolicyEngineConfig(const std::string& xmlFilePath);
 
     DeviceVector getCachedDevices(product_strategy_t ps) const;
 
@@ -150,4 +155,3 @@
 } // namespace audio_policy
 
 } // namespace android
-
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 84e7cb8..88cbb7d 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -59,9 +59,8 @@
     return legacyStrategy;
 }
 
-Engine::Engine()
-{
-    auto result = EngineBase::loadAudioPolicyEngineConfig();
+status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath) {
+    auto result = EngineBase::loadAudioPolicyEngineConfig(xmlFilePath);
     ALOGE_IF(result.nbSkippedElement != 0,
              "Policy Engine configuration is partially invalid, skipped %zu elements",
              result.nbSkippedElement);
@@ -70,6 +69,8 @@
     for (const auto &strategy : legacyStrategy) {
         mLegacyStrategyMap[getProductStrategyByName(strategy.name)] = strategy.id;
     }
+
+    return OK;
 }
 
 status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
@@ -845,5 +846,3 @@
 
 } // namespace audio_policy
 } // namespace android
-
-
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 2e4decf..8410560 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -45,9 +45,14 @@
 class Engine : public EngineBase
 {
 public:
-    Engine();
+    Engine() = default;
     virtual ~Engine() = default;
 
+    ///
+    /// from EngineInterface
+    ///
+    status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
+
 private:
     ///
     /// from EngineBase, so from EngineInterface
@@ -105,4 +110,3 @@
 };
 } // namespace audio_policy
 } // namespace android
-
diff --git a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
index 14f565b..8793085 100644
--- a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
+++ b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
@@ -216,8 +216,9 @@
     virtual void process();
 
    protected:
+    sp<AudioPolicyConfig> mConfig{AudioPolicyConfig::createWritableForTests()};
     std::unique_ptr<AudioPolicyManagerTestClient> mClient{new AudioPolicyManagerTestClient};
-    std::unique_ptr<AudioPolicyTestManager> mManager{new AudioPolicyTestManager(mClient.get())};
+    std::unique_ptr<AudioPolicyTestManager> mManager;
     FuzzedDataProvider *mFdp;
 };
 
@@ -230,7 +231,10 @@
     }
     // init code
     SetUpManagerConfig();
-
+    if (mConfig == nullptr) {
+        return false;
+    }
+    mManager.reset(new AudioPolicyTestManager(mConfig, mClient.get()));
     if (mManager->initialize() != NO_ERROR) {
         return false;
     }
@@ -240,7 +244,7 @@
     return true;
 }
 
-void AudioPolicyManagerFuzzer::SetUpManagerConfig() { mManager->getConfig().setDefault(); }
+void AudioPolicyManagerFuzzer::SetUpManagerConfig() { mConfig->setDefault(); }
 
 bool AudioPolicyManagerFuzzer::getOutputForAttr(
     audio_port_handle_t *selectedDeviceId, audio_format_t format, audio_channel_mask_t channelMask,
@@ -408,7 +412,11 @@
 }
 
 void AudioPolicyManagerFuzzerWithConfigurationFile::SetUpManagerConfig() {
-    deserializeAudioPolicyFile(getConfigFile().c_str(), &mManager->getConfig());
+    const std::string configFilePath = getConfigFile();
+    auto result = AudioPolicyConfig::loadFromCustomXmlConfigForTests(configFilePath);
+    mConfig = result.ok() ? mConfig = result.value() : nullptr;
+    ALOGE_IF(!result.ok(), "%s: Failed to deserialize \"%s\": %d",
+            __func__, configFilePath.c_str(), result.error());
 }
 
 void AudioPolicyManagerFuzzerWithConfigurationFile::traverseAndFuzzXML(xmlDocPtr pDoc,
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 56a692b..e087d8a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -116,14 +116,13 @@
 }
 
 void AudioPolicyManager::broadcastDeviceConnectionState(const sp<DeviceDescriptor> &device,
-                                                        audio_policy_dev_state_t state)
+                                                        media::DeviceConnectedState state)
 {
     audio_port_v7 devicePort;
     device->toAudioPort(&devicePort);
-    if (status_t status = mpClientInterface->setDeviceConnectedState(
-                    &devicePort, state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
+    if (status_t status = mpClientInterface->setDeviceConnectedState(&devicePort, state);
             status != OK) {
-        ALOGE("Error %d while setting connected state for device %s", status,
+        ALOGE("Error %d while setting connected state for device %s", state,
                 device->getDeviceTypeAddr().toString(false).c_str());
     }
 }
@@ -206,14 +205,14 @@
 
             // Before checking outputs, broadcast connect event to allow HAL to retrieve dynamic
             // parameters on newly connected devices (instead of opening the outputs...)
-            broadcastDeviceConnectionState(device, state);
+            broadcastDeviceConnectionState(device, media::DeviceConnectedState::CONNECTED);
 
             if (checkOutputsForDevice(device, state, outputs) != NO_ERROR) {
                 mAvailableOutputDevices.remove(device);
 
                 mHwModules.cleanUpForDevice(device);
 
-                broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
+                broadcastDeviceConnectionState(device, media::DeviceConnectedState::DISCONNECTED);
                 return INVALID_OPERATION;
             }
 
@@ -235,8 +234,9 @@
 
             ALOGV("%s() disconnecting output device %s", __func__, device->toString().c_str());
 
-            // Send Disconnect to HALs
-            broadcastDeviceConnectionState(device, state);
+            // Notify the HAL to prepare to disconnect device
+            broadcastDeviceConnectionState(
+                    device, media::DeviceConnectedState::PREPARE_TO_DISCONNECT);
 
             // remove device from available output devices
             mAvailableOutputDevices.remove(device);
@@ -245,6 +245,9 @@
 
             checkOutputsForDevice(device, state, outputs);
 
+            // Send Disconnect to HALs
+            broadcastDeviceConnectionState(device, media::DeviceConnectedState::DISCONNECTED);
+
             // Reset active device codec
             device->setEncodedFormat(AUDIO_FORMAT_DEFAULT);
 
@@ -384,12 +387,12 @@
 
             // Before checking intputs, broadcast connect event to allow HAL to retrieve dynamic
             // parameters on newly connected devices (instead of opening the inputs...)
-            broadcastDeviceConnectionState(device, state);
+            broadcastDeviceConnectionState(device, media::DeviceConnectedState::CONNECTED);
 
             if (checkInputsForDevice(device, state) != NO_ERROR) {
                 mAvailableInputDevices.remove(device);
 
-                broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
+                broadcastDeviceConnectionState(device, media::DeviceConnectedState::DISCONNECTED);
 
                 mHwModules.cleanUpForDevice(device);
 
@@ -407,13 +410,17 @@
 
             ALOGV("%s() disconnecting input device %s", __func__, device->toString().c_str());
 
-            // Set Disconnect to HALs
-            broadcastDeviceConnectionState(device, state);
+            // Notify the HAL to prepare to disconnect device
+            broadcastDeviceConnectionState(
+                    device, media::DeviceConnectedState::PREPARE_TO_DISCONNECT);
 
             mAvailableInputDevices.remove(device);
 
             checkInputsForDevice(device, state);
 
+            // Set Disconnect to HALs
+            broadcastDeviceConnectionState(device, media::DeviceConnectedState::DISCONNECTED);
+
             // remove device from mReportedFormatsMap cache
             mReportedFormatsMap.erase(device);
         } break;
@@ -1323,7 +1330,7 @@
 
     *selectedDeviceId = getFirstDeviceId(outputDevices);
     for (auto &outputDevice : outputDevices) {
-        if (outputDevice->getId() == getConfig().getDefaultOutputDevice()->getId()) {
+        if (outputDevice->getId() == mConfig->getDefaultOutputDevice()->getId()) {
             *selectedDeviceId = outputDevice->getId();
             break;
         }
@@ -1908,7 +1915,8 @@
 }
 
 bool AudioPolicyManager::msdHasPatchesToAllDevices(const AudioDeviceTypeAddrVector& devices) {
-    DeviceVector devicesToCheck = mOutputDevicesAll.getDevicesFromDeviceTypeAddrVec(devices);
+    DeviceVector devicesToCheck =
+            mConfig->getOutputDevices().getDevicesFromDeviceTypeAddrVec(devices);
     AudioPatchCollection msdPatches = getMsdOutputPatches();
     for (size_t i = 0; i < msdPatches.size(); i++) {
         const auto& patch = msdPatches[i];
@@ -4099,13 +4107,13 @@
     dst->appendFormat(" TTS output %savailable\n", mTtsOutputAvailable ? "" : "not ");
     dst->appendFormat(" Master mono: %s\n", mMasterMono ? "on" : "off");
     dst->appendFormat(" Communication Strategy id: %d\n", mCommunnicationStrategy);
-    dst->appendFormat(" Config source: %s\n", mConfig.getSource().c_str()); // getConfig not const
+    dst->appendFormat(" Config source: %s\n", mConfig->getSource().c_str());
 
     dst->append("\n");
     mAvailableOutputDevices.dump(dst, String8("Available output"), 1);
     dst->append("\n");
     mAvailableInputDevices.dump(dst, String8("Available input"), 1);
-    mHwModulesAll.dump(dst);
+    mHwModules.dump(dst);
     mOutputs.dump(dst);
     mInputs.dump(dst);
     mEffects.dump(dst, 1);
@@ -4612,7 +4620,7 @@
         return OK;
     };
 
-    for (const auto& module : mHwModulesAll) {
+    for (const auto& module : mHwModules) {
         for (const auto& dev : module->getDeclaredDevices()) {
             if (role == media::AudioPortRole::NONE ||
                     ((role == media::AudioPortRole::SOURCE)
@@ -5519,10 +5527,10 @@
     size_t formatsWritten = 0;
     size_t formatsMax = *numSurroundFormats;
 
-    *numSurroundFormats = mConfig.getSurroundFormats().size();
+    *numSurroundFormats = mConfig->getSurroundFormats().size();
     audio_policy_forced_cfg_t forceUse = mEngine->getForceUse(
             AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
-    for (const auto& format: mConfig.getSurroundFormats()) {
+    for (const auto& format: mConfig->getSurroundFormats()) {
         if (formatsWritten < formatsMax) {
             surroundFormats[formatsWritten] = format.first;
             bool formatEnabled = true;
@@ -5575,10 +5583,10 @@
         formatset.insert(encodedFormats.begin(), encodedFormats.end());
         // Filter the formats which are supported by the vendor hardware.
         for (auto it = formatset.begin(); it != formatset.end(); ++it) {
-            if (mConfig.getSurroundFormats().count(*it) != 0) {
+            if (mConfig->getSurroundFormats().count(*it) != 0) {
                 formats.insert(*it);
             } else {
-                for (const auto& pair : mConfig.getSurroundFormats()) {
+                for (const auto& pair : mConfig->getSurroundFormats()) {
                     if (pair.second.count(*it) != 0) {
                         formats.insert(pair.first);
                         break;
@@ -5599,8 +5607,8 @@
 status_t AudioPolicyManager::setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled)
 {
     ALOGV("%s() format 0x%X enabled %d", __func__, audioFormat, enabled);
-    const auto& formatIter = mConfig.getSurroundFormats().find(audioFormat);
-    if (formatIter == mConfig.getSurroundFormats().end()) {
+    const auto& formatIter = mConfig->getSurroundFormats().find(audioFormat);
+    if (formatIter == mConfig->getSurroundFormats().end()) {
         ALOGW("%s() format 0x%X is not a known surround format", __func__, audioFormat);
         return BAD_VALUE;
     }
@@ -5755,7 +5763,7 @@
 
 bool AudioPolicyManager::isCallScreenModeSupported()
 {
-    return getConfig().isCallScreenModeSupported();
+    return mConfig->isCallScreenModeSupported();
 }
 
 
@@ -5988,26 +5996,16 @@
     return mAudioPortGeneration++;
 }
 
-static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
-    if (std::string audioPolicyXmlConfigFile = audio_get_audio_policy_config_file();
-            !audioPolicyXmlConfigFile.empty()) {
-        status_t ret = deserializeAudioPolicyFile(audioPolicyXmlConfigFile.c_str(), &config);
-        if (ret == NO_ERROR) {
-            config.setSource(audioPolicyXmlConfigFile);
-        }
-        return ret;
-    }
-    return BAD_VALUE;
-}
-
-AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface,
-                                       bool /*forTesting*/)
+AudioPolicyManager::AudioPolicyManager(const sp<const AudioPolicyConfig>& config,
+                                       EngineInstance&& engine,
+                                       AudioPolicyClientInterface *clientInterface)
     :
     mUidCached(AID_AUDIOSERVER), // no need to call getuid(), there's only one of us running.
+    mConfig(config),
+    mEngine(std::move(engine)),
     mpClientInterface(clientInterface),
     mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
     mA2dpSuspended(false),
-    mConfig(mHwModulesAll, mOutputDevicesAll, mInputDevicesAll, mDefaultOutputDevice),
     mAudioPortGeneration(1),
     mBeaconMuteRefCount(0),
     mBeaconPlayingRefCount(0),
@@ -6018,32 +6016,9 @@
 {
 }
 
-AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
-        : AudioPolicyManager(clientInterface, false /*forTesting*/)
-{
-    loadConfig();
-}
-
-void AudioPolicyManager::loadConfig() {
-    if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {
-        ALOGE("could not load audio policy configuration file, setting defaults");
-        getConfig().setDefault();
-    }
-}
-
 status_t AudioPolicyManager::initialize() {
-    {
-        auto engLib = EngineLibrary::load(
-                        "libaudiopolicyengine" + getConfig().getEngineLibraryNameSuffix() + ".so");
-        if (!engLib) {
-            ALOGE("%s: Failed to load the engine library", __FUNCTION__);
-            return NO_INIT;
-        }
-        mEngine = engLib->createEngine();
-        if (mEngine == nullptr) {
-            ALOGE("%s: Failed to instantiate the APM engine", __FUNCTION__);
-            return NO_INIT;
-        }
+    if (mEngine == nullptr) {
+        return NO_INIT;
     }
     mEngine->setObserver(this);
     status_t status = mEngine->initCheck();
@@ -6052,31 +6027,22 @@
         return status;
     }
 
-    // If microphones address is empty, set it according to device type
-    for (size_t i = 0; i < mInputDevicesAll.size(); i++) {
-        if (mInputDevicesAll[i]->address().empty()) {
-            if (mInputDevicesAll[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                mInputDevicesAll[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
-            } else if (mInputDevicesAll[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
-                mInputDevicesAll[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
-            }
-        }
-    }
-
     // The actual device selection cache will be updated when calling `updateDevicesAndOutputs`
     // at the end of this function.
     mEngine->initializeDeviceSelectionCache();
     mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
         mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
 
-    // after parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices;
+    // after parsing the config, mConfig contain all known devices;
     // open all output streams needed to access attached devices
     onNewAudioModulesAvailableInt(nullptr /*newDevices*/);
 
     // make sure default device is reachable
-    if (mDefaultOutputDevice == 0 || !mAvailableOutputDevices.contains(mDefaultOutputDevice)) {
-        ALOGE_IF(mDefaultOutputDevice != 0, "Default device %s is unreachable",
-                 mDefaultOutputDevice->toString().c_str());
+    if (const auto defaultOutputDevice = mConfig->getDefaultOutputDevice();
+            defaultOutputDevice == nullptr ||
+            !mAvailableOutputDevices.contains(defaultOutputDevice)) {
+        ALOGE_IF(defaultOutputDevice != nullptr, "Default device %s is unreachable",
+                 defaultOutputDevice->toString().c_str());
         status = NO_INIT;
     }
     ALOGW_IF(mPrimaryOutput == nullptr, "The policy configuration does not declare a primary output");
@@ -6101,8 +6067,8 @@
    mOutputs.clear();
    mInputs.clear();
    mHwModules.clear();
-   mHwModulesAll.clear();
    mManualSurroundFormats.clear();
+   mConfig.clear();
 }
 
 status_t AudioPolicyManager::initCheck()
@@ -6124,7 +6090,7 @@
 
 void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
 {
-    for (const auto& hwModule : mHwModulesAll) {
+    for (const auto& hwModule : mConfig->getHwModules()) {
         if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {
             continue;
         }
@@ -6153,10 +6119,10 @@
             }
 
             const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
-            DeviceVector availProfileDevices = supportedDevices.filter(mOutputDevicesAll);
+            DeviceVector availProfileDevices = supportedDevices.filter(mConfig->getOutputDevices());
             sp<DeviceDescriptor> supportedDevice = 0;
-            if (supportedDevices.contains(mDefaultOutputDevice)) {
-                supportedDevice = mDefaultOutputDevice;
+            if (supportedDevices.contains(mConfig->getDefaultOutputDevice())) {
+                supportedDevice = mConfig->getDefaultOutputDevice();
             } else {
                 // choose first device present in profile's SupportedDevices also part of
                 // mAvailableOutputDevices.
@@ -6165,7 +6131,7 @@
                 }
                 supportedDevice = availProfileDevices.itemAt(0);
             }
-            if (!mOutputDevicesAll.contains(supportedDevice)) {
+            if (!mConfig->getOutputDevices().contains(supportedDevice)) {
                 continue;
             }
             sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
@@ -6220,7 +6186,7 @@
             // chose first device present in profile's SupportedDevices also part of
             // available input devices
             const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
-            DeviceVector availProfileDevices = supportedDevices.filter(mInputDevicesAll);
+            DeviceVector availProfileDevices = supportedDevices.filter(mConfig->getInputDevices());
             if (availProfileDevices.isEmpty()) {
                 ALOGV("%s: Input device list is empty! for profile %s",
                     __func__, inProfile->getTagName().c_str());
@@ -7980,7 +7946,7 @@
     std::unordered_set<audio_format_t> enforcedSurround(
             devDesc->encodedFormats().begin(), devDesc->encodedFormats().end());
     std::unordered_set<audio_format_t> allSurround;  // A flat set of all known surround formats
-    for (const auto& pair : mConfig.getSurroundFormats()) {
+    for (const auto& pair : mConfig->getSurroundFormats()) {
         allSurround.insert(pair.first);
         for (const auto& subformat : pair.second) allSurround.insert(subformat);
     }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 2924ee1..88bafef 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -35,6 +35,7 @@
 #include <media/PatchBuilder.h>
 #include "AudioPolicyInterface.h"
 
+#include <android/media/DeviceConnectedState.h>
 #include <android/media/audio/common/AudioPort.h>
 #include <AudioPolicyManagerObserver.h>
 #include <AudioPolicyConfig.h>
@@ -93,7 +94,9 @@
 {
 
 public:
-        explicit AudioPolicyManager(AudioPolicyClientInterface *clientInterface);
+        AudioPolicyManager(const sp<const AudioPolicyConfig>& config,
+                           EngineInstance&& engine,
+                           AudioPolicyClientInterface *clientInterface);
         virtual ~AudioPolicyManager();
 
         // AudioPolicyInterface
@@ -426,19 +429,7 @@
         status_t initialize();
 
 protected:
-        // A constructor that allows more fine-grained control over initialization process,
-        // used in automatic tests.
-        AudioPolicyManager(AudioPolicyClientInterface *clientInterface, bool forTesting);
-
-        // These methods should be used when finer control over APM initialization
-        // is needed, e.g. in tests. Must be used in conjunction with the constructor
-        // that only performs fields initialization. The public constructor comprises
-        // these steps in the following sequence:
-        //   - field initializing constructor;
-        //   - loadConfig;
-        //   - initialize.
-        AudioPolicyConfig& getConfig() { return mConfig; }
-        void loadConfig();
+        const AudioPolicyConfig& getConfig() const { return *(mConfig.get()); }
 
         // From AudioPolicyManagerObserver
         virtual const AudioPatchCollection &getAudioPatches() const
@@ -472,7 +463,7 @@
         }
         virtual const sp<DeviceDescriptor> &getDefaultOutputDevice() const
         {
-            return mDefaultOutputDevice;
+            return mConfig->getDefaultOutputDevice();
         }
 
         std::vector<volume_group_t> getVolumeGroups() const
@@ -931,6 +922,8 @@
                 sp<SwAudioOutputDescriptor> ignoredOutput, uint32_t delayMs);
 
         const uid_t mUidCached;                         // AID_AUDIOSERVER
+        sp<const AudioPolicyConfig> mConfig;
+        EngineInstance mEngine;                         // Audio Policy Engine instance
         AudioPolicyClientInterface *mpClientInterface;  // audio policy client interface
         sp<SwAudioOutputDescriptor> mPrimaryOutput;     // primary output descriptor
         // list of descriptors for outputs currently opened
@@ -943,8 +936,6 @@
         SwAudioOutputCollection mPreviousOutputs;
         AudioInputCollection mInputs;     // list of input descriptors
 
-        DeviceVector  mOutputDevicesAll; // all output devices from the config
-        DeviceVector  mInputDevicesAll;  // all input devices from the config
         DeviceVector  mAvailableOutputDevices; // all available output devices
         DeviceVector  mAvailableInputDevices;  // all available input devices
 
@@ -954,11 +945,7 @@
         bool    mA2dpSuspended;  // true if A2DP output is suspended
 
         EffectDescriptorCollection mEffects;  // list of registered audio effects
-        sp<DeviceDescriptor> mDefaultOutputDevice; // output device selected by default at boot time
         HwModuleCollection mHwModules; // contains modules that have been loaded successfully
-        HwModuleCollection mHwModulesAll; // contains all modules declared in the config
-
-        AudioPolicyConfig mConfig;
 
         std::atomic<uint32_t> mAudioPortGeneration;
 
@@ -989,9 +976,6 @@
 
         uint32_t nextAudioPortGeneration();
 
-        // Audio Policy Engine Interface.
-        EngineInstance mEngine;
-
         // Surround formats that are enabled manually. Taken into account when
         // "encoded surround" is forced into "manual" mode.
         std::unordered_set<audio_format_t> mManualSurroundFormats;
@@ -1060,13 +1044,16 @@
         void updateAudioProfiles(const sp<DeviceDescriptor>& devDesc, audio_io_handle_t ioHandle,
                 AudioProfileVector &profiles);
 
+        // Notify the policy client to prepare for disconnecting external device.
+        void prepareToDisconnectExternalDevice(const sp<DeviceDescriptor> &device);
+
         // Notify the policy client of any change of device state with AUDIO_IO_HANDLE_NONE,
         // so that the client interprets it as global to audio hardware interfaces.
         // It can give a chance to HAL implementer to retrieve dynamic capabilities associated
         // to this device for example.
         // TODO avoid opening stream to retrieve capabilities of a profile.
         void broadcastDeviceConnectionState(const sp<DeviceDescriptor> &device,
-                                            audio_policy_dev_state_t state);
+                                            media::DeviceConnectedState state);
 
         // updates device caching and output for streams that can influence the
         //    routing of notifications
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.cpp b/services/audiopolicy/managerdefault/EngineLibrary.cpp
index ef699aa..939fbc5 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.cpp
+++ b/services/audiopolicy/managerdefault/EngineLibrary.cpp
@@ -23,9 +23,27 @@
 
 namespace android {
 
-// static
-std::shared_ptr<EngineLibrary> EngineLibrary::load(std::string libraryPath)
+EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
+        const std::string& configXmlFilePath)
 {
+    auto engLib = EngineLibrary::load(librarySuffix);
+    if (!engLib) {
+        ALOGE("%s: Failed to load the engine library, suffix \"%s\"",
+                __func__, librarySuffix.c_str());
+        return nullptr;
+    }
+    auto engine = engLib->createEngineUsingXmlConfig(configXmlFilePath);
+    if (engine == nullptr) {
+        ALOGE("%s: Failed to instantiate the APM engine", __func__);
+        return nullptr;
+    }
+    return engine;
+}
+
+// static
+std::shared_ptr<EngineLibrary> EngineLibrary::load(const std::string& librarySuffix)
+{
+    std::string libraryPath = "libaudiopolicyengine" + librarySuffix + ".so";
     std::shared_ptr<EngineLibrary> engLib(new EngineLibrary());
     return engLib->init(std::move(libraryPath)) ? engLib : nullptr;
 }
@@ -35,6 +53,20 @@
     close();
 }
 
+EngineInstance EngineLibrary::createEngineUsingXmlConfig(const std::string& xmlFilePath) {
+    auto instance = createEngine();
+    if (instance != nullptr) {
+        if (status_t status = instance->loadFromXmlConfigWithFallback(xmlFilePath);
+                status == OK) {
+            return instance;
+        } else {
+            ALOGE("%s: loading of the engine config with XML configuration file \"%s\" failed: %d",
+                    __func__, xmlFilePath.empty() ? "default" : xmlFilePath.c_str(), status);
+        }
+    }
+    return nullptr;
+}
+
 bool EngineLibrary::init(std::string libraryPath)
 {
     mLibraryHandle = dlopen(libraryPath.c_str(), 0);
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.h b/services/audiopolicy/managerdefault/EngineLibrary.h
index f143916..dc138a1 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.h
+++ b/services/audiopolicy/managerdefault/EngineLibrary.h
@@ -26,9 +26,12 @@
 
 using EngineInstance = std::unique_ptr<EngineInterface, std::function<void (EngineInterface*)>>;
 
+EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
+        const std::string& configXmlFilePath = "");
+
 class EngineLibrary : public std::enable_shared_from_this<EngineLibrary> {
 public:
-    static std::shared_ptr<EngineLibrary> load(std::string libraryPath);
+    static std::shared_ptr<EngineLibrary> load(const std::string& librarySuffix);
     ~EngineLibrary();
 
     EngineLibrary(const EngineLibrary&) = delete;
@@ -36,11 +39,12 @@
     EngineLibrary& operator=(const EngineLibrary&) = delete;
     EngineLibrary& operator=(EngineLibrary&&) = delete;
 
-    EngineInstance createEngine();
+    EngineInstance createEngineUsingXmlConfig(const std::string& xmlFilePath);
 
 private:
     EngineLibrary() = default;
     bool init(std::string libraryPath);
+    EngineInstance createEngine();
     void close();
 
     void *mLibraryHandle = nullptr;
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index 10403fa..2f677da 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -52,8 +52,9 @@
         "libsensor",
         "libsensorprivacy",
         "libshmemcompat",
-        "libutils",
         "libstagefright_foundation",
+        "libutils",
+        "libxml2",
         "audioclient-types-aidl-cpp",
         "audioflinger-aidl-cpp",
         "audiopolicy-aidl-cpp",
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 1bb89df..887f210 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -309,13 +309,13 @@
 }
 
 status_t AudioPolicyService::AudioPolicyClient::setDeviceConnectedState(
-        const struct audio_port_v7 *port, bool connected) {
+        const struct audio_port_v7 *port, media::DeviceConnectedState state) {
     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
     if (af == nullptr) {
         ALOGW("%s: could not get AudioFlinger", __func__);
         return PERMISSION_DENIED;
     }
-    return af->setDeviceConnectedState(port, connected);
+    return af->setDeviceConnectedState(port, state);
 }
 
 status_t AudioPolicyService::AudioPolicyClient::invalidateTracks(
@@ -328,5 +328,4 @@
     return af->invalidateTracks(portIds);
 }
 
-
 } // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index c7a60c2..b111865 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -41,26 +41,25 @@
 // AudioPolicyEffects Implementation
 // ----------------------------------------------------------------------------
 
-AudioPolicyEffects::AudioPolicyEffects()
-{
-    status_t loadResult = loadAudioEffectXmlConfig();
+AudioPolicyEffects::AudioPolicyEffects(const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
+    // load xml config with effectsFactoryHal
+    status_t loadResult = loadAudioEffectConfig(effectsFactoryHal);
     if (loadResult == NO_ERROR) {
-        mDefaultDeviceEffectFuture = std::async(
-                    std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
+        mDefaultDeviceEffectFuture =
+                std::async(std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
     } else if (loadResult < 0) {
-        ALOGW("Failed to load XML effect configuration, fallback to .conf");
+        ALOGW("Failed to query effect configuration, fallback to load .conf");
         // load automatic audio effect modules
         if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
-            loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
+            loadAudioEffectConfigLegacy(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
         } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
-            loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
+            loadAudioEffectConfigLegacy(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
         }
     } else if (loadResult > 0) {
         ALOGE("Effect config is partially invalid, skipped %d elements", loadResult);
     }
 }
 
-
 AudioPolicyEffects::~AudioPolicyEffects()
 {
     size_t i = 0;
@@ -907,10 +906,18 @@
     return NO_ERROR;
 }
 
-status_t AudioPolicyEffects::loadAudioEffectXmlConfig() {
-    auto result = effectsConfig::parse();
-    if (result.parsedConfig == nullptr) {
-        return -ENOENT;
+status_t AudioPolicyEffects::loadAudioEffectConfig(
+        const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
+    if (!effectsFactoryHal) {
+        ALOGE("%s Null EffectsFactoryHalInterface", __func__);
+        return UNEXPECTED_NULL;
+    }
+
+    const auto skippedElements = VALUE_OR_RETURN_STATUS(effectsFactoryHal->getSkippedElements());
+    const auto processings = effectsFactoryHal->getProcessings();
+    if (!processings) {
+        ALOGE("%s Null processings with %zu skipped elements", __func__, skippedElements);
+        return UNEXPECTED_NULL;
     }
 
     auto loadProcessingChain = [](auto& processingChain, auto& streams) {
@@ -924,9 +931,8 @@
         }
     };
 
-    auto loadDeviceProcessingChain = [](auto &processingChain, auto& devicesEffects) {
+    auto loadDeviceProcessingChain = [](auto& processingChain, auto& devicesEffects) {
         for (auto& deviceProcess : processingChain) {
-
             auto effectDescs = std::make_unique<EffectDescVector>();
             for (auto& effect : deviceProcess.effects) {
                 effectDescs->mEffects.add(
@@ -938,17 +944,18 @@
         }
     };
 
-    loadProcessingChain(result.parsedConfig->preprocess, mInputSources);
-    loadProcessingChain(result.parsedConfig->postprocess, mOutputStreams);
+    loadProcessingChain(processings->preprocess, mInputSources);
+    loadProcessingChain(processings->postprocess, mOutputStreams);
+
     {
         Mutex::Autolock _l(mLock);
-        loadDeviceProcessingChain(result.parsedConfig->deviceprocess, mDeviceEffects);
+        loadDeviceProcessingChain(processings->deviceprocess, mDeviceEffects);
     }
-    // Casting from ssize_t to status_t is probably safe, there should not be more than 2^31 errors
-    return result.nbSkippedElement;
+
+    return skippedElements;
 }
 
-status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
+status_t AudioPolicyEffects::loadAudioEffectConfigLegacy(const char *path)
 {
     cnode *root;
     char *data;
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 13d5d0c..9f65a96 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -20,22 +20,33 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <future>
+
+#include <android-base/thread_annotations.h>
 #include <cutils/misc.h>
 #include <media/AudioEffect.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
 #include <system/audio.h>
 #include <utils/Vector.h>
 #include <utils/SortedVector.h>
-#include <android-base/thread_annotations.h>
-
-#include <future>
 
 namespace android {
 
 // ----------------------------------------------------------------------------
 
-// AudioPolicyEffects class
-// This class will manage all effects attached to input and output streams in
-// AudioPolicyService as configured in audio_effects.conf.
+/**
+ * AudioPolicyEffects class.
+ *
+ * This class manages all effects attached to input and output streams in AudioPolicyService.
+ * The effect configurations can be queried in several ways:
+ *
+ * With HIDL HAL, the configuration file `audio_effects.xml` will be loaded by libAudioHal. If this
+ * file does not exist, AudioPolicyEffects class will fallback to load configuration from
+ * `/vendor/etc/audio_effects.conf` (AUDIO_EFFECT_VENDOR_CONFIG_FILE). If this file also does not
+ * exist, the configuration will be loaded from the file `/system/etc/audio_effects.conf`.
+ *
+ * With AIDL HAL, the configuration will be queried with the method `IFactory::queryProcessing()`.
+ */
 class AudioPolicyEffects : public RefBase
 {
 
@@ -44,7 +55,7 @@
     // The constructor will parse audio_effects.conf
     // First it will look whether vendor specific file exists,
     // otherwise it will parse the system default file.
-	         AudioPolicyEffects();
+    explicit AudioPolicyEffects(const sp<EffectsFactoryHalInterface>& effectsFactoryHal);
     virtual ~AudioPolicyEffects();
 
     // NOTE: methods on AudioPolicyEffects should never be called with the AudioPolicyService
@@ -218,7 +229,6 @@
 
     };
 
-
     static const char * const kInputSourceNames[AUDIO_SOURCE_CNT -1];
     static audio_source_t inputSourceNameToEnum(const char *name);
 
@@ -226,8 +236,8 @@
     audio_stream_type_t streamNameToEnum(const char *name);
 
     // Parse audio_effects.conf
-    status_t loadAudioEffectConfig(const char *path); // TODO: add legacy in the name
-    status_t loadAudioEffectXmlConfig(); // TODO: remove "Xml" in the name
+    status_t loadAudioEffectConfigLegacy(const char *path);
+    status_t loadAudioEffectConfig(const sp<EffectsFactoryHalInterface>& effectsFactoryHal);
 
     // Load all effects descriptors in configuration file
     status_t loadEffects(cnode *root, Vector <EffectDesc *>& effects);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index af7be52..0d12060 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -476,14 +476,14 @@
     }
     ALOGV("startOutput()");
     sp<AudioPlaybackClient> client;
-    sp<AudioPolicyEffects>audioPolicyEffects;
+    sp<AudioPolicyEffects> audioPolicyEffects;
 
     getPlaybackClientAndEffects(portId, client, audioPolicyEffects, __func__);
 
     if (audioPolicyEffects != 0) {
         // create audio processors according to stream
-        status_t status = audioPolicyEffects->addOutputSessionEffects(
-            client->io, client->stream, client->session);
+        status_t status = audioPolicyEffects->addOutputSessionEffects(client->io, client->stream,
+                                                                      client->session);
         if (status != NO_ERROR && status != ALREADY_EXISTS) {
             ALOGW("Failed to add effects on session %d", client->session);
         }
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 974ae38..bc3c199 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -46,6 +46,7 @@
 
 #include <system/audio.h>
 #include <system/audio_policy.h>
+#include <AudioPolicyConfig.h>
 #include <AudioPolicyManager.h>
 
 namespace android {
@@ -185,7 +186,10 @@
 
 static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
 {
-    AudioPolicyManager *apm = new AudioPolicyManager(clientInterface);
+    auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback();  // This can't fail.
+    AudioPolicyManager *apm = new AudioPolicyManager(
+            config, loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
+            clientInterface);
     status_t status = apm->initialize();
     if (status != NO_ERROR) {
         delete apm;
@@ -259,7 +263,8 @@
     }
 
     // load audio processing modules
-    sp<AudioPolicyEffects> audioPolicyEffects = new AudioPolicyEffects();
+    const sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
+    sp<AudioPolicyEffects> audioPolicyEffects = new AudioPolicyEffects(effectsFactoryHal);
     sp<UidPolicy> uidPolicy = new UidPolicy(this);
     sp<SensorPrivacyPolicy> sensorPrivacyPolicy = new SensorPrivacyPolicy(this);
     {
@@ -278,7 +283,7 @@
         AudioDeviceTypeAddrVector devices;
         bool hasSpatializer = mAudioPolicyManager->canBeSpatialized(&attr, nullptr, devices);
         if (hasSpatializer) {
-            mSpatializer = Spatializer::create(this);
+            mSpatializer = Spatializer::create(this, effectsFactoryHal);
         }
         if (mSpatializer == nullptr) {
             // No spatializer created, signal the reason: NO_INIT a failure, OK means intended.
@@ -1694,7 +1699,7 @@
     }
 }
 
-void AudioPolicyService::UidPolicy::onUidProcAdjChanged(uid_t uid __unused) {
+void AudioPolicyService::UidPolicy::onUidProcAdjChanged(uid_t uid __unused, int32_t adj __unused) {
 }
 
 void AudioPolicyService::UidPolicy::updateOverrideUid(uid_t uid, bool active, bool insert) {
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 59aabac..981951a 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -484,7 +484,7 @@
         void onUidIdle(uid_t uid, bool disabled) override;
         void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
                 int32_t capability) override;
-        void onUidProcAdjChanged(uid_t uid) override;
+        void onUidProcAdjChanged(uid_t uid, int32_t adj) override;
 
         void addOverrideUid(uid_t uid, bool active) { updateOverrideUid(uid, active, true); }
         void removeOverrideUid(uid_t uid) { updateOverrideUid(uid, false, false); }
@@ -847,7 +847,7 @@
                 const TrackSecondaryOutputsMap& trackSecondaryOutputs) override;
 
         status_t setDeviceConnectedState(
-                const struct audio_port_v7 *port, bool connected) override;
+                const struct audio_port_v7 *port, media::DeviceConnectedState state) override;
 
         status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) override;
 
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 95b8e7c..ee2e0eb 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -30,7 +30,6 @@
 #include <audio_utils/fixedfft.h>
 #include <cutils/bitops.h>
 #include <hardware/sensors.h>
-#include <media/audiohal/EffectsFactoryHalInterface.h>
 #include <media/stagefright/foundation/AHandler.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/MediaMetricsItem.h>
@@ -215,18 +214,17 @@
 };
 
 // ---------------------------------------------------------------------------
-sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
+sp<Spatializer> Spatializer::create(SpatializerPolicyCallback* callback,
+                                    const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
     sp<Spatializer> spatializer;
 
-    sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
     if (effectsFactoryHal == nullptr) {
         ALOGW("%s failed to create effect factory interface", __func__);
         return spatializer;
     }
 
     std::vector<effect_descriptor_t> descriptors;
-    status_t status =
-            effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
+    status_t status = effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
     if (status != NO_ERROR) {
         ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
         return spatializer;
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index 23de0c0..0d4d3f6 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -27,6 +27,7 @@
 #include <audio_utils/SimpleLog.h>
 #include <math.h>
 #include <media/AudioEffect.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
 #include <media/VectorRecorder.h>
 #include <media/audiohal/EffectHalInterface.h>
 #include <media/stagefright/foundation/ALooper.h>
@@ -95,7 +96,8 @@
                     private SpatializerPoseController::Listener,
                     public virtual AudioSystem::SupportedLatencyModesCallback {
   public:
-    static sp<Spatializer> create(SpatializerPolicyCallback *callback);
+    static sp<Spatializer> create(SpatializerPolicyCallback* callback,
+                                  const sp<EffectsFactoryHalInterface>& effectsFactoryHal);
 
            ~Spatializer() override;
 
diff --git a/services/audiopolicy/service/SpatializerPoseController.h b/services/audiopolicy/service/SpatializerPoseController.h
index 9d78188..7fa4f86 100644
--- a/services/audiopolicy/service/SpatializerPoseController.h
+++ b/services/audiopolicy/service/SpatializerPoseController.h
@@ -121,9 +121,7 @@
     mutable std::timed_mutex mMutex;
     Listener* const mListener;
     const std::chrono::microseconds mSensorPeriod;
-    // Order matters for the following two members to ensure correct destruction.
     std::unique_ptr<media::HeadTrackingProcessor> mProcessor;
-    std::unique_ptr<media::SensorPoseProvider> mPoseProvider;
     int32_t mHeadSensor = media::SensorPoseProvider::INVALID_HANDLE;
     int32_t mScreenSensor = media::SensorPoseProvider::INVALID_HANDLE;
     std::optional<media::HeadTrackingMode> mActualMode;
@@ -146,6 +144,9 @@
         4 /* vectorSize */, std::chrono::minutes(1), 10 /* maxLogLine */,
         { 3 } /* delimiterIdx */};
 
+    // Next to last variable as releasing this stops the callbacks
+    std::unique_ptr<media::SensorPoseProvider> mPoseProvider;
+
     // It's important that mThread is the last variable in this class
     // since we starts mThread in initializer list
     std::thread mThread;
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index bf82680..285b354 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -19,19 +19,20 @@
     ],
 
     shared_libs: [
+        "framework-permission-aidl-cpp",
         "libaudioclient",
         "libaudiofoundation",
         "libaudiopolicy",
         "libaudiopolicymanagerdefault",
         "libbase",
+        "libbinder",
+        "libcutils",
         "libhidlbase",
         "liblog",
         "libmedia_helper",
         "libutils",
         "libcutils",
         "libxml2",
-        "framework-permission-aidl-cpp",
-        "libbinder",
     ],
 
     static_libs: [
@@ -73,17 +74,19 @@
     require_root: true,
 
     shared_libs: [
-        "libaudiofoundation",
+        "audioclient-types-aidl-cpp",
         "libaudioclient",
+        "libaudioclient_aidl_conversion",
+        "libaudiofoundation",
         "libaudiopolicymanagerdefault",
+        "libcutils",
         "liblog",
         "libmedia_helper",
-        "libutils",
-        "libaudioclient_aidl_conversion",
-        "libstagefright_foundation",
         "libshmemcompat",
         "libshmemutil",
-        "audioclient-types-aidl-cpp",
+        "libstagefright_foundation",
+        "libutils",
+        "libxml2",
     ],
 
     static_libs: ["libaudiopolicycomponents"],
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index 6eca7cc..3629c16 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -103,10 +103,11 @@
         ++mAudioPortListUpdateCount;
     }
 
-    status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) override {
-        if (connected) {
+    status_t setDeviceConnectedState(const struct audio_port_v7 *port,
+                                     media::DeviceConnectedState state) override {
+        if (state == media::DeviceConnectedState::CONNECTED) {
             mConnectedDevicePorts.push_back(*port);
-        } else {
+        } else if (state == media::DeviceConnectedState::DISCONNECTED){
             mDisconnectedDevicePorts.push_back(*port);
         }
         return NO_ERROR;
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index 0c04e35..71e34e3 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -96,8 +96,8 @@
             const TrackSecondaryOutputsMap& trackSecondaryOutputs __unused) override {
         return NO_INIT;
     }
-    status_t setDeviceConnectedState(
-            const struct audio_port_v7 *port __unused, bool connected __unused) override {
+    status_t setDeviceConnectedState(const struct audio_port_v7 *port __unused,
+                                     media::DeviceConnectedState state __unused) override {
         return NO_INIT;
     }
     status_t invalidateTracks(const std::vector<audio_port_handle_t>& /*portIds*/) override {
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index 2a7a060..31ee252 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -22,9 +22,13 @@
 class AudioPolicyTestManager : public AudioPolicyManager {
   public:
     explicit AudioPolicyTestManager(AudioPolicyClientInterface *clientInterface)
-            : AudioPolicyManager(clientInterface, true /*forTesting*/) { }
+            : AudioPolicyTestManager(AudioPolicyConfig::createDefault(), clientInterface) {}
+    AudioPolicyTestManager(const sp<const AudioPolicyConfig>& config,
+            AudioPolicyClientInterface *clientInterface)
+            : AudioPolicyManager(config,
+                    loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
+                    clientInterface) {}
     using AudioPolicyManager::getConfig;
-    using AudioPolicyManager::loadConfig;
     using AudioPolicyManager::initialize;
     using AudioPolicyManager::getOutputs;
     using AudioPolicyManager::getAvailableOutputDevices;
diff --git a/services/audiopolicy/tests/audio_health_tests.cpp b/services/audiopolicy/tests/audio_health_tests.cpp
index 798332c..70a3022 100644
--- a/services/audiopolicy/tests/audio_health_tests.cpp
+++ b/services/audiopolicy/tests/audio_health_tests.cpp
@@ -21,6 +21,7 @@
 
 #include <gtest/gtest.h>
 
+#include <AudioPolicyConfig.h>
 #include <media/AudioSystem.h>
 #include <media/TypeConverter.h>
 #include <system/audio.h>
@@ -65,19 +66,17 @@
     }
     free(audioPorts);
 
-    AudioPolicyManagerTestClient client;
-    AudioPolicyTestManager manager(&client);
-    manager.loadConfig();
-    ASSERT_NE("AudioPolicyConfig::setDefault", manager.getConfig().getSource());
+    auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback();
+    ASSERT_NE(AudioPolicyConfig::kDefaultConfigSource, config->getSource());
 
-    for (auto desc : manager.getConfig().getInputDevices()) {
+    for (const auto& desc : config->getInputDevices()) {
         if (attachedDevices.find(desc->type()) == attachedDevices.end()) {
             std::string deviceType;
             (void)DeviceConverter::toString(desc->type(), deviceType);
             ADD_FAILURE() << "Input device \"" << deviceType << "\" not found";
         }
     }
-    for (auto desc : manager.getConfig().getOutputDevices()) {
+    for (const auto& desc : config->getOutputDevices()) {
         if (attachedDevices.find(desc->type()) == attachedDevices.end()) {
             std::string deviceType;
             (void)DeviceConverter::toString(desc->type(), deviceType);
@@ -87,13 +86,13 @@
 }
 
 TEST(AudioHealthTest, ConnectSupportedDevice) {
+    auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback();
+    ASSERT_NE(AudioPolicyConfig::kDefaultConfigSource, config->getSource());
     AudioPolicyManagerTestClient client;
-    AudioPolicyTestManager manager(&client);
-    manager.loadConfig();
-    ASSERT_NE("AudioPolicyConfig::setDefault", manager.getConfig().getSource());
+    AudioPolicyTestManager manager(config, &client);
 
     DeviceVector devices;
-    for (const auto& hwModule : manager.getConfig().getHwModules()) {
+    for (const auto& hwModule : config->getHwModules()) {
         for (const auto& profile : hwModule->getOutputProfiles()) {
             devices.merge(profile->getSupportedDevices());
         }
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 412ab19..97a1e0d 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -92,11 +92,44 @@
 
 } // namespace
 
+TEST(AudioPolicyConfigTest, DefaultConfigForTestsIsEmpty) {
+    auto config = AudioPolicyConfig::createWritableForTests();
+    EXPECT_TRUE(config->getSource().empty());
+    EXPECT_TRUE(config->getHwModules().isEmpty());
+    EXPECT_TRUE(config->getInputDevices().isEmpty());
+    EXPECT_TRUE(config->getOutputDevices().isEmpty());
+}
+
+TEST(AudioPolicyConfigTest, FallbackToDefault) {
+    auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback(
+            base::GetExecutableDirectory() + "/test_invalid_audio_policy_configuration.xml");
+    EXPECT_EQ(AudioPolicyConfig::kDefaultConfigSource, config->getSource());
+}
+
+TEST(AudioPolicyConfigTest, LoadForTests) {
+    {
+        auto result = AudioPolicyConfig::loadFromCustomXmlConfigForTests(
+                base::GetExecutableDirectory() + "/test_invalid_audio_policy_configuration.xml");
+        EXPECT_FALSE(result.ok());
+    }
+    {
+        const std::string source =
+                base::GetExecutableDirectory() + "/test_audio_policy_configuration.xml";
+        auto result = AudioPolicyConfig::loadFromCustomXmlConfigForTests(source);
+        ASSERT_TRUE(result.ok());
+        EXPECT_EQ(source, result.value()->getSource());
+        EXPECT_FALSE(result.value()->getHwModules().isEmpty());
+        EXPECT_FALSE(result.value()->getInputDevices().isEmpty());
+        EXPECT_FALSE(result.value()->getOutputDevices().isEmpty());
+    }
+}
+
 TEST(AudioPolicyManagerTestInit, EngineFailure) {
     AudioPolicyTestClient client;
-    AudioPolicyTestManager manager(&client);
-    manager.getConfig().setDefault();
-    manager.getConfig().setEngineLibraryNameSuffix("non-existent");
+    auto config = AudioPolicyConfig::createWritableForTests();
+    config->setDefault();
+    config->setEngineLibraryNameSuffix("non-existent");
+    AudioPolicyTestManager manager(config, &client);
     ASSERT_EQ(NO_INIT, manager.initialize());
     ASSERT_EQ(NO_INIT, manager.initCheck());
 }
@@ -104,41 +137,12 @@
 TEST(AudioPolicyManagerTestInit, ClientFailure) {
     AudioPolicyTestClient client;
     AudioPolicyTestManager manager(&client);
-    manager.getConfig().setDefault();
     // Since the default client fails to open anything,
     // APM should indicate that the initialization didn't succeed.
     ASSERT_EQ(NO_INIT, manager.initialize());
     ASSERT_EQ(NO_INIT, manager.initCheck());
 }
 
-// Verifies that a failure while loading a config doesn't leave
-// APM config in a "dirty" state. Since AudioPolicyConfig object
-// is a proxy for the data hosted by APM, it isn't possible
-// to "deep copy" it, and thus we have to test its elements
-// individually.
-TEST(AudioPolicyManagerTestInit, ConfigLoadingIsTransactional) {
-    AudioPolicyTestClient client;
-    AudioPolicyTestManager manager(&client);
-    ASSERT_TRUE(manager.getConfig().getHwModules().isEmpty());
-    ASSERT_TRUE(manager.getConfig().getInputDevices().isEmpty());
-    ASSERT_TRUE(manager.getConfig().getOutputDevices().isEmpty());
-    status_t status = deserializeAudioPolicyFile(
-            (base::GetExecutableDirectory() +
-                    "/test_invalid_audio_policy_configuration.xml").c_str(),
-            &manager.getConfig());
-    ASSERT_NE(NO_ERROR, status);
-    EXPECT_TRUE(manager.getConfig().getHwModules().isEmpty());
-    EXPECT_TRUE(manager.getConfig().getInputDevices().isEmpty());
-    EXPECT_TRUE(manager.getConfig().getOutputDevices().isEmpty());
-    status = deserializeAudioPolicyFile(
-            (base::GetExecutableDirectory() + "/test_audio_policy_configuration.xml").c_str(),
-            &manager.getConfig());
-    ASSERT_EQ(NO_ERROR, status);
-    EXPECT_FALSE(manager.getConfig().getHwModules().isEmpty());
-    EXPECT_FALSE(manager.getConfig().getInputDevices().isEmpty());
-    EXPECT_FALSE(manager.getConfig().getOutputDevices().isEmpty());
-}
-
 
 class PatchCountCheck {
   public:
@@ -200,6 +204,7 @@
     static audio_port_handle_t getDeviceIdFromPatch(const struct audio_patch* patch);
     virtual AudioPolicyManagerTestClient* getClient() { return new AudioPolicyManagerTestClient; }
 
+    sp<AudioPolicyConfig> mConfig;
     std::unique_ptr<AudioPolicyManagerTestClient> mClient;
     std::unique_ptr<AudioPolicyTestManager> mManager;
 
@@ -208,8 +213,8 @@
 
 void AudioPolicyManagerTest::SetUp() {
     mClient.reset(getClient());
-    mManager.reset(new AudioPolicyTestManager(mClient.get()));
     ASSERT_NO_FATAL_FAILURE(SetUpManagerConfig());  // Subclasses may want to customize the config.
+    mManager.reset(new AudioPolicyTestManager(mConfig, mClient.get()));
     ASSERT_EQ(NO_ERROR, mManager->initialize());
     ASSERT_EQ(NO_ERROR, mManager->initCheck());
 }
@@ -220,7 +225,8 @@
 }
 
 void AudioPolicyManagerTest::SetUpManagerConfig() {
-    mManager->getConfig().setDefault();
+    mConfig = AudioPolicyConfig::createWritableForTests();
+    mConfig->setDefault();
 }
 
 void AudioPolicyManagerTest::dumpToLog() {
@@ -467,7 +473,6 @@
 void AudioPolicyManagerTestMsd::SetUpManagerConfig() {
     // TODO: Consider using Serializer to load part of the config from a string.
     ASSERT_NO_FATAL_FAILURE(AudioPolicyManagerTest::SetUpManagerConfig());
-    AudioPolicyConfig& config = mManager->getConfig();
     mMsdOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_BUS);
     sp<AudioProfile> pcmOutputProfile = new AudioProfile(
             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, k48000SamplingRate);
@@ -483,26 +488,26 @@
     sp<AudioProfile> pcmInputProfile = new AudioProfile(
             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 44100);
     mMsdInputDevice->addAudioProfile(pcmInputProfile);
-    config.addDevice(mMsdOutputDevice);
-    config.addDevice(mMsdInputDevice);
+    mConfig->addDevice(mMsdOutputDevice);
+    mConfig->addDevice(mMsdInputDevice);
 
     if (mExpectedAudioPatchCount == 2) {
         // Add SPDIF device with PCM output profile as a second device for dual MSD audio patching.
         mSpdifDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPDIF);
         mSpdifDevice->addAudioProfile(pcmOutputProfile);
-        config.addDevice(mSpdifDevice);
+        mConfig->addDevice(mSpdifDevice);
 
         sp<OutputProfile> spdifOutputProfile = new OutputProfile("spdif output");
         spdifOutputProfile->addAudioProfile(pcmOutputProfile);
         spdifOutputProfile->addSupportedDevice(mSpdifDevice);
-        config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+        mConfig->getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
                 addOutputProfile(spdifOutputProfile);
     }
 
     sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
-    HwModuleCollection modules = config.getHwModules();
+    HwModuleCollection modules = mConfig->getHwModules();
     modules.add(msdModule);
-    config.setHwModules(modules);
+    mConfig->setHwModules(modules);
 
     sp<OutputProfile> msdOutputProfile = new OutputProfile("msd input");
     msdOutputProfile->addAudioProfile(pcmOutputProfile);
@@ -530,15 +535,15 @@
     // of streams that are not supported by MSD.
     sp<AudioProfile> dtsOutputProfile = new AudioProfile(
             AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, k48000SamplingRate);
-    config.getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
+    mConfig->getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
     sp<OutputProfile> primaryEncodedOutputProfile = new OutputProfile("encoded");
     primaryEncodedOutputProfile->addAudioProfile(dtsOutputProfile);
     primaryEncodedOutputProfile->setFlags(AUDIO_OUTPUT_FLAG_DIRECT);
-    primaryEncodedOutputProfile->addSupportedDevice(config.getDefaultOutputDevice());
-    config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+    primaryEncodedOutputProfile->addSupportedDevice(mConfig->getDefaultOutputDevice());
+    mConfig->getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
             addOutputProfile(primaryEncodedOutputProfile);
 
-    mDefaultOutputDevice = config.getDefaultOutputDevice();
+    mDefaultOutputDevice = mConfig->getDefaultOutputDevice();
     if (mExpectedAudioPatchCount == 2) {
         mSpdifDevice->addAudioProfile(dtsOutputProfile);
         primaryEncodedOutputProfile->addSupportedDevice(mSpdifDevice);
@@ -549,12 +554,12 @@
     sp<AudioProfile> iec958InputProfile = new AudioProfile(
             AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_INDEX_MASK_24, k48000SamplingRate);
     mHdmiInputDevice->addAudioProfile(iec958InputProfile);
-    config.addDevice(mHdmiInputDevice);
+    mConfig->addDevice(mHdmiInputDevice);
     sp<InputProfile> hdmiInputProfile = new InputProfile("hdmi input");
     hdmiInputProfile->addAudioProfile(iec958InputProfile);
     hdmiInputProfile->setFlags(AUDIO_INPUT_FLAG_DIRECT);
     hdmiInputProfile->addSupportedDevice(mHdmiInputDevice);
-    config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+    mConfig->getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
             addInputProfile(hdmiInputProfile);
 }
 
@@ -721,7 +726,7 @@
     int countDirectProfilesPrimary = 0;
     const auto& primary = mManager->getConfig().getHwModules()
             .getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY);
-    for (const auto outputProfile : primary->getOutputProfiles()) {
+    for (const auto& outputProfile : primary->getOutputProfiles()) {
         if (outputProfile->asAudioPort()->isDirectOutput()) {
             countDirectProfilesPrimary += outputProfile->asAudioPort()->getAudioProfiles().size();
         }
@@ -731,7 +736,7 @@
     int countDirectProfilesMsd = 0;
     const auto& msd = mManager->getConfig().getHwModules()
             .getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
-    for (const auto outputProfile : msd->getOutputProfiles()) {
+    for (const auto& outputProfile : msd->getOutputProfiles()) {
         if (outputProfile->asAudioPort()->isDirectOutput()) {
             countDirectProfilesMsd += outputProfile->asAudioPort()->getAudioProfiles().size();
         }
@@ -922,9 +927,9 @@
         sExecutableDir + "test_audio_policy_configuration.xml";
 
 void AudioPolicyManagerTestWithConfigurationFile::SetUpManagerConfig() {
-    status_t status = deserializeAudioPolicyFile(getConfigFile().c_str(), &mManager->getConfig());
-    ASSERT_EQ(NO_ERROR, status);
-    mManager->getConfig().setSource(getConfigFile());
+    auto result = AudioPolicyConfig::loadFromCustomXmlConfigForTests(getConfigFile());
+    ASSERT_TRUE(result.ok());
+    mConfig = result.value();
 }
 
 TEST_F(AudioPolicyManagerTestWithConfigurationFile, InitSuccess) {
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a2aafdf..cecced4 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2602,6 +2602,19 @@
     }
 }
 
+void CameraService::notifyMonitoredUids(const std::unordered_set<uid_t> &notifyUidSet) {
+    Mutex::Autolock lock(mStatusListenerLock);
+
+    for (const auto& it : mListenerList) {
+        if (notifyUidSet.find(it->getListenerUid()) != notifyUidSet.end()) {
+            ALOGV("%s: notifying uid %d", __FUNCTION__, it->getListenerUid());
+            auto ret = it->getListener()->onCameraAccessPrioritiesChanged();
+            it->handleBinderStatus(ret, "%s: Failed to trigger permission callback for %d:%d: %d",
+                    __FUNCTION__, it->getListenerUid(), it->getListenerPid(), ret.exceptionCode());
+        }
+    }
+}
+
 Status CameraService::notifyDeviceStateChange(int64_t newState) {
     const int pid = CameraThreadState::getCallingPid();
     const int selfPid = getpid();
@@ -2823,7 +2836,7 @@
         // permissions the listener process has / whether it is a vendor listener. Since it might be
         // eligible to listen to other camera ids.
         mListenerList.emplace_back(serviceListener);
-        mUidPolicy->registerMonitorUid(clientUid);
+        mUidPolicy->registerMonitorUid(clientUid, /*openCamera*/false);
     }
 
     /* Collect current devices and status */
@@ -2891,7 +2904,7 @@
         Mutex::Autolock lock(mStatusListenerLock);
         for (auto it = mListenerList.begin(); it != mListenerList.end(); it++) {
             if (IInterface::asBinder((*it)->getListener()) == IInterface::asBinder(listener)) {
-                mUidPolicy->unregisterMonitorUid((*it)->getListenerUid());
+                mUidPolicy->unregisterMonitorUid((*it)->getListenerUid(), /*closeCamera*/false);
                 IInterface::asBinder(listener)->unlinkToDeath(*it);
                 mListenerList.erase(it);
                 return Status::ok();
@@ -3680,7 +3693,7 @@
     // Transition device availability listeners from PRESENT -> NOT_AVAILABLE
     sCameraService->updateStatus(StatusInternal::NOT_AVAILABLE, mCameraIdStr);
 
-    sCameraService->mUidPolicy->registerMonitorUid(mClientUid);
+    sCameraService->mUidPolicy->registerMonitorUid(mClientUid, /*openCamera*/true);
 
     // Notify listeners of camera open/close status
     sCameraService->updateOpenCloseStatus(mCameraIdStr, true/*open*/, mClientPackageName);
@@ -3788,7 +3801,7 @@
     }
     mOpsCallback.clear();
 
-    sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid);
+    sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid, /*closeCamera*/true);
 
     // Notify listeners of camera open/close status
     sCameraService->updateOpenCloseStatus(mCameraIdStr, false/*open*/, mClientPackageName);
@@ -3988,24 +4001,51 @@
     }
 }
 
-void CameraService::UidPolicy::onUidProcAdjChanged(uid_t uid) {
-    bool procAdjChange = false;
+/**
+ * When the OOM adj of the uid owning the camera changes, a different uid waiting on camera
+ * privileges may take precedence if the owner's new OOM adj is greater than the waiting package.
+ * Here, we track which monitoredUid has the camera, and track its adj relative to other
+ * monitoredUids. If it is revised above some other monitoredUid, signal
+ * onCameraAccessPrioritiesChanged. This only needs to capture the case where there are two
+ * foreground apps in split screen - state changes will capture all other cases.
+ */
+void CameraService::UidPolicy::onUidProcAdjChanged(uid_t uid, int32_t adj) {
+    std::unordered_set<uid_t> notifyUidSet;
     {
         Mutex::Autolock _l(mUidLock);
-        if (mMonitoredUids.find(uid) != mMonitoredUids.end()) {
-            procAdjChange = true;
+        auto it = mMonitoredUids.find(uid);
+
+        if (it != mMonitoredUids.end()) {
+            if (it->second.hasCamera) {
+                for (auto &monitoredUid : mMonitoredUids) {
+                    if (monitoredUid.first != uid && adj > monitoredUid.second.procAdj) {
+                        notifyUidSet.emplace(monitoredUid.first);
+                    }
+                }
+                notifyUidSet.emplace(uid);
+            } else {
+                for (auto &monitoredUid : mMonitoredUids) {
+                    if (monitoredUid.second.hasCamera && adj < monitoredUid.second.procAdj) {
+                        notifyUidSet.emplace(uid);
+                    }
+                }
+            }
+            it->second.procAdj = adj;
         }
     }
 
-    if (procAdjChange) {
+    if (notifyUidSet.size() > 0) {
         sp<CameraService> service = mService.promote();
         if (service != nullptr) {
-            service->notifyMonitoredUids();
+            service->notifyMonitoredUids(notifyUidSet);
         }
     }
 }
 
-void CameraService::UidPolicy::registerMonitorUid(uid_t uid) {
+/**
+ * Register a uid for monitoring, and note whether it owns a camera.
+ */
+void CameraService::UidPolicy::registerMonitorUid(uid_t uid, bool openCamera) {
     Mutex::Autolock _l(mUidLock);
     auto it = mMonitoredUids.find(uid);
     if (it != mMonitoredUids.end()) {
@@ -4013,18 +4053,28 @@
     } else {
         MonitoredUid monitoredUid;
         monitoredUid.procState = ActivityManager::PROCESS_STATE_NONEXISTENT;
+        monitoredUid.procAdj = resource_policy::UNKNOWN_ADJ;
         monitoredUid.refCount = 1;
-        mMonitoredUids.emplace(std::pair<uid_t, MonitoredUid>(uid, monitoredUid));
+        it = mMonitoredUids.emplace(std::pair<uid_t, MonitoredUid>(uid, monitoredUid)).first;
+    }
+
+    if (openCamera) {
+        it->second.hasCamera = true;
     }
 }
 
-void CameraService::UidPolicy::unregisterMonitorUid(uid_t uid) {
+/**
+ * Unregister a uid for monitoring, and note whether it lost ownership of a camera.
+ */
+void CameraService::UidPolicy::unregisterMonitorUid(uid_t uid, bool closeCamera) {
     Mutex::Autolock _l(mUidLock);
     auto it = mMonitoredUids.find(uid);
     if (it != mMonitoredUids.end()) {
         it->second.refCount--;
         if (it->second.refCount == 0) {
             mMonitoredUids.erase(it);
+        } else if (closeCamera) {
+            it->second.hasCamera = false;
         }
     } else {
         ALOGE("%s: Trying to unregister uid: %d which is not monitored!", __FUNCTION__, uid);
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index ecec15f..8c57d26 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -233,6 +233,7 @@
 
     // Monitored UIDs availability notification
     void                notifyMonitoredUids();
+    void                notifyMonitoredUids(const std::unordered_set<uid_t> &notifyUidSet);
 
     // Stores current open session device info in temp file.
     void cacheDump();
@@ -763,13 +764,13 @@
         void onUidIdle(uid_t uid, bool disabled) override;
         void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
                 int32_t capability) override;
-        void onUidProcAdjChanged(uid_t uid) override;
+        void onUidProcAdjChanged(uid_t uid, int adj) override;
 
         void addOverrideUid(uid_t uid, String16 callingPackage, bool active);
         void removeOverrideUid(uid_t uid, String16 callingPackage);
 
-        void registerMonitorUid(uid_t uid);
-        void unregisterMonitorUid(uid_t uid);
+        void registerMonitorUid(uid_t uid, bool openCamera);
+        void unregisterMonitorUid(uid_t uid, bool closeCamera);
 
         // Implementation of IServiceManager::LocalRegistrationCallback
         virtual void onServiceRegistration(const String16& name,
@@ -784,6 +785,8 @@
 
         struct MonitoredUid {
             int32_t procState;
+            int32_t procAdj;
+            bool hasCamera;
             size_t refCount;
         };
 
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.cpp b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
index e80064a..28dff7d 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.cpp
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "CameraServiceWatchdog"
 
 #include "CameraServiceWatchdog.h"
+#include "android/set_abort_message.h"
 #include "utils/CameraServiceProxyWrapper.h"
 
 namespace android {
@@ -36,12 +37,15 @@
     {
         AutoMutex _l(mWatchdogLock);
 
-        for (auto it = tidToCycleCounterMap.begin(); it != tidToCycleCounterMap.end(); it++) {
+        for (auto it = mTidMap.begin(); it != mTidMap.end(); it++) {
             uint32_t currentThreadId = it->first;
 
-            tidToCycleCounterMap[currentThreadId]++;
+            mTidMap[currentThreadId].cycles++;
 
-            if (tidToCycleCounterMap[currentThreadId] >= mMaxCycles) {
+            if (mTidMap[currentThreadId].cycles >= mMaxCycles) {
+                std::string abortMessage = getAbortMessage(getpid(), currentThreadId,
+                        mTidMap[currentThreadId].functionName);
+                android_set_abort_message(abortMessage.c_str());
                 ALOGW("CameraServiceWatchdog triggering abort for pid: %d tid: %d", getpid(),
                         currentThreadId);
                 mCameraServiceProxyWrapper->logClose(mCameraId, 0 /*latencyMs*/,
@@ -56,13 +60,20 @@
     return true;
 }
 
+std::string CameraServiceWatchdog::getAbortMessage(int pid, int tid, std::string functionName) {
+    std::string res = "CameraServiceWatchdog triggering abort during "
+            + functionName + " | pid: " + std::to_string(pid)
+            + " tid: " + std::to_string(tid);
+    return res;
+}
+
 void CameraServiceWatchdog::requestExit()
 {
     Thread::requestExit();
 
     AutoMutex _l(mWatchdogLock);
 
-    tidToCycleCounterMap.clear();
+    mTidMap.clear();
 
     if (mPause) {
         mPause = false;
@@ -85,18 +96,21 @@
 {
     AutoMutex _l(mWatchdogLock);
 
-    tidToCycleCounterMap.erase(tid);
+    mTidMap.erase(tid);
 
-    if (tidToCycleCounterMap.empty()) {
+    if (mTidMap.empty()) {
         mPause = true;
     }
 }
 
-void CameraServiceWatchdog::start(uint32_t tid)
+void CameraServiceWatchdog::start(uint32_t tid, const char* functionName)
 {
     AutoMutex _l(mWatchdogLock);
 
-    tidToCycleCounterMap[tid] = 0;
+    MonitoredFunction monitoredFunction = {};
+    monitoredFunction.cycles = 0;
+    monitoredFunction.functionName = functionName;
+    mTidMap[tid] = monitoredFunction;
 
     if (mPause) {
         mPause = false;
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.h b/services/camera/libcameraservice/CameraServiceWatchdog.h
index 6617873..6f8858a 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.h
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.h
@@ -40,9 +40,9 @@
 #include "utils/CameraServiceProxyWrapper.h"
 
 // Used to wrap the call of interest in start and stop calls
-#define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid())
+#define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid(), __FUNCTION__)
 #define WATCH_CUSTOM_TIMER(toMonitor, cycles, cycleLength) \
-        watchThread([&]() { return toMonitor;}, gettid(), cycles, cycleLength);
+        watchThread([&]() { return toMonitor;}, gettid(), __FUNCTION__, cycles, cycleLength);
 
 // Default cycles and cycle length values used to calculate permitted elapsed time
 const static size_t   kMaxCycles     = 100;
@@ -52,6 +52,11 @@
 
 class CameraServiceWatchdog : public Thread {
 
+struct MonitoredFunction {
+    uint32_t cycles;
+    std::string functionName;
+};
+
 public:
     explicit CameraServiceWatchdog(const String8 &cameraId,
             std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
@@ -75,7 +80,8 @@
 
     /** Used to wrap monitored calls in start and stop functions using custom timer values */
     template<typename T>
-    auto watchThread(T func, uint32_t tid, uint32_t cycles, uint32_t cycleLength) {
+    auto watchThread(T func, uint32_t tid, const char* functionName, uint32_t cycles,
+            uint32_t cycleLength) {
         decltype(func()) res;
 
         if (cycles != mMaxCycles || cycleLength != mCycleLengthMs) {
@@ -91,17 +97,17 @@
             status_t status = tempWatchdog->run("CameraServiceWatchdog");
             if (status != OK) {
                 ALOGE("Unable to watch thread: %s (%d)", strerror(-status), status);
-                res = watchThread(func, tid);
+                res = watchThread(func, tid, functionName);
                 return res;
             }
 
-            res = tempWatchdog->watchThread(func, tid);
+            res = tempWatchdog->watchThread(func, tid, functionName);
             tempWatchdog->requestExit();
             tempWatchdog.clear();
         } else {
             // If custom timer values are equivalent to set class timer values, use
             // current thread
-            res = watchThread(func, tid);
+            res = watchThread(func, tid, functionName);
         }
 
         return res;
@@ -109,12 +115,12 @@
 
     /** Used to wrap monitored calls in start and stop functions using class timer values */
     template<typename T>
-    auto watchThread(T func, uint32_t tid) {
+    auto watchThread(T func, uint32_t tid, const char* functionName) {
         decltype(func()) res;
         AutoMutex _l(mEnabledLock);
 
         if (mEnabled) {
-            start(tid);
+            start(tid, functionName);
             res = func();
             stop(tid);
         } else {
@@ -130,7 +136,7 @@
      * Start adds a cycle counter for the calling thread. When threadloop is blocked/paused,
      * start() unblocks and starts the watchdog
      */
-    void start(uint32_t tid);
+    void start(uint32_t tid, const char* functionName);
 
     /**
      * If there are no calls left to be monitored, stop blocks/pauses threadloop
@@ -138,6 +144,8 @@
      */
     void stop(uint32_t tid);
 
+    std::string getAbortMessage(int pid, int tid, std::string functionName);
+
     virtual bool    threadLoop();
 
     Mutex           mWatchdogLock;      // Lock for condition variable
@@ -151,7 +159,9 @@
 
     std::shared_ptr<CameraServiceProxyWrapper> mCameraServiceProxyWrapper;
 
-    std::unordered_map<uint32_t, uint32_t> tidToCycleCounterMap; // Thread Id to cycle counter map
+    std::unordered_map<uint32_t, MonitoredFunction> mTidMap; // Thread Id to MonitoredFunction type
+                                                             // which retrieves the num of cycles
+                                                             // and name of the function
 };
 
 }   // namespace android
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index fda6af3..38c615d 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -957,7 +957,7 @@
     bool isHeicCompositeStream = camera3::HeicCompositeStream::isHeicCompositeStream(surfaces[0]);
     bool isJpegRCompositeStream =
         camera3::JpegRCompositeStream::isJpegRCompositeStream(surfaces[0]) &&
-        !mDevice->supportNativeJpegR();
+        !mDevice->isCompositeJpegRDisabled();
     if (isDepthCompositeStream || isHeicCompositeStream || isJpegRCompositeStream) {
         sp<CompositeStream> compositeStream;
         if (isDepthCompositeStream) {
@@ -1851,7 +1851,7 @@
             isCompositeStream = camera3::DepthCompositeStream::isDepthCompositeStream(s) ||
                 camera3::HeicCompositeStream::isHeicCompositeStream(s) ||
                 (camera3::JpegRCompositeStream::isJpegRCompositeStream(s) &&
-                 !mDevice->supportNativeJpegR());
+                 !mDevice->isCompositeJpegRDisabled());
             if (isCompositeStream) {
                 auto compositeIdx = mCompositeStreamMap.indexOfKey(IInterface::asBinder(gbp));
                 if (compositeIdx == NAME_NOT_FOUND) {
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 66077c5..86a0ebc 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -264,7 +264,7 @@
     mOpsActive = true;
 
     // Transition device state to OPEN
-    sCameraService->mUidPolicy->registerMonitorUid(mClientUid);
+    sCameraService->mUidPolicy->registerMonitorUid(mClientUid, /*openCamera*/true);
 
     return OK;
 }
@@ -288,7 +288,7 @@
     }
     mOpsCallback.clear();
 
-    sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid);
+    sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid, /*closeCamera*/true);
 
     return OK;
 }
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 530b03e..919108d 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -113,7 +113,7 @@
      */
     virtual const CameraMetadata& infoPhysical(const String8& physicalId) const = 0;
 
-    virtual bool supportNativeJpegR() const { return false; };
+    virtual bool isCompositeJpegRDisabled() const { return false; };
 
     struct PhysicalCameraSettings {
         std::string cameraId;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index b7c86c6..6f4c04a 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -316,16 +316,16 @@
     return deviceInfo->supportNativeZoomRatio();
 }
 
-bool CameraProviderManager::supportNativeJpegR(const std::string &id) const {
+bool CameraProviderManager::isCompositeJpegRDisabled(const std::string &id) const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
-    return supportNativeJpegRLocked(id);
+    return isCompositeJpegRDisabledLocked(id);
 }
 
-bool CameraProviderManager::supportNativeJpegRLocked(const std::string &id) const {
+bool CameraProviderManager::isCompositeJpegRDisabledLocked(const std::string &id) const {
     auto deviceInfo = findDeviceInfoLocked(id);
     if (deviceInfo == nullptr) return false;
 
-    return deviceInfo->supportNativeJpegR();
+    return deviceInfo->isCompositeJpegRDisabled();
 }
 
 status_t CameraProviderManager::getResourceCost(const std::string &id,
@@ -1120,7 +1120,7 @@
 }
 
 status_t CameraProviderManager::ProviderInfo::DeviceInfo3::deriveJpegRTags(bool maxResolution) {
-    if (kFrameworkJpegRDisabled || mSupportsNativeJpegR) {
+    if (kFrameworkJpegRDisabled || mCompositeJpegRDisabled) {
         return OK;
     }
 
@@ -1166,6 +1166,18 @@
         return OK;
     }
 
+    if (!isConcurrentDynamicRangeCaptureSupported(c,
+                ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10,
+                ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) &&
+            !property_get_bool("ro.camera.enableCompositeAPI0JpegR", false)) {
+        // API0, P010 only Jpeg/R support is meant to be used only as a reference due to possible
+        // impact on quality and performance.
+        // This data path will be turned off by default and individual device builds must enable
+        // 'ro.camera.enableCompositeAPI0JpegR' in order to experiment using it.
+        mCompositeJpegRDisabled = true;
+        return OK;
+    }
+
     getSupportedSizes(c, scalerSizesTag,
             static_cast<android_pixel_format_t>(HAL_PIXEL_FORMAT_BLOB), &supportedBlobSizes);
     getSupportedSizes(c, scalerSizesTag,
@@ -2526,6 +2538,10 @@
             (mDeviceStateOrientationMap.find(newState) != mDeviceStateOrientationMap.end())) {
         mCameraCharacteristics.update(ANDROID_SENSOR_ORIENTATION,
                 &mDeviceStateOrientationMap[newState], 1);
+        if (mCameraCharNoPCOverride.get() != nullptr) {
+            mCameraCharNoPCOverride->update(ANDROID_SENSOR_ORIENTATION,
+                &mDeviceStateOrientationMap[newState], 1);
+        }
     }
 }
 
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index ce4129c..e6e4619 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -248,9 +248,9 @@
     bool supportNativeZoomRatio(const std::string &id) const;
 
     /**
-     * Return true if the camera device has native Jpeg/R support.
+     * Return true if the camera device has no composite Jpeg/R support.
      */
-    bool supportNativeJpegR(const std::string &id) const;
+    bool isCompositeJpegRDisabled(const std::string &id) const;
 
     /**
      * Return the resource cost of this camera device
@@ -573,7 +573,7 @@
 
             bool hasFlashUnit() const { return mHasFlashUnit; }
             bool supportNativeZoomRatio() const { return mSupportNativeZoomRatio; }
-            bool supportNativeJpegR() const { return mSupportsNativeJpegR; }
+            bool isCompositeJpegRDisabled() const { return mCompositeJpegRDisabled; }
             virtual status_t setTorchMode(bool enabled) = 0;
             virtual status_t turnOnTorchWithStrengthLevel(int32_t torchStrength) = 0;
             virtual status_t getTorchStrengthLevel(int32_t *torchStrength) = 0;
@@ -615,14 +615,14 @@
                     mParentProvider(parentProvider), mTorchStrengthLevel(0),
                     mTorchMaximumStrengthLevel(0), mTorchDefaultStrengthLevel(0),
                     mHasFlashUnit(false), mSupportNativeZoomRatio(false),
-                    mPublicCameraIds(publicCameraIds), mSupportsNativeJpegR(false) {}
+                    mPublicCameraIds(publicCameraIds), mCompositeJpegRDisabled(false) {}
             virtual ~DeviceInfo() {}
         protected:
 
             bool mHasFlashUnit; // const after constructor
             bool mSupportNativeZoomRatio; // const after constructor
             const std::vector<std::string>& mPublicCameraIds;
-            bool mSupportsNativeJpegR;
+            bool mCompositeJpegRDisabled;
         };
         std::vector<std::unique_ptr<DeviceInfo>> mDevices;
         std::unordered_set<std::string> mUniqueCameraIds;
@@ -811,7 +811,7 @@
     // No guarantees on the order of traversal
     ProviderInfo::DeviceInfo* findDeviceInfoLocked(const std::string& id) const;
 
-    bool supportNativeJpegRLocked(const std::string &id) const;
+    bool isCompositeJpegRDisabledLocked(const std::string &id) const;
 
     // Map external providers to USB devices in order to handle USB hotplug
     // events for lazy HALs
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index 64098ea..b18cbd4 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -483,7 +483,7 @@
         }
     }
 
-    mSupportsNativeJpegR = mCameraCharacteristics.exists(
+    mCompositeJpegRDisabled = mCameraCharacteristics.exists(
             ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS);
 
     mSystemCameraKind = getSystemCameraKind();
@@ -735,7 +735,7 @@
     camera::device::StreamConfiguration streamConfiguration;
     bool earlyExit = false;
     auto bRes = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
-            String8(mId.c_str()), mCameraCharacteristics, mSupportsNativeJpegR, getMetadata,
+            String8(mId.c_str()), mCameraCharacteristics, mCompositeJpegRDisabled, getMetadata,
             mPhysicalIds, streamConfiguration, overrideForPerfClass, &earlyExit);
 
     if (!bRes.isOk()) {
@@ -802,7 +802,7 @@
             SessionConfigurationUtils::convertToHALStreamCombination(
                     cameraIdAndSessionConfig.mSessionConfiguration,
                     String8(cameraId.c_str()), deviceInfo,
-                    mManager->supportNativeJpegRLocked(cameraId), getMetadata,
+                    mManager->isCompositeJpegRDisabledLocked(cameraId), getMetadata,
                     physicalCameraIds, streamConfiguration,
                     overrideForPerfClass, &shouldExit);
         if (!bStatus.isOk()) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 9de14a2..f5f50a5 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -81,7 +81,7 @@
         mLegacyClient(legacyClient),
         mOperatingMode(NO_MODE),
         mIsConstrainedHighSpeedConfiguration(false),
-        mSupportNativeJpegR(false),
+        mIsCompositeJpegRDisabled(false),
         mStatus(STATUS_UNINITIALIZED),
         mStatusWaiters(0),
         mUsePartialResult(false),
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 5cc5ab0..b1dd135 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -119,7 +119,7 @@
     status_t dumpWatchedEventsToVector(std::vector<std::string> &out) override;
     const CameraMetadata& info() const override;
     const CameraMetadata& infoPhysical(const String8& physicalId) const override;
-    bool supportNativeJpegR() const override { return mSupportNativeJpegR; };
+    bool isCompositeJpegRDisabled() const override { return mIsCompositeJpegRDisabled; };
 
     // Capture and setStreamingRequest will configure streams if currently in
     // idle state
@@ -553,7 +553,7 @@
 
     CameraMetadata             mDeviceInfo;
     bool                       mSupportNativeZoomRatio;
-    bool                       mSupportNativeJpegR;
+    bool                       mIsCompositeJpegRDisabled;
     std::unordered_map<std::string, CameraMetadata> mPhysicalDeviceInfoMap;
 
     CameraMetadata             mRequestTemplateCache[CAMERA_TEMPLATE_COUNT];
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index beef0da..f2a62fa 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -1444,7 +1444,7 @@
     //
     nsecs_t captureInterval = t - mLastCaptureTime;
     if (captureInterval > kSpacingResetIntervalNs) {
-        for (size_t i = 0; i < VsyncEventData::kFrameTimelinesLength; i++) {
+        for (size_t i = 0; i < vsyncEventData.frameTimelinesLength; i++) {
             const auto& timeline = vsyncEventData.frameTimelines[i];
             if (timeline.deadlineTimestamp >= currentTime &&
                     timeline.expectedPresentationTime > minPresentT) {
@@ -1513,7 +1513,7 @@
     // - For variable FPS, or if the capture interval deviates from refresh
     //   interval for more than 5%, find a presentation time closest to the
     //   (lastPresentationTime + captureToPresentOffset) instead.
-    int maxTimelines = std::min(kMaxTimelines, (int)VsyncEventData::kFrameTimelinesLength);
+    int maxTimelines = std::min(kMaxTimelines, (int)vsyncEventData.frameTimelinesLength);
     float biasForShortDelay = 1.0f;
     for (int i = 0; i < maxTimelines; i ++) {
         const auto& vsyncTime = vsyncEventData.frameTimelines[i];
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index e186f13..aa941b0 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -205,7 +205,7 @@
         return res;
     }
     mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
-    mSupportNativeJpegR = manager->supportNativeJpegR(mId.string());
+    mIsCompositeJpegRDisabled = manager->isCompositeJpegRDisabled(mId.string());
 
     std::vector<std::string> physicalCameraIds;
     bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index e25f972..ffd9f01 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -677,7 +677,8 @@
 binder::Status
 convertToHALStreamCombination(
         const SessionConfiguration& sessionConfiguration,
-        const String8 &logicalCameraId, const CameraMetadata &deviceInfo, bool supportNativeJpegR,
+        const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
+        bool isCompositeJpegRDisabled,
         metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
         aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
         bool overrideForPerfClass, bool *earlyExit) {
@@ -822,7 +823,7 @@
                         camera3::HeicCompositeStream::isHeicCompositeStream(surface);
                 bool isJpegRCompositeStream =
                         camera3::JpegRCompositeStream::isJpegRCompositeStream(surface) &&
-                        !supportNativeJpegR;
+                        !isCompositeJpegRDisabled;
                 if (isDepthCompositeStream || isHeicCompositeStream || isJpegRCompositeStream) {
                     // We need to take in to account that composite streams can have
                     // additional internal camera streams.
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index d27144e..dc143da 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -138,7 +138,7 @@
 binder::Status
 convertToHALStreamCombination(
     const SessionConfiguration& sessionConfiguration,
-    const String8 &logicalCameraId, const CameraMetadata &deviceInfo, bool supportNativeJpegR,
+    const String8 &logicalCameraId, const CameraMetadata &deviceInfo, bool isCompositeJpegRDisabled,
     metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
     aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
     bool overrideForPerfClass, bool *earlyExit);
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
index d960024..111c1bf 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
@@ -111,8 +111,8 @@
         bool overrideForPerfClass, bool *earlyExit) {
     aidl::android::hardware::camera::device::StreamConfiguration aidlStreamConfiguration;
     auto ret = convertToHALStreamCombination(sessionConfiguration, logicalCameraId, deviceInfo,
-            false /*supportNativeJpegR*/, getMetadata, physicalCameraIds, aidlStreamConfiguration,
-            overrideForPerfClass, earlyExit);
+            false /*isCompositeJpegRDisabled*/, getMetadata, physicalCameraIds,
+            aidlStreamConfiguration, overrideForPerfClass, earlyExit);
     if (!ret.isOk()) {
         return ret;
     }
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
index cb5e783..158914a 100644
--- a/services/mediametrics/statsd_codec.cpp
+++ b/services/mediametrics/statsd_codec.cpp
@@ -438,7 +438,7 @@
     }
     AStatsEvent_writeInt32(event, hdr10PlusInfo);
 
-    int32_t hdrFormat= -1;
+    int32_t hdrFormat = -1;
     if (item->getInt32("android.media.mediacodec.hdr-format", &hdrFormat)) {
         metrics_proto.set_hdr_format(hdrFormat);
     }
@@ -450,6 +450,61 @@
     }
     AStatsEvent_writeInt64(event, codecId);
 
+    int32_t arrayMode = -1;
+    if (item->getInt32("android.media.mediacodec.array-mode", &arrayMode)) {
+        metrics_proto.set_array_mode(arrayMode);
+    }
+    AStatsEvent_writeInt32(event, arrayMode);
+
+    int32_t operationMode = -1;
+    if (item->getInt32("android.media.mediacodec.operation-mode", &operationMode)) {
+        metrics_proto.set_operation_mode(operationMode);
+    }
+    AStatsEvent_writeInt32(event, operationMode);
+
+    int32_t outputSurface = -1;
+    if (item->getInt32("android.media.mediacodec.output-surface", &outputSurface)) {
+        metrics_proto.set_output_surface(outputSurface);
+    }
+    AStatsEvent_writeInt32(event, outputSurface);
+
+    int32_t appMaxInputSize = -1;
+    if (item->getInt32("android.media.mediacodec.app-max-input-size", &appMaxInputSize)) {
+        metrics_proto.set_app_max_input_size(appMaxInputSize);
+    }
+    AStatsEvent_writeInt32(event, appMaxInputSize);
+
+    int32_t usedMaxInputSize = -1;
+    if (item->getInt32("android.media.mediacodec.used-max-input-size", &usedMaxInputSize)) {
+        metrics_proto.set_used_max_input_size(usedMaxInputSize);
+    }
+    AStatsEvent_writeInt32(event, usedMaxInputSize);
+
+    int32_t codecMaxInputSize = -1;
+    if (item->getInt32("android.media.mediacodec.codec-max-input-size", &codecMaxInputSize)) {
+        metrics_proto.set_codec_max_input_size(codecMaxInputSize);
+    }
+    AStatsEvent_writeInt32(event, codecMaxInputSize);
+
+    int32_t flushCount = -1;
+    if (item->getInt32("android.media.mediacodec.flush-count", &flushCount)) {
+        metrics_proto.set_flush_count(flushCount);
+    }
+    AStatsEvent_writeInt32(event, flushCount);
+
+    int32_t setSurfaceCount = -1;
+    if (item->getInt32("android.media.mediacodec.set-surface-count", &setSurfaceCount)) {
+        metrics_proto.set_set_surface_count(setSurfaceCount);
+    }
+    AStatsEvent_writeInt32(event, setSurfaceCount);
+
+    int32_t resolutionChangeCount = -1;
+    if (item->getInt32("android.media.mediacodec.resolution-change-count",
+            &resolutionChangeCount)) {
+        metrics_proto.set_resolution_change_count(resolutionChangeCount);
+    }
+    AStatsEvent_writeInt32(event, resolutionChangeCount);
+
     int err = AStatsEvent_write(event);
     if (err < 0) {
       ALOGE("Failed to write codec metrics to statsd (%d)", err);
diff --git a/services/mediaresourcemanager/UidObserver.cpp b/services/mediaresourcemanager/UidObserver.cpp
index f321ebc..4bcd325 100644
--- a/services/mediaresourcemanager/UidObserver.cpp
+++ b/services/mediaresourcemanager/UidObserver.cpp
@@ -170,7 +170,7 @@
                                     int32_t /*capability*/) {
 }
 
-void UidObserver::onUidProcAdjChanged(uid_t /*uid*/) {
+void UidObserver::onUidProcAdjChanged(uid_t /*uid*/, int32_t /*adj*/) {
 }
 
 void UidObserver::binderDied(const wp<IBinder>& /*who*/) {
diff --git a/services/mediaresourcemanager/UidObserver.h b/services/mediaresourcemanager/UidObserver.h
index ed76839..b5cc3b9 100644
--- a/services/mediaresourcemanager/UidObserver.h
+++ b/services/mediaresourcemanager/UidObserver.h
@@ -74,7 +74,7 @@
     void onUidIdle(uid_t uid, bool disabled) override;
     void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
             int32_t capability) override;
-    void onUidProcAdjChanged(uid_t uid) override;
+    void onUidProcAdjChanged(uid_t uid, int32_t adj) override;
 
     // IServiceManager::LocalRegistrationCallback implementation.
     void onServiceRegistration(const String16& name,
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 2b94dbf..e7d14a0 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -196,11 +196,11 @@
             : AUDIO_SOURCE_DEFAULT;
     audio_flags_mask_t flags;
     if (direction == AAUDIO_DIRECTION_OUTPUT) {
-        flags = static_cast<audio_flags_mask_t>(AUDIO_FLAG_LOW_LATENCY
-                | AAudioConvert_allowCapturePolicyToAudioFlagsMask(
+        flags = AAudio_computeAudioFlagsMask(
                         params->getAllowedCapturePolicy(),
                         params->getSpatializationBehavior(),
-                        params->isContentSpatialized()));
+                        params->isContentSpatialized(),
+                        AUDIO_OUTPUT_FLAG_FAST);
     } else {
         flags = static_cast<audio_flags_mask_t>(AUDIO_FLAG_LOW_LATENCY
                 | AAudioConvert_privacySensitiveToAudioFlagsMask(params->isPrivacySensitive()));