Merge "Snap for 9982369 from 1494f05cc32165eef4c73a6eb6b51fe235bc1d64 to simpleperf-release" into simpleperf-release
diff --git a/apex/TEST_MAPPING b/apex/TEST_MAPPING
index 4b7c019..bb4f089 100644
--- a/apex/TEST_MAPPING
+++ b/apex/TEST_MAPPING
@@ -7,16 +7,16 @@
   "presubmit": [
     // The following tests validate codec and drm path.
     {
-      "name": "GtsMediaTestCases",
+      "name": "WvtsDeviceTestCases",
       "options" : [
         {
           "include-annotation": "android.platform.test.annotations.Presubmit"
         },
         {
-          "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+          "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
         },
         {
-          "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
+          "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests"
         }
       ]
     }
diff --git a/drm/TEST_MAPPING b/drm/TEST_MAPPING
index b2d4d6e..a9b4b2a 100644
--- a/drm/TEST_MAPPING
+++ b/drm/TEST_MAPPING
@@ -2,16 +2,16 @@
   "presubmit": [
     // The following tests validate codec and drm path.
     {
-      "name": "GtsMediaTestCases",
+      "name": "WvtsDeviceTestCases",
       "options" : [
         {
           "include-annotation": "android.platform.test.annotations.Presubmit"
         },
         {
-          "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+          "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
         },
         {
-          "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
+          "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests"
         }
       ]
     }
diff --git a/drm/libmediadrm/DrmMetricsLogger.cpp b/drm/libmediadrm/DrmMetricsLogger.cpp
index bc004c8..ce4d730 100644
--- a/drm/libmediadrm/DrmMetricsLogger.cpp
+++ b/drm/libmediadrm/DrmMetricsLogger.cpp
@@ -41,49 +41,59 @@
 
 DrmMetricsLogger::~DrmMetricsLogger() {}
 
-int MediaErrorToJavaError(status_t err) {
+int MediaErrorToEnum(status_t err) {
+#define ERROR_BAD_VALUE (BAD_VALUE)
+#define ERROR_DEAD_OBJECT (DEAD_OBJECT)
 #define STATUS_CASE(status) \
-    case status: \
-        return J##status
+    case ERROR_##status: \
+        return ENUM_##status
 
     switch (err) {
-        STATUS_CASE(ERROR_DRM_UNKNOWN);
-        STATUS_CASE(ERROR_DRM_NO_LICENSE);
-        STATUS_CASE(ERROR_DRM_LICENSE_EXPIRED);
-        STATUS_CASE(ERROR_DRM_RESOURCE_BUSY);
-        STATUS_CASE(ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION);
-        STATUS_CASE(ERROR_DRM_SESSION_NOT_OPENED);
-        STATUS_CASE(ERROR_DRM_CANNOT_HANDLE);
-        STATUS_CASE(ERROR_DRM_INSUFFICIENT_SECURITY);
-        STATUS_CASE(ERROR_DRM_FRAME_TOO_LARGE);
-        STATUS_CASE(ERROR_DRM_SESSION_LOST_STATE);
-        STATUS_CASE(ERROR_DRM_CERTIFICATE_MALFORMED);
-        STATUS_CASE(ERROR_DRM_CERTIFICATE_MISSING);
-        STATUS_CASE(ERROR_DRM_CRYPTO_LIBRARY);
-        STATUS_CASE(ERROR_DRM_GENERIC_OEM);
-        STATUS_CASE(ERROR_DRM_GENERIC_PLUGIN);
-        STATUS_CASE(ERROR_DRM_INIT_DATA);
-        STATUS_CASE(ERROR_DRM_KEY_NOT_LOADED);
-        STATUS_CASE(ERROR_DRM_LICENSE_PARSE);
-        STATUS_CASE(ERROR_DRM_LICENSE_POLICY);
-        STATUS_CASE(ERROR_DRM_LICENSE_RELEASE);
-        STATUS_CASE(ERROR_DRM_LICENSE_REQUEST_REJECTED);
-        STATUS_CASE(ERROR_DRM_LICENSE_RESTORE);
-        STATUS_CASE(ERROR_DRM_LICENSE_STATE);
-        STATUS_CASE(ERROR_DRM_MEDIA_FRAMEWORK);
-        STATUS_CASE(ERROR_DRM_PROVISIONING_CERTIFICATE);
-        STATUS_CASE(ERROR_DRM_PROVISIONING_CONFIG);
-        STATUS_CASE(ERROR_DRM_PROVISIONING_PARSE);
-        STATUS_CASE(ERROR_DRM_PROVISIONING_REQUEST_REJECTED);
-        STATUS_CASE(ERROR_DRM_PROVISIONING_RETRY);
-        STATUS_CASE(ERROR_DRM_RESOURCE_CONTENTION);
-        STATUS_CASE(ERROR_DRM_SECURE_STOP_RELEASE);
-        STATUS_CASE(ERROR_DRM_STORAGE_READ);
-        STATUS_CASE(ERROR_DRM_STORAGE_WRITE);
-        STATUS_CASE(ERROR_DRM_ZERO_SUBSAMPLES);
+        STATUS_CASE(DRM_UNKNOWN);
+        STATUS_CASE(DRM_NO_LICENSE);
+        STATUS_CASE(DRM_LICENSE_EXPIRED);
+        STATUS_CASE(DRM_RESOURCE_BUSY);
+        STATUS_CASE(DRM_INSUFFICIENT_OUTPUT_PROTECTION);
+        STATUS_CASE(DRM_SESSION_NOT_OPENED);
+        STATUS_CASE(DRM_CANNOT_HANDLE);
+        STATUS_CASE(DRM_INSUFFICIENT_SECURITY);
+        STATUS_CASE(DRM_FRAME_TOO_LARGE);
+        STATUS_CASE(DRM_SESSION_LOST_STATE);
+        STATUS_CASE(DRM_CERTIFICATE_MALFORMED);
+        STATUS_CASE(DRM_CERTIFICATE_MISSING);
+        STATUS_CASE(DRM_CRYPTO_LIBRARY);
+        STATUS_CASE(DRM_GENERIC_OEM);
+        STATUS_CASE(DRM_GENERIC_PLUGIN);
+        STATUS_CASE(DRM_INIT_DATA);
+        STATUS_CASE(DRM_KEY_NOT_LOADED);
+        STATUS_CASE(DRM_LICENSE_PARSE);
+        STATUS_CASE(DRM_LICENSE_POLICY);
+        STATUS_CASE(DRM_LICENSE_RELEASE);
+        STATUS_CASE(DRM_LICENSE_REQUEST_REJECTED);
+        STATUS_CASE(DRM_LICENSE_RESTORE);
+        STATUS_CASE(DRM_LICENSE_STATE);
+        STATUS_CASE(DRM_MEDIA_FRAMEWORK);
+        STATUS_CASE(DRM_PROVISIONING_CERTIFICATE);
+        STATUS_CASE(DRM_PROVISIONING_CONFIG);
+        STATUS_CASE(DRM_PROVISIONING_PARSE);
+        STATUS_CASE(DRM_PROVISIONING_REQUEST_REJECTED);
+        STATUS_CASE(DRM_PROVISIONING_RETRY);
+        STATUS_CASE(DRM_RESOURCE_CONTENTION);
+        STATUS_CASE(DRM_SECURE_STOP_RELEASE);
+        STATUS_CASE(DRM_STORAGE_READ);
+        STATUS_CASE(DRM_STORAGE_WRITE);
+        STATUS_CASE(DRM_ZERO_SUBSAMPLES);
+        STATUS_CASE(DRM_INVALID_STATE);
+        STATUS_CASE(BAD_VALUE);
+        STATUS_CASE(DRM_NOT_PROVISIONED);
+        STATUS_CASE(DRM_DEVICE_REVOKED);
+        STATUS_CASE(DRM_DECRYPT);
+        STATUS_CASE(DEAD_OBJECT);
+#undef ERROR_BAD_VALUE
+#undef ERROR_DEAD_OBJECT
 #undef STATUS_CASE
     }
-    return static_cast<int>(err);
+    return ENUM_DRM_UNKNOWN;
 }
 
 int DrmPluginSecurityLevelToJavaSecurityLevel(DrmPlugin::SecurityLevel securityLevel) {
@@ -187,12 +197,12 @@
 
 DrmStatus DrmMetricsLogger::closeSession(Vector<uint8_t> const& sessionId) {
     std::vector<uint8_t> sid = toStdVec(sessionId);
-    {
+    DrmStatus status = mImpl->closeSession(sessionId);
+    if (status == OK) {
         const std::lock_guard<std::mutex> lock(mSessionMapMutex);
         mSessionMap.erase(sid);
-    }
-    DrmStatus status = mImpl->closeSession(sessionId);
-    if (status != OK) {
+    } else {
+        // TODO(b/275729711): reclaim sessions that failed to close
         reportMediaDrmErrored(status, __func__, sid);
     }
     return status;
@@ -582,7 +592,7 @@
         }
     }
     mediametrics_setCString(handle, "api", api);
-    mediametrics_setInt32(handle, "error_code", MediaErrorToJavaError(error_code));
+    mediametrics_setInt32(handle, "error_code", MediaErrorToEnum(error_code));
     mediametrics_setInt32(handle, "cdm_err", error_code.getCdmErr());
     mediametrics_setInt32(handle, "oem_err", error_code.getOemErr());
     mediametrics_setInt32(handle, "error_context", error_code.getContext());
diff --git a/drm/libmediadrm/TEST_MAPPING b/drm/libmediadrm/TEST_MAPPING
index bc15879..8d7be22 100644
--- a/drm/libmediadrm/TEST_MAPPING
+++ b/drm/libmediadrm/TEST_MAPPING
@@ -1,19 +1,19 @@
 {
   "presubmit": [
     {
-      "name": "GtsMediaTestCases",
+      "name": "WvtsDeviceTestCases",
       "options" : [
         {
 	  "include-annotation": "android.platform.test.annotations.Presubmit"
         },
         {
-          "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+          "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
         },
         {
-          "include-filter": "com.google.android.media.gts.MediaDrmTest"
+          "include-filter": "com.google.android.media.wvts.MediaDrmTest"
         },
         {
-          "include-filter": "com.google.android.media.gts.WidevineDashPolicyTests"
+          "include-filter": "com.google.android.media.wvts.WidevineDashPolicyTests"
         }
       ]
     }
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
index 7666f04..e72f7f7 100644
--- a/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
+++ b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
@@ -25,41 +25,49 @@
 
 namespace android {
 
+// Keep enums in sync with frameworks/proto_logging/stats/enums/media/drm/enums.proto
+
 enum {
-    JERROR_DRM_UNKNOWN = 0,
-    JERROR_DRM_NO_LICENSE = 1,
-    JERROR_DRM_LICENSE_EXPIRED = 2,
-    JERROR_DRM_RESOURCE_BUSY = 3,
-    JERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = 4,
-    JERROR_DRM_SESSION_NOT_OPENED = 5,
-    JERROR_DRM_CANNOT_HANDLE = 6,
-    JERROR_DRM_INSUFFICIENT_SECURITY = 7,
-    JERROR_DRM_FRAME_TOO_LARGE = 8,
-    JERROR_DRM_SESSION_LOST_STATE = 9,
-    JERROR_DRM_CERTIFICATE_MALFORMED = 10,
-    JERROR_DRM_CERTIFICATE_MISSING = 11,
-    JERROR_DRM_CRYPTO_LIBRARY = 12,
-    JERROR_DRM_GENERIC_OEM = 13,
-    JERROR_DRM_GENERIC_PLUGIN = 14,
-    JERROR_DRM_INIT_DATA = 15,
-    JERROR_DRM_KEY_NOT_LOADED = 16,
-    JERROR_DRM_LICENSE_PARSE = 17,
-    JERROR_DRM_LICENSE_POLICY = 18,
-    JERROR_DRM_LICENSE_RELEASE = 19,
-    JERROR_DRM_LICENSE_REQUEST_REJECTED = 20,
-    JERROR_DRM_LICENSE_RESTORE = 21,
-    JERROR_DRM_LICENSE_STATE = 22,
-    JERROR_DRM_MEDIA_FRAMEWORK = 23,
-    JERROR_DRM_PROVISIONING_CERTIFICATE = 24,
-    JERROR_DRM_PROVISIONING_CONFIG = 25,
-    JERROR_DRM_PROVISIONING_PARSE = 26,
-    JERROR_DRM_PROVISIONING_REQUEST_REJECTED = 27,
-    JERROR_DRM_PROVISIONING_RETRY = 28,
-    JERROR_DRM_RESOURCE_CONTENTION = 29,
-    JERROR_DRM_SECURE_STOP_RELEASE = 30,
-    JERROR_DRM_STORAGE_READ = 31,
-    JERROR_DRM_STORAGE_WRITE = 32,
-    JERROR_DRM_ZERO_SUBSAMPLES = 33,
+    ENUM_DRM_UNKNOWN = 0,
+    ENUM_DRM_NO_LICENSE = 1,
+    ENUM_DRM_LICENSE_EXPIRED = 2,
+    ENUM_DRM_RESOURCE_BUSY = 3,
+    ENUM_DRM_INSUFFICIENT_OUTPUT_PROTECTION = 4,
+    ENUM_DRM_SESSION_NOT_OPENED = 5,
+    ENUM_DRM_CANNOT_HANDLE = 6,
+    ENUM_DRM_INSUFFICIENT_SECURITY = 7,
+    ENUM_DRM_FRAME_TOO_LARGE = 8,
+    ENUM_DRM_SESSION_LOST_STATE = 9,
+    ENUM_DRM_CERTIFICATE_MALFORMED = 10,
+    ENUM_DRM_CERTIFICATE_MISSING = 11,
+    ENUM_DRM_CRYPTO_LIBRARY = 12,
+    ENUM_DRM_GENERIC_OEM = 13,
+    ENUM_DRM_GENERIC_PLUGIN = 14,
+    ENUM_DRM_INIT_DATA = 15,
+    ENUM_DRM_KEY_NOT_LOADED = 16,
+    ENUM_DRM_LICENSE_PARSE = 17,
+    ENUM_DRM_LICENSE_POLICY = 18,
+    ENUM_DRM_LICENSE_RELEASE = 19,
+    ENUM_DRM_LICENSE_REQUEST_REJECTED = 20,
+    ENUM_DRM_LICENSE_RESTORE = 21,
+    ENUM_DRM_LICENSE_STATE = 22,
+    ENUM_DRM_MEDIA_FRAMEWORK = 23,
+    ENUM_DRM_PROVISIONING_CERTIFICATE = 24,
+    ENUM_DRM_PROVISIONING_CONFIG = 25,
+    ENUM_DRM_PROVISIONING_PARSE = 26,
+    ENUM_DRM_PROVISIONING_REQUEST_REJECTED = 27,
+    ENUM_DRM_PROVISIONING_RETRY = 28,
+    ENUM_DRM_RESOURCE_CONTENTION = 29,
+    ENUM_DRM_SECURE_STOP_RELEASE = 30,
+    ENUM_DRM_STORAGE_READ = 31,
+    ENUM_DRM_STORAGE_WRITE = 32,
+    ENUM_DRM_ZERO_SUBSAMPLES = 33,
+    ENUM_DRM_INVALID_STATE = 34,
+    ENUM_BAD_VALUE = 35,
+    ENUM_DRM_NOT_PROVISIONED = 36,
+    ENUM_DRM_DEVICE_REVOKED = 37,
+    ENUM_DRM_DECRYPT = 38,
+    ENUM_DEAD_OBJECT = 39,
 };
 
 enum {
diff --git a/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp b/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp
deleted file mode 100644
index e03a896..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2018 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_NDEBUG 0
-#define LOG_TAG "hidl_ClearkeyDecryptor"
-#include <utils/Log.h>
-
-#include <openssl/aes.h>
-
-#include "AesCtrDecryptor.h"
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::SubSample;
-using ::android::hardware::drm::V1_0::Status;
-
-static const size_t kBlockBitCount = kBlockSize * 8;
-
-Status AesCtrDecryptor::decrypt(
-        const std::vector<uint8_t>& key,
-        const Iv iv, const uint8_t* source,
-        uint8_t* destination,
-        const std::vector<SubSample> subSamples,
-        size_t numSubSamples,
-        size_t* bytesDecryptedOut) {
-    uint32_t blockOffset = 0;
-    uint8_t previousEncryptedCounter[kBlockSize];
-    memset(previousEncryptedCounter, 0, kBlockSize);
-
-    if (key.size() != kBlockSize || (sizeof(Iv) / sizeof(uint8_t)) != kBlockSize) {
-        android_errorWriteLog(0x534e4554, "63982768");
-        return Status::ERROR_DRM_DECRYPT;
-    }
-
-    size_t offset = 0;
-    AES_KEY opensslKey;
-    AES_set_encrypt_key(key.data(), kBlockBitCount, &opensslKey);
-    Iv opensslIv;
-    memcpy(opensslIv, iv, sizeof(opensslIv));
-
-    for (size_t i = 0; i < numSubSamples; ++i) {
-        const SubSample& subSample = subSamples[i];
-
-        if (subSample.numBytesOfClearData > 0) {
-            memcpy(destination + offset, source + offset,
-                    subSample.numBytesOfClearData);
-            offset += subSample.numBytesOfClearData;
-        }
-
-        if (subSample.numBytesOfEncryptedData > 0) {
-            AES_ctr128_encrypt(source + offset, destination + offset,
-                    subSample.numBytesOfEncryptedData, &opensslKey,
-                    opensslIv, previousEncryptedCounter,
-                    &blockOffset);
-            offset += subSample.numBytesOfEncryptedData;
-        }
-    }
-
-    *bytesDecryptedOut = offset;
-    return Status::OK;
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Android.bp b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
deleted file mode 100644
index b82d996..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/Android.bp
+++ /dev/null
@@ -1,167 +0,0 @@
-//
-// Copyright (C) 2018 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.
-//
-
-// *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS.  PLEASE
-//     CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
-//     DEPENDING ON IT IN YOUR PROJECT. ***
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_av_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    //   legacy_by_exception_only (by exception only)
-    default_applicable_licenses: ["frameworks_av_license"],
-}
-
-cc_defaults {
-    name: "clearkey_service_defaults",
-    vendor: true,
-
-    srcs: [
-        "AesCtrDecryptor.cpp",
-        "Base64.cpp",
-        "Buffer.cpp",
-        "CreatePluginFactories.cpp",
-        "CryptoFactory.cpp",
-        "CryptoPlugin.cpp",
-        "DeviceFiles.cpp",
-        "DrmFactory.cpp",
-        "DrmPlugin.cpp",
-        "InitDataParser.cpp",
-        "JsonWebKey.cpp",
-        "MemoryFileSystem.cpp",
-        "Session.cpp",
-        "SessionLibrary.cpp",
-    ],
-
-    relative_install_path: "hw",
-
-    cflags: ["-Wall", "-Werror", "-Wthread-safety"],
-
-    shared_libs: [
-        "android.hardware.drm@1.0",
-        "android.hardware.drm@1.1",
-        "android.hardware.drm@1.2",
-        "android.hardware.drm@1.3",
-        "android.hardware.drm@1.4",
-        "libbase",
-        "libbinder",
-        "libcrypto",
-        "libhidlbase",
-        "libhidlmemory",
-        "liblog",
-        "libprotobuf-cpp-lite",
-        "libutils",
-    ],
-
-    static_libs: [
-        "libclearkeycommon",
-        "libclearkeydevicefiles-protos",
-        "libjsmn",
-    ],
-
-    local_include_dirs: ["include"],
-
-    export_static_lib_headers: ["libjsmn"],
-
-    sanitize: {
-        integer_overflow: true,
-    },
-}
-cc_library_static {
-    name: "libclearkeydevicefiles-protos",
-    vendor: true,
-
-    proto: {
-        export_proto_headers: true,
-        type: "lite",
-    },
-    srcs: ["protos/DeviceFiles.proto"],
-}
-
-cc_library {
-    name: "libclearkeyhidl",
-    defaults: ["clearkey_service_defaults"],
-}
-
-cc_binary {
-    name: "android.hardware.drm@1.2-service.clearkey",
-    defaults: ["clearkey_service_defaults"],
-    srcs: ["service.cpp"],
-    init_rc: ["android.hardware.drm@1.2-service.clearkey.rc"],
-    vintf_fragments: ["manifest_android.hardware.drm@1.2-service.clearkey.xml"],
-}
-
-cc_binary {
-    name: "android.hardware.drm@1.2-service-lazy.clearkey",
-    overrides: ["android.hardware.drm@1.2-service.clearkey"],
-    defaults: ["clearkey_service_defaults"],
-    srcs: ["serviceLazy.cpp"],
-    init_rc: ["android.hardware.drm@1.2-service-lazy.clearkey.rc"],
-    vintf_fragments: ["manifest_android.hardware.drm@1.2-service.clearkey.xml"],
-}
-
-cc_binary {
-    name: "android.hardware.drm@1.4-service.clearkey",
-    defaults: ["clearkey_service_defaults"],
-    srcs: ["service.cpp"],
-    init_rc: ["android.hardware.drm@1.4-service.clearkey.rc"],
-    vintf_fragments: ["manifest_android.hardware.drm@1.4-service.clearkey.xml"],
-}
-
-cc_binary {
-    name: "android.hardware.drm@1.4-service-lazy.clearkey",
-    overrides: ["android.hardware.drm@1.4-service.clearkey"],
-    defaults: ["clearkey_service_defaults"],
-    srcs: ["serviceLazy.cpp"],
-    init_rc: ["android.hardware.drm@1.4-service-lazy.clearkey.rc"],
-    vintf_fragments: ["manifest_android.hardware.drm@1.4-service.clearkey.xml"],
-}
-
-cc_fuzz {
-    name: "clearkeyV1.4_fuzzer",
-    vendor: true,
-    srcs: [
-        "fuzzer/clearkeyV1.4_fuzzer.cpp",
-    ],
-    static_libs: [
-        "libclearkeyhidl",
-        "libclearkeycommon",
-        "libclearkeydevicefiles-protos",
-        "libjsmn",
-        "libprotobuf-cpp-lite",
-    ],
-    shared_libs: [
-        "android.hidl.allocator@1.0",
-        "android.hardware.drm@1.0",
-        "android.hardware.drm@1.1",
-        "android.hardware.drm@1.2",
-        "android.hardware.drm@1.3",
-        "android.hardware.drm@1.4",
-        "libcrypto",
-        "libhidlbase",
-        "libhidlmemory",
-        "liblog",
-        "libutils",
-    ],
-    fuzz_config: {
-        cc: [
-            "android-media-fuzzing-reports@google.com",
-        ],
-        componentid: 155276,
-    },
-}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp b/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp
deleted file mode 100644
index d81f875..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2018 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 "Base64.h"
-
-#include <string>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-sp<Buffer> decodeBase64(const std::string &s) {
-    size_t n = s.size();
-
-    if ((n % 4) != 0) {
-        return nullptr;
-    }
-
-    size_t padding = 0;
-    if (n >= 1 && s.c_str()[n - 1] == '=') {
-        padding = 1;
-
-        if (n >= 2 && s.c_str()[n - 2] == '=') {
-            padding = 2;
-
-            if (n >= 3 && s.c_str()[n - 3] == '=') {
-                padding = 3;
-            }
-        }
-    }
-
-    // We divide first to avoid overflow. It's OK to do this because we
-    // already made sure that n % 4 == 0.
-    size_t outLen = (n / 4) * 3 - padding;
-
-    sp<Buffer> buffer = new Buffer(outLen);
-    uint8_t *out = buffer->data();
-    if (out == nullptr || buffer->size() < outLen) {
-        return nullptr;
-    }
-
-    size_t j = 0;
-    uint32_t accum = 0;
-    for (size_t i = 0; i < n; ++i) {
-        char c = s.c_str()[i];
-        unsigned value;
-        if (c >= 'A' && c <= 'Z') {
-            value = c - 'A';
-        } else if (c >= 'a' && c <= 'z') {
-            value = 26 + c - 'a';
-        } else if (c >= '0' && c <= '9') {
-            value = 52 + c - '0';
-        } else if (c == '+' || c == '-') {
-            value = 62;
-        } else if (c == '/' || c == '_') {
-            value = 63;
-        } else if (c != '=') {
-            return nullptr;
-        } else {
-            if (i < n - padding) {
-                return nullptr;
-            }
-
-            value = 0;
-        }
-
-        accum = (accum << 6) | value;
-
-        if (((i + 1) % 4) == 0) {
-            if (j < outLen) { out[j++] = (accum >> 16); }
-            if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
-            if (j < outLen) { out[j++] = accum & 0xff; }
-
-            accum = 0;
-        }
-    }
-
-    return buffer;
-}
-
-static char encode6Bit(unsigned x) {
-    if (x <= 25) {
-        return 'A' + x;
-    } else if (x <= 51) {
-        return 'a' + x - 26;
-    } else if (x <= 61) {
-        return '0' + x - 52;
-    } else if (x == 62) {
-        return '+';
-    } else {
-        return '/';
-    }
-}
-
-void encodeBase64(const void *_data, size_t size, std::string *out) {
-    out->clear();
-
-    const uint8_t *data = (const uint8_t *)_data;
-
-    size_t i;
-    for (i = 0; i < (size / 3) * 3; i += 3) {
-        uint8_t x1 = data[i];
-        uint8_t x2 = data[i + 1];
-        uint8_t x3 = data[i + 2];
-
-        out->push_back(encode6Bit(x1 >> 2));
-        out->push_back(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
-        out->push_back(encode6Bit((x2 << 2 | x3 >> 6) & 0x3f));
-        out->push_back(encode6Bit(x3 & 0x3f));
-    }
-    switch (size % 3) {
-        case 0:
-            break;
-        case 2:
-        {
-            uint8_t x1 = data[i];
-            uint8_t x2 = data[i + 1];
-            out->push_back(encode6Bit(x1 >> 2));
-            out->push_back(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
-            out->push_back(encode6Bit((x2 << 2) & 0x3f));
-            out->push_back('=');
-            break;
-        }
-        default:
-        {
-            uint8_t x1 = data[i];
-            out->push_back(encode6Bit(x1 >> 2));
-            out->push_back(encode6Bit((x1 << 4) & 0x3f));
-            out->append("==");
-            break;
-        }
-    }
-}
-
-void encodeBase64Url(const void *_data, size_t size, std::string *out) {
-    encodeBase64(_data, size, out);
-
-    if ((std::string::npos != out->find("+")) ||
-            (std::string::npos != out->find("/"))) {
-        size_t outLen = out->size();
-        char *base64url = new char[outLen];
-        for (size_t i = 0; i < outLen; ++i) {
-            if (out->c_str()[i] == '+')
-                base64url[i] = '-';
-            else if (out->c_str()[i] == '/')
-                base64url[i] = '_';
-            else
-                base64url[i] = out->c_str()[i];
-        }
-
-        out->assign(base64url, outLen);
-        delete[] base64url;
-    }
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp b/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp
deleted file mode 100644
index dcb76f4..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2018 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 "Buffer.h"
-
-#include <android/hardware/drm/1.0/types.h>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-Buffer::Buffer(size_t capacity)
-      : mRangeOffset(0),
-      mOwnsData(true) {
-    mData = malloc(capacity);
-    if (mData == nullptr) {
-        mCapacity = 0;
-        mRangeLength = 0;
-    } else {
-        mCapacity = capacity;
-        mRangeLength = capacity;
-    }
-}
-
-Buffer::~Buffer() {
-    if (mOwnsData) {
-        if (mData != nullptr) {
-            free(mData);
-            mData = nullptr;
-        }
-    }
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp b/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
deleted file mode 100644
index 4ab33d3..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2018 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 "CreatePluginFactories.h"
-
-#include "CryptoFactory.h"
-#include "DrmFactory.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-extern "C" {
-
-IDrmFactory* createDrmFactory() {
-    return new DrmFactory();
-}
-
-ICryptoFactory* createCryptoFactory() {
-    return new CryptoFactory();
-}
-
-} // extern "C"
-
-}  // namespace clearkey
-}  // namespace V1_4
-}  // namespace drm
-}  // namespace hardware
-}  // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
deleted file mode 100644
index 0bebc3b..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2018 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_NDEBUG 0
-#define LOG_TAG "hidl_ClearKeyCryptoFactory"
-#include <utils/Log.h>
-
-#include "CryptoFactory.h"
-
-#include "ClearKeyUUID.h"
-#include "CryptoPlugin.h"
-#include "TypeConvert.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_4::clearkey::CryptoPlugin;
-
-Return<bool> CryptoFactory::isCryptoSchemeSupported(
-    const hidl_array<uint8_t, 16> &uuid)
-{
-    return clearkeydrm::isClearKeyUUID(uuid.data());
-}
-
-Return<void> CryptoFactory::createPlugin(
-    const hidl_array<uint8_t, 16> &uuid,
-    const hidl_vec<uint8_t> &initData,
-    createPlugin_cb _hidl_cb) {
-
-    if (!isCryptoSchemeSupported(uuid.data())) {
-        ALOGE("Clearkey Drm HAL: failed to create clearkey plugin, " \
-                "invalid crypto scheme");
-        _hidl_cb(Status::BAD_VALUE, nullptr);
-        return Void();
-    }
-
-    CryptoPlugin *cryptoPlugin = new CryptoPlugin(initData);
-    Status status = cryptoPlugin->getInitStatus();
-    if (status == Status::OK) {
-        _hidl_cb(Status::OK, cryptoPlugin);
-    } else {
-        delete cryptoPlugin;
-        _hidl_cb(status, nullptr);
-    }
-    return Void();
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
deleted file mode 100644
index 64a43b0..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2018 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_NDEBUG 0
-#define LOG_TAG "hidl_ClearKeyCryptoPlugin"
-#include <utils/Log.h>
-
-#include "CryptoPlugin.h"
-#include "SessionLibrary.h"
-#include "TypeConvert.h"
-
-#include <hidlmemory/mapping.h>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::BufferType;
-
-Return<void> CryptoPlugin::setSharedBufferBase(
-        const hidl_memory& base, uint32_t bufferId) {
-    sp<IMemory> hidlMemory = mapMemory(base);
-    ALOGE_IF(hidlMemory == nullptr, "mapMemory returns nullptr");
-
-    std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock);
-
-    // allow mapMemory to return nullptr
-    mSharedBufferMap[bufferId] = hidlMemory;
-    return Void();
-}
-
-Return<void> CryptoPlugin::decrypt(
-    bool secure,
-    const hidl_array<uint8_t, 16>& keyId,
-    const hidl_array<uint8_t, 16>& iv,
-    Mode mode,
-    const Pattern& pattern,
-    const hidl_vec<SubSample>& subSamples,
-    const SharedBuffer& source,
-    uint64_t offset,
-    const DestinationBuffer& destination,
-    decrypt_cb _hidl_cb) {
-
-  Status status = Status::ERROR_DRM_UNKNOWN;
-  hidl_string detailedError;
-  uint32_t bytesWritten = 0;
-
-  Return<void> hResult = decrypt_1_2(
-      secure, keyId, iv, mode, pattern, subSamples, source, offset, destination,
-      [&](Status_V1_2 hStatus, uint32_t hBytesWritten, hidl_string hDetailedError) {
-        status = toStatus_1_0(hStatus);
-        bytesWritten = hBytesWritten;
-        detailedError = hDetailedError;
-      }
-    );
-
-  status = hResult.isOk() ? status : Status::ERROR_DRM_CANNOT_HANDLE;
-  _hidl_cb(status, bytesWritten, detailedError);
-  return Void();
-}
-
-// Returns negative values for error code and positive values for the size of
-// decrypted data.  In theory, the output size can be larger than the input
-// size, but in practice this will never happen for AES-CTR.
-Return<void> CryptoPlugin::decrypt_1_2(
-        bool secure,
-        const hidl_array<uint8_t, KEY_ID_SIZE>& keyId,
-        const hidl_array<uint8_t, KEY_IV_SIZE>& iv,
-        Mode mode,
-        const Pattern& pattern,
-        const hidl_vec<SubSample>& subSamples,
-        const SharedBuffer& source,
-        uint64_t offset,
-        const DestinationBuffer& destination,
-        decrypt_1_2_cb _hidl_cb) {
-    UNUSED(pattern);
-
-    if (secure) {
-        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
-            "Secure decryption is not supported with ClearKey.");
-        return Void();
-    }
-
-    std::unique_lock<std::mutex> shared_buffer_lock(mSharedBufferLock);
-    if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
-      _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
-               "source decrypt buffer base not set");
-      return Void();
-    }
-
-    if (destination.type == BufferType::SHARED_MEMORY) {
-      const SharedBuffer& dest = destination.nonsecureMemory;
-      if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) {
-        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
-                 "destination decrypt buffer base not set");
-        return Void();
-      }
-    } else {
-        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
-                 "destination type not supported");
-        return Void();
-    }
-
-    sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
-    if (sourceBase == nullptr) {
-        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr");
-        return Void();
-    }
-
-    size_t totalSize = 0;
-    if (__builtin_add_overflow(source.offset, offset, &totalSize) ||
-        __builtin_add_overflow(totalSize, source.size, &totalSize) ||
-        totalSize > sourceBase->getSize()) {
-        android_errorWriteLog(0x534e4554, "176496160");
-        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
-        return Void();
-    }
-
-    uint8_t *base = static_cast<uint8_t *>
-            (static_cast<void *>(sourceBase->getPointer()));
-    uint8_t* srcPtr = static_cast<uint8_t *>(base + source.offset + offset);
-    void* destPtr = NULL;
-    // destination.type == BufferType::SHARED_MEMORY
-    const SharedBuffer& destBuffer = destination.nonsecureMemory;
-    sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
-    if (destBase == nullptr) {
-        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
-        return Void();
-    }
-
-    base = static_cast<uint8_t *>(static_cast<void *>(destBase->getPointer()));
-
-    totalSize = 0;
-    if (__builtin_add_overflow(destBuffer.offset, destBuffer.size, &totalSize) ||
-        totalSize > destBase->getSize()) {
-        android_errorWriteLog(0x534e4554, "176444622");
-        _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "invalid buffer size");
-        return Void();
-    }
-    destPtr = static_cast<void*>(base + destination.nonsecureMemory.offset);
-
-    // release mSharedBufferLock
-    shared_buffer_lock.unlock();
-
-    // Calculate the output buffer size and determine if any subsamples are
-    // encrypted.
-    size_t destSize = 0;
-    size_t srcSize = 0;
-    bool haveEncryptedSubsamples = false;
-    for (size_t i = 0; i < subSamples.size(); i++) {
-        const SubSample &subSample = subSamples[i];
-        if (__builtin_add_overflow(destSize, subSample.numBytesOfClearData, &destSize) ||
-            __builtin_add_overflow(srcSize, subSample.numBytesOfClearData, &srcSize)) {
-            _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample clear size overflow");
-            return Void();
-        }
-        if (__builtin_add_overflow(destSize, subSample.numBytesOfEncryptedData, &destSize) ||
-            __builtin_add_overflow(srcSize, subSample.numBytesOfEncryptedData, &srcSize)) {
-            _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample encrypted size overflow");
-            return Void();
-        }
-        if (subSample.numBytesOfEncryptedData > 0) {
-        haveEncryptedSubsamples = true;
-        }
-    }
-
-    if (destSize > destBuffer.size || srcSize > source.size) {
-        _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample sum too large");
-        return Void();
-    }
-
-    if (mode == Mode::UNENCRYPTED) {
-        if (haveEncryptedSubsamples) {
-            _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
-                    "Encrypted subsamples found in allegedly unencrypted data.");
-            return Void();
-        }
-
-        size_t offset = 0;
-        for (size_t i = 0; i < subSamples.size(); ++i) {
-            const SubSample& subSample = subSamples[i];
-            if (subSample.numBytesOfClearData != 0) {
-                memcpy(reinterpret_cast<uint8_t*>(destPtr) + offset,
-                       reinterpret_cast<const uint8_t*>(srcPtr) + offset,
-                       subSample.numBytesOfClearData);
-                offset += subSample.numBytesOfClearData;
-            }
-        }
-
-        _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(offset), "");
-        return Void();
-    } else if (mode == Mode::AES_CTR) {
-        size_t bytesDecrypted;
-        if (keyId.size() != kBlockSize || iv.size() != kBlockSize) {
-            android_errorWriteLog(0x534e4554, "244569759");
-            _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid decrypt parameter size");
-            return Void();
-        }
-        if (!mSession) {
-            _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "session not found");
-            return Void();
-        }
-        Status_V1_2 res = mSession->decrypt(keyId.data(), iv.data(), srcPtr,
-                static_cast<uint8_t*>(destPtr), toVector(subSamples), &bytesDecrypted);
-        if (res == Status_V1_2::OK) {
-            _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(bytesDecrypted), "");
-            return Void();
-        } else {
-            _hidl_cb(res, 0, "Decryption Error");
-            return Void();
-        }
-    } else {
-        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
-                "Selected encryption mode is not supported by the ClearKey DRM Plugin.");
-        return Void();
-    }
-}
-
-Return<Status> CryptoPlugin::setMediaDrmSession(
-        const hidl_vec<uint8_t>& sessionId) {
-    if (!sessionId.size()) {
-        mSession = nullptr;
-    } else {
-        mSession = SessionLibrary::get()->findSession(sessionId);
-        if (!mSession.get()) {
-            return Status::ERROR_DRM_SESSION_NOT_OPENED;
-        }
-    }
-    return Status::OK;
-}
-
-Return<void> CryptoPlugin::getLogMessages(
-        getLogMessages_cb _hidl_cb) {
-    using std::chrono::duration_cast;
-    using std::chrono::milliseconds;
-    using std::chrono::system_clock;
-
-    auto timeMillis = duration_cast<milliseconds>(
-            system_clock::now().time_since_epoch()).count();
-
-    std::vector<LogMessage> logs = {
-            { timeMillis, LogPriority::ERROR, std::string("Not implemented") }};
-    _hidl_cb(drm::V1_4::Status::OK, toHidlVec(logs));
-    return Void();
-}
-
-} // namespace clearkey
-} // namespace V1_4.
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp b/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp
deleted file mode 100644
index 0385d8f..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
-// source code may only be used and distributed under the Widevine Master
-// License Agreement.
-
-#include <utils/Log.h>
-
-#include <string>
-#include <sys/stat.h>
-
-#include "DeviceFiles.h"
-#include "Utils.h"
-
-#include <openssl/sha.h>
-
-// Protobuf generated classes.
-using android::hardware::drm::V1_2::clearkey::OfflineFile;
-using android::hardware::drm::V1_2::clearkey::HashedFile;
-using android::hardware::drm::V1_2::clearkey::License;
-using android::hardware::drm::V1_2::clearkey::License_LicenseState_ACTIVE;
-using android::hardware::drm::V1_2::clearkey::License_LicenseState_RELEASING;
-
-namespace {
-const char kLicenseFileNameExt[] = ".lic";
-
-bool Hash(const std::string& data, std::string* hash) {
-    if (!hash) return false;
-
-    hash->resize(SHA256_DIGEST_LENGTH);
-
-    const unsigned char* input = reinterpret_cast<const unsigned char*>(data.data());
-    unsigned char* output = reinterpret_cast<unsigned char*>(&(*hash)[0]);
-    SHA256(input, data.size(), output);
-    return true;
-}
-
-}  // namespace
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-bool DeviceFiles::StoreLicense(
-        const std::string& keySetId, LicenseState state,
-        const std::string& licenseResponse) {
-
-    OfflineFile file;
-    file.set_type(OfflineFile::LICENSE);
-    file.set_version(OfflineFile::VERSION_1);
-
-    License* license = file.mutable_license();
-    switch (state) {
-        case kLicenseStateActive:
-            license->set_state(License_LicenseState_ACTIVE);
-            license->set_license(licenseResponse);
-            break;
-        case kLicenseStateReleasing:
-            license->set_state(License_LicenseState_RELEASING);
-            license->set_license(licenseResponse);
-            break;
-        default:
-            ALOGW("StoreLicense: Unknown license state: %u", state);
-            return false;
-    }
-
-    std::string serializedFile;
-    file.SerializeToString(&serializedFile);
-
-    return StoreFileWithHash(keySetId + kLicenseFileNameExt, serializedFile);
-}
-
-bool DeviceFiles::StoreFileWithHash(const std::string& fileName,
-        const std::string& serializedFile) {
-    std::string hash;
-    if (!Hash(serializedFile, &hash)) {
-        ALOGE("StoreFileWithHash: Failed to compute hash");
-        return false;
-    }
-
-    HashedFile hashFile;
-    hashFile.set_file(serializedFile);
-    hashFile.set_hash(hash);
-
-    std::string serializedHashFile;
-    hashFile.SerializeToString(&serializedHashFile);
-
-    return StoreFileRaw(fileName, serializedHashFile);
-}
-
-bool DeviceFiles::StoreFileRaw(const std::string& fileName, const std::string& serializedHashFile) {
-    MemoryFileSystem::MemoryFile memFile;
-    memFile.setFileName(fileName);
-    memFile.setContent(serializedHashFile);
-    memFile.setFileSize(serializedHashFile.size());
-    size_t len = mFileHandle.Write(fileName, memFile);
-
-    if (len != static_cast<size_t>(serializedHashFile.size())) {
-        ALOGE("StoreFileRaw: Failed to write %s", fileName.c_str());
-        ALOGD("StoreFileRaw: expected=%zd, actual=%zu", serializedHashFile.size(), len);
-        return false;
-    }
-
-    ALOGD("StoreFileRaw: wrote %zu bytes to %s", serializedHashFile.size(), fileName.c_str());
-    return true;
-}
-
-bool DeviceFiles::RetrieveLicense(
-    const std::string& keySetId, LicenseState* state, std::string* offlineLicense) {
-
-    OfflineFile file;
-    if (!RetrieveHashedFile(keySetId + kLicenseFileNameExt, &file)) {
-        return false;
-    }
-
-    if (file.type() != OfflineFile::LICENSE) {
-        ALOGE("RetrieveLicense: Invalid file type");
-        return false;
-    }
-
-    if (file.version() != OfflineFile::VERSION_1) {
-        ALOGE("RetrieveLicense: Invalid file version");
-        return false;
-    }
-
-    if (!file.has_license()) {
-        ALOGE("RetrieveLicense: License not present");
-        return false;
-    }
-
-    License license = file.license();
-    switch (license.state()) {
-        case License_LicenseState_ACTIVE:
-            *state = kLicenseStateActive;
-            break;
-        case License_LicenseState_RELEASING:
-            *state = kLicenseStateReleasing;
-            break;
-        default:
-            ALOGW("RetrieveLicense: Unrecognized license state: %u",
-                    kLicenseStateUnknown);
-            *state = kLicenseStateUnknown;
-            break;
-    }
-    *offlineLicense = license.license();
-    return true;
-}
-
-bool DeviceFiles::DeleteLicense(const std::string& keySetId) {
-    return mFileHandle.RemoveFile(keySetId + kLicenseFileNameExt);
-}
-
-bool DeviceFiles::DeleteAllLicenses() {
-    return mFileHandle.RemoveAllFiles();
-}
-
-bool DeviceFiles::LicenseExists(const std::string& keySetId) {
-    return mFileHandle.FileExists(keySetId + kLicenseFileNameExt);
-}
-
-std::vector<std::string> DeviceFiles::ListLicenses() const {
-    std::vector<std::string> licenses = mFileHandle.ListFiles();
-    for (size_t i = 0; i < licenses.size(); i++) {
-        std::string& license = licenses[i];
-        license = license.substr(0, license.size() - strlen(kLicenseFileNameExt));
-    }
-    return licenses;
-}
-
-bool DeviceFiles::RetrieveHashedFile(const std::string& fileName, OfflineFile* deSerializedFile) {
-    if (!deSerializedFile) {
-        ALOGE("RetrieveHashedFile: invalid file parameter");
-        return false;
-    }
-
-    if (!FileExists(fileName)) {
-        ALOGE("RetrieveHashedFile: %s does not exist", fileName.c_str());
-        return false;
-    }
-
-    ssize_t bytes = GetFileSize(fileName);
-    if (bytes <= 0) {
-        ALOGE("RetrieveHashedFile: invalid file size: %s", fileName.c_str());
-        // Remove the corrupted file so the caller will not get the same error
-        // when trying to access the file repeatedly, causing the system to stall.
-        RemoveFile(fileName);
-        return false;
-    }
-
-    std::string serializedHashFile;
-    serializedHashFile.resize(bytes);
-    bytes = mFileHandle.Read(fileName, &serializedHashFile);
-
-    if (bytes != static_cast<ssize_t>(serializedHashFile.size())) {
-        ALOGE("RetrieveHashedFile: Failed to read from %s", fileName.c_str());
-        ALOGV("RetrieveHashedFile: expected: %zd, actual: %zd", serializedHashFile.size(), bytes);
-        // Remove the corrupted file so the caller will not get the same error
-        // when trying to access the file repeatedly, causing the system to stall.
-        RemoveFile(fileName);
-        return false;
-    }
-
-    ALOGV("RetrieveHashedFile: read %zd from %s", bytes, fileName.c_str());
-
-    HashedFile hashFile;
-    if (!hashFile.ParseFromString(serializedHashFile)) {
-        ALOGE("RetrieveHashedFile: Unable to parse hash file");
-        // Remove corrupt file.
-        RemoveFile(fileName);
-        return false;
-    }
-
-    std::string hash;
-    if (!Hash(hashFile.file(), &hash)) {
-        ALOGE("RetrieveHashedFile: Hash computation failed");
-        return false;
-    }
-
-    if (hash != hashFile.hash()) {
-        ALOGE("RetrieveHashedFile: Hash mismatch");
-        // Remove corrupt file.
-        RemoveFile(fileName);
-        return false;
-    }
-
-    if (!deSerializedFile->ParseFromString(hashFile.file())) {
-        ALOGE("RetrieveHashedFile: Unable to parse file");
-        // Remove corrupt file.
-        RemoveFile(fileName);
-        return false;
-    }
-
-    return true;
-}
-
-bool DeviceFiles::FileExists(const std::string& fileName) const {
-    return mFileHandle.FileExists(fileName);
-}
-
-bool DeviceFiles::RemoveFile(const std::string& fileName) {
-    return mFileHandle.RemoveFile(fileName);
-}
-
-ssize_t DeviceFiles::GetFileSize(const std::string& fileName) const {
-    return mFileHandle.GetFileSize(fileName);
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
deleted file mode 100644
index 14cb5c1..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2018 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_NDEBUG 0
-#include <vector>
-#define LOG_TAG "hidl_ClearKeyDrmFactory"
-#include <utils/Log.h>
-
-#include <utils/Errors.h>
-
-#include "DrmFactory.h"
-
-#include "DrmPlugin.h"
-#include "ClearKeyUUID.h"
-#include "MimeType.h"
-#include "SessionLibrary.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_1::SecurityLevel;
-using ::android::hardware::drm::V1_4::clearkey::DrmPlugin;
-using ::android::hardware::drm::V1_4::clearkey::SessionLibrary;
-using ::android::hardware::Void;
-
-Return<bool> DrmFactory::isCryptoSchemeSupported(
-        const hidl_array<uint8_t, 16>& uuid) {
-    return clearkeydrm::isClearKeyUUID(uuid.data());
-}
-
-Return<bool> DrmFactory::isCryptoSchemeSupported_1_2(const hidl_array<uint8_t, 16>& uuid,
-                                                     const hidl_string &mimeType,
-                                                     SecurityLevel level) {
-    return isCryptoSchemeSupported(uuid) && isContentTypeSupported(mimeType) &&
-            level == SecurityLevel::SW_SECURE_CRYPTO;
-}
-
-Return<bool> DrmFactory::isContentTypeSupported(const hidl_string &mimeType) {
-    // This should match the mimeTypes handed by InitDataParser.
-    return mimeType == kIsoBmffVideoMimeType ||
-            mimeType == kIsoBmffAudioMimeType ||
-            mimeType == kCencInitDataFormat ||
-            mimeType == kWebmVideoMimeType ||
-            mimeType == kWebmAudioMimeType ||
-            mimeType == kWebmInitDataFormat;
-}
-
-Return<void> DrmFactory::createPlugin(
-    const hidl_array<uint8_t, 16>& uuid,
-    const hidl_string& appPackageName,
-    createPlugin_cb _hidl_cb) {
-    UNUSED(appPackageName);
-
-    DrmPlugin *plugin = NULL;
-    if (!isCryptoSchemeSupported(uuid.data())) {
-        ALOGE("Clear key Drm HAL: failed to create drm plugin, " \
-                "invalid crypto scheme");
-        _hidl_cb(Status::BAD_VALUE, plugin);
-        return Void();
-    }
-
-    plugin = new DrmPlugin(SessionLibrary::get());
-    _hidl_cb(Status::OK, plugin);
-    return Void();
-}
-
-Return<void> DrmFactory::getSupportedCryptoSchemes(
-        getSupportedCryptoSchemes_cb _hidl_cb) {
-    std::vector<hidl_array<uint8_t, 16>> schemes;
-    for (const auto &scheme : clearkeydrm::getSupportedCryptoSchemes()) {
-        schemes.push_back(scheme);
-    }
-    _hidl_cb(schemes);
-    return Void();
-}
-
-Return<void> DrmFactory::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /*args*/) {
-    if (fd.getNativeHandle() == nullptr || fd->numFds < 1) {
-        ALOGE("%s: missing fd for writing", __FUNCTION__);
-        return Void();
-    }
-
-    FILE* out = fdopen(dup(fd->data[0]), "w");
-    uint32_t currentSessions = SessionLibrary::get()->numOpenSessions();
-    fprintf(out, "current open sessions: %u\n", currentSessions);
-    fclose(out);
-    return Void();
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
deleted file mode 100644
index e04dd7e..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ /dev/null
@@ -1,964 +0,0 @@
-/*
- * Copyright (C) 2018 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_NDEBUG 0
-#define LOG_TAG "hidl_ClearKeyPlugin"
-#include <utils/Log.h>
-
-#include <chrono>
-#include <stdio.h>
-#include <inttypes.h>
-
-#include "DrmPlugin.h"
-#include "ClearKeyDrmProperties.h"
-#include "Session.h"
-#include "TypeConvert.h"
-#include "Utils.h"
-
-namespace {
-const std::string kKeySetIdPrefix("ckid");
-const int kKeySetIdLength = 16;
-const int kSecureStopIdStart = 100;
-const std::string kOfflineLicense("\"type\":\"persistent-license\"");
-const std::string kStreaming("Streaming");
-const std::string kTemporaryLicense("\"type\":\"temporary\"");
-const std::string kTrue("True");
-
-const std::string kQueryKeyLicenseType("LicenseType");
-    // Value: "Streaming" or "Offline"
-const std::string kQueryKeyPlayAllowed("PlayAllowed");
-    // Value: "True" or "False"
-const std::string kQueryKeyRenewAllowed("RenewAllowed");
-    // Value: "True" or "False"
-
-const int kSecureStopIdSize = 10;
-
-std::vector<uint8_t> uint32ToVector(uint32_t value) {
-    // 10 bytes to display max value 4294967295 + one byte null terminator
-    char buffer[kSecureStopIdSize];
-    memset(buffer, 0, kSecureStopIdSize);
-    snprintf(buffer, kSecureStopIdSize, "%" PRIu32, value);
-    return std::vector<uint8_t>(buffer, buffer + sizeof(buffer));
-}
-
-}; // unnamed namespace
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-KeyRequestType toKeyRequestType_V1_0(KeyRequestType_V1_1 keyRequestType) {
-  switch (keyRequestType) {
-    case KeyRequestType_V1_1::NONE:
-    case KeyRequestType_V1_1::UPDATE:
-      return KeyRequestType::UNKNOWN;
-    default:
-      return static_cast<KeyRequestType>(keyRequestType);
-  }
-}
-
-DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
-        : mSessionLibrary(sessionLibrary),
-          mOpenSessionOkCount(0),
-          mCloseSessionOkCount(0),
-          mCloseSessionNotOpenedCount(0),
-          mNextSecureStopId(kSecureStopIdStart),
-          mMockError(Status_V1_2::OK) {
-    mPlayPolicy.clear();
-    initProperties();
-    mSecureStops.clear();
-    mReleaseKeysMap.clear();
-    std::srand(std::time(nullptr));
-}
-
-void DrmPlugin::initProperties() {
-    mStringProperties.clear();
-    mStringProperties[kVendorKey] = kVendorValue;
-    mStringProperties[kVersionKey] = kVersionValue;
-    mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue;
-    mStringProperties[kAlgorithmsKey] = kAlgorithmsValue;
-    mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue;
-    mStringProperties[kDrmErrorTestKey] = kDrmErrorTestValue;
-
-    std::vector<uint8_t> valueVector;
-    valueVector.clear();
-    valueVector.insert(valueVector.end(),
-            kTestDeviceIdData, kTestDeviceIdData + sizeof(kTestDeviceIdData) / sizeof(uint8_t));
-    mByteArrayProperties[kDeviceIdKey] = valueVector;
-
-    valueVector.clear();
-    valueVector.insert(valueVector.end(),
-            kMetricsData, kMetricsData + sizeof(kMetricsData) / sizeof(uint8_t));
-    mByteArrayProperties[kMetricsKey] = valueVector;
-}
-
-// The secure stop in ClearKey implementation is not installed securely.
-// This function merely creates a test environment for testing secure stops APIs.
-// The content in this secure stop is implementation dependent, the clearkey
-// secureStop does not serve as a reference implementation.
-void DrmPlugin::installSecureStop(const hidl_vec<uint8_t>& sessionId) {
-    Mutex::Autolock lock(mSecureStopLock);
-
-    ClearkeySecureStop clearkeySecureStop;
-    clearkeySecureStop.id = uint32ToVector(++mNextSecureStopId);
-    clearkeySecureStop.data.assign(sessionId.begin(), sessionId.end());
-
-    mSecureStops.insert(std::pair<std::vector<uint8_t>, ClearkeySecureStop>(
-            clearkeySecureStop.id, clearkeySecureStop));
-}
-
-Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) {
-    sp<Session> session = mSessionLibrary->createSession();
-    processMockError(session);
-    std::vector<uint8_t> sessionId = session->sessionId();
-
-    Status status = setSecurityLevel(sessionId, SecurityLevel::SW_SECURE_CRYPTO);
-    _hidl_cb(status, toHidlVec(sessionId));
-    mOpenSessionOkCount++;
-    return Void();
-}
-
-Return<void> DrmPlugin::openSession_1_1(SecurityLevel securityLevel,
-        openSession_1_1_cb _hidl_cb) {
-    sp<Session> session = mSessionLibrary->createSession();
-    processMockError(session);
-    std::vector<uint8_t> sessionId = session->sessionId();
-
-    Status status = setSecurityLevel(sessionId, securityLevel);
-    if (status == Status::OK) {
-        mOpenSessionOkCount++;
-    } else {
-        mSessionLibrary->destroySession(session);
-        sessionId.clear();
-    }
-    _hidl_cb(status, toHidlVec(sessionId));
-    return Void();
-}
-
-Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) {
-    if (sessionId.size() == 0) {
-        return Status::BAD_VALUE;
-    }
-
-    sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
-    if (session.get()) {
-        mSessionLibrary->destroySession(session);
-        if (session->getMockError() != Status_V1_2::OK) {
-            sendSessionLostState(sessionId);
-            return Status::ERROR_DRM_INVALID_STATE;
-        }
-        mCloseSessionOkCount++;
-        return Status::OK;
-    }
-    mCloseSessionNotOpenedCount++;
-    return Status::ERROR_DRM_SESSION_NOT_OPENED;
-}
-
-Status_V1_2 DrmPlugin::getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
-        const hidl_vec<uint8_t>& initData,
-        const hidl_string& mimeType,
-        KeyType keyType,
-        const hidl_vec<KeyValue>& optionalParameters,
-        std::vector<uint8_t> *request,
-        KeyRequestType_V1_1 *keyRequestType,
-        std::string *defaultUrl) {
-        UNUSED(optionalParameters);
-
-    // GetKeyRequestOfflineKeyTypeNotSupported() in vts 1.0 and 1.1 expects
-    // KeyType::OFFLINE to return ERROR_DRM_CANNOT_HANDLE in clearkey plugin.
-    // Those tests pass in an empty initData, we use the empty initData to
-    // signal such specific use case.
-    if (keyType == KeyType::OFFLINE && 0 == initData.size()) {
-        return Status_V1_2::ERROR_DRM_CANNOT_HANDLE;
-    }
-
-    *defaultUrl = "https://default.url";
-    *keyRequestType = KeyRequestType_V1_1::UNKNOWN;
-    *request = std::vector<uint8_t>();
-
-    if (scope.size() == 0 ||
-            (keyType != KeyType::STREAMING &&
-            keyType != KeyType::OFFLINE &&
-            keyType != KeyType::RELEASE)) {
-        return Status_V1_2::BAD_VALUE;
-    }
-
-    const std::vector<uint8_t> scopeId = toVector(scope);
-    sp<Session> session;
-    if (keyType == KeyType::STREAMING || keyType == KeyType::OFFLINE) {
-        std::vector<uint8_t> sessionId(scopeId.begin(), scopeId.end());
-        session = mSessionLibrary->findSession(sessionId);
-        if (!session.get()) {
-            return Status_V1_2::ERROR_DRM_SESSION_NOT_OPENED;
-        } else if (session->getMockError() != Status_V1_2::OK) {
-            return session->getMockError();
-        }
-
-        *keyRequestType = KeyRequestType_V1_1::INITIAL;
-    }
-
-    Status_V1_2 status = static_cast<Status_V1_2>(
-            session->getKeyRequest(initData, mimeType, keyType, request));
-
-    if (keyType == KeyType::RELEASE) {
-        std::vector<uint8_t> keySetId(scopeId.begin(), scopeId.end());
-        std::string requestString(request->begin(), request->end());
-        if (requestString.find(kOfflineLicense) != std::string::npos) {
-            std::string emptyResponse;
-            std::string keySetIdString(keySetId.begin(), keySetId.end());
-            if (!mFileHandle.StoreLicense(keySetIdString,
-                    DeviceFiles::kLicenseStateReleasing,
-                    emptyResponse)) {
-                ALOGE("Problem releasing offline license");
-                return Status_V1_2::ERROR_DRM_UNKNOWN;
-            }
-            if (mReleaseKeysMap.find(keySetIdString) == mReleaseKeysMap.end()) {
-                sp<Session> session = mSessionLibrary->createSession();
-                mReleaseKeysMap[keySetIdString] = session->sessionId();
-            } else {
-                ALOGI("key is in use, ignore release request");
-            }
-        } else {
-            ALOGE("Offline license not found, nothing to release");
-        }
-        *keyRequestType = KeyRequestType_V1_1::RELEASE;
-    }
-    return status;
-}
-
-Return<void> DrmPlugin::getKeyRequest(
-        const hidl_vec<uint8_t>& scope,
-        const hidl_vec<uint8_t>& initData,
-        const hidl_string& mimeType,
-        KeyType keyType,
-        const hidl_vec<KeyValue>& optionalParameters,
-        getKeyRequest_cb _hidl_cb) {
-    UNUSED(optionalParameters);
-
-    KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
-    std::string defaultUrl("");
-    std::vector<uint8_t> request;
-    Status_V1_2 status = getKeyRequestCommon(
-            scope, initData, mimeType, keyType, optionalParameters,
-            &request, &keyRequestType, &defaultUrl);
-
-    _hidl_cb(toStatus_1_0(status), toHidlVec(request),
-            toKeyRequestType_V1_0(keyRequestType),
-            hidl_string(defaultUrl));
-    return Void();
-}
-
-Return<void> DrmPlugin::getKeyRequest_1_1(
-        const hidl_vec<uint8_t>& scope,
-        const hidl_vec<uint8_t>& initData,
-        const hidl_string& mimeType,
-        KeyType keyType,
-        const hidl_vec<KeyValue>& optionalParameters,
-        getKeyRequest_1_1_cb _hidl_cb) {
-    UNUSED(optionalParameters);
-
-    KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
-    std::string defaultUrl("");
-    std::vector<uint8_t> request;
-    Status_V1_2 status = getKeyRequestCommon(
-            scope, initData, mimeType, keyType, optionalParameters,
-            &request, &keyRequestType, &defaultUrl);
-
-    _hidl_cb(toStatus_1_0(status), toHidlVec(request),
-            keyRequestType, hidl_string(defaultUrl));
-    return Void();
-}
-
-Return<void> DrmPlugin::getKeyRequest_1_2(
-        const hidl_vec<uint8_t>& scope,
-        const hidl_vec<uint8_t>& initData,
-        const hidl_string& mimeType,
-        KeyType keyType,
-        const hidl_vec<KeyValue>& optionalParameters,
-        getKeyRequest_1_2_cb _hidl_cb) {
-    UNUSED(optionalParameters);
-
-    KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
-    std::string defaultUrl("");
-    std::vector<uint8_t> request;
-    Status_V1_2 status = getKeyRequestCommon(
-            scope, initData, mimeType, keyType, optionalParameters,
-            &request, &keyRequestType, &defaultUrl);
-
-    _hidl_cb(status, toHidlVec(request), keyRequestType, hidl_string(defaultUrl));
-    return Void();
-}
-
-void DrmPlugin::setPlayPolicy() {
-    android::Mutex::Autolock lock(mPlayPolicyLock);
-    mPlayPolicy.clear();
-
-    KeyValue policy;
-    policy.key = kQueryKeyLicenseType;
-    policy.value = kStreaming;
-    mPlayPolicy.push_back(policy);
-
-    policy.key = kQueryKeyPlayAllowed;
-    policy.value = kTrue;
-    mPlayPolicy.push_back(policy);
-
-    policy.key = kQueryKeyRenewAllowed;
-    mPlayPolicy.push_back(policy);
-}
-
-bool DrmPlugin::makeKeySetId(std::string* keySetId) {
-    if (!keySetId) {
-        ALOGE("keySetId destination not provided");
-        return false;
-    }
-    std::vector<uint8_t> ksid(kKeySetIdPrefix.begin(), kKeySetIdPrefix.end());
-    ksid.resize(kKeySetIdLength);
-    std::vector<uint8_t> randomData((kKeySetIdLength - kKeySetIdPrefix.size()) / 2, 0);
-
-    while (keySetId->empty()) {
-        for (auto itr = randomData.begin(); itr != randomData.end(); ++itr) {
-            *itr = std::rand() % 0xff;
-        }
-        *keySetId = kKeySetIdPrefix + ByteArrayToHexString(
-                reinterpret_cast<const uint8_t*>(randomData.data()), randomData.size());
-        if (mFileHandle.LicenseExists(*keySetId)) {
-            // collision, regenerate
-            ALOGV("Retry generating KeySetId");
-            keySetId->clear();
-        }
-    }
-    return true;
-}
-
-Return<void> DrmPlugin::provideKeyResponse(
-        const hidl_vec<uint8_t>& scope,
-        const hidl_vec<uint8_t>& response,
-        provideKeyResponse_cb _hidl_cb) {
-    if (scope.size() == 0 || response.size() == 0) {
-        // Returns empty keySetId
-        _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
-        return Void();
-    }
-
-    std::string responseString(
-            reinterpret_cast<const char*>(response.data()), response.size());
-    const std::vector<uint8_t> scopeId = toVector(scope);
-    std::vector<uint8_t> sessionId;
-    std::string keySetId;
-
-    Status status = Status::OK;
-    bool isOfflineLicense = responseString.find(kOfflineLicense) != std::string::npos;
-    if (scopeId.size() < kKeySetIdPrefix.size()) {
-        android_errorWriteLog(0x534e4554, "144507096");
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
-        return Void();
-    }
-    bool isRelease = (memcmp(scopeId.data(), kKeySetIdPrefix.data(), kKeySetIdPrefix.size()) == 0);
-    if (isRelease) {
-        keySetId.assign(scopeId.begin(), scopeId.end());
-
-        auto iter = mReleaseKeysMap.find(std::string(keySetId.begin(), keySetId.end()));
-        if (iter != mReleaseKeysMap.end()) {
-            sessionId.assign(iter->second.begin(), iter->second.end());
-        }
-    } else {
-        sessionId.assign(scopeId.begin(), scopeId.end());
-        // non offline license returns empty keySetId
-        keySetId.clear();
-    }
-
-    sp<Session> session = mSessionLibrary->findSession(sessionId);
-    if (!session.get()) {
-        _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, hidl_vec<uint8_t>());
-        return Void();
-    }
-    setPlayPolicy();
-
-    status = session->provideKeyResponse(response);
-    if (status == Status::OK) {
-        if (isOfflineLicense) {
-            if (isRelease) {
-                mFileHandle.DeleteLicense(keySetId);
-                mSessionLibrary->destroySession(session);
-            } else {
-                if (!makeKeySetId(&keySetId)) {
-                    _hidl_cb(Status::ERROR_DRM_UNKNOWN, hidl_vec<uint8_t>());
-                    return Void();
-                }
-
-                bool ok = mFileHandle.StoreLicense(
-                        keySetId,
-                        DeviceFiles::kLicenseStateActive,
-                        std::string(response.begin(), response.end()));
-                if (!ok) {
-                    ALOGE("Failed to store offline license");
-                }
-            }
-        }
-
-        // Test calling AMediaDrm listeners.
-        sendEvent(EventType::VENDOR_DEFINED, sessionId, sessionId);
-
-        sendExpirationUpdate(sessionId, 100);
-
-        std::vector<KeyStatus_V1_2> keysStatus;
-        KeyStatus_V1_2 keyStatus;
-
-        std::vector<uint8_t> keyId1 = { 0xA, 0xB, 0xC };
-        keyStatus.keyId = keyId1;
-        keyStatus.type = V1_2::KeyStatusType::USABLE;
-        keysStatus.push_back(keyStatus);
-
-        std::vector<uint8_t> keyId2 = { 0xD, 0xE, 0xF };
-        keyStatus.keyId = keyId2;
-        keyStatus.type = V1_2::KeyStatusType::EXPIRED;
-        keysStatus.push_back(keyStatus);
-
-        std::vector<uint8_t> keyId3 = { 0x0, 0x1, 0x2 };
-        keyStatus.keyId = keyId3;
-        keyStatus.type = V1_2::KeyStatusType::USABLEINFUTURE;
-        keysStatus.push_back(keyStatus);
-
-        sendKeysChange_1_2(sessionId, keysStatus, true);
-
-        installSecureStop(sessionId);
-    } else {
-        ALOGE("provideKeyResponse returns error=%d", status);
-    }
-
-    std::vector<uint8_t> keySetIdVec(keySetId.begin(), keySetId.end());
-    _hidl_cb(status, toHidlVec(keySetIdVec));
-    return Void();
-}
-
-Return<Status> DrmPlugin::restoreKeys(
-        const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& keySetId) {
-        if (sessionId.size() == 0 || keySetId.size() == 0) {
-            return Status::BAD_VALUE;
-        }
-
-        DeviceFiles::LicenseState licenseState;
-        std::string offlineLicense;
-        Status status = Status::OK;
-        if (!mFileHandle.RetrieveLicense(std::string(keySetId.begin(), keySetId.end()),
-                &licenseState, &offlineLicense)) {
-            ALOGE("Failed to restore offline license");
-            return Status::ERROR_DRM_NO_LICENSE;
-        }
-
-        if (DeviceFiles::kLicenseStateUnknown == licenseState ||
-                DeviceFiles::kLicenseStateReleasing == licenseState) {
-            ALOGE("Invalid license state=%d", licenseState);
-            return Status::ERROR_DRM_NO_LICENSE;
-        }
-
-        sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
-        if (!session.get()) {
-            return Status::ERROR_DRM_SESSION_NOT_OPENED;
-        }
-        status = session->provideKeyResponse(std::vector<uint8_t>(offlineLicense.begin(),
-                offlineLicense.end()));
-        if (status != Status::OK) {
-            ALOGE("Failed to restore keys");
-        }
-        return status;
-}
-
-Return<void> DrmPlugin::getPropertyString(
-        const hidl_string& propertyName, getPropertyString_cb _hidl_cb) {
-    std::string name(propertyName.c_str());
-    std::string value;
-
-    if (name == kVendorKey) {
-        value = mStringProperties[kVendorKey];
-    } else if (name == kVersionKey) {
-        value = mStringProperties[kVersionKey];
-    } else if (name == kPluginDescriptionKey) {
-        value = mStringProperties[kPluginDescriptionKey];
-    } else if (name == kAlgorithmsKey) {
-        value = mStringProperties[kAlgorithmsKey];
-    } else if (name == kListenerTestSupportKey) {
-        value = mStringProperties[kListenerTestSupportKey];
-    } else if (name == kDrmErrorTestKey) {
-        value = mStringProperties[kDrmErrorTestKey];
-    } else {
-        ALOGE("App requested unknown string property %s", name.c_str());
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, "");
-        return Void();
-    }
-    _hidl_cb(Status::OK, value.c_str());
-    return Void();
-}
-
-Return<void> DrmPlugin::getPropertyByteArray(
-        const hidl_string& propertyName, getPropertyByteArray_cb _hidl_cb) {
-    std::map<std::string, std::vector<uint8_t> >::iterator itr =
-            mByteArrayProperties.find(std::string(propertyName.c_str()));
-    if (itr == mByteArrayProperties.end()) {
-        ALOGE("App requested unknown property: %s", propertyName.c_str());
-        _hidl_cb(Status::BAD_VALUE, std::vector<uint8_t>());
-        return Void();
-    }
-    _hidl_cb(Status::OK, itr->second);
-    return Void();
-
-}
-
-Return<Status> DrmPlugin::setPropertyString(
-    const hidl_string& name, const hidl_string& value) {
-    std::string immutableKeys;
-    immutableKeys.append(kAlgorithmsKey + ",");
-    immutableKeys.append(kPluginDescriptionKey + ",");
-    immutableKeys.append(kVendorKey + ",");
-    immutableKeys.append(kVersionKey + ",");
-
-    std::string key = std::string(name.c_str());
-    if (immutableKeys.find(key) != std::string::npos) {
-        ALOGD("Cannot set immutable property: %s", key.c_str());
-        return Status::BAD_VALUE;
-    }
-
-    std::map<std::string, std::string>::iterator itr =
-            mStringProperties.find(key);
-    if (itr == mStringProperties.end()) {
-        ALOGE("Cannot set undefined property string, key=%s", key.c_str());
-        return Status::BAD_VALUE;
-    }
-
-    if (name == kDrmErrorTestKey) {
-        if (value == kResourceContentionValue) {
-            mMockError = Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION;
-        } else if (value == kLostStateValue) {
-            mMockError = Status_V1_2::ERROR_DRM_SESSION_LOST_STATE;
-        } else if (value == kFrameTooLargeValue) {
-            mMockError = Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE;
-        } else if (value == kInvalidStateValue)  {
-            mMockError = Status_V1_2::ERROR_DRM_INVALID_STATE;
-        } else {
-            mMockError = Status_V1_2::ERROR_DRM_UNKNOWN;
-        }
-    }
-
-    mStringProperties[key] = std::string(value.c_str());
-    return Status::OK;
-}
-
-Return<Status> DrmPlugin::setPropertyByteArray(
-    const hidl_string& name, const hidl_vec<uint8_t>& value) {
-   UNUSED(value);
-   if (name == kDeviceIdKey) {
-      ALOGD("Cannot set immutable property: %s", name.c_str());
-      return Status::BAD_VALUE;
-   } else if (name == kClientIdKey) {
-       mByteArrayProperties[kClientIdKey] = toVector(value);
-       return Status::OK;
-   }
-
-   // Setting of undefined properties is not supported
-   ALOGE("Failed to set property byte array, key=%s", name.c_str());
-   return Status::ERROR_DRM_CANNOT_HANDLE;
-}
-
-Return<void> DrmPlugin::queryKeyStatus(
-        const hidl_vec<uint8_t>& sessionId,
-        queryKeyStatus_cb _hidl_cb) {
-    if (sessionId.size() == 0) {
-        // Returns empty key status KeyValue pair
-        _hidl_cb(Status::BAD_VALUE, hidl_vec<KeyValue>());
-        return Void();
-    }
-
-    std::vector<KeyValue> infoMapVec;
-    infoMapVec.clear();
-
-    mPlayPolicyLock.lock();
-    KeyValue keyValuePair;
-    for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
-        keyValuePair.key = mPlayPolicy[i].key;
-        keyValuePair.value = mPlayPolicy[i].value;
-        infoMapVec.push_back(keyValuePair);
-    }
-    mPlayPolicyLock.unlock();
-    _hidl_cb(Status::OK, toHidlVec(infoMapVec));
-    return Void();
-}
-
-Return<void> DrmPlugin::getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) {
-        uint32_t currentSessions = mSessionLibrary->numOpenSessions();
-        uint32_t maxSessions = 10;
-        _hidl_cb(Status::OK, currentSessions, maxSessions);
-        return Void();
-}
-
-Return<void> DrmPlugin::getSecurityLevel(const hidl_vec<uint8_t>& sessionId,
-            getSecurityLevel_cb _hidl_cb) {
-    if (sessionId.size() == 0) {
-        _hidl_cb(Status::BAD_VALUE, SecurityLevel::UNKNOWN);
-        return Void();
-    }
-
-    std::vector<uint8_t> sid = toVector(sessionId);
-    sp<Session> session = mSessionLibrary->findSession(sid);
-    if (!session.get()) {
-        _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, SecurityLevel::UNKNOWN);
-        return Void();
-    }
-
-    Mutex::Autolock lock(mSecurityLevelLock);
-    std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
-            mSecurityLevel.find(sid);
-    if (itr == mSecurityLevel.end()) {
-        ALOGE("Session id not found");
-        _hidl_cb(Status::ERROR_DRM_INVALID_STATE, SecurityLevel::UNKNOWN);
-        return Void();
-    }
-
-    _hidl_cb(Status::OK, itr->second);
-    return Void();
-}
-
-Return<void> DrmPlugin::getLogMessages(
-        getLogMessages_cb _hidl_cb) {
-    using std::chrono::duration_cast;
-    using std::chrono::milliseconds;
-    using std::chrono::system_clock;
-
-    auto timeMillis = duration_cast<milliseconds>(
-            system_clock::now().time_since_epoch()).count();
-
-    std::vector<LogMessage> logs = {
-            { timeMillis, LogPriority::ERROR, std::string("Not implemented") }};
-    _hidl_cb(drm::V1_4::Status::OK, toHidlVec(logs));
-    return Void();
-}
-
-Return<bool> DrmPlugin::requiresSecureDecoder(
-        const hidl_string& mime, SecurityLevel level) {
-    UNUSED(mime);
-    UNUSED(level);
-    return false;
-}
-
-Return<bool> DrmPlugin::requiresSecureDecoderDefault(const hidl_string& mime) {
-    UNUSED(mime);
-    // Clearkey only supports SW_SECURE_CRYPTO, so we always returns false
-    // regardless of mime type.
-    return false;
-}
-
-Return<Status> DrmPlugin::setPlaybackId(
-    const hidl_vec<uint8_t>& sessionId,
-    const hidl_string& playbackId) {
-    if (sessionId.size() == 0) {
-        ALOGE("Invalid empty session id");
-        return Status::BAD_VALUE;
-    }
-
-    std::vector<uint8_t> sid = toVector(sessionId);
-    mPlaybackId[sid] = playbackId;
-    return Status::OK;
-}
-
-Return<Status> DrmPlugin::setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
-            SecurityLevel level) {
-    if (sessionId.size() == 0) {
-        ALOGE("Invalid empty session id");
-        return Status::BAD_VALUE;
-    }
-
-    if (level > SecurityLevel::SW_SECURE_CRYPTO) {
-        ALOGE("Cannot set security level > max");
-        return Status::ERROR_DRM_CANNOT_HANDLE;
-    }
-
-    std::vector<uint8_t> sid = toVector(sessionId);
-    sp<Session> session = mSessionLibrary->findSession(sid);
-    if (!session.get()) {
-        return Status::ERROR_DRM_SESSION_NOT_OPENED;
-    }
-
-    Mutex::Autolock lock(mSecurityLevelLock);
-    std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
-            mSecurityLevel.find(sid);
-    if (itr != mSecurityLevel.end()) {
-        mSecurityLevel[sid] = level;
-    } else {
-        if (!mSecurityLevel.insert(
-                std::pair<std::vector<uint8_t>, SecurityLevel>(sid, level)).second) {
-            ALOGE("Failed to set security level");
-            return Status::ERROR_DRM_INVALID_STATE;
-        }
-    }
-    return Status::OK;
-}
-
-Return<void> DrmPlugin::getMetrics(getMetrics_cb _hidl_cb) {
-    // Set the open session count metric.
-    DrmMetricGroup::Attribute openSessionOkAttribute = {
-      "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
-    };
-    DrmMetricGroup::Value openSessionMetricValue = {
-      "count", DrmMetricGroup::ValueType::INT64_TYPE, mOpenSessionOkCount, 0.0, ""
-    };
-    DrmMetricGroup::Metric openSessionMetric = {
-      "open_session", { openSessionOkAttribute }, { openSessionMetricValue }
-    };
-
-    // Set the close session count metric.
-    DrmMetricGroup::Attribute closeSessionOkAttribute = {
-      "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
-    };
-    DrmMetricGroup::Value closeSessionMetricValue = {
-      "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionOkCount, 0.0, ""
-    };
-    DrmMetricGroup::Metric closeSessionMetric = {
-      "close_session", { closeSessionOkAttribute }, { closeSessionMetricValue }
-    };
-
-    // Set the close session, not opened metric.
-    DrmMetricGroup::Attribute closeSessionNotOpenedAttribute = {
-      "status", DrmMetricGroup::ValueType::INT64_TYPE,
-      (int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, 0.0, ""
-    };
-    DrmMetricGroup::Value closeSessionNotOpenedMetricValue = {
-      "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionNotOpenedCount, 0.0, ""
-    };
-    DrmMetricGroup::Metric closeSessionNotOpenedMetric = {
-      "close_session", { closeSessionNotOpenedAttribute }, { closeSessionNotOpenedMetricValue }
-    };
-
-    // Set the setPlaybackId metric.
-    std::vector<DrmMetricGroup::Attribute> sids;
-    std::vector<DrmMetricGroup::Value> playbackIds;
-    for (const auto&[key, value] : mPlaybackId) {
-        std::string sid(key.begin(), key.end());
-        DrmMetricGroup::Attribute sessionIdAttribute = {
-            "sid", DrmMetricGroup::ValueType::STRING_TYPE, 0, 0, sid };
-        sids.push_back(sessionIdAttribute);
-
-        DrmMetricGroup::Value playbackIdMetricValue = {
-            "playbackId", DrmMetricGroup::ValueType::STRING_TYPE, 0, 0, value };
-        playbackIds.push_back(playbackIdMetricValue);
-    }
-    DrmMetricGroup::Metric setPlaybackIdMetric = {
-            "set_playback_id", { sids }, { playbackIds }};
-
-    DrmMetricGroup metrics = {
-            { openSessionMetric, closeSessionMetric,
-              closeSessionNotOpenedMetric, setPlaybackIdMetric }};
-    _hidl_cb(Status::OK, hidl_vec<DrmMetricGroup>({metrics}));
-    return Void();
-}
-
-Return<void> DrmPlugin::getOfflineLicenseKeySetIds(getOfflineLicenseKeySetIds_cb _hidl_cb) {
-    std::vector<std::string> licenseNames = mFileHandle.ListLicenses();
-    std::vector<KeySetId> keySetIds;
-    if (mMockError != Status_V1_2::OK) {
-        _hidl_cb(toStatus_1_0(mMockError), keySetIds);
-        return Void();
-    }
-    for (const auto& name : licenseNames) {
-        std::vector<uint8_t> keySetId(name.begin(), name.end());
-        keySetIds.push_back(keySetId);
-    }
-    _hidl_cb(Status::OK, keySetIds);
-    return Void();
-}
-
-
-Return<Status> DrmPlugin::removeOfflineLicense(const KeySetId& keySetId) {
-    if (mMockError != Status_V1_2::OK) {
-        return toStatus_1_0(mMockError);
-    }
-    std::string licenseName(keySetId.begin(), keySetId.end());
-    if (mFileHandle.DeleteLicense(licenseName)) {
-        return Status::OK;
-    }
-    return Status::BAD_VALUE;
-}
-
-Return<void> DrmPlugin::getOfflineLicenseState(const KeySetId& keySetId,
-        getOfflineLicenseState_cb _hidl_cb) {
-    std::string licenseName(keySetId.begin(), keySetId.end());
-    DeviceFiles::LicenseState state;
-    std::string license;
-    OfflineLicenseState hLicenseState;
-    if (mMockError != Status_V1_2::OK) {
-        _hidl_cb(toStatus_1_0(mMockError), OfflineLicenseState::UNKNOWN);
-    } else if (mFileHandle.RetrieveLicense(licenseName, &state, &license)) {
-        switch (state) {
-        case DeviceFiles::kLicenseStateActive:
-            hLicenseState = OfflineLicenseState::USABLE;
-            break;
-        case DeviceFiles::kLicenseStateReleasing:
-            hLicenseState = OfflineLicenseState::INACTIVE;
-            break;
-        case DeviceFiles::kLicenseStateUnknown:
-            hLicenseState = OfflineLicenseState::UNKNOWN;
-            break;
-        }
-        _hidl_cb(Status::OK, hLicenseState);
-    } else {
-        _hidl_cb(Status::BAD_VALUE, OfflineLicenseState::UNKNOWN);
-    }
-    return Void();
-}
-
-Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) {
-    mSecureStopLock.lock();
-    std::vector<SecureStop> stops;
-    for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
-        ClearkeySecureStop clearkeyStop = itr->second;
-        std::vector<uint8_t> stopVec;
-        stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end());
-        stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end());
-
-        SecureStop stop;
-        stop.opaqueData = toHidlVec(stopVec);
-        stops.push_back(stop);
-    }
-    mSecureStopLock.unlock();
-
-    _hidl_cb(Status::OK, stops);
-    return Void();
-}
-
-Return<void> DrmPlugin::getSecureStop(const hidl_vec<uint8_t>& secureStopId,
-        getSecureStop_cb _hidl_cb) {
-    std::vector<uint8_t> stopVec;
-
-    mSecureStopLock.lock();
-    auto itr = mSecureStops.find(toVector(secureStopId));
-    if (itr != mSecureStops.end()) {
-        ClearkeySecureStop clearkeyStop = itr->second;
-        stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end());
-        stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end());
-    }
-    mSecureStopLock.unlock();
-
-    SecureStop stop;
-    if (!stopVec.empty()) {
-        stop.opaqueData = toHidlVec(stopVec);
-        _hidl_cb(Status::OK, stop);
-    } else {
-        _hidl_cb(Status::BAD_VALUE, stop);
-    }
-    return Void();
-}
-
-Return<Status> DrmPlugin::releaseSecureStop(const hidl_vec<uint8_t>& secureStopId) {
-    return removeSecureStop(secureStopId);
-}
-
-Return<Status> DrmPlugin::releaseAllSecureStops() {
-    return removeAllSecureStops();
-}
-
-Return<void> DrmPlugin::getSecureStopIds(getSecureStopIds_cb _hidl_cb) {
-    mSecureStopLock.lock();
-    std::vector<SecureStopId> ids;
-    for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
-        ids.push_back(itr->first);
-    }
-    mSecureStopLock.unlock();
-
-    _hidl_cb(Status::OK, toHidlVec(ids));
-    return Void();
-}
-
-Return<Status> DrmPlugin::releaseSecureStops(const SecureStopRelease& ssRelease) {
-    // OpaqueData starts with 4 byte decimal integer string
-    const size_t kFourBytesOffset = 4;
-    if (ssRelease.opaqueData.size() < kFourBytesOffset) {
-        ALOGE("Invalid secureStopRelease length");
-        return Status::BAD_VALUE;
-    }
-
-    Status status = Status::OK;
-    std::vector<uint8_t> input = toVector(ssRelease.opaqueData);
-
-    if (input.size() < kSecureStopIdSize + kFourBytesOffset) {
-        // The minimum size of SecureStopRelease has to contain
-        // a 4 bytes count and one secureStop id
-        ALOGE("Total size of secureStops is too short");
-        return Status::BAD_VALUE;
-    }
-
-    // The format of opaqueData is shared between the server
-    // and the drm service. The clearkey implementation consists of:
-    //    count - number of secure stops
-    //    list of fixed length secure stops
-    size_t countBufferSize = sizeof(uint32_t);
-    if (input.size() < countBufferSize) {
-        // SafetyNet logging
-        android_errorWriteLog(0x534e4554, "144766455");
-        return Status::BAD_VALUE;
-    }
-    uint32_t count = 0;
-    sscanf(reinterpret_cast<char*>(input.data()), "%04" PRIu32, &count);
-
-    // Avoid divide by 0 below.
-    if (count == 0) {
-        ALOGE("Invalid 0 secureStop count");
-        return Status::BAD_VALUE;
-    }
-
-    // Computes the fixed length secureStop size
-    size_t secureStopSize = (input.size() - kFourBytesOffset) / count;
-    if (secureStopSize < kSecureStopIdSize) {
-        // A valid secureStop contains the id plus data
-        ALOGE("Invalid secureStop size");
-        return Status::BAD_VALUE;
-    }
-    uint8_t* buffer = new uint8_t[secureStopSize];
-    size_t offset = kFourBytesOffset; // skip the count
-    for (size_t i = 0; i < count; ++i, offset += secureStopSize) {
-        memcpy(buffer, input.data() + offset, secureStopSize);
-
-        // A secureStop contains id+data, we only use the id for removal
-        std::vector<uint8_t> id(buffer, buffer + kSecureStopIdSize);
-        status = removeSecureStop(toHidlVec(id));
-        if (Status::OK != status) break;
-    }
-
-    delete[] buffer;
-    return status;
-}
-
-Return<Status> DrmPlugin::removeSecureStop(const hidl_vec<uint8_t>& secureStopId) {
-    Mutex::Autolock lock(mSecureStopLock);
-
-    if (1 != mSecureStops.erase(toVector(secureStopId))) {
-        return Status::BAD_VALUE;
-    }
-    return Status::OK;
-}
-
-Return<Status> DrmPlugin::removeAllSecureStops() {
-    Mutex::Autolock lock(mSecureStopLock);
-
-    mSecureStops.clear();
-    mNextSecureStopId = kSecureStopIdStart;
-    return Status::OK;
-}
-
-}  // namespace clearkey
-}  // namespace V1_4
-}  // namespace drm
-}  // namespace hardware
-}  // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
deleted file mode 100644
index eccc843..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2018 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_NDEBUG 0
-#define LOG_TAG "hidl_InitDataParser"
-
-#include <algorithm>
-#include <utils/Log.h>
-
-#include "InitDataParser.h"
-
-#include "Base64.h"
-
-#include "ClearKeyUUID.h"
-#include "MimeType.h"
-#include "Utils.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-namespace {
-    const size_t kKeyIdSize = 16;
-    const size_t kSystemIdSize = 16;
-}
-
-std::vector<uint8_t> StrToVector(const std::string& str) {
-    std::vector<uint8_t> vec(str.begin(), str.end());
-    return vec;
-}
-
-Status InitDataParser::parse(const std::vector<uint8_t>& initData,
-        const std::string& mimeType,
-        V1_0::KeyType keyType,
-        std::vector<uint8_t>* licenseRequest) {
-    // Build a list of the key IDs
-    std::vector<const uint8_t*> keyIds;
-
-    if (mimeType == kIsoBmffVideoMimeType.c_str() ||
-        mimeType == kIsoBmffAudioMimeType.c_str() ||
-        mimeType == kCencInitDataFormat.c_str()) {
-        Status res = parsePssh(initData, &keyIds);
-        if (res != Status::OK) {
-            return res;
-        }
-    } else if (mimeType == kWebmVideoMimeType.c_str() ||
-        mimeType == kWebmAudioMimeType.c_str() ||
-        mimeType == kWebmInitDataFormat.c_str()) {
-        // WebM "init data" is just a single key ID
-        if (initData.size() != kKeyIdSize) {
-            return Status::ERROR_DRM_CANNOT_HANDLE;
-        }
-        keyIds.push_back(initData.data());
-    } else {
-        return Status::ERROR_DRM_CANNOT_HANDLE;
-    }
-
-    if (keyType == V1_0::KeyType::RELEASE) {
-        // restore key
-    }
-
-    // Build the request
-    std::string requestJson = generateRequest(keyType, keyIds);
-    std::vector<uint8_t> requestJsonVec = StrToVector(requestJson);
-
-    licenseRequest->clear();
-    licenseRequest->insert(licenseRequest->end(), requestJsonVec.begin(), requestJsonVec.end());
-    return Status::OK;
-}
-
-Status InitDataParser::parsePssh(const std::vector<uint8_t>& initData,
-        std::vector<const uint8_t*>* keyIds) {
-    // Description of PSSH format:
-    // https://w3c.github.io/encrypted-media/format-registry/initdata/cenc.html
-    size_t readPosition = 0;
-
-    uint32_t expectedSize = initData.size();
-    const char psshIdentifier[4] = {'p', 's', 's', 'h'};
-    const uint8_t psshVersion1[4] = {1, 0, 0, 0};
-    uint32_t keyIdCount = 0;
-    size_t headerSize = sizeof(expectedSize) + sizeof(psshIdentifier) +
-                        sizeof(psshVersion1) + kSystemIdSize + sizeof(keyIdCount);
-    if (initData.size() < headerSize) {
-        return Status::ERROR_DRM_CANNOT_HANDLE;
-    }
-
-    // Validate size field
-    expectedSize = htonl(expectedSize);
-    if (memcmp(&initData[readPosition], &expectedSize,
-               sizeof(expectedSize)) != 0) {
-        return Status::ERROR_DRM_CANNOT_HANDLE;
-    }
-    readPosition += sizeof(expectedSize);
-
-    // Validate PSSH box identifier
-    if (memcmp(&initData[readPosition], psshIdentifier,
-               sizeof(psshIdentifier)) != 0) {
-        return Status::ERROR_DRM_CANNOT_HANDLE;
-    }
-    readPosition += sizeof(psshIdentifier);
-
-    // Validate EME version number
-    if (memcmp(&initData[readPosition], psshVersion1,
-               sizeof(psshVersion1)) != 0) {
-        return Status::ERROR_DRM_CANNOT_HANDLE;
-    }
-    readPosition += sizeof(psshVersion1);
-
-    // Validate system ID
-    if (!clearkeydrm::isClearKeyUUID(&initData[readPosition])) {
-        return Status::ERROR_DRM_CANNOT_HANDLE;
-    }
-    readPosition += kSystemIdSize;
-
-    // Read key ID count
-    memcpy(&keyIdCount, &initData[readPosition], sizeof(keyIdCount));
-    keyIdCount = ntohl(keyIdCount);
-    readPosition += sizeof(keyIdCount);
-
-    uint64_t psshSize = 0;
-    if (__builtin_mul_overflow(keyIdCount, kKeyIdSize, &psshSize) ||
-        __builtin_add_overflow(readPosition, psshSize, &psshSize) ||
-        psshSize != initData.size() - sizeof(uint32_t) /* DataSize(0) */) {
-        return Status::ERROR_DRM_CANNOT_HANDLE;
-    }
-
-    // Calculate the key ID offsets
-    for (uint32_t i = 0; i < keyIdCount; ++i) {
-        size_t keyIdPosition = readPosition + (i * kKeyIdSize);
-        keyIds->push_back(&initData[keyIdPosition]);
-    }
-    return Status::OK;
-}
-
-std::string InitDataParser::generateRequest(V1_0::KeyType keyType,
-        const std::vector<const uint8_t*>& keyIds) {
-    const std::string kRequestPrefix("{\"kids\":[");
-    const std::string kTemporarySession("],\"type\":\"temporary\"}");
-    const std::string kPersistentSession("],\"type\":\"persistent-license\"}");
-
-    std::string request(kRequestPrefix);
-    std::string encodedId;
-    for (size_t i = 0; i < keyIds.size(); ++i) {
-        encodedId.clear();
-        encodeBase64Url(keyIds[i], kKeyIdSize, &encodedId);
-        if (i != 0) {
-            request.append(",");
-        }
-        request.push_back('\"');
-        request.append(encodedId);
-        request.push_back('\"');
-    }
-    if (keyType == V1_0::KeyType::STREAMING) {
-        request.append(kTemporarySession);
-    } else if (keyType == V1_0::KeyType::OFFLINE ||
-                   keyType == V1_0::KeyType::RELEASE) {
-            request.append(kPersistentSession);
-    }
-
-    // Android's Base64 encoder produces padding. EME forbids padding.
-    const char kBase64Padding = '=';
-    request.erase(std::remove(request.begin(), request.end(), kBase64Padding), request.end());
-
-    return request;
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp b/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp
deleted file mode 100644
index 45cc775..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (C) 2018 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 "hidl_JsonWebKey"
-
-#include <utils/Log.h>
-
-#include "JsonWebKey.h"
-
-#include "Base64.h"
-
-namespace {
-const std::string kBase64Padding("=");
-const std::string kKeysTag("keys");
-const std::string kKeyTypeTag("kty");
-const std::string kKeyTag("k");
-const std::string kKeyIdTag("kid");
-const std::string kMediaSessionType("type");
-const std::string kPersistentLicenseSession("persistent-license");
-const std::string kSymmetricKeyValue("oct");
-const std::string kTemporaryLicenseSession("temporary");
-}
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-JsonWebKey::JsonWebKey() {
-}
-
-JsonWebKey::~JsonWebKey() {
-}
-
-/*
- * Parses a JSON Web Key Set string, initializes a KeyMap with key id:key
- * pairs from the JSON Web Key Set. Both key ids and keys are base64url
- * encoded. The KeyMap contains base64url decoded key id:key pairs.
- *
- * @return Returns false for errors, true for success.
- */
-bool JsonWebKey::extractKeysFromJsonWebKeySet(const std::string& jsonWebKeySet,
-        KeyMap* keys) {
-
-    keys->clear();
-
-    if (!parseJsonWebKeySet(jsonWebKeySet, &mJsonObjects)) {
-        return false;
-    }
-
-    // mJsonObjects[0] contains the entire JSON Web Key Set, including
-    // all the base64 encoded keys. Each key is also stored separately as
-    // a JSON object in mJsonObjects[1..n] where n is the total
-    // number of keys in the set.
-    if (mJsonObjects.size() == 0 || !isJsonWebKeySet(mJsonObjects[0])) {
-        return false;
-    }
-
-    std::string encodedKey, encodedKeyId;
-    std::vector<uint8_t> decodedKey, decodedKeyId;
-
-    // mJsonObjects[1] contains the first JSON Web Key in the set
-    for (size_t i = 1; i < mJsonObjects.size(); ++i) {
-        encodedKeyId.clear();
-        encodedKey.clear();
-
-        if (!parseJsonObject(mJsonObjects[i], &mTokens))
-            return false;
-
-        if (findKey(mJsonObjects[i], &encodedKeyId, &encodedKey)) {
-            if (encodedKeyId.empty() || encodedKey.empty()) {
-                ALOGE("Must have both key id and key in the JsonWebKey set.");
-                continue;
-            }
-
-            if (!decodeBase64String(encodedKeyId, &decodedKeyId)) {
-                ALOGE("Failed to decode key id(%s)", encodedKeyId.c_str());
-                continue;
-            }
-
-            if (!decodeBase64String(encodedKey, &decodedKey)) {
-                ALOGE("Failed to decode key(%s)", encodedKey.c_str());
-                continue;
-            }
-
-            keys->insert(std::pair<std::vector<uint8_t>,
-                    std::vector<uint8_t> >(decodedKeyId, decodedKey));
-        }
-    }
-    return true;
-}
-
-bool JsonWebKey::decodeBase64String(const std::string& encodedText,
-        std::vector<uint8_t>* decodedText) {
-
-    decodedText->clear();
-
-    // encodedText should not contain padding characters as per EME spec.
-    if (encodedText.find(kBase64Padding) != std::string::npos) {
-        return false;
-    }
-
-    // Since decodeBase64() requires padding characters,
-    // add them so length of encodedText is exactly a multiple of 4.
-    int remainder = encodedText.length() % 4;
-    std::string paddedText(encodedText);
-    if (remainder > 0) {
-        for (int i = 0; i < 4 - remainder; ++i) {
-            paddedText.append(kBase64Padding);
-        }
-    }
-
-    sp<Buffer> buffer = decodeBase64(paddedText);
-    if (buffer == nullptr) {
-        ALOGE("Malformed base64 encoded content found.");
-        return false;
-    }
-
-    decodedText->insert(decodedText->end(), buffer->base(), buffer->base() + buffer->size());
-    return true;
-}
-
-bool JsonWebKey::findKey(const std::string& jsonObject, std::string* keyId,
-        std::string* encodedKey) {
-
-    std::string key, value;
-
-    // Only allow symmetric key, i.e. "kty":"oct" pair.
-    if (jsonObject.find(kKeyTypeTag) != std::string::npos) {
-        findValue(kKeyTypeTag, &value);
-        if (0 != value.compare(kSymmetricKeyValue))
-            return false;
-    }
-
-    if (jsonObject.find(kKeyIdTag) != std::string::npos) {
-        findValue(kKeyIdTag, keyId);
-    }
-
-    if (jsonObject.find(kKeyTag) != std::string::npos) {
-        findValue(kKeyTag, encodedKey);
-    }
-    return true;
-}
-
-void JsonWebKey::findValue(const std::string &key, std::string* value) {
-    value->clear();
-    const char* valueToken;
-    for (std::vector<std::string>::const_iterator nextToken = mTokens.begin();
-        nextToken != mTokens.end(); ++nextToken) {
-        if (0 == (*nextToken).compare(key)) {
-            if (nextToken + 1 == mTokens.end())
-                break;
-            valueToken = (*(nextToken + 1)).c_str();
-            value->assign(valueToken);
-            nextToken++;
-            break;
-        }
-    }
-}
-
-bool JsonWebKey::isJsonWebKeySet(const std::string& jsonObject) const {
-    if (jsonObject.find(kKeysTag) == std::string::npos) {
-        ALOGE("JSON Web Key does not contain keys.");
-        return false;
-    }
-    return true;
-}
-
-/*
- * Parses a JSON objects string and initializes a vector of tokens.
- *
- * @return Returns false for errors, true for success.
- */
-bool JsonWebKey::parseJsonObject(const std::string& jsonObject,
-        std::vector<std::string>* tokens) {
-    jsmn_parser parser;
-
-    jsmn_init(&parser);
-    int numTokens = jsmn_parse(&parser,
-        jsonObject.c_str(), jsonObject.size(), nullptr, 0);
-    if (numTokens < 0) {
-        ALOGE("Parser returns error code=%d", numTokens);
-        return false;
-    }
-
-    unsigned int jsmnTokensSize = numTokens * sizeof(jsmntok_t);
-    mJsmnTokens.clear();
-    mJsmnTokens.resize(jsmnTokensSize);
-
-    jsmn_init(&parser);
-    int status = jsmn_parse(&parser, jsonObject.c_str(),
-        jsonObject.size(), mJsmnTokens.data(), numTokens);
-    if (status < 0) {
-        ALOGE("Parser returns error code=%d", status);
-        return false;
-    }
-
-    tokens->clear();
-    std::string token;
-    const char *pjs;
-    for (int j = 0; j < numTokens; ++j) {
-        pjs = jsonObject.c_str() + mJsmnTokens[j].start;
-        if (mJsmnTokens[j].type == JSMN_STRING ||
-                mJsmnTokens[j].type == JSMN_PRIMITIVE) {
-            token.assign(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start);
-            tokens->push_back(token);
-        }
-    }
-    return true;
-}
-
-/*
- * Parses JSON Web Key Set string and initializes a vector of JSON objects.
- *
- * @return Returns false for errors, true for success.
- */
-bool JsonWebKey::parseJsonWebKeySet(const std::string& jsonWebKeySet,
-        std::vector<std::string>* jsonObjects) {
-    if (jsonWebKeySet.empty()) {
-        ALOGE("Empty JSON Web Key");
-        return false;
-    }
-
-    // The jsmn parser only supports unicode encoding.
-    jsmn_parser parser;
-
-    // Computes number of tokens. A token marks the type, offset in
-    // the original string.
-    jsmn_init(&parser);
-    int numTokens = jsmn_parse(&parser,
-            jsonWebKeySet.c_str(), jsonWebKeySet.size(), nullptr, 0);
-    if (numTokens < 0) {
-        ALOGE("Parser returns error code=%d", numTokens);
-        return false;
-    }
-
-    unsigned int jsmnTokensSize = numTokens * sizeof(jsmntok_t);
-    mJsmnTokens.resize(jsmnTokensSize);
-
-    jsmn_init(&parser);
-    int status = jsmn_parse(&parser, jsonWebKeySet.c_str(),
-            jsonWebKeySet.size(), mJsmnTokens.data(), numTokens);
-    if (status < 0) {
-        ALOGE("Parser returns error code=%d", status);
-        return false;
-    }
-
-    std::string token;
-    const char *pjs;
-    for (int i = 0; i < numTokens; ++i) {
-        pjs = jsonWebKeySet.c_str() + mJsmnTokens[i].start;
-        if (mJsmnTokens[i].type == JSMN_OBJECT) {
-            token.assign(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start);
-            jsonObjects->push_back(token);
-        }
-    }
-    return true;
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
diff --git a/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp b/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
deleted file mode 100644
index 56910be..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
-// source code may only be used and distributed under the Widevine Master
-// License Agreement.
-
-#include <utils/Log.h>
-#include <string>
-
-#include "MemoryFileSystem.h"
-#include "Utils.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-std::string MemoryFileSystem::GetFileName(const std::string& path) {
-    size_t index = path.find_last_of('/');
-    if (index != std::string::npos) {
-        return path.substr(index+1);
-    } else {
-        return path;
-    }
-}
-
-bool MemoryFileSystem::FileExists(const std::string& fileName) const {
-    auto result = mMemoryFileSystem.find(fileName);
-    return result != mMemoryFileSystem.end();
-}
-
-ssize_t MemoryFileSystem::GetFileSize(const std::string& fileName) const {
-    auto result = mMemoryFileSystem.find(fileName);
-    if (result != mMemoryFileSystem.end()) {
-        return static_cast<ssize_t>(result->second.getFileSize());
-    } else {
-        ALOGE("Failed to get size for %s", fileName.c_str());
-        return -1;
-    }
-}
-
-std::vector<std::string> MemoryFileSystem::ListFiles() const {
-    std::vector<std::string> list;
-    for (const auto& filename : mMemoryFileSystem) {
-        list.push_back(filename.first);
-    }
-    return list;
-}
-
-size_t MemoryFileSystem::Read(const std::string& path, std::string* buffer) {
-    std::string key = GetFileName(path);
-    auto result = mMemoryFileSystem.find(key);
-    if (result != mMemoryFileSystem.end()) {
-        std::string serializedHashFile = result->second.getContent();
-        buffer->assign(serializedHashFile);
-        return buffer->size();
-    } else {
-        ALOGE("Failed to read from %s", path.c_str());
-        return -1;
-    }
-}
-
-size_t MemoryFileSystem::Write(const std::string& path, const MemoryFile& memoryFile) {
-    std::string key = GetFileName(path);
-    auto result = mMemoryFileSystem.find(key);
-    if (result != mMemoryFileSystem.end()) {
-        mMemoryFileSystem.erase(key);
-    }
-    mMemoryFileSystem.insert(std::pair<std::string, MemoryFile>(key, memoryFile));
-    return memoryFile.getFileSize();
-}
-
-bool MemoryFileSystem::RemoveFile(const std::string& fileName) {
-    auto result = mMemoryFileSystem.find(fileName);
-    if (result != mMemoryFileSystem.end()) {
-        mMemoryFileSystem.erase(result);
-        return true;
-    } else {
-        ALOGE("Cannot find license to remove: %s", fileName.c_str());
-        return false;
-    }
-}
-
-bool MemoryFileSystem::RemoveAllFiles() {
-    mMemoryFileSystem.clear();
-    return mMemoryFileSystem.empty();
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
deleted file mode 100644
index cf668d4..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2018 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_NDEBUG 0
-#define LOG_TAG "hidl_ClearKeySession"
-#include <utils/Log.h>
-
-#include "Session.h"
-#include "Utils.h"
-
-#include "AesCtrDecryptor.h"
-#include "InitDataParser.h"
-#include "JsonWebKey.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::KeyValue;
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_0::SubSample;
-using ::android::hardware::Return;
-using ::android::sp;
-
-using android::Mutex;
-
-Status Session::getKeyRequest(
-        const std::vector<uint8_t>& initData,
-        const std::string& mimeType,
-        V1_0::KeyType keyType,
-        std::vector<uint8_t>* keyRequest) const {
-    InitDataParser parser;
-    return parser.parse(initData, mimeType, keyType, keyRequest);
-}
-
-Status Session::provideKeyResponse(const std::vector<uint8_t>& response) {
-    std::string responseString(
-            reinterpret_cast<const char*>(response.data()), response.size());
-    KeyMap keys;
-
-    Mutex::Autolock lock(mMapLock);
-    JsonWebKey parser;
-    if (parser.extractKeysFromJsonWebKeySet(responseString, &keys)) {
-        for (auto &key : keys) {
-            std::string first(key.first.begin(), key.first.end());
-            std::string second(key.second.begin(), key.second.end());
-            mKeyMap.insert(std::pair<std::vector<uint8_t>,
-                    std::vector<uint8_t> >(key.first, key.second));
-        }
-        return Status::OK;
-    } else {
-        return Status::ERROR_DRM_UNKNOWN;
-    }
-}
-
-Status_V1_2 Session::decrypt(
-        const KeyId keyId, const Iv iv, const uint8_t* srcPtr,
-        uint8_t* destPtr, const std::vector<SubSample> subSamples,
-        size_t* bytesDecryptedOut) {
-    Mutex::Autolock lock(mMapLock);
-
-    if (getMockError() != Status_V1_2::OK) {
-        return getMockError();
-    }
-
-    std::vector<uint8_t> keyIdVector;
-    keyIdVector.clear();
-    keyIdVector.insert(keyIdVector.end(), keyId, keyId + kBlockSize);
-    std::map<std::vector<uint8_t>, std::vector<uint8_t> >::iterator itr;
-    itr = mKeyMap.find(keyIdVector);
-    if (itr == mKeyMap.end()) {
-        return Status_V1_2::ERROR_DRM_NO_LICENSE;
-    }
-
-    AesCtrDecryptor decryptor;
-    Status status = decryptor.decrypt(
-            itr->second /*key*/, iv, srcPtr, destPtr, subSamples,
-            subSamples.size(), bytesDecryptedOut);
-    return static_cast<Status_V1_2>(status);
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp b/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp
deleted file mode 100644
index 88afcc4..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2018 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_NDEBUG 0
-#define LOG_TAG "hidl_ClearKeySessionLibrary"
-#include <utils/Log.h>
-
-#include "SessionLibrary.h"
-#include "Utils.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::sp;
-
-Mutex SessionLibrary::sSingletonLock;
-SessionLibrary* SessionLibrary::sSingleton = NULL;
-
-SessionLibrary* SessionLibrary::get() {
-    Mutex::Autolock lock(sSingletonLock);
-
-    if (sSingleton == NULL) {
-        ALOGD("Instantiating Session Library Singleton.");
-        sSingleton = new SessionLibrary();
-    }
-
-    return sSingleton;
-}
-
-sp<Session> SessionLibrary::createSession() {
-    Mutex::Autolock lock(mSessionsLock);
-
-    char sessionIdRaw[16];
-    snprintf(sessionIdRaw, sizeof(sessionIdRaw), "%u", mNextSessionId);
-
-    mNextSessionId += 1;
-
-    std::vector<uint8_t> sessionId;
-    sessionId.insert(sessionId.end(), sessionIdRaw,
-            sessionIdRaw + sizeof(sessionIdRaw) / sizeof(uint8_t));
-
-    mSessions.insert(std::pair<std::vector<uint8_t>,
-            sp<Session> >(sessionId, new Session(sessionId)));
-    std::map<std::vector<uint8_t>, sp<Session> >::iterator itr =
-            mSessions.find(sessionId);
-    if (itr != mSessions.end()) {
-        return itr->second;
-    } else {
-        return nullptr;
-    }
-}
-
-sp<Session> SessionLibrary::findSession(
-        const std::vector<uint8_t>& sessionId) {
-    Mutex::Autolock lock(mSessionsLock);
-    std::map<std::vector<uint8_t>, sp<Session> >::iterator itr =
-            mSessions.find(sessionId);
-    if (itr != mSessions.end()) {
-        return itr->second;
-    } else {
-        return nullptr;
-    }
-}
-
-void SessionLibrary::destroySession(const sp<Session>& session) {
-    Mutex::Autolock lock(mSessionsLock);
-    mSessions.erase(session->sessionId());
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service-lazy.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service-lazy.clearkey.rc
deleted file mode 100644
index ec4517d..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service-lazy.clearkey.rc
+++ /dev/null
@@ -1,14 +0,0 @@
-service vendor.drm-clearkey-hal-1-2 /vendor/bin/hw/android.hardware.drm@1.2-service-lazy.clearkey
-    interface android.hardware.drm@1.0::ICryptoFactory clearkey
-    interface android.hardware.drm@1.0::IDrmFactory clearkey
-    interface android.hardware.drm@1.1::ICryptoFactory clearkey
-    interface android.hardware.drm@1.1::IDrmFactory clearkey
-    interface android.hardware.drm@1.2::ICryptoFactory clearkey
-    interface android.hardware.drm@1.2::IDrmFactory clearkey
-    disabled
-    oneshot
-    class hal
-    user media
-    group media mediadrm
-    ioprio rt 4
-    task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc
deleted file mode 100644
index 3b48cf2..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc
+++ /dev/null
@@ -1,13 +0,0 @@
-service vendor.drm-clearkey-hal-1-2 /vendor/bin/hw/android.hardware.drm@1.2-service.clearkey
-    interface android.hardware.drm@1.0::ICryptoFactory clearkey
-    interface android.hardware.drm@1.0::IDrmFactory clearkey
-    interface android.hardware.drm@1.1::ICryptoFactory clearkey
-    interface android.hardware.drm@1.1::IDrmFactory clearkey
-    interface android.hardware.drm@1.2::ICryptoFactory clearkey
-    interface android.hardware.drm@1.2::IDrmFactory clearkey
-    disabled
-    class hal
-    user media
-    group media mediadrm
-    ioprio rt 4
-    task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service-lazy.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service-lazy.clearkey.rc
deleted file mode 100644
index 6e64978..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service-lazy.clearkey.rc
+++ /dev/null
@@ -1,16 +0,0 @@
-service vendor.drm-clearkey-hal-1-3 /vendor/bin/hw/android.hardware.drm@1.3-service-lazy.clearkey
-    interface android.hardware.drm@1.0::ICryptoFactory clearkey
-    interface android.hardware.drm@1.0::IDrmFactory clearkey
-    interface android.hardware.drm@1.1::ICryptoFactory clearkey
-    interface android.hardware.drm@1.1::IDrmFactory clearkey
-    interface android.hardware.drm@1.2::ICryptoFactory clearkey
-    interface android.hardware.drm@1.2::IDrmFactory clearkey
-    interface android.hardware.drm@1.3::ICryptoFactory clearkey
-    interface android.hardware.drm@1.3::IDrmFactory clearkey
-    disabled
-    oneshot
-    class hal
-    user media
-    group media mediadrm
-    ioprio rt 4
-    task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service.clearkey.rc
deleted file mode 100644
index e302e1b..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service.clearkey.rc
+++ /dev/null
@@ -1,14 +0,0 @@
-service vendor.drm-clearkey-hal-1-3 /vendor/bin/hw/android.hardware.drm@1.3-service.clearkey
-    interface android.hardware.drm@1.0::ICryptoFactory clearkey
-    interface android.hardware.drm@1.0::IDrmFactory clearkey
-    interface android.hardware.drm@1.1::ICryptoFactory clearkey
-    interface android.hardware.drm@1.1::IDrmFactory clearkey
-    interface android.hardware.drm@1.2::ICryptoFactory clearkey
-    interface android.hardware.drm@1.2::IDrmFactory clearkey
-    interface android.hardware.drm@1.3::ICryptoFactory clearkey
-    interface android.hardware.drm@1.3::IDrmFactory clearkey
-    class hal
-    user media
-    group media mediadrm
-    ioprio rt 4
-    task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service-lazy.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service-lazy.clearkey.rc
deleted file mode 100644
index 84a63a1..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service-lazy.clearkey.rc
+++ /dev/null
@@ -1,18 +0,0 @@
-service vendor.drm-clearkey-hal-1-4 /vendor/bin/hw/android.hardware.drm@1.4-service-lazy.clearkey
-    interface android.hardware.drm@1.0::ICryptoFactory clearkey
-    interface android.hardware.drm@1.0::IDrmFactory clearkey
-    interface android.hardware.drm@1.1::ICryptoFactory clearkey
-    interface android.hardware.drm@1.1::IDrmFactory clearkey
-    interface android.hardware.drm@1.2::ICryptoFactory clearkey
-    interface android.hardware.drm@1.2::IDrmFactory clearkey
-    interface android.hardware.drm@1.3::ICryptoFactory clearkey
-    interface android.hardware.drm@1.3::IDrmFactory clearkey
-    interface android.hardware.drm@1.4::ICryptoFactory clearkey
-    interface android.hardware.drm@1.4::IDrmFactory clearkey
-    disabled
-    oneshot
-    class hal
-    user media
-    group media mediadrm
-    ioprio rt 4
-    task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service.clearkey.rc
deleted file mode 100644
index 649599e..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service.clearkey.rc
+++ /dev/null
@@ -1,16 +0,0 @@
-service vendor.drm-clearkey-hal-1-4 /vendor/bin/hw/android.hardware.drm@1.4-service.clearkey
-    interface android.hardware.drm@1.0::ICryptoFactory clearkey
-    interface android.hardware.drm@1.0::IDrmFactory clearkey
-    interface android.hardware.drm@1.1::ICryptoFactory clearkey
-    interface android.hardware.drm@1.1::IDrmFactory clearkey
-    interface android.hardware.drm@1.2::ICryptoFactory clearkey
-    interface android.hardware.drm@1.2::IDrmFactory clearkey
-    interface android.hardware.drm@1.3::ICryptoFactory clearkey
-    interface android.hardware.drm@1.3::IDrmFactory clearkey
-    interface android.hardware.drm@1.4::ICryptoFactory clearkey
-    interface android.hardware.drm@1.4::IDrmFactory clearkey
-    class hal
-    user media
-    group media mediadrm
-    ioprio rt 4
-    task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/fuzzer/README.md b/drm/mediadrm/plugins/clearkey/hidl/fuzzer/README.md
deleted file mode 100644
index cb45460..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/fuzzer/README.md
+++ /dev/null
@@ -1,52 +0,0 @@
-# Fuzzer for android.hardware.drm@1.4-service.clearkey
-
-## Plugin Design Considerations
-The fuzzer plugin for android.hardware.drm@1.4-service.clearkey is designed based on the understanding of the
-source code and tries to achieve the following:
-
-##### Maximize code coverage
-The configuration parameters are not hardcoded, but instead selected based on
-incoming data. This ensures more code paths are reached by the fuzzer.
-
-android.hardware.drm@1.4-service.clearkey supports the following parameters:
-1. Security Level (parameter name: `securityLevel`)
-2. Mime Type (parameter name: `mimeType`)
-3. Key Type (parameter name: `keyType`)
-4. Crypto Mode (parameter name: `cryptoMode`)
-
-| Parameter| Valid Values| Configured Value|
-|------------- |-------------| ----- |
-| `securityLevel` | 0.`SecurityLevel::UNKNOWN` 1.`SecurityLevel::SW_SECURE_CRYPTO` 2.`SecurityLevel::SW_SECURE_DECODE` 3.`SecurityLevel::HW_SECURE_CRYPTO`  4.`SecurityLevel::HW_SECURE_DECODE` 5.`SecurityLevel::HW_SECURE_ALL`| Value obtained from FuzzedDataProvider in the range 0 to 5|
-| `mimeType` | 0.`video/mp4` 1.`video/mpeg` 2.`video/x-flv` 3.`video/mj2` 4.`video/3gp2` 5.`video/3gpp` 6.`video/3gpp2` 7.`audio/mp4` 8.`audio/mpeg` 9.`audio/aac` 10.`audio/3gp2` 11.`audio/3gpp` 12.`audio/3gpp2` 13.`audio/webm` 14.`video/webm` 15.`webm` 16.`cenc` 17.`video/unknown` 18.`audio/unknown`| Value obtained from FuzzedDataProvider in the range 0 to 18|
-| `keyType` | 0.`KeyType::OFFLINE` 1.`KeyType::STREAMING` 2.`KeyType::RELEASE` | Value obtained from FuzzedDataProvider in the range 0 to 2|
-| `cryptoMode` | 0.`Mode::UNENCRYPTED` 1.`Mode::AES_CTR` 2.`Mode::AES_CBC_CTS` 3.`Mode::AES_CBC` | Value obtained from FuzzedDataProvider in the range 0 to 3|
-
-This also ensures that the plugin is always deterministic for any given input.
-
-##### Maximize utilization of input data
-The plugin feeds the entire input data to the module.
-This ensures that the plugin tolerates any kind of input (empty, huge,
-malformed, etc) and doesnt `exit()` on any input and thereby increasing the
-chance of identifying vulnerabilities.
-
-## Build
-
-This describes steps to build clearkeyV1.4_fuzzer binary.
-
-### Android
-
-#### Steps to build
-Build the fuzzer
-```
-  $ mm -j$(nproc) clearkeyV1.4_fuzzer
-```
-#### Steps to run
-To run on device
-```
-  $ adb sync data
-  $ adb shell /data/fuzz/${TARGET_ARCH}/clearkeyV1.4_fuzzer/vendor/hw/clearkeyV1.4_fuzzer
-```
-
-## References:
- * http://llvm.org/docs/LibFuzzer.html
- * https://github.com/google/oss-fuzz
diff --git a/drm/mediadrm/plugins/clearkey/hidl/fuzzer/clearkeyV1.4_fuzzer.cpp b/drm/mediadrm/plugins/clearkey/hidl/fuzzer/clearkeyV1.4_fuzzer.cpp
deleted file mode 100644
index afe0e6c..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/fuzzer/clearkeyV1.4_fuzzer.cpp
+++ /dev/null
@@ -1,719 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <include/CreatePluginFactories.h>
-
-#include <android/hidl/allocator/1.0/IAllocator.h>
-#include <fuzzer/FuzzedDataProvider.h>
-#include <hidlmemory/mapping.h>
-#include <include/ClearKeyDrmProperties.h>
-#include <include/CryptoFactory.h>
-#include <include/CryptoPlugin.h>
-#include <include/DrmPlugin.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-namespace drm = ::android::hardware::drm;
-using namespace std;
-using namespace android;
-using ::android::sp;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using drm::V1_0::BufferType;
-using drm::V1_0::DestinationBuffer;
-using drm::V1_0::EventType;
-using drm::V1_0::ICryptoPlugin;
-using drm::V1_0::IDrmPlugin;
-using drm::V1_0::IDrmPluginListener;
-using drm::V1_0::KeyedVector;
-using drm::V1_0::KeyStatus;
-using drm::V1_0::KeyStatusType;
-using drm::V1_0::KeyType;
-using drm::V1_0::Mode;
-using drm::V1_0::Pattern;
-using drm::V1_0::SecureStop;
-using drm::V1_0::SharedBuffer;
-using drm::V1_0::Status;
-using drm::V1_0::SubSample;
-using drm::V1_1::DrmMetricGroup;
-using drm::V1_1::HdcpLevel;
-using drm::V1_1::SecureStopRelease;
-using drm::V1_1::SecurityLevel;
-using drm::V1_2::KeySetId;
-using drm::V1_2::OfflineLicenseState;
-using drm::V1_4::clearkey::ICryptoFactory;
-using drm::V1_4::clearkey::IDrmFactory;
-using drm::V1_4::clearkey::kAlgorithmsKey;
-using drm::V1_4::clearkey::kClientIdKey;
-using drm::V1_4::clearkey::kDeviceIdKey;
-using drm::V1_4::clearkey::kDrmErrorTestKey;
-using drm::V1_4::clearkey::kListenerTestSupportKey;
-using drm::V1_4::clearkey::kMetricsKey;
-using drm::V1_4::clearkey::kPluginDescriptionKey;
-using drm::V1_4::clearkey::kVendorKey;
-using drm::V1_4::clearkey::kVersionKey;
-
-typedef ::android::hardware::hidl_vec<uint8_t> SessionId;
-typedef ::android::hardware::hidl_vec<uint8_t> SecureStopId;
-
-static const uint8_t kInvalidUUID[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
-                                       0x70, 0x80, 0x10, 0x20, 0x30, 0x40,
-                                       0x50, 0x60, 0x70, 0x80};
-
-static const uint8_t kClearKeyUUID[] = {0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85,
-                                        0xB3, 0xC9, 0x78, 0x1A, 0xB0, 0x30,
-                                        0xAF, 0x78, 0xD3, 0x0E};
-
-const SecurityLevel kSecurityLevel[] = {
-    SecurityLevel::UNKNOWN,          SecurityLevel::SW_SECURE_CRYPTO,
-    SecurityLevel::SW_SECURE_DECODE, SecurityLevel::HW_SECURE_CRYPTO,
-    SecurityLevel::HW_SECURE_DECODE, SecurityLevel::HW_SECURE_ALL};
-
-const char *kMimeType[] = {
-    "video/mp4",  "video/mpeg",  "video/x-flv",   "video/mj2",    "video/3gp2",
-    "video/3gpp", "video/3gpp2", "audio/mp4",     "audio/mpeg",   "audio/aac",
-    "audio/3gp2", "audio/3gpp",  "audio/3gpp2",   "audio/webm",   "video/webm",
-    "webm",       "cenc",        "video/unknown", "audio/unknown"};
-
-const char *kCipherAlgorithm[] = {"AES/CBC/NoPadding", ""};
-
-const char *kMacAlgorithm[] = {"HmacSHA256", ""};
-
-const char *kRSAAlgorithm[] = {"RSASSA-PSS-SHA1", ""};
-
-const std::string kProperty[] = {kVendorKey,
-                                 kVersionKey,
-                                 kPluginDescriptionKey,
-                                 kAlgorithmsKey,
-                                 kListenerTestSupportKey,
-                                 kDrmErrorTestKey,
-                                 kDeviceIdKey,
-                                 kClientIdKey,
-                                 kMetricsKey,
-                                 "placeholder"};
-
-const KeyType kKeyType[] = {KeyType::OFFLINE, KeyType::STREAMING,
-                            KeyType::RELEASE};
-
-const Mode kCryptoMode[] = {Mode::UNENCRYPTED, Mode::AES_CTR, Mode::AES_CBC_CTS,
-                            Mode::AES_CBC};
-
-const hidl_vec<uint8_t> validInitData = {
-    // BMFF box header (4 bytes size + 'pssh')
-    0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68,
-    // full box header (version = 1 flags = 0)
-    0x01, 0x00, 0x00, 0x00,
-    // system id
-    0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e,
-    0x52, 0xe2, 0xfb, 0x4b,
-    // number of key ids
-    0x00, 0x00, 0x00, 0x01,
-    // key id
-    0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0, 0x0d,
-    0x1e, 0xd0, 0x0d, 0x1e,
-    // size of data, must be zero
-    0x00, 0x00, 0x00, 0x00};
-
-const hidl_vec<uint8_t> validKeyResponse = {
-    0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22,
-    0x6b, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c,
-    0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59, 0x41, 0x59, 0x65,
-    0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41,
-    0x4e, 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b,
-    0x22, 0x3a, 0x22, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65,
-    0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65, 0x36, 0x34,
-    0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a};
-
-const size_t kAESBlockSize = 16;
-const size_t kMaxStringLength = 100;
-const size_t kMaxSubSamples = 10;
-const size_t kMaxNumBytes = 1000;
-const size_t kSegmentIndex = 0;
-
-template <typename T, size_t size>
-T getValueFromArray(FuzzedDataProvider *fdp, const T (&arr)[size]) {
-  return arr[fdp->ConsumeIntegralInRange<int32_t>(0, size - 1)];
-}
-
-class TestDrmPluginListener : public IDrmPluginListener {
-public:
-  TestDrmPluginListener() {}
-  virtual ~TestDrmPluginListener() {}
-
-  virtual Return<void> sendEvent(EventType /*eventType*/,
-                                 const hidl_vec<uint8_t> & /*sessionId*/,
-                                 const hidl_vec<uint8_t> & /*data*/) override {
-    return Return<void>();
-  }
-
-  virtual Return<void>
-  sendExpirationUpdate(const hidl_vec<uint8_t> & /*sessionId*/,
-                       int64_t /*expiryTimeInMS*/) override {
-    return Return<void>();
-  }
-
-  virtual Return<void>
-  sendKeysChange(const hidl_vec<uint8_t> & /*sessionId*/,
-                 const hidl_vec<KeyStatus> & /*keyStatusList*/,
-                 bool /*hasNewUsableKey*/) override {
-    return Return<void>();
-  }
-};
-
-class ClearKeyFuzzer {
-public:
-  ~ClearKeyFuzzer() { deInit(); }
-  bool init();
-  void process(const uint8_t *data, size_t size);
-
-private:
-  void deInit();
-  void invokeDrmPlugin(const uint8_t *data, size_t size);
-  void invokeCryptoPlugin(const uint8_t *data);
-  void invokeDrm(const uint8_t *data, size_t size);
-  void invokeCrypto(const uint8_t *data);
-  void invokeDrmDecryptEncryptAPI(const uint8_t *data, size_t size);
-  bool invokeDrmFactory();
-  bool invokeCryptoFactory();
-  void invokeDrmV1_4API();
-  void invokeDrmSetAlgorithmAPI();
-  void invokeDrmPropertyAPI();
-  void invokeDrmSecureStopAPI();
-  void invokeDrmOfflineLicenseAPI(const uint8_t *data, size_t size);
-  SessionId getSessionId();
-  SecureStopRelease makeSecureRelease(const SecureStop &stop);
-  sp<IDrmFactory> mDrmFactory = nullptr;
-  sp<ICryptoFactory> mCryptoFactory = nullptr;
-  sp<IDrmPlugin> mDrmPlugin = nullptr;
-  sp<drm::V1_1::IDrmPlugin> mDrmPluginV1_1 = nullptr;
-  sp<drm::V1_2::IDrmPlugin> mDrmPluginV1_2 = nullptr;
-  sp<drm::V1_4::IDrmPlugin> mDrmPluginV1_4 = nullptr;
-  sp<drm::V1_4::ICryptoPlugin> mCryptoPluginV1_4 = nullptr;
-  sp<ICryptoPlugin> mCryptoPlugin = nullptr;
-  FuzzedDataProvider *mFDP = nullptr;
-  SessionId mSessionId = {};
-  SessionId mSessionIdV1 = {};
-};
-
-void ClearKeyFuzzer::deInit() {
-  if (mDrmPluginV1_1) {
-    mDrmPluginV1_1->closeSession(mSessionIdV1);
-  }
-  if (mDrmPluginV1_2) {
-    mDrmPluginV1_2->closeSession(mSessionId);
-  }
-  mDrmFactory.clear();
-  mCryptoFactory.clear();
-  mDrmPlugin.clear();
-  mDrmPluginV1_1.clear();
-  mDrmPluginV1_2.clear();
-  mDrmPluginV1_4.clear();
-  mCryptoPlugin.clear();
-  mCryptoPluginV1_4.clear();
-  mSessionId = {};
-  mSessionIdV1 = {};
-}
-
-void ClearKeyFuzzer::invokeDrmV1_4API() {
-  mDrmPluginV1_4->requiresSecureDecoderDefault(
-      getValueFromArray(mFDP, kMimeType));
-  mDrmPluginV1_4->requiresSecureDecoder(
-      getValueFromArray(mFDP, kMimeType),
-      getValueFromArray(mFDP, kSecurityLevel));
-  mDrmPluginV1_4->setPlaybackId(
-      mSessionId, mFDP->ConsumeRandomLengthString(kMaxStringLength).c_str());
-  drm::V1_4::IDrmPlugin::getLogMessages_cb cb =
-      [&]([[maybe_unused]] drm::V1_4::Status status,
-          [[maybe_unused]] hidl_vec<drm::V1_4::LogMessage> logs) {};
-  mDrmPluginV1_4->getLogMessages(cb);
-}
-
-void ClearKeyFuzzer::invokeDrmSetAlgorithmAPI() {
-  const hidl_string cipherAlgo =
-      mFDP->ConsumeBool()
-          ? mFDP->ConsumeRandomLengthString(kMaxStringLength).c_str()
-          : hidl_string(kCipherAlgorithm[mFDP->ConsumeBool()]);
-  mDrmPluginV1_2->setCipherAlgorithm(mSessionId, cipherAlgo);
-
-  const hidl_string macAlgo =
-      mFDP->ConsumeBool()
-          ? mFDP->ConsumeRandomLengthString(kMaxStringLength).c_str()
-          : hidl_string(kMacAlgorithm[mFDP->ConsumeBool()]);
-  mDrmPluginV1_2->setMacAlgorithm(mSessionId, macAlgo);
-}
-
-void ClearKeyFuzzer::invokeDrmPropertyAPI() {
-  mDrmPluginV1_2->setPropertyString(
-      hidl_string(getValueFromArray(mFDP, kProperty)), hidl_string("value"));
-
-  hidl_string stringValue;
-  mDrmPluginV1_2->getPropertyString(
-      getValueFromArray(mFDP, kProperty),
-      [&](Status status, const hidl_string &hValue) {
-        if (status == Status::OK) {
-          stringValue = hValue;
-        }
-      });
-
-  hidl_vec<uint8_t> value = {};
-  mDrmPluginV1_2->setPropertyByteArray(
-      hidl_string(getValueFromArray(mFDP, kProperty)), value);
-
-  hidl_vec<uint8_t> byteValue;
-  mDrmPluginV1_2->getPropertyByteArray(
-      getValueFromArray(mFDP, kProperty),
-      [&](Status status, const hidl_vec<uint8_t> &hValue) {
-        if (status == Status::OK) {
-          byteValue = hValue;
-        }
-      });
-}
-
-SessionId ClearKeyFuzzer::getSessionId() {
-  SessionId emptySessionId = {};
-  return mFDP->ConsumeBool() ? mSessionId : emptySessionId;
-}
-
-void ClearKeyFuzzer::invokeDrmDecryptEncryptAPI(const uint8_t *data,
-                                                size_t size) {
-  uint32_t currSessions, maximumSessions;
-  mDrmPluginV1_2->getNumberOfSessions(
-      [&](Status status, uint32_t hCurrentSessions, uint32_t hMaxSessions) {
-        if (status == Status::OK) {
-          currSessions = hCurrentSessions;
-          maximumSessions = hMaxSessions;
-        }
-      });
-
-  HdcpLevel connected, maximum;
-  mDrmPluginV1_2->getHdcpLevels([&](Status status,
-                                    const HdcpLevel &hConnectedLevel,
-                                    const HdcpLevel &hMaxLevel) {
-    if (status == Status::OK) {
-      connected = hConnectedLevel;
-      maximum = hMaxLevel;
-    }
-  });
-
-  drm::V1_2::HdcpLevel connectedV1_2, maximumV1_2;
-  mDrmPluginV1_2->getHdcpLevels_1_2(
-      [&](drm::V1_2::Status status, const drm::V1_2::HdcpLevel &connectedLevel,
-          const drm::V1_2::HdcpLevel &maxLevel) {
-        if (status == drm::V1_2::Status::OK) {
-          connectedV1_2 = connectedLevel;
-          maximumV1_2 = maxLevel;
-        }
-      });
-
-  SecurityLevel securityLevel;
-  mDrmPluginV1_2->getSecurityLevel(mSessionId,
-                                   [&](Status status, SecurityLevel hLevel) {
-                                     if (status == Status::OK) {
-                                       securityLevel = hLevel;
-                                     }
-                                   });
-
-  hidl_vec<DrmMetricGroup> metrics;
-  mDrmPluginV1_2->getMetrics(
-      [&](Status status, hidl_vec<DrmMetricGroup> hMetricGroups) {
-        if (status == Status::OK) {
-          metrics = hMetricGroups;
-        }
-      });
-
-  hidl_string certificateType;
-  hidl_string certificateAuthority;
-  mDrmPluginV1_2->getProvisionRequest(certificateType, certificateAuthority,
-                                      [&]([[maybe_unused]] Status status,
-                                          const hidl_vec<uint8_t> &,
-                                          const hidl_string &) {});
-
-  mDrmPluginV1_2->getProvisionRequest_1_2(
-      certificateType, certificateAuthority,
-      [&]([[maybe_unused]] drm::V1_2::Status status, const hidl_vec<uint8_t> &,
-          const hidl_string &) {});
-
-  hidl_vec<uint8_t> response;
-  mDrmPluginV1_2->provideProvisionResponse(
-      response, [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &,
-                    const hidl_vec<uint8_t> &) {});
-
-  hidl_vec<uint8_t> initData = {};
-  if (mFDP->ConsumeBool()) {
-    initData = validInitData;
-  } else {
-    initData.setToExternal(const_cast<uint8_t *>(data), kAESBlockSize);
-  }
-  hidl_string mimeType = getValueFromArray(mFDP, kMimeType);
-  KeyType keyType = mFDP->ConsumeBool()
-                        ? static_cast<KeyType>(mFDP->ConsumeIntegral<size_t>())
-                        : getValueFromArray(mFDP, kKeyType);
-  KeyedVector optionalParameters;
-  mDrmPluginV1_2->getKeyRequest_1_2(
-      mSessionId, initData, mimeType, keyType, optionalParameters,
-      [&]([[maybe_unused]] drm::V1_2::Status status, const hidl_vec<uint8_t> &,
-          drm::V1_1::KeyRequestType, const hidl_string &) {});
-  mDrmPluginV1_1->getKeyRequest_1_1(
-      mSessionIdV1, initData, mimeType, keyType, optionalParameters,
-      [&]([[maybe_unused]] drm::V1_0::Status status, const hidl_vec<uint8_t> &,
-          drm::V1_1::KeyRequestType, const hidl_string &) {});
-  hidl_vec<uint8_t> emptyInitData = {};
-  mDrmPlugin->getKeyRequest(
-      mSessionId, mFDP->ConsumeBool() ? initData : emptyInitData, mimeType,
-      keyType, optionalParameters,
-      [&]([[maybe_unused]] drm::V1_0::Status status, const hidl_vec<uint8_t> &,
-          drm::V1_0::KeyRequestType, const hidl_string &) {});
-
-  hidl_vec<uint8_t> keyResponse = {};
-  if (mFDP->ConsumeBool()) {
-    keyResponse = validKeyResponse;
-  } else {
-    keyResponse.setToExternal(const_cast<uint8_t *>(data), size);
-  }
-  hidl_vec<uint8_t> keySetId;
-  hidl_vec<uint8_t> emptyKeyResponse = {};
-  mDrmPluginV1_2->provideKeyResponse(
-      getSessionId(), mFDP->ConsumeBool() ? keyResponse : emptyKeyResponse,
-      [&](Status status, const hidl_vec<uint8_t> &hKeySetId) {
-        if (status == Status::OK) {
-          keySetId = hKeySetId;
-        }
-      });
-
-  mDrmPluginV1_2->restoreKeys(getSessionId(), keySetId);
-
-  mDrmPluginV1_2->queryKeyStatus(
-      getSessionId(),
-      [&]([[maybe_unused]] Status status, KeyedVector /* info */) {});
-
-  hidl_vec<uint8_t> keyId, input, iv;
-  keyId.setToExternal(const_cast<uint8_t *>(data), size);
-  input.setToExternal(const_cast<uint8_t *>(data), size);
-  iv.setToExternal(const_cast<uint8_t *>(data), size);
-  mDrmPluginV1_2->encrypt(
-      getSessionId(), keyId, input, iv,
-      [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &) {});
-
-  mDrmPluginV1_2->decrypt(
-      getSessionId(), keyId, input, iv,
-      [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &) {});
-
-  hidl_vec<uint8_t> message;
-  message.setToExternal(const_cast<uint8_t *>(data), size);
-  mDrmPluginV1_2->sign(
-      getSessionId(), keyId, message,
-      [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &) {});
-
-  hidl_vec<uint8_t> signature;
-  signature.setToExternal(const_cast<uint8_t *>(data), size);
-  mDrmPluginV1_2->verify(getSessionId(), keyId, message, signature,
-                         [&]([[maybe_unused]] Status status, bool) {});
-
-  hidl_vec<uint8_t> wrappedKey;
-  signature.setToExternal(const_cast<uint8_t *>(data), size);
-  mDrmPluginV1_2->signRSA(
-      getSessionId(), kRSAAlgorithm[mFDP->ConsumeBool()], message, wrappedKey,
-      [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &) {});
-
-  mDrmPluginV1_2->removeKeys(getSessionId());
-}
-
-/**
- * Helper function to create a secure release message for
- * a secure stop. The clearkey secure stop release format
- * is just a count followed by the secure stop opaque data.
- */
-SecureStopRelease ClearKeyFuzzer::makeSecureRelease(const SecureStop &stop) {
-  std::vector<uint8_t> stopData = stop.opaqueData;
-  std::vector<uint8_t> buffer;
-  std::string count = "0001";
-
-  auto it = buffer.insert(buffer.begin(), count.begin(), count.end());
-  buffer.insert(it + count.size(), stopData.begin(), stopData.end());
-  SecureStopRelease release = {.opaqueData = hidl_vec<uint8_t>(buffer)};
-  return release;
-}
-
-void ClearKeyFuzzer::invokeDrmSecureStopAPI() {
-  SecureStopId ssid;
-  mDrmPluginV1_2->getSecureStop(
-      ssid, [&]([[maybe_unused]] Status status, const SecureStop &) {});
-
-  mDrmPluginV1_2->getSecureStopIds(
-      [&]([[maybe_unused]] Status status,
-          [[maybe_unused]] const hidl_vec<SecureStopId> &secureStopIds) {});
-
-  SecureStopRelease release;
-  mDrmPluginV1_2->getSecureStops(
-      [&]([[maybe_unused]] Status status, const hidl_vec<SecureStop> &stops) {
-        if (stops.size() > 0) {
-          release = makeSecureRelease(
-              stops[mFDP->ConsumeIntegralInRange<size_t>(0, stops.size() - 1)]);
-        }
-      });
-
-  mDrmPluginV1_2->releaseSecureStops(release);
-
-  mDrmPluginV1_2->removeSecureStop(ssid);
-
-  mDrmPluginV1_2->removeAllSecureStops();
-
-  mDrmPluginV1_2->releaseSecureStop(ssid);
-
-  mDrmPluginV1_2->releaseAllSecureStops();
-}
-
-void ClearKeyFuzzer::invokeDrmOfflineLicenseAPI(const uint8_t *data,
-                                                size_t size) {
-  hidl_vec<KeySetId> keySetIds = {};
-  mDrmPluginV1_2->getOfflineLicenseKeySetIds(
-      [&](Status status, const hidl_vec<KeySetId> &hKeySetIds) {
-        if (status == Status::OK) {
-          keySetIds = hKeySetIds;
-        }
-      });
-
-  OfflineLicenseState licenseState;
-  KeySetId keySetId = {};
-  if (keySetIds.size() > 0) {
-    keySetId = keySetIds[mFDP->ConsumeIntegralInRange<size_t>(
-        0, keySetIds.size() - 1)];
-  } else {
-    keySetId.setToExternal(const_cast<uint8_t *>(data), size);
-  }
-  mDrmPluginV1_2->getOfflineLicenseState(
-      keySetId, [&](Status status, OfflineLicenseState hLicenseState) {
-        if (status == Status::OK) {
-          licenseState = hLicenseState;
-        }
-      });
-
-  mDrmPluginV1_2->removeOfflineLicense(keySetId);
-}
-
-void ClearKeyFuzzer::invokeDrmPlugin(const uint8_t *data, size_t size) {
-  SecurityLevel secLevel =
-      mFDP->ConsumeBool()
-          ? getValueFromArray(mFDP, kSecurityLevel)
-          : static_cast<SecurityLevel>(mFDP->ConsumeIntegral<uint32_t>());
-  mDrmPluginV1_1->openSession_1_1(
-      secLevel, [&]([[maybe_unused]] Status status, const SessionId &id) {
-        mSessionIdV1 = id;
-      });
-  mDrmPluginV1_2->openSession([&]([[maybe_unused]] Status status,
-                                  const SessionId &id) { mSessionId = id; });
-
-  sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
-  mDrmPluginV1_2->setListener(listener);
-  const hidl_vec<KeyStatus> keyStatusList = {
-      {{1}, KeyStatusType::USABLE},
-      {{2}, KeyStatusType::EXPIRED},
-      {{3}, KeyStatusType::OUTPUTNOTALLOWED},
-      {{4}, KeyStatusType::STATUSPENDING},
-      {{5}, KeyStatusType::INTERNALERROR},
-  };
-  mDrmPluginV1_2->sendKeysChange(mSessionId, keyStatusList, true);
-
-  invokeDrmV1_4API();
-  invokeDrmSetAlgorithmAPI();
-  invokeDrmPropertyAPI();
-  invokeDrmDecryptEncryptAPI(data, size);
-  invokeDrmSecureStopAPI();
-  invokeDrmOfflineLicenseAPI(data, size);
-}
-
-void ClearKeyFuzzer::invokeCryptoPlugin(const uint8_t *data) {
-  mCryptoPlugin->requiresSecureDecoderComponent(
-      getValueFromArray(mFDP, kMimeType));
-
-  const uint32_t width = mFDP->ConsumeIntegral<uint32_t>();
-  const uint32_t height = mFDP->ConsumeIntegral<uint32_t>();
-  mCryptoPlugin->notifyResolution(width, height);
-
-  mCryptoPlugin->setMediaDrmSession(mSessionId);
-
-  size_t totalSize = 0;
-  const size_t numSubSamples =
-      mFDP->ConsumeIntegralInRange<size_t>(1, kMaxSubSamples);
-
-  const Pattern pattern = {0, 0};
-  hidl_vec<SubSample> subSamples;
-  subSamples.resize(numSubSamples);
-
-  for (size_t i = 0; i < numSubSamples; ++i) {
-    const uint32_t clearBytes =
-        mFDP->ConsumeIntegralInRange<uint32_t>(0, kMaxNumBytes);
-    const uint32_t encryptedBytes =
-        mFDP->ConsumeIntegralInRange<uint32_t>(0, kMaxNumBytes);
-    subSamples[i].numBytesOfClearData = clearBytes;
-    subSamples[i].numBytesOfEncryptedData = encryptedBytes;
-    totalSize += subSamples[i].numBytesOfClearData;
-    totalSize += subSamples[i].numBytesOfEncryptedData;
-  }
-
-  // The first totalSize bytes of shared memory is the encrypted
-  // input, the second totalSize bytes is the decrypted output.
-  size_t memoryBytes = totalSize * 2;
-
-  sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
-  if (!ashmemAllocator.get()) {
-    return;
-  }
-
-  hidl_memory hidlMemory;
-  ashmemAllocator->allocate(memoryBytes, [&]([[maybe_unused]] bool success,
-                                             const hidl_memory &memory) {
-    mCryptoPlugin->setSharedBufferBase(memory, kSegmentIndex);
-    hidlMemory = memory;
-  });
-
-  sp<IMemory> mappedMemory = mapMemory(hidlMemory);
-  if (!mappedMemory.get()) {
-    return;
-  }
-  mCryptoPlugin->setSharedBufferBase(hidlMemory, kSegmentIndex);
-
-  uint32_t srcBufferId =
-      mFDP->ConsumeBool() ? kSegmentIndex : mFDP->ConsumeIntegral<uint32_t>();
-  const SharedBuffer sourceBuffer = {
-      .bufferId = srcBufferId, .offset = 0, .size = totalSize};
-
-  BufferType type = mFDP->ConsumeBool() ? BufferType::SHARED_MEMORY
-                                        : BufferType::NATIVE_HANDLE;
-  uint32_t destBufferId =
-      mFDP->ConsumeBool() ? kSegmentIndex : mFDP->ConsumeIntegral<uint32_t>();
-  const DestinationBuffer destBuffer = {
-      .type = type,
-      {.bufferId = destBufferId, .offset = totalSize, .size = totalSize},
-      .secureMemory = nullptr};
-
-  const uint64_t offset = 0;
-  uint32_t bytesWritten = 0;
-  hidl_array<uint8_t, kAESBlockSize> keyId =
-      hidl_array<uint8_t, kAESBlockSize>(data);
-  hidl_array<uint8_t, kAESBlockSize> iv =
-      hidl_array<uint8_t, kAESBlockSize>(data);
-  Mode mode = getValueFromArray(mFDP, kCryptoMode);
-  mCryptoPlugin->decrypt(
-      mFDP->ConsumeBool(), keyId, iv, mode, pattern, subSamples, sourceBuffer,
-      offset, destBuffer,
-      [&]([[maybe_unused]] Status status, uint32_t count,
-          [[maybe_unused]] string detailedError) { bytesWritten = count; });
-  drm::V1_4::IDrmPlugin::getLogMessages_cb cb =
-      [&]([[maybe_unused]] drm::V1_4::Status status,
-          [[maybe_unused]] hidl_vec<drm::V1_4::LogMessage> logs) {};
-  mCryptoPluginV1_4->getLogMessages(cb);
-}
-
-bool ClearKeyFuzzer::invokeDrmFactory() {
-  hidl_string packageName(
-      mFDP->ConsumeRandomLengthString(kMaxStringLength).c_str());
-  hidl_string mimeType(getValueFromArray(mFDP, kMimeType));
-  SecurityLevel securityLevel =
-      mFDP->ConsumeBool()
-          ? getValueFromArray(mFDP, kSecurityLevel)
-          : static_cast<SecurityLevel>(mFDP->ConsumeIntegral<uint32_t>());
-  const hidl_array<uint8_t, 16> uuid =
-      mFDP->ConsumeBool() ? kClearKeyUUID : kInvalidUUID;
-  mDrmFactory->isCryptoSchemeSupported_1_2(uuid, mimeType, securityLevel);
-  mDrmFactory->createPlugin(
-      uuid, packageName, [&](Status status, const sp<IDrmPlugin> &plugin) {
-        if (status == Status::OK) {
-          mDrmPlugin = plugin.get();
-          mDrmPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mDrmPlugin);
-          mDrmPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mDrmPlugin);
-          mDrmPluginV1_4 = drm::V1_4::IDrmPlugin::castFrom(mDrmPlugin);
-        }
-      });
-
-  std::vector<hidl_array<uint8_t, 16>> supportedSchemes;
-  mDrmFactory->getSupportedCryptoSchemes(
-      [&](const hidl_vec<hidl_array<uint8_t, 16>> &schemes) {
-        for (const auto &scheme : schemes) {
-          supportedSchemes.push_back(scheme);
-        }
-      });
-
-  if (!(mDrmPlugin && mDrmPluginV1_1 && mDrmPluginV1_2 && mDrmPluginV1_4)) {
-    return false;
-  }
-  return true;
-}
-
-bool ClearKeyFuzzer::invokeCryptoFactory() {
-  const hidl_array<uint8_t, 16> uuid =
-      mFDP->ConsumeBool() ? kClearKeyUUID : kInvalidUUID;
-  mCryptoFactory->createPlugin(
-      uuid, mSessionId, [this](Status status, const sp<ICryptoPlugin> &plugin) {
-        if (status == Status::OK) {
-          mCryptoPlugin = plugin;
-          mCryptoPluginV1_4 = drm::V1_4::ICryptoPlugin::castFrom(mCryptoPlugin);
-        }
-      });
-
-  if (!mCryptoPlugin && !mCryptoPluginV1_4) {
-    return false;
-  }
-  return true;
-}
-
-void ClearKeyFuzzer::invokeDrm(const uint8_t *data, size_t size) {
-  if (!invokeDrmFactory()) {
-    return;
-  }
-  invokeDrmPlugin(data, size);
-}
-
-void ClearKeyFuzzer::invokeCrypto(const uint8_t *data) {
-  if (!invokeCryptoFactory()) {
-    return;
-  }
-  invokeCryptoPlugin(data);
-}
-
-void ClearKeyFuzzer::process(const uint8_t *data, size_t size) {
-  mFDP = new FuzzedDataProvider(data, size);
-  invokeDrm(data, size);
-  invokeCrypto(data);
-  delete mFDP;
-}
-
-bool ClearKeyFuzzer::init() {
-  mCryptoFactory =
-      android::hardware::drm::V1_4::clearkey::createCryptoFactory();
-  mDrmFactory = android::hardware::drm::V1_4::clearkey::createDrmFactory();
-  if (!mDrmFactory && !mCryptoFactory) {
-    return false;
-  }
-  return true;
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  if (size < kAESBlockSize) {
-    return 0;
-  }
-  ClearKeyFuzzer clearKeyFuzzer;
-  if (clearKeyFuzzer.init()) {
-    clearKeyFuzzer.process(data, size);
-  }
-  return 0;
-}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h b/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h
deleted file mode 100644
index 97794f7..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CLEARKEY_AES_CTR_DECRYPTOR_H_
-#define CLEARKEY_AES_CTR_DECRYPTOR_H_
-
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_0::SubSample;
-
-class AesCtrDecryptor {
-public:
-    AesCtrDecryptor() {}
-
-    Status decrypt(const std::vector<uint8_t>& key, const Iv iv,
-            const uint8_t* source, uint8_t* destination,
-            const std::vector<SubSample> subSamples, size_t numSubSamples,
-            size_t* bytesDecryptedOut);
-
-private:
-    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(AesCtrDecryptor);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_AES_CTR_DECRYPTOR_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h b/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h
deleted file mode 100644
index 2349f23..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BASE_64_H_
-
-#define BASE_64_H_
-
-#include <android/hardware/drm/1.0/types.h>
-
-#include "Buffer.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::sp;
-
-struct Buffer;
-
-sp<Buffer> decodeBase64(const std::string &s);
-void encodeBase64(const void *data, size_t size, std::string *out);
-
-void encodeBase64Url(const void *data, size_t size, std::string *out);
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif  // BASE_64_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h b/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h
deleted file mode 100644
index 66aaa73..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BUFFER_H_
-#define BUFFER_H_
-
-#include <android/hardware/drm/1.0/types.h>
-#include <utils/RefBase.h>
-
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::sp;
-
-struct Buffer : public RefBase {
-    explicit Buffer(size_t capacity);
-
-    uint8_t *base() { return reinterpret_cast<uint8_t *>(mData); }
-    uint8_t *data() { return reinterpret_cast<uint8_t *>(mData) + mRangeOffset; }
-    size_t capacity() const { return mCapacity; }
-    size_t size() const { return mRangeLength; }
-    size_t offset() const { return mRangeOffset; }
-
-protected:
-    virtual ~Buffer();
-
-private:
-    void *mData;
-    size_t mCapacity;
-    size_t mRangeOffset;
-    size_t mRangeLength;
-
-    bool mOwnsData;
-
-    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(Buffer);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif  // BUFFER_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
deleted file mode 100644
index 8e47c45..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CLEARKEY_DRM_PROPERTIES_H_
-#define CLEARKEY_DRM_PROPERTIES_H_
-
-#include <string.h>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-static const std::string kVendorKey("vendor");
-static const std::string kVendorValue("Google");
-static const std::string kVersionKey("version");
-static const std::string kVersionValue("1.2");
-static const std::string kPluginDescriptionKey("description");
-static const std::string kPluginDescriptionValue("ClearKey CDM");
-static const std::string kAlgorithmsKey("algorithms");
-static const std::string kAlgorithmsValue("");
-static const std::string kListenerTestSupportKey("listenerTestSupport");
-static const std::string kListenerTestSupportValue("true");
-static const std::string kDrmErrorTestKey("drmErrorTest");
-static const std::string kDrmErrorTestValue("");
-static const std::string kResourceContentionValue("resourceContention");
-static const std::string kLostStateValue("lostState");
-static const std::string kFrameTooLargeValue("frameTooLarge");
-static const std::string kInvalidStateValue("invalidState");
-
-static const std::string kDeviceIdKey("deviceId");
-static const uint8_t kTestDeviceIdData[] =
-        {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
-         0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
-
-// settable byte array property
-static const std::string kClientIdKey("clientId");
-
-// TODO stub out metrics for nw
-static const std::string kMetricsKey("metrics");
-static const uint8_t kMetricsData[] = { 0 };
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_DRM_PROPERTIES_H_
-
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
deleted file mode 100644
index cd18029..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CLEARKEY_MACROS_H_
-#define CLEARKEY_MACROS_H_
-
-#include <android/hardware/drm/1.2/types.h>
-
-#include <map>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::KeyValue;
-using ::android::hardware::drm::V1_1::SecurityLevel;
-using ::android::hardware::hidl_vec;
-
-const uint8_t kBlockSize = 16; //AES_BLOCK_SIZE;
-typedef uint8_t KeyId[kBlockSize];
-typedef uint8_t Iv[kBlockSize];
-
-typedef ::android::hardware::drm::V1_0::SubSample SubSample;
-typedef std::map<std::vector<uint8_t>, std::vector<uint8_t> > KeyMap;
-
-#define CLEARKEY_DISALLOW_COPY_AND_ASSIGN(TypeName) \
-  TypeName(const TypeName&) = delete;      \
-  void operator=(const TypeName&) = delete;
-
-#define CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(TypeName) \
-  TypeName() = delete;                     \
-  TypeName(const TypeName&) = delete;      \
-  void operator=(const TypeName&) = delete;
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_MACROS_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h b/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
deleted file mode 100644
index d4a8a17..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
-#define CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
-
-#include <android/hardware/drm/1.4/ICryptoFactory.h>
-#include <android/hardware/drm/1.4/IDrmFactory.h>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_4::ICryptoFactory;
-using ::android::hardware::drm::V1_4::IDrmFactory;
-
-extern "C" {
-    IDrmFactory* createDrmFactory();
-    ICryptoFactory* createCryptoFactory();
-}
-
-}  // namespace clearkey
-}  // namespace V1_4
-}  // namespace drm
-}  // namespace hardware
-}  // namespace android
-#endif // CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
deleted file mode 100644
index e6b541f..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CLEARKEY_CRYPTO_FACTORY_H_
-#define CLEARKEY_CRYPTO_FACTORY_H_
-
-#include <android/hardware/drm/1.0/ICryptoPlugin.h>
-#include <android/hardware/drm/1.4/ICryptoFactory.h>
-
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_4::ICryptoFactory;
-using ::android::hardware::drm::V1_0::ICryptoPlugin;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_string;
-using ::android::hardware::Return;
-
-struct CryptoFactory : public ICryptoFactory {
-    CryptoFactory() {}
-    virtual ~CryptoFactory() {}
-
-    Return<bool> isCryptoSchemeSupported(const hidl_array<uint8_t, 16>& uuid)
-            override;
-
-    Return<void> createPlugin(
-            const hidl_array<uint8_t, 16>& uuid,
-            const hidl_vec<uint8_t>& initData,
-            createPlugin_cb _hidl_cb) override;
-
-private:
-    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(CryptoFactory);
-
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_CRYPTO_FACTORY_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
deleted file mode 100644
index b272a83..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CLEARKEY_CRYPTO_PLUGIN_H_
-#define CLEARKEY_CRYPTO_PLUGIN_H_
-
-#include <android/hardware/drm/1.4/ICryptoPlugin.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-
-#include <mutex>
-
-#include "ClearKeyTypes.h"
-#include "Session.h"
-#include "Utils.h"
-
-namespace {
-    static const size_t KEY_ID_SIZE = 16;
-    static const size_t KEY_IV_SIZE = 16;
-}
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-namespace drm = ::android::hardware::drm;
-using drm::V1_0::DestinationBuffer;
-using drm::V1_0::Mode;
-using drm::V1_0::Pattern;
-using drm::V1_0::SharedBuffer;
-using drm::V1_0::Status;
-using drm::V1_0::SubSample;
-
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
-
-typedef drm::V1_2::Status Status_V1_2;
-
-struct CryptoPlugin : public drm::V1_4::ICryptoPlugin {
-    explicit CryptoPlugin(const hidl_vec<uint8_t>& sessionId) {
-        mInitStatus = setMediaDrmSession(sessionId);
-    }
-    virtual ~CryptoPlugin() {}
-
-    Return<bool> requiresSecureDecoderComponent(const hidl_string& mime) {
-        UNUSED(mime);
-        return false;
-    }
-
-    Return<void> notifyResolution(uint32_t width, uint32_t height) {
-        UNUSED(width);
-        UNUSED(height);
-        return Void();
-    }
-
-    Return<void> decrypt(
-            bool secure,
-            const hidl_array<uint8_t, KEY_ID_SIZE>& keyId,
-            const hidl_array<uint8_t, KEY_IV_SIZE>& iv,
-            Mode mode,
-            const Pattern& pattern,
-            const hidl_vec<SubSample>& subSamples,
-            const SharedBuffer& source,
-            uint64_t offset,
-            const DestinationBuffer& destination,
-            decrypt_cb _hidl_cb);
-
-    Return<void> decrypt_1_2(
-            bool secure,
-            const hidl_array<uint8_t, KEY_ID_SIZE>& keyId,
-            const hidl_array<uint8_t, KEY_IV_SIZE>& iv,
-            Mode mode,
-            const Pattern& pattern,
-            const hidl_vec<SubSample>& subSamples,
-            const SharedBuffer& source,
-            uint64_t offset,
-            const DestinationBuffer& destination,
-            decrypt_1_2_cb _hidl_cb) NO_THREAD_SAFETY_ANALYSIS; // use unique_lock
-
-    Return<void> setSharedBufferBase(const hidl_memory& base,
-            uint32_t bufferId);
-
-    Return<Status> setMediaDrmSession(const hidl_vec<uint8_t>& sessionId);
-
-    Return<Status> getInitStatus() const { return mInitStatus; }
-
-    Return<void> getLogMessages(
-            getLogMessages_cb _hidl_cb);
-private:
-    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(CryptoPlugin);
-
-    std::mutex mSharedBufferLock;
-    std::map<uint32_t, sp<IMemory>> mSharedBufferMap GUARDED_BY(mSharedBufferLock);
-    sp<Session> mSession;
-    Status mInitStatus;
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_CRYPTO_PLUGIN_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h b/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h
deleted file mode 100644
index 6466ac3..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
-// source code may only be used and distributed under the Widevine Master
-// License Agreement.
-//
-#ifndef CLEARKEY_DEVICE_FILES_H_
-#define CLEARKEY_DEVICE_FILES_H_
-
-#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "protos/DeviceFiles.pb.h"
-#include "ClearKeyTypes.h"
-#include "MemoryFileSystem.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_2::clearkey::OfflineFile;
-
-class DeviceFiles {
- public:
-    typedef enum {
-        kLicenseStateUnknown,
-        kLicenseStateActive,
-        kLicenseStateReleasing,
-    } LicenseState;
-
-    DeviceFiles() {};
-    virtual ~DeviceFiles() {};
-
-    virtual bool StoreLicense(const std::string& keySetId, LicenseState state,
-            const std::string& keyResponse);
-
-    virtual bool RetrieveLicense(
-            const std::string& key_set_id, LicenseState* state, std::string* offlineLicense);
-
-    virtual bool LicenseExists(const std::string& keySetId);
-
-    virtual std::vector<std::string> ListLicenses() const;
-
-    virtual bool DeleteLicense(const std::string& keySetId);
-
-    virtual bool DeleteAllLicenses();
-
- private:
-    bool FileExists(const std::string& path) const;
-    ssize_t GetFileSize(const std::string& fileName) const;
-    bool RemoveFile(const std::string& fileName);
-
-    bool RetrieveHashedFile(const std::string& fileName, OfflineFile* deSerializedFile);
-    bool StoreFileRaw(const std::string& fileName, const std::string& serializedFile);
-    bool StoreFileWithHash(const std::string& fileName, const std::string& serializedFile);
-
-    MemoryFileSystem mFileHandle;
-
-    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(DeviceFiles);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif  // CLEARKEY_DEVICE_FILES_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
deleted file mode 100644
index fea1ec8..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CLEARKEY_DRM_FACTORY_H_
-#define CLEARKEY_DRM_FACTORY_H_
-
-#include <android/hardware/drm/1.4/IDrmPlugin.h>
-#include <android/hardware/drm/1.4/IDrmFactory.h>
-
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_1::SecurityLevel;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_string;
-using ::android::hardware::Return;
-
-struct DrmFactory : public IDrmFactory {
-    DrmFactory() {}
-    virtual ~DrmFactory() {}
-
-    Return<bool> isCryptoSchemeSupported(const hidl_array<uint8_t, 16>& uuid)
-            override;
-
-    Return<bool> isCryptoSchemeSupported_1_2(const hidl_array<uint8_t, 16>& uuid,
-                                             const hidl_string& mimeType,
-                                             SecurityLevel level) override;
-
-    Return<bool> isContentTypeSupported(const hidl_string &mimeType)
-            override;
-
-    Return<void> createPlugin(
-            const hidl_array<uint8_t, 16>& uuid,
-            const hidl_string& appPackageName,
-            createPlugin_cb _hidl_cb) override;
-
-    Return<void> getSupportedCryptoSchemes(
-            getSupportedCryptoSchemes_cb _hidl_cb) override;
-
-    Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args);
-
-private:
-    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(DrmFactory);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_DRM_FACTORY_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
deleted file mode 100644
index 1019520..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CLEARKEY_DRM_PLUGIN_H_
-#define CLEARKEY_DRM_PLUGIN_H_
-
-#include <android/hardware/drm/1.4/IDrmPlugin.h>
-#include <android/hardware/drm/1.2/IDrmPluginListener.h>
-
-#include <map>
-#include <stdio.h>
-
-#include <utils/List.h>
-
-#include "DeviceFiles.h"
-#include "SessionLibrary.h"
-#include "Utils.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-namespace drm = ::android::hardware::drm;
-using drm::V1_0::EventType;
-using drm::V1_0::IDrmPluginListener;
-using drm::V1_0::KeyRequestType;
-using drm::V1_0::KeyStatus;
-using drm::V1_0::KeyType;
-using drm::V1_0::KeyValue;
-using drm::V1_0::SecureStop;
-using drm::V1_0::SecureStopId;
-using drm::V1_0::SessionId;
-using drm::V1_0::Status;
-using drm::V1_1::DrmMetricGroup;
-using drm::V1_1::HdcpLevel;
-using drm::V1_1::SecureStopRelease;
-using drm::V1_1::SecurityLevel;
-using drm::V1_2::KeySetId;
-using drm::V1_2::OfflineLicenseState;
-using drm::V1_4::clearkey::DeviceFiles;
-using drm::V1_4::clearkey::Session;
-using drm::V1_4::clearkey::SessionLibrary;
-using drm::V1_4::IDrmPlugin;
-
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-
-typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1;
-typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
-typedef drm::V1_2::KeyStatus KeyStatus_V1_2;
-typedef drm::V1_2::Status Status_V1_2;
-typedef drm::V1_2::HdcpLevel HdcpLevel_V1_2;
-
-struct DrmPlugin : public IDrmPlugin {
-    explicit DrmPlugin(SessionLibrary* sessionLibrary);
-
-    virtual ~DrmPlugin() { mFileHandle.DeleteAllLicenses(); }
-
-    Return<void> openSession(openSession_cb _hidl_cb) override;
-    Return<void> openSession_1_1(SecurityLevel securityLevel,
-            openSession_cb _hidl_cb) override;
-
-    Return<Status> closeSession(const hidl_vec<uint8_t>& sessionId) override;
-
-    Return<void> getKeyRequest(
-        const hidl_vec<uint8_t>& scope,
-        const hidl_vec<uint8_t>& initData,
-        const hidl_string& mimeType,
-        KeyType keyType,
-        const hidl_vec<KeyValue>& optionalParameters,
-        getKeyRequest_cb _hidl_cb) override;
-
-    Return<void> getKeyRequest_1_1(
-        const hidl_vec<uint8_t>& scope,
-        const hidl_vec<uint8_t>& initData,
-        const hidl_string& mimeType,
-        KeyType keyType,
-        const hidl_vec<KeyValue>& optionalParameters,
-        getKeyRequest_1_1_cb _hidl_cb) override;
-
-    Return<void> getKeyRequest_1_2(
-        const hidl_vec<uint8_t>& scope,
-        const hidl_vec<uint8_t>& initData,
-        const hidl_string& mimeType,
-        KeyType keyType,
-        const hidl_vec<KeyValue>& optionalParameters,
-        getKeyRequest_1_2_cb _hidl_cb) override;
-
-    Return<void> provideKeyResponse(
-        const hidl_vec<uint8_t>& scope,
-        const hidl_vec<uint8_t>& response,
-        provideKeyResponse_cb _hidl_cb) override;
-
-    Return<Status> removeKeys(const hidl_vec<uint8_t>& sessionId) {
-        if (sessionId.size() == 0) {
-            return Status::BAD_VALUE;
-        }
-        return Status::ERROR_DRM_CANNOT_HANDLE;
-    }
-
-    Return<Status> restoreKeys(
-        const hidl_vec<uint8_t>& sessionId,
-        const hidl_vec<uint8_t>& keySetId) override;
-
-    Return<void> queryKeyStatus(
-        const hidl_vec<uint8_t>& sessionId,
-        queryKeyStatus_cb _hidl_cb) override;
-
-    Return<void> getProvisionRequest(
-        const hidl_string& certificateType,
-        const hidl_string& certificateAuthority,
-        getProvisionRequest_cb _hidl_cb) {
-        UNUSED(certificateType);
-        UNUSED(certificateAuthority);
-
-        hidl_string defaultUrl;
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(), defaultUrl);
-        return Void();
-    }
-
-    Return<void> getProvisionRequest_1_2(
-        const hidl_string& certificateType,
-        const hidl_string& certificateAuthority,
-        getProvisionRequest_1_2_cb _hidl_cb) {
-        UNUSED(certificateType);
-        UNUSED(certificateAuthority);
-
-        hidl_string defaultUrl;
-        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(), defaultUrl);
-        return Void();
-    }
-
-    Return<void> provideProvisionResponse(
-        const hidl_vec<uint8_t>& response,
-        provideProvisionResponse_cb _hidl_cb) {
-
-        if (response.size() == 0) {
-            _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>(), hidl_vec<uint8_t>());
-            return Void();
-        }
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(), hidl_vec<uint8_t>());
-        return Void();
-    }
-
-    Return<void> getHdcpLevels(getHdcpLevels_cb _hidl_cb) {
-        HdcpLevel connectedLevel = HdcpLevel::HDCP_NONE;
-        HdcpLevel maxLevel = HdcpLevel::HDCP_NO_OUTPUT;
-        _hidl_cb(Status::OK, connectedLevel, maxLevel);
-        return Void();
-    }
-
-    Return<void> getHdcpLevels_1_2(getHdcpLevels_1_2_cb _hidl_cb) {
-        HdcpLevel_V1_2 connectedLevel = HdcpLevel_V1_2::HDCP_NONE;
-        HdcpLevel_V1_2 maxLevel = HdcpLevel_V1_2::HDCP_NO_OUTPUT;
-        _hidl_cb(Status_V1_2::OK, connectedLevel, maxLevel);
-        return Void();
-    }
-
-    Return<void> getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) override;
-
-    Return<void> getSecurityLevel(const hidl_vec<uint8_t>& sessionId,
-            getSecurityLevel_cb _hidl_cb) override;
-
-    Return<void> getMetrics(getMetrics_cb _hidl_cb) override;
-
-    Return<void> getOfflineLicenseKeySetIds(getOfflineLicenseKeySetIds_cb _hidl_cb) override;
-
-    Return<Status> removeOfflineLicense(const KeySetId &keySetId) override;
-
-    Return<void> getOfflineLicenseState(const KeySetId &keySetId,
-            getOfflineLicenseState_cb _hidl_cb) override;
-
-    Return<void> getPropertyString(
-        const hidl_string& name,
-        getPropertyString_cb _hidl_cb) override;
-
-    Return<void> getPropertyByteArray(
-        const hidl_string& name,
-        getPropertyByteArray_cb _hidl_cb) override;
-
-    Return<Status> setPropertyString(
-            const hidl_string& name, const hidl_string& value) override;
-
-    Return<Status> setPropertyByteArray(
-            const hidl_string& name, const hidl_vec<uint8_t>& value) override;
-
-    Return<void> getLogMessages(
-        getLogMessages_cb _hidl_cb) override;
-
-    Return<Status> setPlaybackId(
-        const hidl_vec<uint8_t>& sessionId,
-        const hidl_string& playbackId) override;
-
-    Return<bool> requiresSecureDecoder(
-            const hidl_string& mime, SecurityLevel level) override;
-
-    Return<bool> requiresSecureDecoderDefault(const hidl_string& mime) override;
-
-    Return<Status> setCipherAlgorithm(
-            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
-        if (sessionId.size() == 0 || algorithm.size() == 0) {
-            return Status::BAD_VALUE;
-        }
-        return Status::ERROR_DRM_CANNOT_HANDLE;
-    }
-
-    Return<Status> setMacAlgorithm(
-            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
-        if (sessionId.size() == 0 || algorithm.size() == 0) {
-            return Status::BAD_VALUE;
-        }
-        return Status::ERROR_DRM_CANNOT_HANDLE;
-    }
-
-    Return<void> encrypt(
-            const hidl_vec<uint8_t>& sessionId,
-            const hidl_vec<uint8_t>& keyId,
-            const hidl_vec<uint8_t>& input,
-            const hidl_vec<uint8_t>& iv,
-            encrypt_cb _hidl_cb) {
-        if (sessionId.size() == 0 || keyId.size() == 0 ||
-                input.size() == 0 || iv.size() == 0) {
-            _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
-            return Void();
-        }
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
-        return Void();
-    }
-
-    Return<void> decrypt(
-            const hidl_vec<uint8_t>& sessionId,
-            const hidl_vec<uint8_t>& keyId,
-            const hidl_vec<uint8_t>& input,
-            const hidl_vec<uint8_t>& iv,
-            decrypt_cb _hidl_cb) {
-        if (sessionId.size() == 0 || keyId.size() == 0 ||
-                input.size() == 0 || iv.size() == 0) {
-            _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
-            return Void();
-        }
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
-        return Void();
-    }
-
-    Return<void> sign(
-            const hidl_vec<uint8_t>& sessionId,
-            const hidl_vec<uint8_t>& keyId,
-            const hidl_vec<uint8_t>& message,
-            sign_cb _hidl_cb) {
-        if (sessionId.size() == 0 || keyId.size() == 0 ||
-                message.size() == 0) {
-            _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
-            return Void();
-        }
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
-        return Void();
-    }
-
-    Return<void> verify(
-            const hidl_vec<uint8_t>& sessionId,
-            const hidl_vec<uint8_t>& keyId,
-            const hidl_vec<uint8_t>& message,
-            const hidl_vec<uint8_t>& signature,
-            verify_cb _hidl_cb) {
-
-        if (sessionId.size() == 0 || keyId.size() == 0 ||
-                message.size() == 0 || signature.size() == 0) {
-            _hidl_cb(Status::BAD_VALUE, false);
-            return Void();
-        }
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, false);
-        return Void();
-    }
-
-    Return<void> signRSA(
-            const hidl_vec<uint8_t>& sessionId,
-            const hidl_string& algorithm,
-            const hidl_vec<uint8_t>& message,
-            const hidl_vec<uint8_t>& wrappedKey,
-            signRSA_cb _hidl_cb) {
-        if (sessionId.size() == 0 || algorithm.size() == 0 ||
-                message.size() == 0 || wrappedKey.size() == 0) {
-             _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
-             return Void();
-         }
-         _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
-         return Void();
-    }
-
-    Return<void> setListener(const sp<IDrmPluginListener>& listener) {
-        mListener = listener;
-        mListenerV1_2 = IDrmPluginListener_V1_2::castFrom(listener);
-        return Void();
-    };
-
-    Return<void> sendEvent(
-            EventType eventType,
-            const hidl_vec<uint8_t>& sessionId,
-            const hidl_vec<uint8_t>& data) {
-        if (mListenerV1_2 != NULL) {
-            mListenerV1_2->sendEvent(eventType, sessionId, data);
-        } else if (mListener != NULL) {
-            mListener->sendEvent(eventType, sessionId, data);
-        } else {
-            ALOGE("Null event listener, event not sent");
-        }
-        return Void();
-    }
-
-    Return<void> sendExpirationUpdate(
-            const hidl_vec<uint8_t>& sessionId,
-            int64_t expiryTimeInMS) {
-        if (mListenerV1_2 != NULL) {
-            mListenerV1_2->sendExpirationUpdate(sessionId, expiryTimeInMS);
-        } else if (mListener != NULL) {
-            mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
-        } else {
-            ALOGE("Null event listener, event not sent");
-        }
-        return Void();
-    }
-
-    Return<void> sendKeysChange(
-            const hidl_vec<uint8_t>& sessionId,
-            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
-        if (mListenerV1_2 != NULL) {
-            mListenerV1_2->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
-        } else if (mListener != NULL) {
-            mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
-        } else {
-            ALOGE("Null event listener, event not sent");
-        }
-        return Void();
-    }
-
-    Return<void> sendKeysChange_1_2(
-            const hidl_vec<uint8_t>& sessionId,
-            const hidl_vec<KeyStatus_V1_2>& keyStatusList, bool hasNewUsableKey) {
-        if (mListenerV1_2 != NULL) {
-            mListenerV1_2->sendKeysChange_1_2(sessionId, keyStatusList, hasNewUsableKey);
-        }
-        return Void();
-    }
-
-    Return<void> sendSessionLostState(
-            const hidl_vec<uint8_t>& sessionId) {
-        if (mListenerV1_2 != NULL) {
-            mListenerV1_2->sendSessionLostState(sessionId);
-        }
-        return Void();
-    }
-
-    Return<void> getSecureStops(getSecureStops_cb _hidl_cb);
-
-    Return<void> getSecureStop(const hidl_vec<uint8_t>& secureStopId,
-            getSecureStop_cb _hidl_cb);
-
-    Return<Status> releaseSecureStop(const hidl_vec<uint8_t>& ssRelease);
-
-    Return<Status> releaseAllSecureStops();
-
-    Return<void> getSecureStopIds(getSecureStopIds_cb _hidl_cb);
-
-    Return<Status> releaseSecureStops(const SecureStopRelease& ssRelease);
-
-    Return<Status> removeSecureStop(const hidl_vec<uint8_t>& secureStopId);
-
-    Return<Status> removeAllSecureStops();
-
-private:
-    void initProperties();
-    void installSecureStop(const hidl_vec<uint8_t>& sessionId);
-    bool makeKeySetId(std::string* keySetId);
-    void setPlayPolicy();
-
-    Return<Status> setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
-            SecurityLevel level);
-
-    Status_V1_2 getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
-            const hidl_vec<uint8_t>& initData,
-            const hidl_string& mimeType,
-            KeyType keyType,
-            const hidl_vec<KeyValue>& optionalParameters,
-            std::vector<uint8_t> *request,
-            KeyRequestType_V1_1 *getKeyRequestType,
-            std::string *defaultUrl);
-
-    struct ClearkeySecureStop {
-        std::vector<uint8_t> id;
-        std::vector<uint8_t> data;
-    };
-
-    std::map<std::vector<uint8_t>, ClearkeySecureStop> mSecureStops;
-    std::vector<KeyValue> mPlayPolicy;
-    std::map<std::string, std::string> mStringProperties;
-    std::map<std::string, std::vector<uint8_t> > mByteArrayProperties;
-    std::map<std::string, std::vector<uint8_t> > mReleaseKeysMap;
-    std::map<std::vector<uint8_t>, std::string> mPlaybackId;
-    std::map<std::vector<uint8_t>, SecurityLevel> mSecurityLevel
-        GUARDED_BY(mSecurityLevelLock);
-    sp<IDrmPluginListener> mListener;
-    sp<IDrmPluginListener_V1_2> mListenerV1_2;
-    SessionLibrary *mSessionLibrary;
-    int64_t mOpenSessionOkCount;
-    int64_t mCloseSessionOkCount;
-    int64_t mCloseSessionNotOpenedCount;
-    uint32_t mNextSecureStopId;
-    android::Mutex mPlayPolicyLock;
-
-    // set by property to mock error scenarios
-    Status_V1_2 mMockError;
-
-    void processMockError(const sp<Session> &session) {
-        session->setMockError(mMockError);
-        mMockError = Status_V1_2::OK;
-    }
-
-    DeviceFiles mFileHandle;
-    Mutex mSecureStopLock;
-    Mutex mSecurityLevelLock;
-
-    CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_DRM_PLUGIN_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h b/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h
deleted file mode 100644
index 59338c9..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *            http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CLEARKEY_INIT_DATA_PARSER_H_
-#define CLEARKEY_INIT_DATA_PARSER_H_
-
-#include <android/hardware/drm/1.0/types.h>
-
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::Status;
-
-class InitDataParser {
-public:
-    InitDataParser() {}
-
-    Status parse(const std::vector<uint8_t>& initData,
-            const std::string& mimeType,
-            V1_0::KeyType keyType,
-            std::vector<uint8_t>* licenseRequest);
-
-private:
-    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(InitDataParser);
-
-    Status parsePssh(const std::vector<uint8_t>& initData,
-            std::vector<const uint8_t*>* keyIds);
-
-    std::string generateRequest(V1_0::KeyType keyType,
-            const std::vector<const uint8_t*>& keyIds);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_INIT_DATA_PARSER_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h b/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h
deleted file mode 100644
index 40a2d74..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef CLEARKEY_JSON_WEB_KEY_H_
-#define CLEARKEY_JSON_WEB_KEY_H_
-
-#include "jsmn.h"
-#include "Utils.h"
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-class JsonWebKey {
- public:
-    JsonWebKey();
-    virtual ~JsonWebKey();
-
-    bool extractKeysFromJsonWebKeySet(const std::string& jsonWebKeySet,
-            KeyMap* keys);
-
- private:
-    std::vector<jsmntok_t> mJsmnTokens;
-    std::vector<std::string> mJsonObjects;
-    std::vector<std::string> mTokens;
-
-    bool decodeBase64String(const std::string& encodedText,
-            std::vector<uint8_t>* decodedText);
-    bool findKey(const std::string& jsonObject, std::string* keyId,
-            std::string* encodedKey);
-    void findValue(const std::string &key, std::string* value);
-    bool isJsonWebKeySet(const std::string& jsonObject) const;
-    bool parseJsonObject(const std::string& jsonObject,
-            std::vector<std::string>* tokens);
-    bool parseJsonWebKeySet(const std::string& jsonWebKeySet,
-            std::vector<std::string>* jsonObjects);
-
-    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(JsonWebKey);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif  // CLEARKEY_JSON_WEB_KEY_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h b/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
deleted file mode 100644
index 1d98860..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
-// source code may only be used and distributed under the Widevine Master
-// License Agreement.
-//
-#ifndef CLEARKEY_MEMORY_FILE_SYSTEM_H_
-#define CLEARKEY_MEMORY_FILE_SYSTEM_H_
-
-#include <map>
-#include <string>
-
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-// Using android file system requires clearkey plugin to update
-// its sepolicy. However, we are unable to update sepolicy for
-// older vendor partitions. To provide backward compatibility,
-// clearkey plugin implements a very simple file system in memory.
-// This memory file system does not support directory structure.
-class MemoryFileSystem {
- public:
-    struct MemoryFile {
-        std::string fileName;  // excludes path
-        std::string content;
-        size_t fileSize;
-
-        std::string getContent() const { return content; }
-        size_t getFileSize() const { return fileSize; }
-        void setContent(const std::string& file) { content = file; }
-        void setFileName(const std::string& name) { fileName = name; }
-        void setFileSize(size_t size) {
-            content.resize(size); fileSize = size;
-        }
-    };
-
-    MemoryFileSystem() {};
-    virtual ~MemoryFileSystem() {};
-
-    bool FileExists(const std::string& fileName) const;
-    ssize_t GetFileSize(const std::string& fileName) const;
-    std::vector<std::string> ListFiles() const;
-    size_t Read(const std::string& pathName, std::string* buffer);
-    bool RemoveAllFiles();
-    bool RemoveFile(const std::string& fileName);
-    size_t Write(const std::string& pathName, const MemoryFile& memoryFile);
-
- private:
-    // License file name is made up of a unique keySetId, therefore,
-    // the filename can be used as the key to locate licenses in the
-    // memory file system.
-    std::map<std::string, MemoryFile> mMemoryFileSystem;
-
-    std::string GetFileName(const std::string& path);
-
-    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(MemoryFileSystem);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif  // CLEARKEY_MEMORY_FILE_SYSTEM_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
deleted file mode 100644
index 05cb8c8..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CLEARKEY_SESSION_H_
-#define CLEARKEY_SESSION_H_
-
-#include <utils/Mutex.h>
-#include <utils/RefBase.h>
-#include <vector>
-
-#include "ClearKeyTypes.h"
-
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-namespace drm = ::android::hardware::drm;
-using drm::V1_0::Status;
-using drm::V1_0::SubSample;
-
-typedef drm::V1_2::Status Status_V1_2;
-
-class Session : public RefBase {
-public:
-    explicit Session(const std::vector<uint8_t>& sessionId)
-        : mSessionId(sessionId), mMockError(Status_V1_2::OK) {}
-    virtual ~Session() {}
-
-    const std::vector<uint8_t>& sessionId() const { return mSessionId; }
-
-    Status getKeyRequest(
-            const std::vector<uint8_t>& initDataType,
-            const std::string& mimeType,
-            V1_0::KeyType keyType,
-            std::vector<uint8_t>* keyRequest) const;
-
-    Status provideKeyResponse(
-            const std::vector<uint8_t>& response);
-
-    Status_V1_2 decrypt(
-            const KeyId keyId, const Iv iv, const uint8_t* srcPtr,
-            uint8_t* dstPtr, const std::vector<SubSample> subSamples,
-            size_t* bytesDecryptedOut);
-
-    void setMockError(Status_V1_2 error) {mMockError = error;}
-    Status_V1_2 getMockError() const {return mMockError;}
-
-private:
-    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(Session);
-
-    const std::vector<uint8_t> mSessionId;
-    KeyMap mKeyMap;
-    Mutex mMapLock;
-
-    // For mocking error return scenarios
-    Status_V1_2 mMockError;
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_SESSION_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h b/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h
deleted file mode 100644
index 5e77438..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CLEARKEY_SESSION_LIBRARY_H_
-#define CLEARKEY_SESSION_LIBRARY_H_
-
-#include <utils/RefBase.h>
-#include <utils/Mutex.h>
-
-#include "ClearKeyTypes.h"
-#include "Session.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::sp;
-
-class SessionLibrary : public RefBase {
-public:
-    static SessionLibrary* get();
-
-    sp<Session> createSession();
-
-    sp<Session> findSession(
-            const std::vector<uint8_t>& sessionId);
-
-    void destroySession(const sp<Session>& session);
-
-    size_t numOpenSessions() const { return mSessions.size(); }
-
-private:
-    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(SessionLibrary);
-
-    SessionLibrary() : mNextSessionId(1) {}
-
-    static Mutex sSingletonLock;
-    static SessionLibrary* sSingleton;
-
-    Mutex mSessionsLock;
-    uint32_t mNextSessionId;
-    std::map<std::vector<uint8_t>, sp<Session> > mSessions;
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_SESSION_LIBRARY_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
deleted file mode 100644
index 22eeccd..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CLEARKEY_ANDROID_HARDWARE_DRM_V1_4_TYPECONVERT
-#define CLEARKEY_ANDROID_HARDWARE_DRM_V1_4_TYPECONVERT
-
-#include <vector>
-
-#include <android/hardware/drm/1.0/types.h>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_vec;
-
-template<typename T> const hidl_vec<T> toHidlVec(const std::vector<T> &vec) {
-    hidl_vec<T> hVec;
-    hVec.setToExternal(const_cast<T *>(vec.data()), vec.size());
-    return hVec;
-}
-
-template<typename T> hidl_vec<T> toHidlVec(std::vector<T> &vec) {
-    hidl_vec<T> hVec;
-    hVec.setToExternal(vec.data(), vec.size());
-    return hVec;
-}
-
-template<typename T> const std::vector<T> toVector(const hidl_vec<T> &hVec) {
-    std::vector<T> vec;
-    vec.assign(hVec.data(), hVec.data() + hVec.size());
-    return *const_cast<const std::vector<T> *>(&vec);
-}
-
-template<typename T> std::vector<T> toVector(hidl_vec<T> &hVec) {
-    std::vector<T> vec;
-    vec.assign(hVec.data(), hVec.data() + hVec.size());
-    return vec;
-}
-
-template<typename T, size_t SIZE> const std::vector<T> toVector(
-        const hidl_array<T, SIZE> &hArray) {
-    std::vector<T> vec;
-    vec.assign(hArray.data(), hArray.data() + hArray.size());
-    return vec;
-}
-
-template<typename T, size_t SIZE> std::vector<T> toVector(
-        hidl_array<T, SIZE> &hArray) {
-    std::vector<T> vec;
-    vec.assign(hArray.data(), hArray.data() + hArray.size());
-    return vec;
-}
-
-inline Status toStatus_1_0(Status_V1_2 status) {
-  switch (status) {
-    case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY:
-    case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE:
-    case Status_V1_2::ERROR_DRM_SESSION_LOST_STATE:
-      return Status::ERROR_DRM_UNKNOWN;
-    default:
-      return static_cast<Status>(status);
-  }
-}
-
-}  // namespace clearkey
-}  // namespace V1_4
-}  // namespace drm
-}  // namespace hardware
-}  // namespace android
-
-#endif // CLEARKEY_ANDROID_HARDWARE_DRM_V1_4_TYPECONVERT
diff --git a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.2-service.clearkey.xml b/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.2-service.clearkey.xml
deleted file mode 100644
index 16cba11..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.2-service.clearkey.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 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.
--->
-<manifest version="1.0" type="device">
-    <hal format="hidl">
-        <name>android.hardware.drm</name>
-        <transport>hwbinder</transport>
-        <fqname>@1.2::ICryptoFactory/clearkey</fqname>
-        <fqname>@1.2::IDrmFactory/clearkey</fqname>
-    </hal>
-</manifest>
diff --git a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.3-service.clearkey.xml b/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.3-service.clearkey.xml
deleted file mode 100644
index 229ee96..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.3-service.clearkey.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 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.
--->
-<manifest version="1.0" type="device">
-    <hal format="hidl">
-        <name>android.hardware.drm</name>
-        <transport>hwbinder</transport>
-        <fqname>@1.3::ICryptoFactory/clearkey</fqname>
-        <fqname>@1.3::IDrmFactory/clearkey</fqname>
-    </hal>
-</manifest>
diff --git a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.4-service.clearkey.xml b/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.4-service.clearkey.xml
deleted file mode 100644
index 31ddb5f..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.4-service.clearkey.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<manifest version="1.0" type="device">
-    <hal format="hidl">
-        <name>android.hardware.drm</name>
-        <transport>hwbinder</transport>
-        <fqname>@1.4::ICryptoFactory/clearkey</fqname>
-        <fqname>@1.4::IDrmFactory/clearkey</fqname>
-    </hal>
-</manifest>
diff --git a/drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto b/drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto
deleted file mode 100644
index 3e11f0b..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto
+++ /dev/null
@@ -1,47 +0,0 @@
-// ----------------------------------------------------------------------------
-// device_files.proto
-// ----------------------------------------------------------------------------
-// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
-// source code may only be used and distributed under the Widevine Master
-// License Agreement.
-//
-// Description:
-//   Format of various files stored at the device.
-//
-syntax = "proto2";
-
-package android.hardware.drm.V1_2.clearkey;
-
-// need this if we are using libprotobuf-cpp-2.3.0-lite
-option optimize_for = LITE_RUNTIME;
-
-message License {
-  enum LicenseState {
-    ACTIVE = 1;
-    RELEASING = 2;
-  }
-
-  optional LicenseState state = 1;
-  optional bytes license = 2;
-}
-
-message OfflineFile {
-  enum FileType {
-    LICENSE = 1;
-  }
-
-  enum FileVersion {
-    VERSION_1 = 1;
-  }
-
-  optional FileType type = 1;
-  optional FileVersion version = 2 [default = VERSION_1];
-  optional License license = 3;
-
-}
-
-message HashedFile {
-  optional bytes file = 1;
-  // A raw (not hex-encoded) SHA256, taken over the bytes of 'file'.
-  optional bytes hash = 2;
-}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/service.cpp b/drm/mediadrm/plugins/clearkey/hidl/service.cpp
deleted file mode 100644
index d3d6905..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/service.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2018 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 <CryptoFactory.h>
-#include <DrmFactory.h>
-
-#include <android-base/logging.h>
-#include <binder/ProcessState.h>
-#include <hidl/HidlLazyUtils.h>
-#include <hidl/HidlTransportSupport.h>
-
-using ::android::hardware::configureRpcThreadpool;
-using ::android::hardware::joinRpcThreadpool;
-using ::android::sp;
-
-using android::hardware::drm::V1_4::ICryptoFactory;
-using android::hardware::drm::V1_4::IDrmFactory;
-using android::hardware::drm::V1_4::clearkey::CryptoFactory;
-using android::hardware::drm::V1_4::clearkey::DrmFactory;
-
-int main(int /* argc */, char** /* argv */) {
-    sp<IDrmFactory> drmFactory = new DrmFactory;
-    sp<ICryptoFactory> cryptoFactory = new CryptoFactory;
-
-    configureRpcThreadpool(8, true /* callerWillJoin */);
-
-    // Setup hwbinder service
-    CHECK_EQ(drmFactory->registerAsService("clearkey"), android::NO_ERROR)
-        << "Failed to register Clearkey Factory HAL";
-    CHECK_EQ(cryptoFactory->registerAsService("clearkey"), android::NO_ERROR)
-        << "Failed to register Clearkey Crypto  HAL";
-
-    joinRpcThreadpool();
-}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp b/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp
deleted file mode 100644
index 358b5cc..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2019 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 <CryptoFactory.h>
-#include <DrmFactory.h>
-
-#include <android-base/logging.h>
-#include <binder/ProcessState.h>
-#include <hidl/HidlLazyUtils.h>
-#include <hidl/HidlTransportSupport.h>
-
-using ::android::hardware::configureRpcThreadpool;
-using ::android::hardware::joinRpcThreadpool;
-using ::android::sp;
-
-using android::hardware::drm::V1_4::ICryptoFactory;
-using android::hardware::drm::V1_4::IDrmFactory;
-using android::hardware::drm::V1_4::clearkey::CryptoFactory;
-using android::hardware::drm::V1_4::clearkey::DrmFactory;
-using android::hardware::LazyServiceRegistrar;
-
-int main(int /* argc */, char** /* argv */) {
-    sp<IDrmFactory> drmFactory = new DrmFactory;
-    sp<ICryptoFactory> cryptoFactory = new CryptoFactory;
-
-    configureRpcThreadpool(8, true /* callerWillJoin */);
-
-    // Setup hwbinder service
-    auto serviceRegistrar = LazyServiceRegistrar::getInstance();
-
-    // Setup hwbinder service
-    CHECK_EQ(serviceRegistrar.registerService(drmFactory, "clearkey"), android::NO_ERROR)
-        << "Failed to register Clearkey Factory HAL";
-    CHECK_EQ(serviceRegistrar.registerService(cryptoFactory, "clearkey"), android::NO_ERROR)
-        << "Failed to register Clearkey Crypto  HAL";
-
-    joinRpcThreadpool();
-}
diff --git a/include/drm/TEST_MAPPING b/include/drm/TEST_MAPPING
index 74fa50d..8595f12 100644
--- a/include/drm/TEST_MAPPING
+++ b/include/drm/TEST_MAPPING
@@ -1,16 +1,16 @@
 {
   "presubmit": [
     {
-      "name": "GtsMediaTestCases",
+      "name": "WvtsDeviceTestCases",
       "options" : [
         {
           "include-annotation": "android.platform.test.annotations.Presubmit"
         },
         {
-          "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+          "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
         },
         {
-          "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
+          "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests"
         }
       ]
     }
diff --git a/include/media/Interpolator.h b/include/media/Interpolator.h
index 71e7604..0ee8779 100644
--- a/include/media/Interpolator.h
+++ b/include/media/Interpolator.h
@@ -122,7 +122,7 @@
             // monotonic computation.
             // we use lazy computation here - if we precompute in
             // a single pass, duplicate secant computations may be avoided.
-            S sec, sec0, sec1;
+            S sec{}, sec0{}, sec1{};  // initialization not needed, used for clang-tidy
             if (!catmullRom || monotonic) {
                 sec = (high->second - low->second) / interval;
                 sec0 = low2 != this->end()
@@ -269,7 +269,7 @@
 
         // Note: We don't need to check size is within some bounds as
         // the Parcel read will fail if size is incorrectly specified too large.
-        float lastx;
+        float lastx = 0.f; // initialization not needed, used for clang tidy
         for (uint32_t i = 0; i < size; ++i) {
             float x = config.xy[i * 2];
             float y = config.xy[i * 2 + 1];
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
index 9aa896c..87256c8 100644
--- a/media/TEST_MAPPING
+++ b/media/TEST_MAPPING
@@ -21,16 +21,16 @@
     ],
     "presubmit": [
         {
-            "name": "GtsMediaTestCases",
+            "name": "WvtsDeviceTestCases",
             "options" : [
                 {
                     "include-annotation": "android.platform.test.annotations.Presubmit"
                 },
                 {
-                    "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+                    "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
                 },
                 {
-                    "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
+                    "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests"
                 }
             ],
             "file_patterns": ["(?i)drm|crypto"]
diff --git a/media/audioaidlconversion/AidlConversionCore.cpp b/media/audioaidlconversion/AidlConversionCore.cpp
new file mode 100644
index 0000000..948e35d
--- /dev/null
+++ b/media/audioaidlconversion/AidlConversionCore.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "AidlConversionCore"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <media/AidlConversionCore.h>
+#include <media/AidlConversionCppNdk.h>
+
+namespace aidl {
+namespace android {
+
+using MicrophoneDirection = hardware::audio::core::IStreamIn::MicrophoneDirection;
+using ::android::BAD_VALUE;
+using ::android::OK;
+using ::android::status_t;
+using ::android::base::unexpected;
+
+ConversionResult<audio_microphone_direction_t>
+aidl2legacy_MicrophoneDirection_audio_microphone_direction_t(MicrophoneDirection aidl) {
+    switch (aidl) {
+        case MicrophoneDirection::UNSPECIFIED:
+            return MIC_DIRECTION_UNSPECIFIED;
+        case MicrophoneDirection::FRONT:
+            return MIC_DIRECTION_FRONT;
+        case MicrophoneDirection::BACK:
+            return MIC_DIRECTION_BACK;
+        case MicrophoneDirection::EXTERNAL:
+            return MIC_DIRECTION_EXTERNAL;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<MicrophoneDirection>
+legacy2aidl_audio_microphone_direction_t_MicrophoneDirection(audio_microphone_direction_t legacy) {
+    switch (legacy) {
+        case MIC_DIRECTION_UNSPECIFIED:
+            return MicrophoneDirection::UNSPECIFIED;
+        case MIC_DIRECTION_FRONT:
+            return MicrophoneDirection::FRONT;
+        case MIC_DIRECTION_BACK:
+            return MicrophoneDirection::BACK;
+        case MIC_DIRECTION_EXTERNAL:
+            return MicrophoneDirection::EXTERNAL;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+}  // namespace android
+}  // aidl
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 8c2b940..0cfd128 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <stdio.h>
+
 #include <algorithm>
 #include <map>
 #include <utility>
@@ -570,7 +572,6 @@
                 GET_DEVICE_DESC_CONNECTION(BT_LE));
         return pairs;
     }();
-#undef GET_DEVICE_DESC_CONNECTION
     return pairs;
 }
 
@@ -998,55 +999,161 @@
     }
 }
 
+AudioDeviceAddress::Tag suggestDeviceAddressTag(const AudioDeviceDescription& description) {
+    using Tag = AudioDeviceAddress::Tag;
+    if (std::string connection = description.connection;
+            connection == GET_DEVICE_DESC_CONNECTION(BT_A2DP) ||
+            // Note: BT LE Broadcast uses a "group id".
+            (description.type != AudioDeviceType::OUT_BROADCAST &&
+                    connection == GET_DEVICE_DESC_CONNECTION(BT_LE)) ||
+            connection == GET_DEVICE_DESC_CONNECTION(BT_SCO) ||
+            connection == GET_DEVICE_DESC_CONNECTION(WIRELESS)) {
+        return Tag::mac;
+    } else if (connection == GET_DEVICE_DESC_CONNECTION(IP_V4)) {
+        return Tag::ipv4;
+    } else if (connection == GET_DEVICE_DESC_CONNECTION(USB)) {
+        return Tag::alsa;
+    }
+    return Tag::id;
+}
+
 ::android::status_t aidl2legacy_AudioDevice_audio_device(
         const AudioDevice& aidl,
         audio_devices_t* legacyType, char* legacyAddress) {
-    *legacyType = VALUE_OR_RETURN_STATUS(
-            aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
-    return aidl2legacy_string(
-                    aidl.address.get<AudioDeviceAddress::id>(),
-                    legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN);
+    std::string stringAddress;
+    RETURN_STATUS_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+                    aidl, legacyType, &stringAddress));
+    return aidl2legacy_string(stringAddress, legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN);
 }
 
 ::android::status_t aidl2legacy_AudioDevice_audio_device(
         const AudioDevice& aidl,
         audio_devices_t* legacyType, String8* legacyAddress) {
-    *legacyType = VALUE_OR_RETURN_STATUS(
-            aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
-    *legacyAddress = VALUE_OR_RETURN_STATUS(aidl2legacy_string_view_String8(
-                    aidl.address.get<AudioDeviceAddress::id>()));
+    std::string stringAddress;
+    RETURN_STATUS_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+                    aidl, legacyType, &stringAddress));
+    *legacyAddress = VALUE_OR_RETURN_STATUS(aidl2legacy_string_view_String8(stringAddress));
     return OK;
 }
 
 ::android::status_t aidl2legacy_AudioDevice_audio_device(
         const AudioDevice& aidl,
         audio_devices_t* legacyType, std::string* legacyAddress) {
+    using Tag = AudioDeviceAddress::Tag;
     *legacyType = VALUE_OR_RETURN_STATUS(
             aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
-    *legacyAddress = aidl.address.get<AudioDeviceAddress::id>();
+    char addressBuffer[AUDIO_DEVICE_MAX_ADDRESS_LEN]{};
+    // 'aidl.address' can be empty even when the connection type is not.
+    // This happens for device ports that act as "blueprints". In this case
+    // we pass an empty string using the 'id' variant.
+    switch (aidl.address.getTag()) {
+        case Tag::mac: {
+            const std::vector<uint8_t>& mac = aidl.address.get<AudioDeviceAddress::mac>();
+            if (mac.size() != 6) return BAD_VALUE;
+            snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%02X:%02X:%02X:%02X:%02X:%02X",
+                    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+        } break;
+        case Tag::ipv4: {
+            const std::vector<uint8_t>& ipv4 = aidl.address.get<AudioDeviceAddress::ipv4>();
+            if (ipv4.size() != 4) return BAD_VALUE;
+            snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%u.%u.%u.%u",
+                    ipv4[0], ipv4[1], ipv4[2], ipv4[3]);
+        } break;
+        case Tag::ipv6: {
+            const std::vector<int32_t>& ipv6 = aidl.address.get<AudioDeviceAddress::ipv6>();
+            if (ipv6.size() != 8) return BAD_VALUE;
+            snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN,
+                    "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X",
+                    ipv6[0], ipv6[1], ipv6[2], ipv6[3], ipv6[4], ipv6[5], ipv6[6], ipv6[7]);
+        } break;
+        case Tag::alsa: {
+            const std::vector<int32_t>& alsa = aidl.address.get<AudioDeviceAddress::alsa>();
+            if (alsa.size() != 2) return BAD_VALUE;
+            snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "card=%d;device=%d",
+                    alsa[0], alsa[1]);
+        } break;
+        case Tag::id: {
+            RETURN_STATUS_IF_ERROR(aidl2legacy_string(aidl.address.get<AudioDeviceAddress::id>(),
+                            addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN));
+        } break;
+    }
+    *legacyAddress = addressBuffer;
     return OK;
 }
 
 ConversionResult<AudioDevice> legacy2aidl_audio_device_AudioDevice(
         audio_devices_t legacyType, const char* legacyAddress) {
-    AudioDevice aidl;
-    aidl.type = VALUE_OR_RETURN(
-            legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
-    const std::string aidl_id = VALUE_OR_RETURN(
+    const std::string stringAddress = VALUE_OR_RETURN(
             legacy2aidl_string(legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN));
-    aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
-    return aidl;
+    return legacy2aidl_audio_device_AudioDevice(legacyType, stringAddress);
 }
 
 ConversionResult<AudioDevice>
 legacy2aidl_audio_device_AudioDevice(
         audio_devices_t legacyType, const String8& legacyAddress) {
+    const std::string stringAddress = VALUE_OR_RETURN(legacy2aidl_String8_string(legacyAddress));
+    return legacy2aidl_audio_device_AudioDevice(legacyType, stringAddress);
+}
+
+ConversionResult<AudioDevice>
+legacy2aidl_audio_device_AudioDevice(
+        audio_devices_t legacyType, const std::string& legacyAddress) {
+    using Tag = AudioDeviceAddress::Tag;
     AudioDevice aidl;
     aidl.type = VALUE_OR_RETURN(
             legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
-    const std::string aidl_id = VALUE_OR_RETURN(
-            legacy2aidl_String8_string(legacyAddress));
-    aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
+    // 'legacyAddress' can be empty even when the connection type is not.
+    // This happens for device ports that act as "blueprints". In this case
+    // we pass an empty string using the 'id' variant.
+    if (!legacyAddress.empty()) {
+        switch (suggestDeviceAddressTag(aidl.type)) {
+            case Tag::mac: {
+                std::vector<uint8_t> mac(6);
+                int status = sscanf(legacyAddress.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
+                        &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
+                if (status != mac.size()) {
+                    ALOGE("%s: malformed MAC address: \"%s\"", __func__, legacyAddress.c_str());
+                    return unexpected(BAD_VALUE);
+                }
+                aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::mac>(std::move(mac));
+            } break;
+            case Tag::ipv4: {
+                std::vector<uint8_t> ipv4(4);
+                int status = sscanf(legacyAddress.c_str(), "%hhu.%hhu.%hhu.%hhu",
+                        &ipv4[0], &ipv4[1], &ipv4[2], &ipv4[3]);
+                if (status != ipv4.size()) {
+                    ALOGE("%s: malformed IPv4 address: \"%s\"", __func__, legacyAddress.c_str());
+                    return unexpected(BAD_VALUE);
+                }
+                aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::ipv4>(std::move(ipv4));
+            } break;
+            case Tag::ipv6: {
+                std::vector<int32_t> ipv6(8);
+                int status = sscanf(legacyAddress.c_str(), "%X:%X:%X:%X:%X:%X:%X:%X",
+                        &ipv6[0], &ipv6[1], &ipv6[2], &ipv6[3], &ipv6[4], &ipv6[5], &ipv6[6],
+                        &ipv6[7]);
+                if (status != ipv6.size()) {
+                    ALOGE("%s: malformed IPv6 address: \"%s\"", __func__, legacyAddress.c_str());
+                    return unexpected(BAD_VALUE);
+                }
+                aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::ipv6>(std::move(ipv6));
+            } break;
+            case Tag::alsa: {
+                std::vector<int32_t> alsa(2);
+                int status = sscanf(legacyAddress.c_str(), "card=%d;device=%d", &alsa[0], &alsa[1]);
+                if (status != alsa.size()) {
+                    ALOGE("%s: malformed ALSA address: \"%s\"", __func__, legacyAddress.c_str());
+                    return unexpected(BAD_VALUE);
+                }
+                aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::alsa>(std::move(alsa));
+            } break;
+            case Tag::id: {
+                aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(legacyAddress);
+            } break;
+        }
+    } else {
+        aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(legacyAddress);
+    }
     return aidl;
 }
 
@@ -3009,6 +3116,8 @@
 
 }  // namespace android
 
+#undef GET_DEVICE_DESC_CONNECTION
+
 #if defined(BACKEND_NDK)
 }  // aidl
 #endif
diff --git a/media/audioaidlconversion/AidlConversionNdk.cpp b/media/audioaidlconversion/AidlConversionNdk.cpp
index 71c547c..9b14a5e 100644
--- a/media/audioaidlconversion/AidlConversionNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionNdk.cpp
@@ -79,39 +79,42 @@
 }  // namespace
 
 // buffer_provider_t is not supported thus skipped
-ConversionResult<buffer_config_t> aidl2legacy_AudioConfigBase_buffer_config_t(
-        const media::audio::common::AudioConfigBase& aidl, bool isInput) {
+ConversionResult<buffer_config_t> aidl2legacy_AudioConfig_buffer_config_t(
+        const media::audio::common::AudioConfig& aidl, bool isInput) {
     buffer_config_t legacy;
 
-    legacy.samplingRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
+    legacy.samplingRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.base.sampleRate));
     legacy.mask |= EFFECT_CONFIG_SMP_RATE;
 
     legacy.channels = VALUE_OR_RETURN(
-            aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
+            aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.base.channelMask, isInput));
     legacy.mask |= EFFECT_CONFIG_CHANNELS;
 
-    legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
+    legacy.format =
+            VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.base.format));
     legacy.mask |= EFFECT_CONFIG_FORMAT;
+    legacy.buffer.frameCount = aidl.frameCount;
 
     // TODO: add accessMode and mask
     return legacy;
 }
 
-ConversionResult<media::audio::common::AudioConfigBase>
-legacy2aidl_buffer_config_t_AudioConfigBase(const buffer_config_t& legacy, bool isInput) {
-    media::audio::common::AudioConfigBase aidl;
+ConversionResult<media::audio::common::AudioConfig>
+legacy2aidl_buffer_config_t_AudioConfig(const buffer_config_t& legacy, bool isInput) {
+    media::audio::common::AudioConfig aidl;
 
     if (legacy.mask & EFFECT_CONFIG_SMP_RATE) {
-        aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.samplingRate));
+        aidl.base.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.samplingRate));
     }
     if (legacy.mask & EFFECT_CONFIG_CHANNELS) {
-        aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+        aidl.base.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
                 static_cast<audio_channel_mask_t>(legacy.channels), isInput));
     }
     if (legacy.mask & EFFECT_CONFIG_FORMAT) {
-        aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(
+        aidl.base.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(
                 static_cast<audio_format_t>(legacy.format)));
     }
+    aidl.frameCount = legacy.buffer.frameCount;
 
     // TODO: add accessMode and mask
     return aidl;
diff --git a/media/audioaidlconversion/Android.bp b/media/audioaidlconversion/Android.bp
index bdb3a2c..1ec4849 100644
--- a/media/audioaidlconversion/Android.bp
+++ b/media/audioaidlconversion/Android.bp
@@ -152,6 +152,37 @@
 }
 
 /**
+ * Only including AIDL core HAL conversion.
+ */
+cc_library {
+    name: "libaudio_aidl_conversion_core_ndk",
+    srcs: [
+        "AidlConversionCore.cpp",
+    ],
+    header_libs: [
+        "libaudio_aidl_conversion_common_util_ndk",
+    ],
+    export_header_lib_headers: [
+        "libaudio_aidl_conversion_common_util_ndk",
+    ],
+    defaults: [
+        "audio_aidl_conversion_common_default",
+        "latest_android_hardware_audio_common_ndk_shared",
+        "latest_android_hardware_audio_core_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    shared_libs: [
+        "libaudio_aidl_conversion_common_ndk",
+        "libbinder_ndk",
+        "libbase",
+    ],
+    cflags: [
+        "-DBACKEND_NDK",
+    ],
+    min_sdk_version: "31", //AParcelableHolder has been introduced in 31
+}
+
+/**
  * Only including AIDL effect HAL conversion.
  */
 cc_library {
diff --git a/media/audioaidlconversion/include/media/AidlConversionCore.h b/media/audioaidlconversion/include/media/AidlConversionCore.h
new file mode 100644
index 0000000..aaa2e53
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionCore.h
@@ -0,0 +1,36 @@
+/*
+ * 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
+
+/**
+ * Can only handle conversion between AIDL (NDK backend) and legacy type.
+ */
+#include <aidl/android/hardware/audio/core/IStreamIn.h>
+#include <media/AidlConversionUtil.h>
+#include <system/audio.h>
+
+namespace aidl {
+namespace android {
+
+ConversionResult<audio_microphone_direction_t>
+aidl2legacy_MicrophoneDirection_audio_microphone_direction_t(
+        hardware::audio::core::IStreamIn::MicrophoneDirection aidl);
+ConversionResult<hardware::audio::core::IStreamIn::MicrophoneDirection>
+legacy2aidl_audio_microphone_direction_t_MicrophoneDirection(audio_microphone_direction_t legacy);
+
+}  // namespace android
+}  // namespace aidl
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
index 9100892..ec1f75c 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
@@ -190,6 +190,9 @@
 ConversionResult<media::audio::common::AudioDeviceDescription>
 legacy2aidl_audio_devices_t_AudioDeviceDescription(audio_devices_t legacy);
 
+media::audio::common::AudioDeviceAddress::Tag suggestDeviceAddressTag(
+        const media::audio::common::AudioDeviceDescription& description);
+
 ::android::status_t aidl2legacy_AudioDevice_audio_device(
         const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
         char* legacyAddress);
@@ -204,6 +207,8 @@
         audio_devices_t legacyType, const char* legacyAddress);
 ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
         audio_devices_t legacyType, const ::android::String8& legacyAddress);
+ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
+        audio_devices_t legacyType, const std::string& legacyAddress);
 
 ConversionResult<audio_extra_audio_descriptor>
 aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
diff --git a/media/audioaidlconversion/include/media/AidlConversionNdk.h b/media/audioaidlconversion/include/media/AidlConversionNdk.h
index e92f1a9..813a728 100644
--- a/media/audioaidlconversion/include/media/AidlConversionNdk.h
+++ b/media/audioaidlconversion/include/media/AidlConversionNdk.h
@@ -34,9 +34,9 @@
 namespace aidl {
 namespace android {
 
-ConversionResult<buffer_config_t> aidl2legacy_AudioConfigBase_buffer_config_t(
-        const media::audio::common::AudioConfigBase& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioConfigBase> legacy2aidl_buffer_config_t_AudioConfigBase(
+ConversionResult<buffer_config_t> aidl2legacy_AudioConfig_buffer_config_t(
+        const media::audio::common::AudioConfig& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioConfig> legacy2aidl_buffer_config_t_AudioConfig(
         const buffer_config_t& legacy, bool isInput);
 
 ::android::status_t aidl2legacy_AudioAttributesTags(
diff --git a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
index ed91e2c..b179cbb 100644
--- a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
@@ -58,15 +58,15 @@
 ConversionResult<To> convertIntegral(From from) {
     // Special handling is required for signed / vs. unsigned comparisons, since otherwise we may
     // have the signed converted to unsigned and produce wrong results.
-    if (std::is_signed_v<From> && !std::is_signed_v<To>) {
+    if constexpr (std::is_signed_v<From> && !std::is_signed_v<To>) {
         if (from < 0 || from > std::numeric_limits<To>::max()) {
             return ::android::base::unexpected(::android::BAD_VALUE);
         }
-    } else if (std::is_signed_v<To> && !std::is_signed_v<From>) {
+    } else if constexpr (std::is_signed_v<To> && !std::is_signed_v<From>) {
         if (from > std::numeric_limits<To>::max()) {
             return ::android::base::unexpected(::android::BAD_VALUE);
         }
-    } else {
+    } else /* constexpr */ {
         if (from < std::numeric_limits<To>::min() || from > std::numeric_limits<To>::max()) {
             return ::android::base::unexpected(::android::BAD_VALUE);
         }
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index 5d2856a..e424860 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -334,7 +334,10 @@
         // By default needsUpdate = false in case the supplied level does meet
         // the requirements. For Level 1b, we want to update the level anyway,
         // so we set it to true in that case.
-        bool needsUpdate = (me.v.level == LEVEL_AVC_1B);
+        bool needsUpdate = false;
+        if (me.v.level == LEVEL_AVC_1B || !me.F(me.v.level).supportsAtAll(me.v.level)) {
+            needsUpdate = true;
+        }
         for (const LevelLimits &limit : kLimits) {
             if (mbs <= limit.mbs && mbsPerSec <= limit.mbsPerSec &&
                     bitrate.v.value <= limit.bitrate) {
@@ -356,7 +359,7 @@
                 needsUpdate = true;
             }
         }
-        if (!found) {
+        if (!found || me.v.level > LEVEL_AVC_5) {
             // We set to the highest supported level.
             me.set().level = LEVEL_AVC_5;
         }
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index 9c26c02..ec1dd14 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -341,6 +341,9 @@
         // By default needsUpdate = false in case the supplied level does meet
         // the requirements.
         bool needsUpdate = false;
+        if (!me.F(me.v.level).supportsAtAll(me.v.level)) {
+            needsUpdate = true;
+        }
         for (const LevelLimits &limit : kLimits) {
             if (samples <= limit.samples && samplesPerSec <= limit.samplesPerSec &&
                     bitrate.v.value <= limit.bitrate) {
@@ -362,7 +365,7 @@
                 needsUpdate = true;
             }
         }
-        if (!found) {
+        if (!found || me.v.level > LEVEL_HEVC_MAIN_5_2) {
             // We set to the highest supported level.
             me.set().level = LEVEL_HEVC_MAIN_5_2;
         }
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
index d5e8c56..acc42e9 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
@@ -49,6 +49,8 @@
 const char *MEDIA_MIMETYPE_VIDEO = MEDIA_MIMETYPE_VIDEO_H263;
 #endif
 
+constexpr float VBV_DELAY = 5.0f;
+
 } // namepsace
 
 class C2SoftMpeg4Enc::IntfImpl : public SimpleInterface<void>::BaseParams {
@@ -131,7 +133,7 @@
                             C2Config::LEVEL_MP4V_1,
                             C2Config::LEVEL_MP4V_2})
                 })
-                .withSetter(ProfileLevelSetter)
+                .withSetter(ProfileLevelSetter, mSize, mFrameRate, mBitrate)
                 .build());
 #else
         addParameter(
@@ -148,7 +150,7 @@
                             C2Config::LEVEL_H263_40,
                             C2Config::LEVEL_H263_45})
                 })
-                .withSetter(ProfileLevelSetter)
+                .withSetter(ProfileLevelSetter, mSize, mFrameRate, mBitrate)
                 .build());
 #endif
     }
@@ -179,7 +181,10 @@
 
     static C2R ProfileLevelSetter(
             bool mayBlock,
-            C2P<C2StreamProfileLevelInfo::output> &me) {
+            C2P<C2StreamProfileLevelInfo::output> &me,
+            const C2P<C2StreamPictureSizeInfo::input> &size,
+            const C2P<C2StreamFrameRateInfo::output> &frameRate,
+            const C2P<C2StreamBitrateInfo::output> &bitrate) {
         (void)mayBlock;
         if (!me.F(me.v.profile).supportsAtAll(me.v.profile)) {
 #ifdef MPEG4
@@ -188,13 +193,91 @@
             me.set().profile = PROFILE_H263_BASELINE;
 #endif
         }
-        if (!me.F(me.v.level).supportsAtAll(me.v.level)) {
+
+        struct LevelLimits {
+            C2Config::level_t level;
+            uint32_t sampleRate;
+            uint32_t width;
+            uint32_t height;
+            uint32_t frameRate;
+            uint32_t bitrate;
+            uint32_t vbvSize;
+        };
+
+        constexpr LevelLimits kLimits[] = {
 #ifdef MPEG4
-            me.set().level = LEVEL_MP4V_2;
+            { LEVEL_MP4V_0, 380160, 176, 144, 15, 64000, 163840 },
+            // { LEVEL_MP4V_0B, 380160, 176, 144, 15, 128000, 163840 },
+            { LEVEL_MP4V_1, 380160, 176, 144, 30, 64000, 163840 },
+            { LEVEL_MP4V_2, 1520640, 352, 288, 30, 128000, 655360 },
 #else
-            me.set().level = LEVEL_H263_45;
+            // HRD Buffer Size = (B + BPPmaxKb * 1024 bits)
+            // where, (BPPmaxKb * 1024) is maximum number of bits per picture
+            // that has been negotiated for use in the bitstream Sec 3.6 of T-Rec-H.263
+            // and B = 4 * Rmax / PCF. Rmax is max bit rate and PCF is picture
+            // clock frequency
+            { LEVEL_H263_10, 380160, 176, 144, 15, 64000, 74077 },
+            { LEVEL_H263_45, 380160, 176, 144, 15, 128000, 82619 },
+            { LEVEL_H263_20, 1520640, 352, 288, 30, 128000, 279227 },
+            { LEVEL_H263_30, 3041280, 352, 288, 30, 384000, 313395 },
+            { LEVEL_H263_40, 3041280, 352, 288, 30, 2048000, 535483 },
+            // { LEVEL_H263_50, 5068800, 352, 288, 60, 4096000, 808823 },
 #endif
+        };
+
+        auto mbs = ((size.v.width + 15) / 16) * ((size.v.height + 15) / 16);
+        auto sampleRate = mbs * frameRate.v.value * 16 * 16;
+        auto vbvSize = bitrate.v.value * VBV_DELAY;
+
+        // Check if the supplied level meets the MB / bitrate requirements. If
+        // not, update the level with the lowest level meeting the requirements.
+        bool found = false;
+
+        // By default needsUpdate = false in case the supplied level does meet
+        // the requirements.
+        bool needsUpdate = false;
+#ifdef MPEG4
+        // For Level 0b, we want to update the level anyway, as library does not
+        // seem to accept this value.
+        if (me.v.level == LEVEL_MP4V_0B) {
+            needsUpdate = true;
         }
+#endif
+        if (!me.F(me.v.level).supportsAtAll(me.v.level)) {
+            needsUpdate = true;
+        }
+        for (const LevelLimits &limit : kLimits) {
+            if (sampleRate <= limit.sampleRate && size.v.width <= limit.width &&
+                    vbvSize <= limit.vbvSize && size.v.height <= limit.height &&
+                    bitrate.v.value <= limit.bitrate && frameRate.v.value <= limit.frameRate) {
+                // This is the lowest level that meets the requirements, and if
+                // we haven't seen the supplied level yet, that means we don't
+                // need the update.
+                if (needsUpdate) {
+                    ALOGD("Given level %x does not cover current configuration: "
+                          "adjusting to %x", me.v.level, limit.level);
+                    me.set().level = limit.level;
+                }
+                found = true;
+                break;
+            }
+            if (me.v.level == limit.level) {
+                // We break out of the loop when the lowest feasible level is
+                // found. The fact that we're here means that our level doesn't
+                // meet the requirement and needs to be updated.
+                needsUpdate = true;
+            }
+        }
+        // If not found or exceeds max level, set to the highest supported level.
+#ifdef MPEG4
+        if (!found || me.v.level > LEVEL_MP4V_2) {
+            me.set().level = LEVEL_MP4V_2;
+        }
+#else
+        if (!found || (me.v.level != LEVEL_H263_45 && me.v.level > LEVEL_H263_40)) {
+            me.set().level = LEVEL_H263_40;
+        }
+#endif
         return C2R::Ok();
     }
 
@@ -325,7 +408,7 @@
     mEncParams->encHeight[0] = mSize->height;
     mEncParams->encFrameRate[0] = mFrameRate->value + 0.5;
     mEncParams->rcType = VBR_1;
-    mEncParams->vbvDelay = 5.0f;
+    mEncParams->vbvDelay = VBV_DELAY;
     mEncParams->profile_level = CORE_PROFILE_LEVEL2;
     mEncParams->packetSize = 32;
     mEncParams->rvlcEnable = PV_OFF;
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.cpp b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
index 5700e5d..e903069 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
@@ -263,6 +263,9 @@
     // By default needsUpdate = false in case the supplied level does meet
     // the requirements.
     bool needsUpdate = false;
+    if (!me.F(me.v.level).supportsAtAll(me.v.level)) {
+        needsUpdate = true;
+    }
     for (const LevelLimits& limit : kLimits) {
         if (samples <= limit.samples && samplesPerSec <= limit.samplesPerSec &&
             bitrate.v.value <= limit.bitrate && dimension <= limit.dimension) {
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index a008dc2..e8969dd 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -2543,17 +2543,6 @@
 }
 
 void CCodec::initiateReleaseIfStuck() {
-    std::string name;
-    bool pendingDeadline = false;
-    {
-        Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
-        if (deadline->get() < std::chrono::steady_clock::now()) {
-            name = deadline->getName();
-        }
-        if (deadline->get() != TimePoint::max()) {
-            pendingDeadline = true;
-        }
-    }
     bool tunneled = false;
     bool isMediaTypeKnown = false;
     {
@@ -2591,6 +2580,17 @@
         tunneled = config->mTunneled;
         isMediaTypeKnown = (kKnownMediaTypes.count(config->mCodingMediaType) != 0);
     }
+    std::string name;
+    bool pendingDeadline = false;
+    {
+        Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
+        if (deadline->get() < std::chrono::steady_clock::now()) {
+            name = deadline->getName();
+        }
+        if (deadline->get() != TimePoint::max()) {
+            pendingDeadline = true;
+        }
+    }
     if (!tunneled && isMediaTypeKnown && name.empty()) {
         constexpr std::chrono::steady_clock::duration kWorkDurationThreshold = 3s;
         std::chrono::steady_clock::duration elapsed = mChannel->elapsed();
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index fc82426..0142686 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -2066,7 +2066,10 @@
     // csd cannot be re-ordered and will always arrive first.
     if (initData != nullptr) {
         Mutexed<Output>::Locked output(mOutput);
-        if (output->buffers && outputFormat) {
+        if (!output->buffers) {
+            return false;
+        }
+        if (outputFormat) {
             output->buffers->updateSkipCutBuffer(outputFormat);
             output->buffers->setFormat(outputFormat);
         }
@@ -2075,7 +2078,7 @@
         }
         size_t index;
         sp<MediaCodecBuffer> outBuffer;
-        if (output->buffers && output->buffers->registerCsd(initData, &index, &outBuffer) == OK) {
+        if (output->buffers->registerCsd(initData, &index, &outBuffer) == OK) {
             outBuffer->meta()->setInt64("timeUs", timestamp.peek());
             outBuffer->meta()->setInt32("flags", BUFFER_FLAG_CODEC_CONFIG);
             ALOGV("[%s] onWorkDone: csd index = %zu [%p]", mName, index, outBuffer.get());
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index dfdd84d..2dea84c 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -15,7 +15,7 @@
  */
 
 #define LOG_TAG "C2Store"
-#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
 #include <utils/Log.h>
 
 #include <C2AllocatorBlob.h>
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 6ffbdc4..7c7b65b 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -250,6 +250,12 @@
     return af->setMode(mode);
 }
 
+status_t AudioSystem::setSimulateDeviceConnections(bool enabled) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->setSimulateDeviceConnections(enabled);
+}
+
 status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) {
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
@@ -1544,6 +1550,15 @@
     return OK;
 }
 
+status_t AudioSystem::listDeclaredDevicePorts(media::AudioPortRole role,
+                                              std::vector<media::AudioPortFw>* result) {
+    if (result == nullptr) return BAD_VALUE;
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(aps->listDeclaredDevicePorts(role, result)));
+    return OK;
+}
+
 status_t AudioSystem::getAudioPort(struct audio_port_v7* port) {
     if (port == nullptr) {
         return BAD_VALUE;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index ff4b071..12f5013 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1598,13 +1598,16 @@
     }
 
     AutoMutex lock(mLock);
+    // IAudioTrack::stop() isn't synchronous; we don't know when presentation completes
+    if (mState == STATE_STOPPED || mState == STATE_FLUSHED) {
+        *position = 0;
+        return NO_ERROR;
+    }
     // FIXME: offloaded and direct tracks call into the HAL for render positions
     // for compressed/synced data; however, we use proxy position for pure linear pcm data
     // as we do not know the capability of the HAL for pcm position support and standby.
     // There may be some latency differences between the HAL position and the proxy position.
     if (isOffloadedOrDirect_l() && !isPurePcmData_l()) {
-        uint32_t dspFrames = 0;
-
         if (isOffloaded_l() && ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING))) {
             ALOGV("%s(%d): called in paused state, return cached position %u",
                 __func__, mPortId, mPausedPosition);
@@ -1612,13 +1615,15 @@
             return NO_ERROR;
         }
 
+        uint32_t dspFrames = 0;
         if (mOutput != AUDIO_IO_HANDLE_NONE) {
             uint32_t halFrames; // actually unused
-            (void) AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames);
             // FIXME: on getRenderPosition() error, we return OK with frame position 0.
+            if (AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames) != NO_ERROR) {
+                *position = 0;
+                return NO_ERROR;
+            }
         }
-        // FIXME: dspFrames may not be zero in (mState == STATE_STOPPED || mState == STATE_FLUSHED)
-        // due to hardware latency. We leave this behavior for now.
         *position = dspFrames;
     } else {
         if (mCblk->mFlags & CBLK_INVALID) {
@@ -1626,11 +1631,9 @@
             // FIXME: for compatibility with the Java API we ignore the restoreTrack_l()
             // error here (e.g. DEAD_OBJECT) and return OK with the last recorded server position.
         }
-
-        // IAudioTrack::stop() isn't synchronous; we don't know when presentation completes
-        *position = (mState == STATE_STOPPED || mState == STATE_FLUSHED) ?
-                0 : updateAndGetPosition_l().value();
+        *position = updateAndGetPosition_l().value();
     }
+
     return NO_ERROR;
 }
 
@@ -2484,11 +2487,22 @@
         timeout.tv_sec = WAIT_STREAM_END_TIMEOUT_SEC;
         timeout.tv_nsec = 0;
 
+        // Use timestamp progress to safeguard we don't falsely time out.
+        AudioTimestamp timestamp{};
+        const bool isTimestampValid = getTimestamp(timestamp) == OK;
+        const auto frameCount = isTimestampValid ? timestamp.mPosition : 0;
+
         status_t status = proxy->waitStreamEndDone(&timeout);
         switch (status) {
+        case TIMED_OUT:
+            if (isTimestampValid
+                    && getTimestamp(timestamp) == OK && frameCount != timestamp.mPosition) {
+                ALOGD("%s: waitStreamEndDone retrying", __func__);
+                break;  // we retry again (and recheck possible state change).
+            }
+            [[fallthrough]];
         case NO_ERROR:
         case DEAD_OBJECT:
-        case TIMED_OUT:
             if (status != DEAD_OBJECT) {
                 // for DEAD_OBJECT, we do not send a EVENT_STREAM_END after stop();
                 // instead, the application should handle the EVENT_NEW_IAUDIOTRACK.
@@ -2506,6 +2520,7 @@
                 }
             }
             if (waitStreamEnd && status != DEAD_OBJECT) {
+               ALOGV("%s: waitStreamEndDone complete", __func__);
                return NS_INACTIVE;
             }
             break;
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index a005ab4..7bf7b98 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -809,6 +809,10 @@
     return statusTFromBinderStatus(mDelegate->setDeviceConnectedState(aidlPort, connected));
 }
 
+status_t AudioFlingerClientAdapter::setSimulateDeviceConnections(bool enabled) {
+    return statusTFromBinderStatus(mDelegate->setSimulateDeviceConnections(enabled));
+}
+
 status_t AudioFlingerClientAdapter::setRequestedLatencyMode(
         audio_io_handle_t output, audio_latency_mode_t mode) {
     int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
@@ -1355,6 +1359,10 @@
     return Status::fromStatusT(mDelegate->setDeviceConnectedState(&portLegacy, connected));
 }
 
+Status AudioFlingerServerAdapter::setSimulateDeviceConnections(bool enabled) {
+    return Status::fromStatusT(mDelegate->setSimulateDeviceConnections(enabled));
+}
+
 Status AudioFlingerServerAdapter::setRequestedLatencyMode(
         int32_t output, media::audio::common::AudioLatencyMode modeAidl) {
     audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 7c44c74..e676d89 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -229,6 +229,9 @@
 
     void setDeviceConnectedState(in AudioPortFw devicePort, boolean connected);
 
+    // Used for tests only. Requires AIDL HAL to work.
+    void setSimulateDeviceConnections(boolean enabled);
+
     /**
      * Requests a given latency mode (See AudioLatencyMode.aidl) on an output stream.
      * This can be used when some use case on a given mixer/stream can only be enabled
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index ed7e243..fb87042 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -202,7 +202,9 @@
                                     in AudioAttributesInternal attributes);
 
     /**
-     * List available audio ports and their attributes. Returns the generation.
+     * List currently attached audio ports and their attributes. Returns the generation.
+     * The generation is incremented each time when anything changes in the ports
+     * configuration.
      *
      * On input, count represents the maximum length of the returned array.
      * On output, count is the total number of elements, which may be larger than the array size.
@@ -214,6 +216,13 @@
                        inout Int count,
                        out AudioPortFw[] ports);
 
+    /**
+     * List all device ports declared in the configuration (including currently detached ones)
+     * 'role' can be 'NONE' to get both input and output devices,
+     * 'SINK' for output devices, and 'SOURCE' for input devices.
+     */
+    AudioPortFw[] listDeclaredDevicePorts(AudioPortRole role);
+
     /** Get attributes for the audio port with the given id (AudioPort.hal.id field). */
     AudioPortFw getAudioPort(int /* audio_port_handle_t */ portId);
 
diff --git a/media/libaudioclient/fuzzer/Android.bp b/media/libaudioclient/fuzzer/Android.bp
index b1feb60..6080314 100644
--- a/media/libaudioclient/fuzzer/Android.bp
+++ b/media/libaudioclient/fuzzer/Android.bp
@@ -80,5 +80,13 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libaudioflinger",
+        vector: "local_no_privileges_required",
+        service_privilege: "privileged",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 543ce00..3e3b79c 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -23,6 +23,7 @@
 #include <vector>
 
 #include <android/content/AttributionSourceState.h>
+#include <android/media/AudioPortFw.h>
 #include <android/media/AudioVibratorInfo.h>
 #include <android/media/BnAudioFlingerClient.h>
 #include <android/media/BnAudioPolicyServiceClient.h>
@@ -121,6 +122,9 @@
     // set audio mode in audio hardware
     static status_t setMode(audio_mode_t mode);
 
+    // test API: switch HALs into the mode which simulates external device connections
+    static status_t setSimulateDeviceConnections(bool enabled);
+
     // returns true in *state if tracks are active on the specified stream or have been active
     // in the past inPastMs milliseconds
     static status_t isStreamActive(audio_stream_type_t stream, bool *state, uint32_t inPastMs);
@@ -378,6 +382,9 @@
                                    struct audio_port_v7 *ports,
                                    unsigned int *generation);
 
+    static status_t listDeclaredDevicePorts(media::AudioPortRole role,
+                                            std::vector<media::AudioPortFw>* result);
+
     /* Get attributes for a given audio port. On input, the port
      * only needs the 'id' field to be filled in. */
     static status_t getAudioPort(struct audio_port_v7 *port);
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 25b5414..b1491da 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -360,6 +360,8 @@
 
     virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) = 0;
 
+    virtual status_t setSimulateDeviceConnections(bool enabled) = 0;
+
     virtual status_t setRequestedLatencyMode(
             audio_io_handle_t output, audio_latency_mode_t mode) = 0;
 
@@ -473,6 +475,7 @@
     int32_t getAAudioMixerBurstCount() override;
     int32_t getAAudioHardwareBurstMinUsec() override;
     status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) override;
+    status_t setSimulateDeviceConnections(bool enabled) override;
     status_t setRequestedLatencyMode(audio_io_handle_t output,
             audio_latency_mode_t mode) override;
     status_t getSupportedLatencyModes(
@@ -569,6 +572,7 @@
             GET_AAUDIO_MIXER_BURST_COUNT = media::BnAudioFlingerService::TRANSACTION_getAAudioMixerBurstCount,
             GET_AAUDIO_HARDWARE_BURST_MIN_USEC = media::BnAudioFlingerService::TRANSACTION_getAAudioHardwareBurstMinUsec,
             SET_DEVICE_CONNECTED_STATE = media::BnAudioFlingerService::TRANSACTION_setDeviceConnectedState,
+            SET_SIMULATE_DEVICE_CONNECTIONS = media::BnAudioFlingerService::TRANSACTION_setSimulateDeviceConnections,
             SET_REQUESTED_LATENCY_MODE = media::BnAudioFlingerService::TRANSACTION_setRequestedLatencyMode,
             GET_SUPPORTED_LATENCY_MODES = media::BnAudioFlingerService::TRANSACTION_getSupportedLatencyModes,
             SET_BLUETOOTH_VARIABLE_LATENCY_ENABLED =
@@ -698,6 +702,7 @@
     Status getAAudioMixerBurstCount(int32_t* _aidl_return) override;
     Status getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
     Status setDeviceConnectedState(const media::AudioPortFw& port, bool connected) override;
+    Status setSimulateDeviceConnections(bool enabled) override;
     Status setRequestedLatencyMode(
             int output, media::audio::common::AudioLatencyMode mode) override;
     Status getSupportedLatencyModes(int output,
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index 2189521..1e8dcca 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -14,6 +14,12 @@
         "-Wall",
         "-Werror",
     ],
+    shared_libs: [
+        "libbinder",
+        "libcutils",
+        "liblog",
+        "libutils",
+    ],
     sanitize: {
         misc_undefined: [
             "unsigned-integer-overflow",
@@ -22,37 +28,35 @@
     },
 }
 
-cc_test {
-    name: "audio_aidl_conversion_tests",
+cc_defaults {
+    name: "audio_aidl_conversion_test_defaults",
     defaults: [
         "libaudioclient_tests_defaults",
         "latest_android_media_audio_common_types_cpp_static",
     ],
-    srcs: ["audio_aidl_legacy_conversion_tests.cpp"],
-    shared_libs: [
-        "libbinder",
-        "libcutils",
-        "liblog",
-        "libutils",
-    ],
     static_libs: [
-        "libaudioclient_aidl_conversion",
-        "libaudio_aidl_conversion_common_cpp",
         "audioclient-types-aidl-cpp",
         "av-types-aidl-cpp",
+        "libaudio_aidl_conversion_common_cpp",
+        "libaudioclient_aidl_conversion",
         "libstagefright_foundation",
     ],
 }
 
 cc_test {
+    name: "audio_aidl_conversion_tests",
+    defaults: [
+        "audio_aidl_conversion_test_defaults",
+    ],
+    srcs: ["audio_aidl_legacy_conversion_tests.cpp"],
+}
+
+cc_test {
     name: "audio_aidl_status_tests",
     defaults: ["libaudioclient_tests_defaults"],
     srcs: ["audio_aidl_status_tests.cpp"],
     shared_libs: [
         "libaudioclient_aidl_conversion",
-        "libbinder",
-        "libcutils",
-        "libutils",
     ],
 }
 
@@ -70,9 +74,6 @@
     shared_libs: [
         "framework-permission-aidl-cpp",
         "libaudioclient",
-        "libbinder",
-        "libcutils",
-        "libutils",
     ],
     data: ["track_test_input_*.txt"],
 }
@@ -89,35 +90,23 @@
         "libmediametrics_headers",
     ],
     shared_libs: [
-        "libaudioclient",
-        "libbinder",
-        "libcutils",
-        "libutils",
         "framework-permission-aidl-cpp",
+        "libaudioclient",
     ],
     data: ["record_test_input_*.txt"],
 }
 
 cc_defaults {
     name: "libaudioclient_gtests_defaults",
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
     defaults: [
-        "latest_android_media_audio_common_types_cpp_static",
+        "audio_aidl_conversion_test_defaults",
     ],
     shared_libs: [
         "capture_state_listener-aidl-cpp",
         "framework-permission-aidl-cpp",
-        "libaudioclient_aidl_conversion",
-        "libaudio_aidl_conversion_common_cpp",
         "libbase",
-        "libbinder",
         "libcgrouprc",
-        "libcutils",
         "libdl",
-        "liblog",
         "libmedia",
         "libmediametrics",
         "libmediautils",
@@ -125,8 +114,6 @@
         "libnblog",
         "libprocessgroup",
         "libshmemcompat",
-        "libstagefright_foundation",
-        "libutils",
         "libxml2",
         "mediametricsservice-aidl-cpp",
         "packagemanager_aidl-cpp",
@@ -148,7 +135,6 @@
     ],
     data: ["bbb*.raw"],
     test_config_template: "audio_test_template.xml",
-    test_suites: ["device-tests"],
 }
 
 cc_test {
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index e2216a0..91ef7b3 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <iostream>
+#include <string>
 
 #include <gtest/gtest.h>
 
@@ -32,6 +33,7 @@
 using media::AudioPortType;
 using media::audio::common::AudioChannelLayout;
 using media::audio::common::AudioDevice;
+using media::audio::common::AudioDeviceAddress;
 using media::audio::common::AudioDeviceDescription;
 using media::audio::common::AudioDeviceType;
 using media::audio::common::AudioEncapsulationMetadataType;
@@ -131,6 +133,14 @@
     return make_AudioDeviceDescription(AudioDeviceType::IN_DEFAULT);
 }
 
+AudioDeviceDescription make_ADD_MicIn() {
+    return make_AudioDeviceDescription(AudioDeviceType::IN_MICROPHONE);
+}
+
+AudioDeviceDescription make_ADD_RSubmixIn() {
+    return make_AudioDeviceDescription(AudioDeviceType::IN_SUBMIX);
+}
+
 AudioDeviceDescription make_ADD_DefaultOut() {
     return make_AudioDeviceDescription(AudioDeviceType::OUT_DEFAULT);
 }
@@ -145,6 +155,39 @@
                                        AudioDeviceDescription::CONNECTION_BT_SCO());
 }
 
+AudioDeviceDescription make_ADD_BtA2dpHeadphone() {
+    return make_AudioDeviceDescription(AudioDeviceType::OUT_HEADPHONE,
+                                       AudioDeviceDescription::CONNECTION_BT_A2DP());
+}
+
+AudioDeviceDescription make_ADD_BtLeHeadset() {
+    return make_AudioDeviceDescription(AudioDeviceType::OUT_HEADSET,
+                                       AudioDeviceDescription::CONNECTION_BT_LE());
+}
+
+AudioDeviceDescription make_ADD_BtLeBroadcast() {
+    return make_AudioDeviceDescription(AudioDeviceType::OUT_BROADCAST,
+                                       AudioDeviceDescription::CONNECTION_BT_LE());
+}
+
+AudioDeviceDescription make_ADD_IpV4Device() {
+    return make_AudioDeviceDescription(AudioDeviceType::OUT_DEVICE,
+                                       AudioDeviceDescription::CONNECTION_IP_V4());
+}
+
+AudioDeviceDescription make_ADD_UsbHeadset() {
+    return make_AudioDeviceDescription(AudioDeviceType::OUT_HEADSET,
+                                       AudioDeviceDescription::CONNECTION_USB());
+}
+
+AudioDevice make_AudioDevice(const AudioDeviceDescription& type,
+                             const AudioDeviceAddress& address) {
+    AudioDevice result;
+    result.type = type;
+    result.address = address;
+    return result;
+}
+
 AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
     AudioFormatDescription result;
     result.type = type;
@@ -390,6 +433,48 @@
                                          make_ADD_DefaultOut(), make_ADD_WiredHeadset(),
                                          make_ADD_BtScoHeadset()));
 
+class AudioDeviceRoundTripTest : public testing::TestWithParam<AudioDevice> {};
+TEST_P(AudioDeviceRoundTripTest, Aidl2Legacy2Aidl) {
+    const auto initial = GetParam();
+    audio_devices_t legacyType;
+    String8 legacyAddress;
+    status_t status = aidl2legacy_AudioDevice_audio_device(initial, &legacyType, &legacyAddress);
+    ASSERT_EQ(OK, status);
+    auto convBack = legacy2aidl_audio_device_AudioDevice(legacyType, legacyAddress);
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(
+        AudioDeviceRoundTrip, AudioDeviceRoundTripTest,
+        testing::Values(
+                make_AudioDevice(make_ADD_MicIn(),
+                                 AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("bottom")),
+                make_AudioDevice(make_ADD_RSubmixIn(),
+                                 AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("1:2-in-3")),
+                // The case of a "blueprint" device port for an external device.
+                make_AudioDevice(make_ADD_BtScoHeadset(),
+                                 AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("")),
+                make_AudioDevice(make_ADD_BtScoHeadset(),
+                                 AudioDeviceAddress::make<AudioDeviceAddress::Tag::mac>(
+                                         std::vector<uint8_t>{1, 2, 3, 4, 5, 6})),
+                // Another "blueprint"
+                make_AudioDevice(make_ADD_BtA2dpHeadphone(),
+                                 AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("")),
+                make_AudioDevice(make_ADD_BtA2dpHeadphone(),
+                                 AudioDeviceAddress::make<AudioDeviceAddress::Tag::mac>(
+                                         std::vector<uint8_t>{1, 2, 3, 4, 5, 6})),
+                make_AudioDevice(make_ADD_BtLeHeadset(),
+                                 AudioDeviceAddress::make<AudioDeviceAddress::Tag::mac>(
+                                         std::vector<uint8_t>{1, 2, 3, 4, 5, 6})),
+                make_AudioDevice(make_ADD_BtLeBroadcast(),
+                                 AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("42")),
+                make_AudioDevice(make_ADD_IpV4Device(),
+                                 AudioDeviceAddress::make<AudioDeviceAddress::Tag::ipv4>(
+                                         std::vector<uint8_t>{192, 168, 0, 1})),
+                make_AudioDevice(make_ADD_UsbHeadset(),
+                                 AudioDeviceAddress::make<AudioDeviceAddress::Tag::alsa>(
+                                         std::vector<int32_t>{1, 2}))));
+
 class AudioFormatDescriptionRoundTripTest : public testing::TestWithParam<AudioFormatDescription> {
 };
 TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) {
diff --git a/media/libaudioclient/tests/audiosystem_tests.cpp b/media/libaudioclient/tests/audiosystem_tests.cpp
index 682f43e..d43b669 100644
--- a/media/libaudioclient/tests/audiosystem_tests.cpp
+++ b/media/libaudioclient/tests/audiosystem_tests.cpp
@@ -18,12 +18,19 @@
 
 #include <string.h>
 
+#include <set>
+
 #include <gtest/gtest.h>
+#include <media/AidlConversionCppNdk.h>
 #include <media/IAudioFlinger.h>
 #include <utils/Log.h>
 
 #include "audio_test_utils.h"
 
+using android::media::audio::common::AudioDeviceAddress;
+using android::media::audio::common::AudioDeviceDescription;
+using android::media::audio::common::AudioDeviceType;
+using android::media::audio::common::AudioPortExt;
 using namespace android;
 
 void anyPatchContainsInputDevice(audio_port_handle_t deviceId, bool& res) {
@@ -579,3 +586,106 @@
     EXPECT_EQ(NO_ERROR, AudioSystem::setUserIdDeviceAffinities(userId, outputDevices));
     EXPECT_EQ(NO_ERROR, AudioSystem::removeUserIdDeviceAffinities(userId));
 }
+
+namespace {
+
+class WithSimulatedDeviceConnections {
+  public:
+    WithSimulatedDeviceConnections()
+        : mIsSupported(AudioSystem::setSimulateDeviceConnections(true) == OK) {}
+    ~WithSimulatedDeviceConnections() {
+        if (mIsSupported) {
+            if (status_t status = AudioSystem::setSimulateDeviceConnections(false); status != OK) {
+                ALOGE("Error restoring device connections simulation state: %d", status);
+            }
+        }
+    }
+    bool isSupported() const { return mIsSupported; }
+
+  private:
+    const bool mIsSupported;
+};
+
+android::media::audio::common::AudioPort GenerateUniqueDeviceAddress(
+        const android::media::audio::common::AudioPort& port) {
+    static int nextId = 0;
+    using Tag = AudioDeviceAddress::Tag;
+    AudioDeviceAddress address;
+    switch (suggestDeviceAddressTag(port.ext.get<AudioPortExt::Tag::device>().device.type)) {
+        case Tag::id:
+            address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
+            break;
+        case Tag::mac:
+            address = AudioDeviceAddress::make<Tag::mac>(
+                    std::vector<uint8_t>{1, 2, 3, 4, 5, static_cast<uint8_t>(++nextId & 0xff)});
+            break;
+        case Tag::ipv4:
+            address = AudioDeviceAddress::make<Tag::ipv4>(
+                    std::vector<uint8_t>{192, 168, 0, static_cast<uint8_t>(++nextId & 0xff)});
+            break;
+        case Tag::ipv6:
+            address = AudioDeviceAddress::make<Tag::ipv6>(std::vector<int32_t>{
+                    0xfc00, 0x0123, 0x4567, 0x89ab, 0xcdef, 0, 0, ++nextId & 0xffff});
+            break;
+        case Tag::alsa:
+            address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
+            break;
+    }
+    android::media::audio::common::AudioPort result = port;
+    result.ext.get<AudioPortExt::Tag::device>().device.address = std::move(address);
+    return result;
+}
+
+}  // namespace
+
+TEST_F(AudioSystemTest, SetDeviceConnectedState) {
+    WithSimulatedDeviceConnections connSim;
+    if (!connSim.isSupported()) {
+        GTEST_SKIP() << "Simulation of external device connections not supported";
+    }
+    std::vector<media::AudioPortFw> ports;
+    ASSERT_EQ(OK, AudioSystem::listDeclaredDevicePorts(media::AudioPortRole::NONE, &ports));
+    if (ports.empty()) {
+        GTEST_SKIP() << "No ports returned by the audio system";
+    }
+    const std::set<AudioDeviceType> typesToUse{
+            AudioDeviceType::IN_DEVICE,       AudioDeviceType::IN_HEADSET,
+            AudioDeviceType::IN_MICROPHONE,   AudioDeviceType::OUT_DEVICE,
+            AudioDeviceType::OUT_HEADPHONE,   AudioDeviceType::OUT_HEADSET,
+            AudioDeviceType::OUT_HEARING_AID, AudioDeviceType::OUT_SPEAKER};
+    std::vector<media::AudioPortFw> externalDevicePorts;
+    for (const auto& port : ports) {
+        if (const auto& device = port.hal.ext.get<AudioPortExt::device>().device;
+            !device.type.connection.empty() && typesToUse.count(device.type.type)) {
+            externalDevicePorts.push_back(port);
+        }
+    }
+    if (externalDevicePorts.empty()) {
+        GTEST_SKIP() << "No ports for considered non-attached devices";
+    }
+    for (auto& port : externalDevicePorts) {
+        android::media::audio::common::AudioPort aidlPort = GenerateUniqueDeviceAddress(port.hal);
+        SCOPED_TRACE(aidlPort.toString());
+        audio_devices_t type;
+        char address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
+        status_t status = aidl2legacy_AudioDevice_audio_device(
+                aidlPort.ext.get<AudioPortExt::Tag::device>().device, &type, address);
+        ASSERT_EQ(OK, status);
+        audio_policy_dev_state_t deviceState = AudioSystem::getDeviceConnectionState(type, address);
+        EXPECT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, deviceState);
+        if (deviceState != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) continue;
+        // !!! Instead of the default format, use each format from 'ext.encodedFormats'
+        // !!! if they are not empty
+        status = AudioSystem::setDeviceConnectionState(AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+                                                       aidlPort, AUDIO_FORMAT_DEFAULT);
+        EXPECT_EQ(OK, status);
+        if (status != OK) continue;
+        deviceState = AudioSystem::getDeviceConnectionState(type, address);
+        EXPECT_EQ(AUDIO_POLICY_DEVICE_STATE_AVAILABLE, deviceState);
+        status = AudioSystem::setDeviceConnectionState(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+                                                       aidlPort, AUDIO_FORMAT_DEFAULT);
+        EXPECT_EQ(OK, status);
+        deviceState = AudioSystem::getDeviceConnectionState(type, address);
+        EXPECT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, deviceState);
+    }
+}
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
index 2170cd8..999e263 100644
--- a/media/libaudiofoundation/AudioProfile.cpp
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -327,6 +327,24 @@
     return false;
 }
 
+const SampleRateSet AudioProfileVector::getSampleRatesFor(audio_format_t format) const {
+    for (const auto& profile : *this) {
+        if (profile->getFormat() == format) {
+            return profile->getSampleRates();
+        }
+    }
+    return {};
+}
+
+const ChannelMaskSet AudioProfileVector::getChannelMasksFor(audio_format_t format) const {
+    for (const auto& profile : *this) {
+        if (profile->getFormat() == format) {
+            return profile->getChannels();
+        }
+    }
+    return {};
+}
+
 bool AudioProfileVector::contains(const sp<AudioProfile>& profile, bool ignoreDynamicFlags) const
 {
     for (const auto& audioProfile : *this) {
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
index 79dfd12..a668afe 100644
--- a/media/libaudiofoundation/include/media/AudioProfile.h
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -139,6 +139,9 @@
     bool hasDynamicProfile() const;
     bool hasDynamicRateFor(audio_format_t format) const;
 
+    const SampleRateSet getSampleRatesFor(audio_format_t format) const;
+    const ChannelMaskSet getChannelMasksFor(audio_format_t format) const;
+
     bool contains(const sp<AudioProfile>& profile, bool ignoreDynamicFlags = false) const;
 
     virtual void dump(std::string *dst, int spaces) const;
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index f47dd0b..1dbcb86 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -76,3 +76,11 @@
 
     export_include_dirs: ["include"],
 }
+
+cc_library_headers {
+    name: "libaudiohalimpl_headers",
+
+    header_libs: ["libaudiohal_headers"],
+    export_header_lib_headers: ["libaudiohal_headers"],
+    export_include_dirs: ["impl"],
+}
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index d5f6598..1e3d45f 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -274,6 +274,7 @@
         "EffectsFactoryHalAidl.cpp",
         "EffectsFactoryHalEntry.cpp",
         "StreamHalAidl.cpp",
+        ":audio_effectproxy_src_files"
     ],
     static_libs: [
         "android.hardware.common-V2-ndk",
@@ -283,6 +284,7 @@
         "libbinder_ndk",
         "libaudio_aidl_conversion_common_cpp",
         "libaudio_aidl_conversion_common_ndk",
+        "libaudio_aidl_conversion_core_ndk",
         "libaudio_aidl_conversion_effect_ndk",
         "libaudioaidlcommon",
     ],
@@ -297,3 +299,8 @@
         "-DBACKEND_CPP_NDK",
     ],
 }
+
+filegroup {
+    name: "audio_effectproxy_src_files",
+    srcs: ["EffectProxy.cpp"],
+}
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 8b88f24..a8a48ae 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -23,6 +23,8 @@
 #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/AidlConversionUtil.h>
@@ -34,32 +36,42 @@
 #include "StreamHalAidl.h"
 
 using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::media::audio::common::AudioChannelLayout;
 using aidl::android::media::audio::common::AudioConfig;
 using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
 using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatType;
 using aidl::android::media::audio::common::AudioInputFlags;
 using aidl::android::media::audio::common::AudioIoFlags;
 using aidl::android::media::audio::common::AudioLatencyMode;
+using aidl::android::media::audio::common::AudioMMapPolicy;
+using aidl::android::media::audio::common::AudioMMapPolicyInfo;
+using aidl::android::media::audio::common::AudioMMapPolicyType;
 using aidl::android::media::audio::common::AudioMode;
 using aidl::android::media::audio::common::AudioOutputFlags;
 using aidl::android::media::audio::common::AudioPort;
 using aidl::android::media::audio::common::AudioPortConfig;
 using aidl::android::media::audio::common::AudioPortDeviceExt;
+using aidl::android::media::audio::common::AudioPortExt;
 using aidl::android::media::audio::common::AudioPortMixExt;
 using aidl::android::media::audio::common::AudioPortMixExtUseCase;
-using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioProfile;
 using aidl::android::media::audio::common::AudioSource;
-using aidl::android::media::audio::common::Int;
 using aidl::android::media::audio::common::Float;
-using aidl::android::hardware::audio::common::getFrameSizeInBytes;
-using aidl::android::hardware::audio::common::isBitPositionFlagSet;
-using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
+using aidl::android::media::audio::common::Int;
 using aidl::android::media::audio::common::MicrophoneDynamicInfo;
 using aidl::android::media::audio::common::MicrophoneInfo;
+using aidl::android::hardware::audio::common::getFrameSizeInBytes;
+using aidl::android::hardware::audio::common::isBitPositionFlagSet;
+using aidl::android::hardware::audio::common::isDefaultAudioFormat;
+using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
 using aidl::android::hardware::audio::common::RecordTrackMetadata;
 using aidl::android::hardware::audio::core::AudioPatch;
+using aidl::android::hardware::audio::core::AudioRoute;
 using aidl::android::hardware::audio::core::IModule;
 using aidl::android::hardware::audio::core::ITelephony;
+using aidl::android::hardware::audio::core::ModuleDebug;
 using aidl::android::hardware::audio::core::StreamDescriptor;
 
 namespace android {
@@ -84,6 +96,75 @@
     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));
+    return cpp;
+}
+
 }  // namespace
 
 status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
@@ -116,6 +197,7 @@
     }
     ALOGI("%s: module %s default port ids: input %d, output %d",
             __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
+    RETURN_STATUS_IF_ERROR(updateRoutes());
     std::vector<AudioPortConfig> portConfigs;
     RETURN_STATUS_IF_ERROR(
             statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs)));  // OK if empty
@@ -257,9 +339,9 @@
     AudioPortConfig mixPortConfig;
     Cleanups cleanups;
     audio_config writableConfig = *config;
-    int32_t nominalLatency;
+    AudioPatch aidlPatch;
     RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
-                    &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+                    &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
     *size = aidlConfig.frameCount *
             getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
     // Do not disarm cleanups to release temporary port configs.
@@ -270,7 +352,11 @@
         int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
         AudioSource aidlSource, struct audio_config* config,
         Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
-        int32_t* nominalLatency) {
+        AudioPatch* aidlPatch) {
+    ALOGD("%p %s::%s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
+            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());
     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.
@@ -281,25 +367,23 @@
         cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
     }
     RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
-                    mixPortConfig, &created));
+                    std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
     if (created) {
         cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
     }
     setConfigFromPortConfig(aidlConfig, *mixPortConfig);
-    AudioPatch patch;
     if (isInput) {
         RETURN_STATUS_IF_ERROR(findOrCreatePatch(
-                        {devicePortConfig.id}, {mixPortConfig->id}, &patch, &created));
+                        {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
     } else {
         RETURN_STATUS_IF_ERROR(findOrCreatePatch(
-                        {mixPortConfig->id}, {devicePortConfig.id}, &patch, &created));
+                        {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
     }
     if (created) {
-        cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
+        cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
     }
-    *nominalLatency = patch.latenciesMs[0];
     if (aidlConfig->frameCount <= 0) {
-        aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
+        aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
     }
     *config = VALUE_OR_RETURN_STATUS(
             ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
@@ -445,10 +529,10 @@
     AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
     AudioPortConfig mixPortConfig;
     Cleanups cleanups;
-    int32_t nominalLatency;
+    AudioPatch aidlPatch;
     RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
                     AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
-                    config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+                    config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
     ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
     args.portConfigId = mixPortConfig.id;
     const bool isOffload = isBitPositionFlagSet(
@@ -472,8 +556,9 @@
                 __func__, ret.desc.toString().c_str());
         return NO_INIT;
     }
-    *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
+    *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
             std::move(ret.stream), this /*callbackBroker*/);
+    mStreams.insert(std::pair(*outStream, aidlPatch.id));
     void* cbCookie = (*outStream).get();
     {
         std::lock_guard l(mLock);
@@ -510,9 +595,9 @@
             ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
     AudioPortConfig mixPortConfig;
     Cleanups cleanups;
-    int32_t nominalLatency;
+    AudioPatch aidlPatch;
     RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
-                    config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+                    config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
     ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
     args.portConfigId = mixPortConfig.id;
     RecordTrackMetadata aidlTrackMetadata{
@@ -532,8 +617,9 @@
                 __func__, ret.desc.toString().c_str());
         return NO_INIT;
     }
-    *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), nominalLatency,
+    *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
             std::move(ret.stream), this /*micInfoProvider*/);
+    mStreams.insert(std::pair(*inStream, aidlPatch.id));
     cleanups.disarmAll();
     return OK;
 }
@@ -601,20 +687,41 @@
             __func__, ::android::internal::ToString(aidlSources).c_str(),
             ::android::internal::ToString(aidlSinks).c_str());
     auto fillPortConfigs = [&](
-            const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
+            const std::vector<AudioPortConfig>& configs,
+            const std::set<int32_t>& destinationPortIds,
+            std::vector<int32_t>* ids, std::set<int32_t>* portIds) -> status_t {
         for (const auto& s : configs) {
             AudioPortConfig portConfig;
             bool created = false;
-            RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
+            RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
+                            s, destinationPortIds, &portConfig, &created));
             if (created) {
                 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
             }
             ids->push_back(portConfig.id);
+            if (portIds != nullptr) {
+                portIds->insert(portConfig.portId);
+            }
         }
         return OK;
     };
-    RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
-    RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
+    // When looking up port configs, the destinationPortId is only used for mix ports.
+    // Thus, we process device port configs first, and look up the destination port ID from them.
+    bool sourceIsDevice = std::any_of(aidlSources.begin(), aidlSources.end(),
+            [](const auto& config) { return config.ext.getTag() == AudioPortExt::device; });
+    const std::vector<AudioPortConfig>& devicePortConfigs =
+            sourceIsDevice ? aidlSources : aidlSinks;
+    std::vector<int32_t>* devicePortConfigIds =
+            sourceIsDevice ? &aidlPatch.sourcePortConfigIds : &aidlPatch.sinkPortConfigIds;
+    const std::vector<AudioPortConfig>& mixPortConfigs =
+            sourceIsDevice ? aidlSinks : aidlSources;
+    std::vector<int32_t>* mixPortConfigIds =
+            sourceIsDevice ? &aidlPatch.sinkPortConfigIds : &aidlPatch.sourcePortConfigIds;
+    std::set<int32_t> devicePortIds;
+    RETURN_STATUS_IF_ERROR(fillPortConfigs(
+                    devicePortConfigs, std::set<int32_t>(), devicePortConfigIds, &devicePortIds));
+    RETURN_STATUS_IF_ERROR(fillPortConfigs(
+                    mixPortConfigs, devicePortIds, mixPortConfigIds, nullptr));
     if (existingPatchIt != mPatches.end()) {
         RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
                         mModule->setAudioPatch(aidlPatch, &aidlPatch)));
@@ -649,22 +756,68 @@
     return OK;
 }
 
-status_t DeviceHalAidl::getAudioPort(struct audio_port* port __unused) {
-    TIME_CHECK();
-    ALOGE("%s not implemented yet", __func__);
-    return INVALID_OPERATION;
-}
-
-status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port __unused) {
-    TIME_CHECK();
-    ALOGE("%s not implemented yet", __func__);
-    return INVALID_OPERATION;
-}
-
-status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config __unused) {
+status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
     TIME_CHECK();
     if (!mModule) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
+    if (port == nullptr) {
+        return BAD_VALUE;
+    }
+    audio_port_v7 portV7;
+    audio_populate_audio_port_v7(port, &portV7);
+    RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
+    return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
+}
+
+status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    if (port == nullptr) {
+        return BAD_VALUE;
+    }
+    bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
+            ::aidl::android::AudioPortDirection::INPUT;
+    auto aidlPort = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
+    if (aidlPort.ext.getTag() != AudioPortExt::device) {
+        ALOGE("%s: provided port is not a device port (module %s): %s",
+                __func__, mInstance.c_str(), aidlPort.toString().c_str());
+        return BAD_VALUE;
+    }
+    const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
+    // It seems that we don't have to call HAL since all valid ports have been added either
+    // during initialization, or while handling connection of an external device.
+    auto portsIt = findPort(matchDevice);
+    if (portsIt == mPorts.end()) {
+        ALOGE("%s: device port for device %s is not found in the module %s",
+                __func__, matchDevice.toString().c_str(), mInstance.c_str());
+        return BAD_VALUE;
+    }
+    const int32_t fwkId = aidlPort.id;
+    aidlPort = portsIt->second;
+    aidlPort.id = fwkId;
+    *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
+                    aidlPort, isInput));
+    return OK;
+}
+
+status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    if (config == nullptr) {
+        return BAD_VALUE;
+    }
+    bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
+                    config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
+    AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
+                    *config, isInput, 0 /*portId*/));
+    AudioPortConfig portConfig;
+    bool created = false;
+    RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
+                    requestedPortConfig, std::set<int32_t>(), &portConfig, &created));
     return OK;
 }
 
@@ -732,23 +885,41 @@
 }
 
 status_t DeviceHalAidl::getMmapPolicyInfos(
-        media::audio::common::AudioMMapPolicyType policyType __unused,
-        std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos __unused) {
+        media::audio::common::AudioMMapPolicyType policyType,
+        std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
     TIME_CHECK();
-    ALOGE("%s not implemented yet", __func__);
+    AudioMMapPolicyType mmapPolicyType =
+            VALUE_OR_RETURN_STATUS(cpp2ndk_Enum<AudioMMapPolicyType>(policyType));
+
+    std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
+
+    if (status_t status = statusTFromBinderStatus(
+            mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
+        return status;
+    }
+
+    *policyInfos = VALUE_OR_RETURN_STATUS(
+            convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
+                mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
     return OK;
 }
 
 int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
     TIME_CHECK();
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    int32_t mixerBurstCount = 0;
+    if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
+        return mixerBurstCount;
+    }
+    return 0;
 }
 
 int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
     TIME_CHECK();
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    int32_t hardwareBurstMinUsec = 0;
+    if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
+        return hardwareBurstMinUsec;
+    }
+    return 0;
 }
 
 error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
@@ -764,12 +935,82 @@
     TIME_CHECK();
     if (!mModule) return NO_INIT;
     return mModule->dump(fd, Args(args).args(), args.size());
-};
+}
 
-int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
+int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
     TIME_CHECK();
-    ALOGE("%s not implemented yet", __func__);
-    return INVALID_OPERATION;
+    if (!mModule) return NO_INIT;
+    if (supports == nullptr) {
+        return BAD_VALUE;
+    }
+    return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
+}
+
+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;
+    }
+    bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
+            ::aidl::android::AudioPortDirection::INPUT;
+    AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
+    if (aidlPort.ext.getTag() != AudioPortExt::device) {
+        ALOGE("%s: provided port is not a device port (module %s): %s",
+                __func__, mInstance.c_str(), aidlPort.toString().c_str());
+        return BAD_VALUE;
+    }
+    if (connected) {
+        AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
+        // Reset the device address to find the "template" port.
+        matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
+        auto portsIt = findPort(matchDevice);
+        if (portsIt == mPorts.end()) {
+            ALOGW("%s: device port for device %s is not found in the module %s",
+                    __func__, matchDevice.toString().c_str(), mInstance.c_str());
+            return BAD_VALUE;
+        }
+        // Use the ID of the "template" port, use all the information from the provided port.
+        aidlPort.id = portsIt->first;
+        AudioPort connectedPort;
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
+                                aidlPort, &connectedPort)));
+        const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
+        LOG_ALWAYS_FATAL_IF(!inserted,
+                "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
+                __func__, mInstance.c_str(), connectedPort.toString().c_str(),
+                it->second.toString().c_str());
+    } else {  // !connected
+        AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
+        auto portsIt = findPort(matchDevice);
+        if (portsIt == mPorts.end()) {
+            ALOGW("%s: device port for device %s is not found in the module %s",
+                    __func__, matchDevice.toString().c_str(), mInstance.c_str());
+            return BAD_VALUE;
+        }
+        // Any streams opened on the external device must be closed by this time,
+        // thus we can clean up patches and port configs that were created for them.
+        resetUnusedPatchesAndPortConfigs();
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
+                                portsIt->second.id)));
+        mPorts.erase(portsIt);
+    }
+    return updateRoutes();
+}
+
+status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    ModuleDebug debug{ .simulateDeviceConnections = enabled };
+    status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
+    // This is important to log as it affects HAL behavior.
+    if (status == OK) {
+        ALOGI("%s: set enabled: %d", __func__, enabled);
+    } else {
+        ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
+    }
+    return status;
 }
 
 bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
@@ -865,7 +1106,8 @@
 
 status_t DeviceHalAidl::findOrCreatePortConfig(
         const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
-        AudioSource source, AudioPortConfig* portConfig, bool* created) {
+        AudioSource source, const std::set<int32_t>& destinationPortIds,
+        AudioPortConfig* portConfig, bool* created) {
     // These flags get removed one by one in this order when retrying port finding.
     static const std::vector<AudioInputFlags> kOptionalInputFlags{
         AudioInputFlags::FAST, AudioInputFlags::RAW };
@@ -873,7 +1115,7 @@
     if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
         auto optionalInputFlagsIt = kOptionalInputFlags.begin();
         AudioIoFlags matchFlags = flags.value();
-        auto portsIt = findPort(config, matchFlags);
+        auto portsIt = findPort(config, matchFlags, destinationPortIds);
         while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
                 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
             if (!isBitPositionFlagSet(
@@ -883,7 +1125,7 @@
             }
             matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
                     ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
-            portsIt = findPort(config, matchFlags);
+            portsIt = findPort(config, matchFlags, destinationPortIds);
             ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
                     "retried with flags %s", __func__, config.toString().c_str(),
                     flags.value().toString().c_str(), mInstance.c_str(),
@@ -919,7 +1161,8 @@
 }
 
 status_t DeviceHalAidl::findOrCreatePortConfig(
-        const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
+        const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
+        AudioPortConfig* portConfig, bool* created) {
     using Tag = AudioPortExt::Tag;
     if (requestedPortConfig.ext.getTag() == Tag::mix) {
         if (const auto& p = requestedPortConfig;
@@ -936,7 +1179,8 @@
                 requestedPortConfig.ext.get<Tag::mix>().usecase.
                 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
         return findOrCreatePortConfig(config, requestedPortConfig.flags,
-                requestedPortConfig.ext.get<Tag::mix>().handle, source, portConfig, created);
+                requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
+                portConfig, created);
     } else if (requestedPortConfig.ext.getTag() == Tag::device) {
         return findOrCreatePortConfig(
                 requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
@@ -968,20 +1212,30 @@
             [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
 }
 
+
 DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
-            const AudioConfig& config, const AudioIoFlags& flags) {
+            const AudioConfig& config, const AudioIoFlags& flags,
+            const std::set<int32_t>& destinationPortIds) {
+    auto belongsToProfile = [&config](const AudioProfile& prof) {
+        return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
+                (config.base.channelMask.getTag() == AudioChannelLayout::none ||
+                        std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
+                                config.base.channelMask) != prof.channelMasks.end()) &&
+                (config.base.sampleRate == 0 ||
+                        std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
+                                config.base.sampleRate) != prof.sampleRates.end());
+    };
     auto matcher = [&](const auto& pair) {
         const auto& p = pair.second;
         return p.ext.getTag() == AudioPortExt::Tag::mix &&
                 p.flags == flags &&
-                std::find_if(p.profiles.begin(), p.profiles.end(),
-                        [&](const auto& prof) {
-                            return prof.format == config.base.format &&
-                                    std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
-                                            config.base.channelMask) != prof.channelMasks.end() &&
-                                    std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
-                                            config.base.sampleRate) != prof.sampleRates.end();
-                        }) != p.profiles.end(); };
+                (destinationPortIds.empty() ||
+                        std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
+                                [&](const int32_t destId) { return mRoutingMatrix.count(
+                                            std::make_pair(p.id, destId)) != 0; })) &&
+                (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);
 }
 
@@ -1006,34 +1260,7 @@
                         (!flags.has_value() || p.flags.value() == flags.value()) &&
                         p.ext.template get<Tag::mix>().handle == ioHandle; });
 }
-/*
-DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
-        const AudioPortConfig& portConfig) {
-    using Tag = AudioPortExt::Tag;
-    if (portConfig.ext.getTag() == Tag::mix) {
-        return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
-                [&](const auto& pair) {
-                    const auto& p = pair.second;
-                    LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
-                            !p.sampleRate.has_value() || !p.channelMask.has_value() ||
-                            !p.format.has_value() || !p.flags.has_value(),
-                            "%s: stored mix port config is not fully specified: %s",
-                            __func__, p.toString().c_str());
-                    return p.ext.getTag() == Tag::mix &&
-                            (!portConfig.sampleRate.has_value() ||
-                                    p.sampleRate == portConfig.sampleRate) &&
-                            (!portConfig.channelMask.has_value() ||
-                                    p.channelMask == portConfig.channelMask) &&
-                            (!portConfig.format.has_value() || p.format == portConfig.format) &&
-                            (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
-                            p.ext.template get<Tag::mix>().handle ==
-                            portConfig.ext.template get<Tag::mix>().handle; });
-    } else if (portConfig.ext.getTag() == Tag::device) {
-        return findPortConfig(portConfig.ext.get<Tag::device>().device);
-    }
-    return mPortConfigs.end();
-}
-*/
+
 void DeviceHalAidl::resetPatch(int32_t patchId) {
     if (auto it = mPatches.find(patchId); it != mPatches.end()) {
         mPatches.erase(it);
@@ -1061,6 +1288,56 @@
     ALOGE("%s: port config id %d not found", __func__, portConfigId);
 }
 
+void DeviceHalAidl::resetUnusedPatches() {
+    // Since patches can be created independently of streams via 'createAudioPatch',
+    // here we only clean up patches for released streams.
+    for (auto it = mStreams.begin(); it != mStreams.end(); ) {
+        if (auto streamSp = it->first.promote(); streamSp) {
+            ++it;
+        } else {
+            resetPatch(it->second);
+            it = mStreams.erase(it);
+        }
+    }
+}
+
+void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
+    resetUnusedPatches();
+    resetUnusedPortConfigs();
+}
+
+void DeviceHalAidl::resetUnusedPortConfigs() {
+    // The assumption is that port configs are used to create patches
+    // (or to open streams, but that involves creation of patches, too). Thus,
+    // orphaned port configs can and should be reset.
+    std::set<int32_t> portConfigIds;
+    std::transform(mPortConfigs.begin(), mPortConfigs.end(),
+            std::inserter(portConfigIds, portConfigIds.end()),
+            [](const auto& pcPair) { return pcPair.first; });
+    for (const auto& p : mPatches) {
+        for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
+        for (int32_t id : p.second.sinkPortConfigIds) 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",
+            __func__, mInstance.c_str());
+    mRoutingMatrix.clear();
+    for (const auto& r : routes) {
+        for (auto portId : r.sourcePortIds) {
+            mRoutingMatrix.emplace(r.sinkPortId, portId);
+            mRoutingMatrix.emplace(portId, r.sinkPortId);
+        }
+    }
+    return OK;
+}
+
 void DeviceHalAidl::clearCallbacks(void* cookie) {
     std::lock_guard l(mLock);
     mCallbacks.erase(cookie);
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 0a86ddc..fd0cd54 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -24,6 +24,7 @@
 #include <android-base/thread_annotations.h>
 #include <media/audiohal/DeviceHalInterface.h>
 #include <media/audiohal/EffectHalInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
 
 #include "ConversionHelperAidl.h"
 
@@ -138,7 +139,7 @@
     status_t setAudioPortConfig(const struct audio_port_config* config) override;
 
     // List microphones
-    status_t getMicrophones(std::vector<audio_microphone_characteristic_t>* microphones);
+    status_t getMicrophones(std::vector<audio_microphone_characteristic_t>* microphones) override;
 
     status_t addDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
 
@@ -154,10 +155,14 @@
 
     error::Result<audio_hw_sync_t> getHwAvSync() override;
 
-    status_t dump(int __unused, const Vector<String16>& __unused) override;
-
     int32_t supportsBluetoothVariableLatency(bool* supports __unused) override;
 
+    status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override;
+
+    status_t setSimulateDeviceConnections(bool enabled) override;
+
+    status_t dump(int __unused, const Vector<String16>& __unused) override;
+
   private:
     friend class sp<DeviceHalAidl>;
 
@@ -176,6 +181,10 @@
     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>;
+    // 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>>;
+    using Streams = std::map<wp<StreamHalInterface>, int32_t /*patch ID*/>;
     class Cleanups;
 
     // Must not be constructed directly by clients.
@@ -209,25 +218,25 @@
             const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
             int32_t ioHandle,
             ::aidl::android::media::audio::common::AudioSource aidlSource,
+            const std::set<int32_t>& destinationPortIds,
             ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
     status_t findOrCreatePortConfig(
         const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
+        const std::set<int32_t>& destinationPortIds,
         ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
     Patches::iterator findPatch(const std::set<int32_t>& sourcePortConfigIds,
             const std::set<int32_t>& sinkPortConfigIds);
     Ports::iterator findPort(const ::aidl::android::media::audio::common::AudioDevice& device);
     Ports::iterator findPort(
             const ::aidl::android::media::audio::common::AudioConfig& config,
-            const ::aidl::android::media::audio::common::AudioIoFlags& flags);
+            const ::aidl::android::media::audio::common::AudioIoFlags& flags,
+            const std::set<int32_t>& destinationPortIds);
     PortConfigs::iterator findPortConfig(
             const ::aidl::android::media::audio::common::AudioDevice& device);
     PortConfigs::iterator findPortConfig(
             const ::aidl::android::media::audio::common::AudioConfig& config,
             const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
             int32_t ioHandle);
-    // Currently unused but may be useful for implementing setAudioPortConfig
-    // PortConfigs::iterator findPortConfig(
-    //         const ::aidl::android::media::audio::common::AudioPortConfig& portConfig);
     status_t prepareToOpenStream(
         int32_t aidlHandle,
         const ::aidl::android::media::audio::common::AudioDevice& aidlDevice,
@@ -237,9 +246,13 @@
         Cleanups* cleanups,
         ::aidl::android::media::audio::common::AudioConfig* aidlConfig,
         ::aidl::android::media::audio::common::AudioPortConfig* mixPortConfig,
-        int32_t* nominalLatency);
+        ::aidl::android::hardware::audio::core::AudioPatch* aidlPatch);
     void resetPatch(int32_t patchId);
     void resetPortConfig(int32_t portConfigId);
+    void resetUnusedPatches();
+    void resetUnusedPatchesAndPortConfigs();
+    void resetUnusedPortConfigs();
+    status_t updateRoutes();
 
     // CallbackBroker implementation
     void clearCallbacks(void* cookie) override;
@@ -266,6 +279,8 @@
     int32_t mDefaultOutputPortId = -1;
     PortConfigs mPortConfigs;
     Patches mPatches;
+    RoutingMatrix mRoutingMatrix;
+    Streams mStreams;
     Microphones mMicrophones;
     std::mutex mLock;
     std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 052eb65..132aad7 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -126,6 +126,11 @@
 
     status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override;
 
+    status_t setSimulateDeviceConnections(bool enabled __unused) override {
+        // Only supported by AIDL HALs.
+        return INVALID_OPERATION;
+    }
+
     error::Result<audio_hw_sync_t> getHwAvSync() override;
 
     status_t dump(int fd, const Vector<String16>& args) override;
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 519b871..52fed91 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <cstddef>
 #include <cstdint>
 #include <cstring>
 #include <optional>
@@ -29,6 +30,7 @@
 #include <utils/Log.h>
 
 #include "EffectConversionHelperAidl.h"
+#include "EffectProxy.h"
 
 namespace android {
 namespace effect {
@@ -37,10 +39,13 @@
 using ::aidl::android::hardware::audio::effect::CommandId;
 using ::aidl::android::hardware::audio::effect::Descriptor;
 using ::aidl::android::hardware::audio::effect::Flags;
+using ::aidl::android::hardware::audio::effect::IEffect;
 using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::State;
 using ::aidl::android::media::audio::common::AudioDeviceDescription;
 using ::aidl::android::media::audio::common::AudioMode;
 using ::aidl::android::media::audio::common::AudioSource;
+using ::android::hardware::EventFlag;
 using android::effect::utils::EffectParamReader;
 using android::effect::utils::EffectParamWriter;
 
@@ -72,7 +77,9 @@
       mIoId(ioId),
       mDesc(desc),
       mEffect(std::move(effect)),
-      mIsInputStream(mDesc.common.flags.type == Flags::Type::PRE_PROC) {
+      mIsInputStream(mDesc.common.flags.type == Flags::Type::PRE_PROC),
+      mIsProxyEffect(mDesc.common.id.proxy.has_value() &&
+                     mDesc.common.id.proxy.value() == mDesc.common.id.uuid) {
     mCommon.session = sessionId;
     mCommon.ioHandle = ioId;
     mCommon.input = mCommon.output = kDefaultAudioConfig;
@@ -96,8 +103,8 @@
         return BAD_VALUE;
     }
 
-    return *(status_t*)pReplyData =
-                   statusTFromBinderStatus(mEffect->open(mCommon, std::nullopt, &mOpenReturn));
+    // Do nothing for EFFECT_CMD_INIT, call IEffect.open() with EFFECT_CMD_SET_CONFIG
+    return *(status_t*)pReplyData = OK;
 }
 
 status_t EffectConversionHelperAidl::handleSetParameter(uint32_t cmdSize, const void* pCmdData,
@@ -122,6 +129,8 @@
 status_t EffectConversionHelperAidl::handleGetParameter(uint32_t cmdSize, const void* pCmdData,
                                                         uint32_t* replySize, void* pReplyData) {
     if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize || !pReplyData) {
+        ALOGE("%s illegal cmdSize %u pCmdData %p replySize %p replyData %p", __func__, cmdSize,
+              pCmdData, replySize, pReplyData);
         return BAD_VALUE;
     }
 
@@ -154,22 +163,61 @@
     }
 
     effect_config_t* config = (effect_config_t*)pCmdData;
-    Parameter::Common aidlCommon = {
-            .session = mSessionId,
-            .ioHandle = mIoId,
-            .input = {.base = VALUE_OR_RETURN_STATUS(
-                              ::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
-                                      config->inputCfg, mIsInputStream))},
-            .output = {.base = VALUE_OR_RETURN_STATUS(
-                               ::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
-                                       config->outputCfg, mIsInputStream))}};
+    Parameter::Common common = {
+            .input =
+                    VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfig(
+                            config->inputCfg, mIsInputStream)),
+            .output =
+                    VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfig(
+                            config->outputCfg, mIsInputStream)),
+            .session = mCommon.session,
+            .ioHandle = mCommon.ioHandle};
 
-    Parameter aidlParam = UNION_MAKE(Parameter, common, aidlCommon);
+    State state;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
+    // in case of buffer/ioHandle re-configure for an opened effect, close it and re-open
+    if (state != State::INIT && mCommon != common) {
+        ALOGI("%s at state %s, closing effect", __func__,
+              android::internal::ToString(state).c_str());
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->close()));
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
+        mStatusQ.reset();
+        mInputQ.reset();
+        mOutputQ.reset();
+    }
 
-    status_t ret = statusTFromBinderStatus(mEffect->setParameter(aidlParam));
-    EffectParamWriter writer(*(effect_param_t*)pReplyData);
-    writer.setStatus(ret);
-    return ret;
+    if (state == State::INIT) {
+        ALOGI("%s at state %s, opening effect with input %s output %s", __func__,
+              android::internal::ToString(state).c_str(), common.input.toString().c_str(),
+              common.output.toString().c_str());
+        IEffect::OpenEffectReturn openReturn;
+        RETURN_STATUS_IF_ERROR(
+                statusTFromBinderStatus(mEffect->open(common, std::nullopt, &openReturn)));
+
+        if (mIsProxyEffect) {
+            const auto& ret =
+                    std::static_pointer_cast<EffectProxy>(mEffect)->getEffectReturnParam();
+            mStatusQ = std::make_shared<StatusMQ>(ret->statusMQ);
+            mInputQ = std::make_shared<DataMQ>(ret->inputDataMQ);
+            mOutputQ = std::make_shared<DataMQ>(ret->outputDataMQ);
+        } else {
+            mStatusQ = std::make_shared<StatusMQ>(openReturn.statusMQ);
+            mInputQ = std::make_shared<DataMQ>(openReturn.inputDataMQ);
+            mOutputQ = std::make_shared<DataMQ>(openReturn.outputDataMQ);
+        }
+
+        if (status_t status = updateEventFlags(); status != OK) {
+            mEffect->close();
+            return status;
+        }
+        mCommon = common;
+    } else if (mCommon != common) {
+        ALOGI("%s at state %s, setParameter", __func__, android::internal::ToString(state).c_str());
+        Parameter aidlParam = UNION_MAKE(Parameter, common, mCommon);
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam)));
+    }
+
+    return *static_cast<int32_t*>(pReplyData) = OK;
 }
 
 status_t EffectConversionHelperAidl::handleGetConfig(uint32_t cmdSize __unused,
@@ -187,11 +235,9 @@
     const auto& common = param.get<Parameter::common>();
     effect_config_t* pConfig = (effect_config_t*)pReplyData;
     pConfig->inputCfg = VALUE_OR_RETURN_STATUS(
-            ::aidl::android::aidl2legacy_AudioConfigBase_buffer_config_t(common.input.base, true));
-    pConfig->outputCfg =
-            VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioConfigBase_buffer_config_t(
-                    common.output.base, false));
-    mCommon = common;
+            ::aidl::android::aidl2legacy_AudioConfig_buffer_config_t(common.input, true));
+    pConfig->outputCfg = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_AudioConfig_buffer_config_t(common.output, false));
     return OK;
 }
 
@@ -294,7 +340,21 @@
               pReplyData);
         return BAD_VALUE;
     }
-    // TODO: handle this after effectproxy implemented in libaudiohal
+    effect_offload_param_t* offload = (effect_offload_param_t*)pCmdData;
+    // send to proxy to update active sub-effect
+    if (mIsProxyEffect) {
+        ALOGI("%s offload param offload %s ioHandle %d", __func__,
+              offload->isOffload ? "true" : "false", offload->ioHandle);
+        mCommon.ioHandle = offload->ioHandle;
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+                std::static_pointer_cast<EffectProxy>(mEffect)->setOffloadParam(offload)));
+        // update FMQs
+        const auto& ret = std::static_pointer_cast<EffectProxy>(mEffect)->getEffectReturnParam();
+        mStatusQ = std::make_shared<StatusMQ>(ret->statusMQ);
+        mInputQ = std::make_shared<DataMQ>(ret->inputDataMQ);
+        mOutputQ = std::make_shared<DataMQ>(ret->outputDataMQ);
+        RETURN_STATUS_IF_ERROR(updateEventFlags());
+    }
     return *static_cast<int32_t*>(pReplyData) = OK;
 }
 
@@ -338,5 +398,20 @@
     return visualizerMeasure(replySize, pReplyData);
 }
 
+status_t EffectConversionHelperAidl::updateEventFlags() {
+    status_t status = BAD_VALUE;
+    EventFlag* efGroup = nullptr;
+    if (mStatusQ->isValid()) {
+        status = EventFlag::createEventFlag(mStatusQ->getEventFlagWord(), &efGroup);
+        if (status != OK || !efGroup) {
+            ALOGE("%s: create EventFlagGroup failed, ret %d, egGroup %p", __func__, status,
+                  efGroup);
+            status = (status == OK) ? BAD_VALUE : status;
+        }
+    }
+    mEfGroup.reset(efGroup, EventFlagDeleter());
+    return status;
+}
+
 }  // namespace effect
 }  // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 54df1b8..0c682ff 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -19,6 +19,7 @@
 #include <utils/Errors.h>
 
 #include <aidl/android/hardware/audio/effect/BpEffect.h>
+#include <fmq/AidlMessageQueue.h>
 #include <system/audio_effect.h>
 #include <system/audio_effects/audio_effects_utils.h>
 
@@ -30,10 +31,16 @@
     status_t handleCommand(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData, uint32_t* replySize,
                            void* pReplyData);
     virtual ~EffectConversionHelperAidl() {}
-    const ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn&
-    getEffectReturnParam() const {
-        return mOpenReturn;
-    }
+
+    using StatusMQ = ::android::AidlMessageQueue<
+            ::aidl::android::hardware::audio::effect::IEffect::Status,
+            ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+    using DataMQ = ::android::AidlMessageQueue<
+            float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+    std::shared_ptr<StatusMQ> getStatusMQ() { return mStatusQ; }
+    std::shared_ptr<DataMQ> getInputMQ() { return mInputQ; }
+    std::shared_ptr<DataMQ> getOutputMQ() { return mOutputQ; }
+    std::shared_ptr<android::hardware::EventFlag> getEventFlagGroup() { return mEfGroup; }
 
   protected:
     const int32_t mSessionId;
@@ -42,7 +49,6 @@
     const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> mEffect;
     // whether the effect is instantiated on an input stream
     const bool mIsInputStream;
-    ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn mOpenReturn;
     ::aidl::android::hardware::audio::effect::Parameter::Common mCommon;
 
     EffectConversionHelperAidl(
@@ -59,6 +65,7 @@
     const aidl::android::media::audio::common::AudioFormatDescription kDefaultFormatDescription = {
             .type = aidl::android::media::audio::common::AudioFormatType::PCM,
             .pcm = aidl::android::media::audio::common::PcmType::FLOAT_32_BIT};
+    const bool mIsProxyEffect;
 
     static constexpr int kDefaultframeCount = 0x100;
 
@@ -75,6 +82,20 @@
                                                                    uint32_t* /* replySize */,
                                                                    void* /* pReplyData */);
     static const std::map<uint32_t /* effect_command_e */, CommandHandler> mCommandHandlerMap;
+    // data and status FMQ
+    std::shared_ptr<StatusMQ> mStatusQ = nullptr;
+    std::shared_ptr<DataMQ> mInputQ = nullptr, mOutputQ = nullptr;
+
+
+    struct EventFlagDeleter {
+        void operator()(::android::hardware::EventFlag* flag) const {
+            if (flag) {
+                ::android::hardware::EventFlag::deleteEventFlag(&flag);
+            }
+        }
+    };
+    std::shared_ptr<android::hardware::EventFlag> mEfGroup = nullptr;
+    status_t updateEventFlags();
 
     status_t handleInit(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
                         void* pReplyData);
@@ -112,6 +133,7 @@
     virtual status_t visualizerMeasure(uint32_t* replySize __unused, void* pReplyData __unused) {
         return BAD_VALUE;
     }
+
 };
 
 }  // namespace effect
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index 0c19ac8..faf5f45 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -31,6 +31,7 @@
 #include <utils/Log.h>
 
 #include "EffectHalAidl.h"
+#include "EffectProxy.h"
 
 #include <aidl/android/hardware/audio/effect/IEffect.h>
 
@@ -61,19 +62,22 @@
 
 EffectHalAidl::EffectHalAidl(const std::shared_ptr<IFactory>& factory,
                              const std::shared_ptr<IEffect>& effect, uint64_t effectId,
-                             int32_t sessionId, int32_t ioId, const Descriptor& desc)
+                             int32_t sessionId, int32_t ioId, const Descriptor& desc,
+                             bool isProxyEffect)
     : mFactory(factory),
       mEffect(effect),
       mEffectId(effectId),
       mSessionId(sessionId),
       mIoId(ioId),
-      mDesc(desc) {
+      mDesc(desc),
+      mIsProxyEffect(isProxyEffect) {
     createAidlConversion(effect, sessionId, ioId, desc);
 }
 
 EffectHalAidl::~EffectHalAidl() {
-    if (mFactory) {
-        mFactory->destroyEffect(mEffect);
+    if (mEffect) {
+        mIsProxyEffect ? std::static_pointer_cast<EffectProxy>(mEffect)->destroy()
+                       : mFactory->destroyEffect(mEffect);
     }
 }
 
@@ -157,37 +161,54 @@
     return OK;
 }
 
-
 // write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ
 status_t EffectHalAidl::process() {
-    size_t available = mInputQ->availableToWrite();
+    auto statusQ = mConversion->getStatusMQ();
+    auto inputQ = mConversion->getInputMQ();
+    auto outputQ = mConversion->getOutputMQ();
+    auto efGroup = mConversion->getEventFlagGroup();
+    if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ ||
+        !outputQ->isValid() || !efGroup) {
+        ALOGE("%s invalid FMQ [Status %d I %d O %d] efGroup %p", __func__,
+              statusQ ? statusQ->isValid() : 0, inputQ ? inputQ->isValid() : 0,
+              outputQ ? outputQ->isValid() : 0, efGroup.get());
+        return INVALID_OPERATION;
+    }
+
+    size_t available = inputQ->availableToWrite();
     size_t floatsToWrite = std::min(available, mInBuffer->getSize() / sizeof(float));
     if (floatsToWrite == 0) {
-        ALOGW("%s not able to write, floats in buffer %zu, space in FMQ %zu", __func__,
+        ALOGE("%s not able to write, floats in buffer %zu, space in FMQ %zu", __func__,
               mInBuffer->getSize() / sizeof(float), available);
         return INVALID_OPERATION;
     }
-    if (!mInputQ->write((float*)mInBuffer->ptr(), floatsToWrite)) {
-        ALOGW("%s failed to write %zu into inputQ", __func__, floatsToWrite);
+    if (!mInBuffer->audioBuffer() ||
+        !inputQ->write((float*)mInBuffer->audioBuffer()->f32, floatsToWrite)) {
+        ALOGE("%s failed to write %zu floats from audiobuffer %p to inputQ [avail %zu]", __func__,
+              floatsToWrite, mInBuffer->audioBuffer(), inputQ->availableToWrite());
         return INVALID_OPERATION;
     }
+    efGroup->wake(aidl::android::hardware::audio::effect::kEventFlagNotEmpty);
 
     IEffect::Status retStatus{};
-    if (!mStatusQ->readBlocking(&retStatus, 1) || retStatus.status != OK ||
+    if (!statusQ->readBlocking(&retStatus, 1) || retStatus.status != OK ||
         (size_t)retStatus.fmqConsumed != floatsToWrite || retStatus.fmqProduced == 0) {
-        ALOGW("%s read status failed: %s", __func__, retStatus.toString().c_str());
+        ALOGE("%s read status failed: %s", __func__, retStatus.toString().c_str());
         return INVALID_OPERATION;
     }
 
-    available = mOutputQ->availableToRead();
+    available = outputQ->availableToRead();
     size_t floatsToRead = std::min(available, mOutBuffer->getSize() / sizeof(float));
     if (floatsToRead == 0) {
-        ALOGW("%s not able to read, buffer space %zu, floats in FMQ %zu", __func__,
+        ALOGE("%s not able to read, buffer space %zu, floats in FMQ %zu", __func__,
               mOutBuffer->getSize() / sizeof(float), available);
         return INVALID_OPERATION;
     }
-    if (!mOutputQ->read((float*)mOutBuffer->ptr(), floatsToRead)) {
-        ALOGW("%s failed to read %zu from outputQ", __func__, floatsToRead);
+    // always read floating point data for AIDL
+    if (!mOutBuffer->audioBuffer() ||
+        !outputQ->read(mOutBuffer->audioBuffer()->f32, floatsToRead)) {
+        ALOGE("%s failed to read %zu from outputQ to audioBuffer %p", __func__, floatsToRead,
+              mOutBuffer->audioBuffer());
         return INVALID_OPERATION;
     }
 
@@ -210,20 +231,7 @@
         return INVALID_OPERATION;
     }
 
-    status_t ret = mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
-    // update FMQs when effect open successfully
-    if (ret == OK && cmdCode == EFFECT_CMD_INIT) {
-        const auto& retParam = mConversion->getEffectReturnParam();
-        mStatusQ = std::make_unique<StatusMQ>(retParam.statusMQ);
-        mInputQ = std::make_unique<DataMQ>(retParam.inputDataMQ);
-        mOutputQ = std::make_unique<DataMQ>(retParam.outputDataMQ);
-        if (!mStatusQ->isValid() || !mInputQ->isValid() || !mOutputQ->isValid()) {
-            ALOGE("%s return with invalid FMQ", __func__);
-            return NO_INIT;
-        }
-    }
-
-    return ret;
+    return mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
 }
 
 status_t EffectHalAidl::getDescriptor(effect_descriptor_t* pDescriptor) {
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
index 194150d..47049d7 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -23,6 +23,7 @@
 #include <fmq/AidlMessageQueue.h>
 #include <media/audiohal/EffectHalInterface.h>
 #include <system/audio_effect.h>
+#include <system/audio_effects/aidl_effects_utils.h>
 
 #include "EffectConversionHelperAidl.h"
 
@@ -31,11 +32,6 @@
 
 class EffectHalAidl : public EffectHalInterface {
   public:
-    using StatusMQ = ::android::AidlMessageQueue<
-            ::aidl::android::hardware::audio::effect::IEffect::Status,
-            ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
-    using DataMQ = ::android::AidlMessageQueue<
-            float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
 
     // Set the input buffer.
     status_t setInBuffer(const sp<EffectBufferHalInterface>& buffer) override;
@@ -83,12 +79,11 @@
     const int32_t mSessionId;
     const int32_t mIoId;
     const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
+    const bool mIsProxyEffect;
+
     std::unique_ptr<EffectConversionHelperAidl> mConversion;
-    std::unique_ptr<StatusMQ> mStatusQ;
-    std::unique_ptr<DataMQ> mInputQ, mOutputQ;
 
     sp<EffectBufferHalInterface> mInBuffer, mOutBuffer;
-    effect_config_t mConfig;
 
     status_t createAidlConversion(
             std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
@@ -99,8 +94,10 @@
             const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory>& factory,
             const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& effect,
             uint64_t effectId, int32_t sessionId, int32_t ioId,
-            const ::aidl::android::hardware::audio::effect::Descriptor& desc);
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+            bool isProxyEffect);
     bool setEffectReverse(bool reverse);
+    bool needUpdateReturnParam(uint32_t cmdCode);
 
     // The destructor automatically releases the effect.
     virtual ~EffectHalAidl();
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
new file mode 100644
index 0000000..b61532d
--- /dev/null
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -0,0 +1,291 @@
+/*
+ * 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 <memory>
+#define LOG_TAG "EffectProxy"
+//#define LOG_NDEBUG 0
+
+#include <fmq/AidlMessageQueue.h>
+#include <utils/Log.h>
+
+#include "EffectProxy.h"
+
+using ::aidl::android::hardware::audio::effect::CommandId;
+using ::aidl::android::hardware::audio::effect::Descriptor;
+using ::aidl::android::hardware::audio::effect::Flags;
+using ::aidl::android::hardware::audio::effect::IEffect;
+using ::aidl::android::hardware::audio::effect::IFactory;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::State;
+using ::aidl::android::media::audio::common::AudioUuid;
+
+namespace android {
+namespace effect {
+
+EffectProxy::EffectProxy(const Descriptor::Identity& id, const std::shared_ptr<IFactory>& factory)
+    : mIdentity([](const Descriptor::Identity& subId) {
+          // update EffectProxy implementation UUID to the sub-effect proxy UUID
+          ALOG_ASSERT(subId.proxy.has_value(), "Sub-effect Identity must have valid proxy UUID");
+          Descriptor::Identity tempId = subId;
+          tempId.uuid = subId.proxy.value();
+          return tempId;
+      }(id)),
+      mFactory(factory) {}
+
+EffectProxy::~EffectProxy() {
+    close();
+    destroy();
+    mSubEffects.clear();
+}
+
+// sub effect must have same proxy UUID as EffectProxy, and the type UUID must match.
+ndk::ScopedAStatus EffectProxy::addSubEffect(const Descriptor& sub) {
+    ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+    if (0 != mSubEffects.count(sub.common.id) || !sub.common.id.proxy.has_value() ||
+        sub.common.id.proxy.value() != mIdentity.uuid) {
+        ALOGE("%s sub effect already exist or mismatch %s", __func__, sub.toString().c_str());
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                "illegalSubEffect");
+    }
+
+    // not create sub-effect yet
+    std::get<SubEffectTupleIndex::HANDLE>(mSubEffects[sub.common.id]) = nullptr;
+    std::get<SubEffectTupleIndex::DESCRIPTOR>(mSubEffects[sub.common.id]) = sub;
+    // set the last added sub-effect to active before setOffloadParam()
+    mActiveSub = sub.common.id;
+    ALOGI("%s add %s to proxy %s flag %s", __func__, mActiveSub.toString().c_str(),
+          mIdentity.toString().c_str(), sub.common.flags.toString().c_str());
+
+    if (sub.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL) {
+        mSubFlags.hwAcceleratorMode = Flags::HardwareAccelerator::TUNNEL;
+    }
+
+    // initial flag values before we know which sub-effect to active (with setOffloadParam)
+    // same as HIDL EffectProxy flags
+    mSubFlags.type = Flags::Type::INSERT;
+    mSubFlags.insert = Flags::Insert::LAST;
+    mSubFlags.volume = Flags::Volume::CTRL;
+
+    // set indication if any sub-effect indication was set
+    mSubFlags.offloadIndication |= sub.common.flags.offloadIndication;
+    mSubFlags.deviceIndication |= sub.common.flags.deviceIndication;
+    mSubFlags.audioModeIndication |= sub.common.flags.audioModeIndication;
+    mSubFlags.audioSourceIndication |= sub.common.flags.audioSourceIndication;
+
+    // set bypass when all sub-effects are bypassing
+    mSubFlags.bypass &= sub.common.flags.bypass;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectProxy::create() {
+    ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+    ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
+
+    for (auto& sub : mSubEffects) {
+        auto& effectHandle = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
+        ALOGI("%s sub-effect %s", __func__, sub.first.uuid.toString().c_str());
+        status = mFactory->createEffect(sub.first.uuid, &effectHandle);
+        if (!status.isOk() || !effectHandle) {
+            ALOGE("%s sub-effect failed %s", __func__, sub.first.uuid.toString().c_str());
+            break;
+        }
+    }
+
+    // destroy all created effects if failure
+    if (!status.isOk()) {
+        destroy();
+    }
+    return status;
+}
+
+ndk::ScopedAStatus EffectProxy::destroy() {
+    ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+    return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
+        ndk::ScopedAStatus status = mFactory->destroyEffect(effect);
+        if (status.isOk()) {
+            effect.reset();
+        }
+        return status;
+    });
+}
+
+const IEffect::OpenEffectReturn* EffectProxy::getEffectReturnParam() {
+    return &std::get<SubEffectTupleIndex::RETURN>(mSubEffects[mActiveSub]);
+}
+
+ndk::ScopedAStatus EffectProxy::setOffloadParam(const effect_offload_param_t* offload) {
+    const auto& itor = std::find_if(mSubEffects.begin(), mSubEffects.end(), [&](const auto& sub) {
+        const auto& desc = std::get<SubEffectTupleIndex::DESCRIPTOR>(sub.second);
+        ALOGI("%s: isOffload %d sub-effect: %s, flags %s", __func__, offload->isOffload,
+              desc.common.id.uuid.toString().c_str(), desc.common.flags.toString().c_str());
+        return offload->isOffload ==
+               (desc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL);
+    });
+    if (itor == mSubEffects.end()) {
+        ALOGE("%s no %soffload sub-effect found", __func__, offload->isOffload ? "" : "non-");
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
+                                                                "noActiveEffctFound");
+    }
+
+    mActiveSub = itor->first;
+    ALOGI("%s: active %soffload sub-effect: %s, flags %s", __func__,
+          offload->isOffload ? "" : "non-", mActiveSub.uuid.toString().c_str(),
+          std::get<SubEffectTupleIndex::DESCRIPTOR>(itor->second).common.flags.toString().c_str());
+    return ndk::ScopedAStatus::ok();
+}
+
+// EffectProxy go over sub-effects and call IEffect interfaces
+ndk::ScopedAStatus EffectProxy::open(const Parameter::Common& common,
+                                     const std::optional<Parameter::Specific>& specific,
+                                     IEffect::OpenEffectReturn* ret __unused) {
+    ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+    ndk::ScopedAStatus status = ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+            EX_ILLEGAL_ARGUMENT, "nullEffectHandle");
+    for (auto& sub : mSubEffects) {
+        auto& effect = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
+        auto& openRet = std::get<SubEffectTupleIndex::RETURN>(sub.second);
+        if (!effect || !(status = effect->open(common, specific, &openRet)).isOk()) {
+            ALOGE("%s: failed to open UUID %s", __func__, sub.first.uuid.toString().c_str());
+            break;
+        }
+    }
+
+    // close all opened effects if failure
+    if (!status.isOk()) {
+        close();
+    }
+
+    return status;
+}
+
+ndk::ScopedAStatus EffectProxy::close() {
+    ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+    return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
+        return effect->close();
+    });
+}
+
+ndk::ScopedAStatus EffectProxy::getDescriptor(Descriptor* desc) {
+    if (!desc) {
+        ALOGE("%s: nuull descriptor pointer", __func__);
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER, "nullptr");
+    }
+
+    auto& activeSubEffect = std::get<SubEffectTupleIndex::HANDLE>(mSubEffects[mActiveSub]);
+    // return initial descriptor if no active sub-effect exist
+    if (!activeSubEffect) {
+        desc->common.id = mIdentity;
+        desc->common.flags = mSubFlags;
+        desc->common.name = "Proxy";
+        desc->common.implementor = "AOSP";
+    } else {
+        *desc = std::get<SubEffectTupleIndex::DESCRIPTOR>(mSubEffects[mActiveSub]);
+        desc->common.id = mIdentity;
+    }
+
+    ALOGI("%s with %s", __func__, desc->toString().c_str());
+    return ndk::ScopedAStatus::ok();
+}
+
+// Handle with active sub-effect first, only send to other sub-effects when success
+ndk::ScopedAStatus EffectProxy::command(CommandId id) {
+    ALOGV("%s: %s, command %s", __func__, mIdentity.type.toString().c_str(),
+          android::internal::ToString(id).c_str());
+    return runWithActiveSubEffectThenOthers(
+            [&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
+                return effect->command(id);
+            });
+}
+
+// Return the active sub-effect state
+ndk::ScopedAStatus EffectProxy::getState(State* state) {
+    return runWithActiveSubEffect(
+            [&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
+                return effect->getState(state);
+            });
+}
+
+// Handle with active sub-effect first, only send to other sub-effects when success
+ndk::ScopedAStatus EffectProxy::setParameter(const Parameter& param) {
+    return runWithActiveSubEffectThenOthers(
+            [&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
+                return effect->setParameter(param);
+            });
+}
+
+// Return the active sub-effect parameter
+ndk::ScopedAStatus EffectProxy::getParameter(const Parameter::Id& id, Parameter* param) {
+    return runWithActiveSubEffect(
+            [&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
+                return effect->getParameter(id, param);
+            });
+}
+
+ndk::ScopedAStatus EffectProxy::runWithActiveSubEffectThenOthers(
+        std::function<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> const& func) {
+    ndk::ScopedAStatus status = runWithActiveSubEffect(func);
+    if (!status.isOk()) {
+        return status;
+    }
+
+    // proceed with others if active sub-effect success
+    for (const auto& sub : mSubEffects) {
+        auto& effect = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
+        if (sub.first != mActiveSub) {
+            if (!effect) {
+                ALOGE("%s null sub-effect interface for %s", __func__,
+                      sub.first.toString().c_str());
+                continue;
+            }
+            func(effect);
+        }
+    }
+    return status;
+}
+
+ndk::ScopedAStatus EffectProxy::runWithActiveSubEffect(
+        std::function<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> const& func) {
+    auto& effect = std::get<SubEffectTupleIndex::HANDLE>(mSubEffects[mActiveSub]);
+    if (!effect) {
+        ALOGE("%s null active sub-effect interface, active %s", __func__,
+              mActiveSub.toString().c_str());
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
+                                                                "activeSubEffectNull");
+    }
+    return func(effect);
+}
+
+ndk::ScopedAStatus EffectProxy::runWithAllSubEffects(
+        std::function<ndk::ScopedAStatus(std::shared_ptr<IEffect>&)> const& func) {
+    ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
+    // proceed with others if active sub-effect success
+    for (auto& sub : mSubEffects) {
+        auto& effect = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
+        if (!effect) {
+            ALOGW("%s null sub-effect interface for %s", __func__, sub.first.toString().c_str());
+            continue;
+        }
+        ndk::ScopedAStatus temp = func(effect);
+        if (!temp.isOk()) {
+            status = ndk::ScopedAStatus::fromStatus(temp.getStatus());
+        }
+    }
+    return status;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectProxy.h b/media/libaudiohal/impl/EffectProxy.h
new file mode 100644
index 0000000..ffb8a19
--- /dev/null
+++ b/media/libaudiohal/impl/EffectProxy.h
@@ -0,0 +1,130 @@
+/*
+ * 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
+
+#include <map>
+#include <memory>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <aidl/android/hardware/audio/effect/BnFactory.h>
+#include <fmq/AidlMessageQueue.h>
+#include <system/audio_effect.h>
+
+namespace android {
+namespace effect {
+
+/**
+ * EffectProxy is the proxy for one or more effect AIDL implementations (sub effect) of same type.
+ * The audio framework use EffectProxy as a composite implementation of all sub effect
+ * implementations.
+ *
+ * At any given time, there is only one active effect which consuming and producing data for each
+ * proxy. All setter commands (except the legacy EFFECT_CMD_OFFLOAD, it will be handled by the audio
+ * framework directly) and parameters will be pass through to all sub effects, the getter commands
+ * and parameters will only passthrough to the active sub-effect.
+ *
+ */
+class EffectProxy final : public ::aidl::android::hardware::audio::effect::BnEffect {
+  public:
+    EffectProxy(const ::aidl::android::hardware::audio::effect::Descriptor::Identity& id,
+                const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory>& factory);
+
+    /**
+     * Add a sub effect into the proxy, the descriptor of candidate sub-effect need to have same
+     * proxy UUID as mUuid.
+     */
+    ndk::ScopedAStatus addSubEffect(
+            const ::aidl::android::hardware::audio::effect::Descriptor& sub);
+
+    /**
+     * Create all sub-effects via AIDL IFactory, always call create() after all sub-effects added
+     * successfully with addSubEffect.
+     */
+    ndk::ScopedAStatus create();
+
+    /**
+     * Destroy all sub-effects via AIDL IFactory, always call create() after all sub-effects added
+     * successfully with addSubEffect.
+     */
+    ndk::ScopedAStatus destroy();
+
+    /**
+     * Handle offload parameter setting from framework.
+     */
+    ndk::ScopedAStatus setOffloadParam(const effect_offload_param_t* offload);
+
+    /**
+     * Get the const reference of the active sub-effect return parameters.
+     * Always use this interface to get the effect open return parameters (FMQs) after a success
+     * setOffloadParam() call.
+     */
+    const IEffect::OpenEffectReturn* getEffectReturnParam();
+
+    // IEffect interfaces override
+    ndk::ScopedAStatus open(
+            const ::aidl::android::hardware::audio::effect::Parameter::Common& common,
+            const std::optional<::aidl::android::hardware::audio::effect::Parameter::Specific>&
+                    specific,
+            ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn* ret) override;
+    ndk::ScopedAStatus close() override;
+    ndk::ScopedAStatus getDescriptor(
+            ::aidl::android::hardware::audio::effect::Descriptor* desc) override;
+    ndk::ScopedAStatus command(::aidl::android::hardware::audio::effect::CommandId id) override;
+    ndk::ScopedAStatus getState(::aidl::android::hardware::audio::effect::State* state) override;
+    ndk::ScopedAStatus setParameter(
+            const ::aidl::android::hardware::audio::effect::Parameter& param) override;
+    ndk::ScopedAStatus getParameter(
+            const ::aidl::android::hardware::audio::effect::Parameter::Id& id,
+            ::aidl::android::hardware::audio::effect::Parameter* param) override;
+
+  private:
+    // Proxy identity, copy from one sub-effect, and update the implementation UUID to proxy UUID
+    const ::aidl::android::hardware::audio::effect::Descriptor::Identity mIdentity;
+    const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory> mFactory;
+
+    // A map of sub effects descriptor to the IEffect handle and return FMQ
+    enum SubEffectTupleIndex { HANDLE, DESCRIPTOR, RETURN };
+    using EffectProxySub =
+            std::tuple<std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>,
+                       ::aidl::android::hardware::audio::effect::Descriptor,
+                       ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn>;
+    std::map<const ::aidl::android::hardware::audio::effect::Descriptor::Identity, EffectProxySub>
+            mSubEffects;
+
+    // Descriptor of the only active effect in the mSubEffects map
+    ::aidl::android::hardware::audio::effect::Descriptor::Identity mActiveSub;
+
+    // keep the flag of sub-effects
+    ::aidl::android::hardware::audio::effect::Flags mSubFlags;
+
+    ndk::ScopedAStatus runWithActiveSubEffectThenOthers(
+            std::function<ndk::ScopedAStatus(
+                    const std::shared_ptr<
+                            ::aidl::android::hardware::audio::effect::IEffect>&)> const& func);
+
+    ndk::ScopedAStatus runWithActiveSubEffect(
+            std::function<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> const& func);
+
+    ndk::ScopedAStatus runWithAllSubEffects(
+            std::function<ndk::ScopedAStatus(std::shared_ptr<IEffect>&)> const& func);
+
+    // close and release all sub-effects
+    ~EffectProxy();
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
index f289f24..bc05aa0 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -15,7 +15,9 @@
  */
 
 #include <algorithm>
+#include <cstddef>
 #include <cstdint>
+#include <iterator>
 #include <memory>
 #define LOG_TAG "EffectsFactoryHalAidl"
 //#define LOG_NDEBUG 0
@@ -29,10 +31,12 @@
 
 #include "EffectBufferHalAidl.h"
 #include "EffectHalAidl.h"
+#include "EffectProxy.h"
 #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;
@@ -42,12 +46,56 @@
 
 EffectsFactoryHalAidl::EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFactory)
     : mFactory(effectsFactory),
-      mHalVersion(AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, [this]() {
-          int32_t majorVersion = 0;
-          return (mFactory && mFactory->getInterfaceVersion(&majorVersion).isOk()) ? majorVersion
-                                                                                   : 0;
-      }())) {
-    ALOG_ASSERT(effectsFactory != nullptr, "Provided IEffectsFactory service is NULL");
+      mHalVersion(AudioHalVersionInfo(
+              AudioHalVersionInfo::Type::AIDL,
+              [this]() {
+                  int32_t majorVersion = 0;
+                  return (mFactory && mFactory->getInterfaceVersion(&majorVersion).isOk())
+                                 ? majorVersion
+                                 : 0;
+              }())),
+      mHalDescList([this]() {
+          std::vector<Descriptor> list;
+          if (mFactory) {
+              mFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &list).isOk();
+          }
+          return list;
+      }()),
+      mUuidProxyMap([this]() {
+          std::map<AudioUuid, std::shared_ptr<EffectProxy>> proxyMap;
+          for (const auto& desc : mHalDescList) {
+              // create EffectProxy
+              if (desc.common.id.proxy.has_value()) {
+                  const auto& uuid = desc.common.id.proxy.value();
+                  if (0 == proxyMap.count(uuid)) {
+                      proxyMap.insert({uuid, ndk::SharedRefBase::make<EffectProxy>(desc.common.id,
+                                                                                   mFactory)});
+                  }
+                  proxyMap[uuid]->addSubEffect(desc);
+                  ALOGI("%s addSubEffect %s", __func__, desc.common.toString().c_str());
+              }
+          }
+          return proxyMap;
+      }()),
+      mProxyDescList([this]() {
+          std::vector<Descriptor> list;
+          for (const auto& proxy : mUuidProxyMap) {
+              if (Descriptor desc; proxy.second && proxy.second->getDescriptor(&desc).isOk()) {
+                  list.emplace_back(std::move(desc));
+              }
+          }
+          return list;
+      }()),
+      mNonProxyDescList([this]() {
+          std::vector<Descriptor> list;
+          std::copy_if(mHalDescList.begin(), mHalDescList.end(), std::back_inserter(list),
+                       [](const Descriptor& desc) { return !desc.common.id.proxy.has_value(); });
+          return list;
+      }()),
+      mEffectCount(mNonProxyDescList.size() + mProxyDescList.size()) {
+    ALOG_ASSERT(mFactory != nullptr, "Provided IEffectsFactory service is NULL");
+    ALOGI("%s with %zu nonProxyEffects and %zu proxyEffects", __func__, mNonProxyDescList.size(),
+          mProxyDescList.size());
 }
 
 status_t EffectsFactoryHalAidl::queryNumberEffects(uint32_t *pNumEffects) {
@@ -55,11 +103,7 @@
         return BAD_VALUE;
     }
 
-    {
-        std::lock_guard lg(mLock);
-        RETURN_STATUS_IF_ERROR(queryEffectList_l());
-        *pNumEffects = mDescList->size();
-    }
+    *pNumEffects = mEffectCount;
     ALOGI("%s %d", __func__, *pNumEffects);
     return OK;
 }
@@ -69,42 +113,43 @@
         return BAD_VALUE;
     }
 
-    std::lock_guard lg(mLock);
-    RETURN_STATUS_IF_ERROR(queryEffectList_l());
-
-    auto listSize = mDescList->size();
-    if (index >= listSize) {
-        ALOGE("%s index %d exceed size DescList %zd", __func__, index, listSize);
+    if (index >= mEffectCount) {
+        ALOGE("%s index %d exceed max number %zu", __func__, index, mEffectCount);
         return INVALID_OPERATION;
     }
 
-    *pDescriptor = VALUE_OR_RETURN_STATUS(
-            ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(mDescList->at(index)));
+    if (index >= mNonProxyDescList.size()) {
+        *pDescriptor =
+                VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_Descriptor_effect_descriptor(
+                        mProxyDescList.at(index - mNonProxyDescList.size())));
+    } else {
+        *pDescriptor =
+                VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_Descriptor_effect_descriptor(
+                        mNonProxyDescList.at(index)));
+    }
     return OK;
 }
 
 status_t EffectsFactoryHalAidl::getDescriptor(const effect_uuid_t* halUuid,
                                               effect_descriptor_t* pDescriptor) {
-    if (halUuid == nullptr || pDescriptor == nullptr) {
+    if (halUuid == nullptr) {
         return BAD_VALUE;
     }
 
-    AudioUuid uuid = VALUE_OR_RETURN_STATUS(
-            ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halUuid));
-    std::lock_guard lg(mLock);
-    return getHalDescriptorWithImplUuid_l(uuid, pDescriptor);
+    AudioUuid uuid =
+            VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halUuid));
+    return getHalDescriptorWithImplUuid(uuid, pDescriptor);
 }
 
 status_t EffectsFactoryHalAidl::getDescriptors(const effect_uuid_t* halType,
                                                std::vector<effect_descriptor_t>* descriptors) {
-    if (halType == nullptr || descriptors == nullptr) {
+    if (halType == nullptr) {
         return BAD_VALUE;
     }
 
-    AudioUuid type = VALUE_OR_RETURN_STATUS(
-            ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halType));
-    std::lock_guard lg(mLock);
-    return getHalDescriptorWithTypeUuid_l(type, descriptors);
+    AudioUuid type =
+            VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halType));
+    return getHalDescriptorWithTypeUuid(type, descriptors);
 }
 
 status_t EffectsFactoryHalAidl::createEffect(const effect_uuid_t* uuid, int32_t sessionId,
@@ -116,18 +161,25 @@
     if (sessionId == AUDIO_SESSION_DEVICE && ioId == AUDIO_IO_HANDLE_NONE) {
         return INVALID_OPERATION;
     }
-
     ALOGI("%s session %d ioId %d", __func__, sessionId, ioId);
 
-    AudioUuid aidlUuid = VALUE_OR_RETURN_STATUS(
-            ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*uuid));
+    AudioUuid aidlUuid =
+            VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*uuid));
     std::shared_ptr<IEffect> aidlEffect;
-    Descriptor desc;
-    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mFactory->createEffect(aidlUuid, &aidlEffect)));
+    // Use EffectProxy interface instead of IFactory to create
+    const bool isProxy = isProxyEffect(aidlUuid);
+    if (isProxy) {
+        aidlEffect = mUuidProxyMap.at(aidlUuid);
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mUuidProxyMap.at(aidlUuid)->create()));
+    } else {
+        RETURN_STATUS_IF_ERROR(
+                statusTFromBinderStatus(mFactory->createEffect(aidlUuid, &aidlEffect)));
+    }
     if (aidlEffect == nullptr) {
-        ALOGE("%s IFactory::createFactory failed UUID %s", __func__, aidlUuid.toString().c_str());
+        ALOGE("%s failed to create effect with UUID: %s", __func__, aidlUuid.toString().c_str());
         return NAME_NOT_FOUND;
     }
+    Descriptor desc;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(aidlEffect->getDescriptor(&desc)));
 
     uint64_t effectId;
@@ -136,13 +188,23 @@
         effectId = ++mEffectIdCounter;
     }
 
-    *effect = sp<EffectHalAidl>::make(mFactory, aidlEffect, effectId, sessionId, ioId, desc);
+    *effect =
+            sp<EffectHalAidl>::make(mFactory, aidlEffect, effectId, sessionId, ioId, desc, isProxy);
     return OK;
 }
 
 status_t EffectsFactoryHalAidl::dumpEffects(int fd) {
-    // TODO: add proxy dump here because AIDL service EffectFactory doesn't have proxy handle
-    return mFactory->dump(fd, nullptr, 0);
+    status_t ret = OK;
+    // record the error ret and continue dump as many effects as possible
+    for (const auto& proxy : mUuidProxyMap) {
+        if (proxy.second) {
+            if (status_t temp = proxy.second->dump(fd, nullptr, 0); temp != OK) {
+                ret = temp;
+            }
+        }
+    }
+    RETURN_STATUS_IF_ERROR(mFactory->dump(fd, nullptr, 0));
+    return ret;
 }
 
 status_t EffectsFactoryHalAidl::allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) {
@@ -160,56 +222,42 @@
     return mHalVersion;
 }
 
-status_t EffectsFactoryHalAidl::queryEffectList_l() {
-    if (!mDescList) {
-        std::vector<Descriptor> list;
-        auto status = mFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &list);
-        if (!status.isOk()) {
-            ALOGE("%s IFactory::queryEffects failed %s", __func__, status.getDescription().c_str());
-            return status.getStatus();
-        }
-
-        mDescList = std::make_unique<std::vector<Descriptor>>(list);
-    }
-    return OK;
-}
-
-status_t EffectsFactoryHalAidl::getHalDescriptorWithImplUuid_l(const AudioUuid& uuid,
-                                                               effect_descriptor_t* pDescriptor) {
+status_t EffectsFactoryHalAidl::getHalDescriptorWithImplUuid(const AudioUuid& uuid,
+                                                             effect_descriptor_t* pDescriptor) {
     if (pDescriptor == nullptr) {
         return BAD_VALUE;
     }
-    if (!mDescList) {
-        RETURN_STATUS_IF_ERROR(queryEffectList_l());
-    }
 
-    auto matchIt = std::find_if(mDescList->begin(), mDescList->end(),
-                                 [&](const auto& desc) { return desc.common.id.uuid == uuid; });
-    if (matchIt == mDescList->end()) {
-        ALOGE("%s UUID %s not found", __func__, uuid.toString().c_str());
+    const auto& list = isProxyEffect(uuid) ? mProxyDescList : mNonProxyDescList;
+    auto matchIt = std::find_if(list.begin(), list.end(),
+                                [&](const auto& desc) { return desc.common.id.uuid == uuid; });
+    if (matchIt == list.end()) {
+        ALOGE("%s UUID not found in HAL and proxy list %s", __func__, uuid.toString().c_str());
         return BAD_VALUE;
     }
+    ALOGI("%s UUID impl found %s", __func__, uuid.toString().c_str());
 
     *pDescriptor = VALUE_OR_RETURN_STATUS(
             ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(*matchIt));
     return OK;
 }
 
-status_t EffectsFactoryHalAidl::getHalDescriptorWithTypeUuid_l(
+status_t EffectsFactoryHalAidl::getHalDescriptorWithTypeUuid(
         const AudioUuid& type, std::vector<effect_descriptor_t>* descriptors) {
     if (descriptors == nullptr) {
         return BAD_VALUE;
     }
-    if (!mDescList) {
-        RETURN_STATUS_IF_ERROR(queryEffectList_l());
-    }
+
     std::vector<Descriptor> result;
-    std::copy_if(mDescList->begin(), mDescList->end(), std::back_inserter(result),
+    std::copy_if(mNonProxyDescList.begin(), mNonProxyDescList.end(), std::back_inserter(result),
                  [&](auto& desc) { return desc.common.id.type == type; });
-    if (result.size() == 0) {
-        ALOGE("%s type UUID %s not found", __func__, type.toString().c_str());
+    std::copy_if(mProxyDescList.begin(), mProxyDescList.end(), std::back_inserter(result),
+                 [&](auto& desc) { return desc.common.id.type == type; });
+    if (result.empty()) {
+        ALOGW("%s UUID type not found in HAL and proxy list %s", __func__, type.toString().c_str());
         return BAD_VALUE;
     }
+    ALOGI("%s UUID type found %zu \n %s", __func__, result.size(), type.toString().c_str());
 
     *descriptors = VALUE_OR_RETURN_STATUS(
             aidl::android::convertContainer<std::vector<effect_descriptor_t>>(
@@ -217,6 +265,10 @@
     return OK;
 }
 
+bool EffectsFactoryHalAidl::isProxyEffect(const AudioUuid& uuid) const {
+    return 0 != mUuidProxyMap.count(uuid);
+}
+
 } // 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 9c3643b..debfacf 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -25,6 +25,8 @@
 #include <media/audiohal/EffectsFactoryHalInterface.h>
 #include <system/thread_defs.h>
 
+#include "EffectProxy.h"
+
 namespace android {
 namespace effect {
 
@@ -60,24 +62,35 @@
 
     detail::AudioHalVersionInfo getHalVersion() const override;
 
-    // for TIME_CHECK
-    const std::string getClassName() const { return "EffectHalAidl"; }
-
   private:
-    std::mutex mLock;
     const std::shared_ptr<IFactory> mFactory;
-    uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0; // Align with HIDL (0 is INVALID_ID)
-    std::unique_ptr<std::vector<Descriptor>> mDescList GUARDED_BY(mLock) = nullptr;
     const detail::AudioHalVersionInfo mHalVersion;
+    // Full list of HAL effect descriptors
+    const std::vector<Descriptor> mHalDescList;
+    // Map of proxy UUID (key) to the proxy object
+    const std::map<::aidl::android::media::audio::common::AudioUuid /* proxy impl UUID */,
+                   std::shared_ptr<EffectProxy>>
+            mUuidProxyMap;
+    // List of effect proxy, initialize after mUuidProxyMap because it need to have all sub-effects
+    const std::vector<Descriptor> mProxyDescList;
+    // List of non-proxy effects
+    const std::vector<Descriptor> mNonProxyDescList;
+    // total number of effects including proxy effects
+    const size_t mEffectCount;
+
+    std::mutex mLock;
+    uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0;  // Align with HIDL (0 is INVALID_ID)
 
     virtual ~EffectsFactoryHalAidl() = default;
-    status_t queryEffectList_l() REQUIRES(mLock);
-    status_t getHalDescriptorWithImplUuid_l(
+    status_t getHalDescriptorWithImplUuid(
             const aidl::android::media::audio::common::AudioUuid& uuid,
-            effect_descriptor_t* pDescriptor) REQUIRES(mLock);
-    status_t getHalDescriptorWithTypeUuid_l(
+            effect_descriptor_t* pDescriptor);
+
+    status_t getHalDescriptorWithTypeUuid(
             const aidl::android::media::audio::common::AudioUuid& type,
-            std::vector<effect_descriptor_t>* descriptors) REQUIRES(mLock);
+            std::vector<effect_descriptor_t>* descriptors);
+
+    bool isProxyEffect(const aidl::android::media::audio::common::AudioUuid& uuid) const;
 };
 
 } // namespace effect
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index cbc1578..6c43591 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -22,6 +22,7 @@
 
 #include <audio_utils/clock.h>
 #include <media/AidlConversion.h>
+#include <media/AidlConversionCore.h>
 #include <media/AidlConversionCppNdk.h>
 #include <media/AidlConversionNdk.h>
 #include <media/AidlConversionUtil.h>
@@ -40,6 +41,7 @@
 using ::aidl::android::hardware::audio::core::IStreamIn;
 using ::aidl::android::hardware::audio::core::IStreamOut;
 using ::aidl::android::hardware::audio::core::StreamDescriptor;
+using ::aidl::android::hardware::audio::core::MmapBufferDescriptor;
 using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;
 
 namespace android {
@@ -166,9 +168,8 @@
     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
     TIME_CHECK();
     values->clear();
-    if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    // AIDL HAL doesn't support getParameters API.
+    return INVALID_OPERATION;
 }
 
 status_t StreamHalAidl::getFrameSize(size_t *size) {
@@ -255,16 +256,23 @@
     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    const auto state = getState();
+    StreamDescriptor::Reply reply;
+    if (state == StreamDescriptor::State::STANDBY) {
+        if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply, true);
+                status != OK) {
+            return status;
+        }
+        return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), &reply, true);
+    }
+
+    return INVALID_OPERATION;
 }
 
 status_t StreamHalAidl::stop() {
     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 standby();
 }
 
 status_t StreamHalAidl::getLatency(uint32_t *latency) {
@@ -290,6 +298,20 @@
     return OK;
 }
 
+status_t StreamHalAidl::getHardwarePosition(int64_t *frames, int64_t *timestamp) {
+    ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+    if (!mStream) return NO_INIT;
+    StreamDescriptor::Reply reply;
+    // TODO: switch to updateCountersIfNeeded once we sort out mWorkerTid initialization
+    if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), &reply, true);
+            status != OK) {
+        return status;
+    }
+    *frames = reply.hardware.frames;
+    *timestamp = reply.hardware.timeNs;
+    return OK;
+}
+
 status_t StreamHalAidl::getXruns(int32_t *frames) {
     ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
     if (!mStream) return NO_INIT;
@@ -419,19 +441,35 @@
 }
 
 status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
-                                  struct audio_mmap_buffer_info *info __unused) {
+                                         struct audio_mmap_buffer_info *info) {
     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
+    if (!mContext.isMmapped()) {
+        return BAD_VALUE;
+    }
+    const MmapBufferDescriptor& bufferDescriptor = mContext.getMmapBufferDescriptor();
+    info->shared_memory_fd = bufferDescriptor.sharedMemory.fd.get();
+    info->buffer_size_frames = mContext.getBufferSizeFrames();
+    info->burst_size_frames = bufferDescriptor.burstSizeFrames;
+    info->flags = static_cast<audio_mmap_buffer_flag>(bufferDescriptor.flags);
+
     return OK;
 }
 
-status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position __unused) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
+    if (!mContext.isMmapped()) {
+        return BAD_VALUE;
+    }
+    int64_t aidlPosition = 0, aidlTimestamp = 0;
+    if (status_t status = getHardwarePosition(&aidlPosition, &aidlTimestamp); status != OK) {
+        return status;
+    }
+
+    position->time_nanoseconds = aidlTimestamp;
+    position->position_frames = static_cast<int32_t>(aidlPosition);
     return OK;
 }
 
@@ -440,19 +478,6 @@
     return OK;
 }
 
-status_t StreamHalAidl::getHalPid(pid_t *pid __unused) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
-    TIME_CHECK();
-    if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
-}
-
-bool StreamHalAidl::requestHalThreadPriority(pid_t threadPid __unused, pid_t threadId __unused) {
-    // Obsolete, must be done by the HAL module.
-    return true;
-}
-
 status_t StreamHalAidl::legacyCreateAudioPatch(const struct audio_port_config& port __unused,
                                                std::optional<audio_source_t> source __unused,
                                                audio_devices_t type __unused) {
@@ -574,11 +599,10 @@
     return statusTFromBinderStatus(mStream->setHwVolume({left, right}));
 }
 
-status_t StreamOutHalAidl::selectPresentation(int presentationId __unused, int programId __unused) {
+status_t StreamOutHalAidl::selectPresentation(int presentationId, int programId) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    return statusTFromBinderStatus(mStream->selectPresentation(presentationId, programId));
 }
 
 status_t StreamOutHalAidl::write(const void *buffer, size_t bytes, size_t *written) {
@@ -684,48 +708,61 @@
     return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
 }
 
-status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
+status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
+    if (mode == nullptr) {
+        return BAD_VALUE;
+    }
+    ::aidl::android::media::audio::common::AudioDualMonoMode aidlMode;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getDualMonoMode(&aidlMode)));
+    *mode = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(aidlMode));
     return OK;
 }
 
-status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
+status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
+    ::aidl::android::media::audio::common::AudioDualMonoMode aidlMode = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
+    return statusTFromBinderStatus(mStream->setDualMonoMode(aidlMode));
+}
+
+status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    if (leveldB == nullptr) {
+        return BAD_VALUE;
+    }
+    return statusTFromBinderStatus(mStream->getAudioDescriptionMixLevel(leveldB));
+}
+
+status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    return statusTFromBinderStatus(mStream->setAudioDescriptionMixLevel(leveldB));
+}
+
+status_t StreamOutHalAidl::getPlaybackRateParameters(audio_playback_rate_t* playbackRate) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    if (playbackRate == nullptr) {
+        return BAD_VALUE;
+    }
+    ::aidl::android::media::audio::common::AudioPlaybackRate aidlRate;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getPlaybackRateParameters(&aidlRate)));
+    *playbackRate = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(aidlRate));
     return OK;
 }
 
-status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
+status_t StreamOutHalAidl::setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
-}
-
-status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB __unused) {
-    TIME_CHECK();
-    if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
-}
-
-status_t StreamOutHalAidl::getPlaybackRateParameters(
-        audio_playback_rate_t* playbackRate __unused) {
-    TIME_CHECK();
-    if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return BAD_VALUE;
-}
-
-status_t StreamOutHalAidl::setPlaybackRateParameters(
-        const audio_playback_rate_t& playbackRate __unused) {
-    TIME_CHECK();
-    if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return BAD_VALUE;
+    ::aidl::android::media::audio::common::AudioPlaybackRate aidlRate = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(playbackRate));
+    return statusTFromBinderStatus(mStream->setPlaybackRateParameters(aidlRate));
 }
 
 status_t StreamOutHalAidl::setEventCallback(
@@ -738,18 +775,27 @@
     return OK;
 }
 
-status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode __unused) {
+status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    ::aidl::android::media::audio::common::AudioLatencyMode aidlMode = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode));
+    return statusTFromBinderStatus(mStream->setLatencyMode(aidlMode));
 };
 
-status_t StreamOutHalAidl::getRecommendedLatencyModes(
-        std::vector<audio_latency_mode_t> *modes __unused) {
+status_t StreamOutHalAidl::getRecommendedLatencyModes(std::vector<audio_latency_mode_t> *modes) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
+    if (modes == nullptr) {
+        return BAD_VALUE;
+    }
+    std::vector<::aidl::android::media::audio::common::AudioLatencyMode> aidlModes;
+    RETURN_STATUS_IF_ERROR(
+            statusTFromBinderStatus(mStream->getRecommendedLatencyModes(&aidlModes)));
+    *modes = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
+                    aidlModes,
+                    ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
     return OK;
 };
 
@@ -845,11 +891,10 @@
                 std::move(context), getStreamCommon(stream)),
           mStream(stream), mMicInfoProvider(micInfoProvider) {}
 
-status_t StreamInHalAidl::setGain(float gain __unused) {
+status_t StreamInHalAidl::setGain(float gain) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    return statusTFromBinderStatus(mStream->setHwGain({gain}));
 }
 
 status_t StreamInHalAidl::read(void *buffer, size_t bytes, size_t *read) {
@@ -922,19 +967,20 @@
     return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
 }
 
-status_t StreamInHalAidl::setPreferredMicrophoneDirection(
-            audio_microphone_direction_t direction __unused) {
+status_t StreamInHalAidl::setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    ::aidl::android::hardware::audio::core::IStreamIn::MicrophoneDirection aidlDirection =
+              VALUE_OR_RETURN_STATUS(
+                      ::aidl::android::legacy2aidl_audio_microphone_direction_t_MicrophoneDirection(
+                              direction));
+    return statusTFromBinderStatus(mStream->setMicrophoneDirection(aidlDirection));
 }
 
-status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
+status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    return statusTFromBinderStatus(mStream->setMicrophoneFieldDimension(zoom));
 }
 
 } // namespace android
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 157e8bb..75a1dd9 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -25,6 +25,7 @@
 #include <aidl/android/hardware/audio/core/BpStreamCommon.h>
 #include <aidl/android/hardware/audio/core/BpStreamIn.h>
 #include <aidl/android/hardware/audio/core/BpStreamOut.h>
+#include <aidl/android/hardware/audio/core/MmapBufferDescriptor.h>
 #include <fmq/AidlMessageQueue.h>
 #include <media/audiohal/EffectHalInterface.h>
 #include <media/audiohal/StreamHalInterface.h>
@@ -34,6 +35,7 @@
 #include "StreamPowerLog.h"
 
 using ::aidl::android::hardware::audio::common::AudioOffloadMetadata;
+using ::aidl::android::hardware::audio::core::MmapBufferDescriptor;
 
 namespace android {
 
@@ -47,21 +49,25 @@
             ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;
 
     explicit StreamContextAidl(
-            const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
+            ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
             bool isAsynchronous)
         : mFrameSizeBytes(descriptor.frameSizeBytes),
           mCommandMQ(new CommandMQ(descriptor.command)),
           mReplyMQ(new ReplyMQ(descriptor.reply)),
           mBufferSizeFrames(descriptor.bufferSizeFrames),
           mDataMQ(maybeCreateDataMQ(descriptor)),
-          mIsAsynchronous(isAsynchronous) {}
+          mIsAsynchronous(isAsynchronous),
+          mIsMmapped(isMmapped(descriptor)),
+          mMmapBufferDescriptor(maybeGetMmapBuffer(descriptor)) {}
     StreamContextAidl(StreamContextAidl&& other) :
             mFrameSizeBytes(other.mFrameSizeBytes),
             mCommandMQ(std::move(other.mCommandMQ)),
             mReplyMQ(std::move(other.mReplyMQ)),
             mBufferSizeFrames(other.mBufferSizeFrames),
             mDataMQ(std::move(other.mDataMQ)),
-            mIsAsynchronous(other.mIsAsynchronous) {}
+            mIsAsynchronous(other.mIsAsynchronous),
+            mIsMmapped(other.mIsMmapped),
+            mMmapBufferDescriptor(std::move(other.mMmapBufferDescriptor)) {}
     StreamContextAidl& operator=(StreamContextAidl&& other) {
         mFrameSizeBytes = other.mFrameSizeBytes;
         mCommandMQ = std::move(other.mCommandMQ);
@@ -69,16 +75,19 @@
         mBufferSizeFrames = other.mBufferSizeFrames;
         mDataMQ = std::move(other.mDataMQ);
         mIsAsynchronous = other.mIsAsynchronous;
+        mIsMmapped = other.mIsMmapped;
+        mMmapBufferDescriptor = std::move(other.mMmapBufferDescriptor);
         return *this;
     }
     bool isValid() const {
         return mFrameSizeBytes != 0 &&
                 mCommandMQ != nullptr && mCommandMQ->isValid() &&
                 mReplyMQ != nullptr && mReplyMQ->isValid() &&
-                (mDataMQ != nullptr || (
+                (mDataMQ == nullptr || (
                         mDataMQ->isValid() &&
                         mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() >=
-                        mFrameSizeBytes * mBufferSizeFrames));
+                        mFrameSizeBytes * mBufferSizeFrames)) &&
+                (!mIsMmapped || mMmapBufferDescriptor.sharedMemory.fd.get() >= 0);
     }
     size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; }
     size_t getBufferSizeFrames() const { return mBufferSizeFrames; }
@@ -87,6 +96,8 @@
     size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
     ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
     bool isAsynchronous() const { return mIsAsynchronous; }
+    bool isMmapped() const { return mIsMmapped; }
+    const MmapBufferDescriptor& getMmapBufferDescriptor() const { return mMmapBufferDescriptor; }
 
   private:
     static std::unique_ptr<DataMQ> maybeCreateDataMQ(
@@ -97,6 +108,19 @@
         }
         return nullptr;
     }
+    static bool isMmapped(
+            const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
+        using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag;
+        return descriptor.audio.getTag() == Tag::mmap;
+    }
+    static MmapBufferDescriptor maybeGetMmapBuffer(
+            ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
+        using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag;
+        if (descriptor.audio.getTag() == Tag::mmap) {
+            return std::move(descriptor.audio.get<Tag::mmap>());
+        }
+        return {};
+    }
 
     size_t mFrameSizeBytes;
     std::unique_ptr<CommandMQ> mCommandMQ;
@@ -104,6 +128,8 @@
     size_t mBufferSizeFrames;
     std::unique_ptr<DataMQ> mDataMQ;
     bool mIsAsynchronous;
+    bool mIsMmapped;
+    MmapBufferDescriptor mMmapBufferDescriptor;
 };
 
 class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelperAidl {
@@ -173,14 +199,12 @@
 
     ~StreamHalAidl() override;
 
-    status_t getHalPid(pid_t *pid);
-
-    bool requestHalThreadPriority(pid_t threadPid, pid_t threadId);
-
     status_t getLatency(uint32_t *latency);
 
     status_t getObservablePosition(int64_t *frames, int64_t *timestamp);
 
+    status_t getHardwarePosition(int64_t *frames, int64_t *timestamp);
+
     status_t getXruns(int32_t *frames);
 
     status_t transfer(void *buffer, size_t bytes, size_t *transferred);
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index c685345..2523ba6 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -128,13 +128,14 @@
             std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) = 0;
     virtual int32_t getAAudioMixerBurstCount() = 0;
     virtual int32_t getAAudioHardwareBurstMinUsec() = 0;
+
     virtual int32_t supportsBluetoothVariableLatency(bool* supports) = 0;
 
     // Update the connection status of an external device.
-    virtual status_t setConnectedState(const struct audio_port_v7* port, bool connected) {
-        ALOGE("%s override me port %p connected %d", __func__, port, connected);
-        return OK;
-    }
+    virtual status_t setConnectedState(const struct audio_port_v7* port, bool connected) = 0;
+
+    // Enable simulation of external devices connection at the HAL level.
+    virtual status_t setSimulateDeviceConnections(bool enabled) = 0;
 
     virtual error::Result<audio_hw_sync_t> getHwAvSync() = 0;
 
diff --git a/media/libaudiohal/tests/Android.bp b/media/libaudiohal/tests/Android.bp
index 2f78dd0..8210f7d 100644
--- a/media/libaudiohal/tests/Android.bp
+++ b/media/libaudiohal/tests/Android.bp
@@ -20,18 +20,12 @@
     default_applicable_licenses: ["frameworks_av_license"],
 }
 
-cc_test {
-    name: "EffectsFactoryHalInterfaceTest",
+cc_defaults {
+    name: "AudioHalTestDefaults",
     test_suites: ["device-tests"],
-
-    srcs: [
-        "EffectsFactoryHalInterface_test.cpp",
-    ],
-
     defaults: [
         "latest_android_media_audio_common_types_ndk_shared",
     ],
-
     cflags: [
         "-Wall",
         "-Wextra",
@@ -48,8 +42,31 @@
         "libutils",
         "libvibrator",
     ],
+}
 
-    header_libs: [
-        "libaudiohal_headers",
+cc_test {
+    name: "EffectsFactoryHalInterfaceTest",
+    srcs: ["EffectsFactoryHalInterface_test.cpp"],
+    defaults: ["AudioHalTestDefaults"],
+    header_libs: ["libaudiohal_headers"],
+}
+
+cc_test {
+    name: "EffectProxyTest",
+    srcs: [
+        "EffectProxy_test.cpp",
+        ":audio_effectproxy_src_files",
     ],
+    defaults: [
+        "AudioHalTestDefaults",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "libaudiohal_default",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    shared_libs: [
+        "android.hardware.common.fmq-V1-ndk",
+        "libbinder_ndk",
+        "libfmq",
+    ],
+    header_libs: ["libaudiohalimpl_headers"],
 }
diff --git a/media/libaudiohal/tests/EffectProxy_test.cpp b/media/libaudiohal/tests/EffectProxy_test.cpp
new file mode 100644
index 0000000..92e3dce
--- /dev/null
+++ b/media/libaudiohal/tests/EffectProxy_test.cpp
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <utility>
+#define LOG_TAG "EffectProxyTest"
+
+#include <aidl/android/media/audio/common/AudioUuid.h>
+#include <aidl/Vintf.h>
+#include <android/binder_manager.h>
+#include <gtest/gtest.h>
+#include <utils/RefBase.h>
+
+#include "EffectProxy.h"
+
+/**
+ * This test suite is depending on audio effect AIDL service.
+ */
+namespace android {
+
+using ::aidl::android::hardware::audio::effect::CommandId;
+using ::aidl::android::hardware::audio::effect::Descriptor;
+using ::aidl::android::hardware::audio::effect::Flags;
+using ::aidl::android::hardware::audio::effect::IEffect;
+using ::aidl::android::hardware::audio::effect::IFactory;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::State;
+using ::aidl::android::media::audio::common::AudioChannelLayout;
+using ::aidl::android::media::audio::common::AudioFormatDescription;
+using ::aidl::android::media::audio::common::AudioFormatType;
+using ::aidl::android::media::audio::common::AudioUuid;
+using ::aidl::android::media::audio::common::PcmType;
+using ::android::effect::EffectProxy;
+
+class EffectProxyTest : public testing::Test {
+  public:
+    void SetUp() override {
+        auto serviceName = android::getAidlHalInstanceNames(IFactory::descriptor);
+        // only unit test with the first one in case more than one EffectFactory service exist
+        ASSERT_NE(0ul, serviceName.size());
+        mFactory = IFactory::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(serviceName[0].c_str())));
+        ASSERT_NE(nullptr, mFactory);
+        mFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &mDescs);
+        for (const auto& desc : mDescs) {
+            if (desc.common.id.proxy.has_value()) {
+                mProxyDescs.insert({desc.common.id, desc});
+            }
+        }
+    }
+
+    void TearDown() override {}
+
+    const AudioFormatDescription kDefaultFormatDescription = {
+            .type = AudioFormatType::PCM, .pcm = PcmType::FLOAT_32_BIT, .encoding = ""};
+
+    Parameter::Common createParamCommon(
+            int session = 0, int ioHandle = -1, int iSampleRate = 48000, int oSampleRate = 48000,
+            long iFrameCount = 0x100, long oFrameCount = 0x100,
+            AudioChannelLayout inputChannelLayout =
+                    AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                            AudioChannelLayout::LAYOUT_STEREO),
+            AudioChannelLayout outputChannelLayout =
+                    AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                            AudioChannelLayout::LAYOUT_STEREO)) {
+        Parameter::Common common;
+        common.session = session;
+        common.ioHandle = ioHandle;
+
+        auto& input = common.input;
+        auto& output = common.output;
+        input.base.sampleRate = iSampleRate;
+        input.base.channelMask = inputChannelLayout;
+        input.base.format = kDefaultFormatDescription;
+        input.frameCount = iFrameCount;
+        output.base.sampleRate = oSampleRate;
+        output.base.channelMask = outputChannelLayout;
+        output.base.format = kDefaultFormatDescription;
+        output.frameCount = oFrameCount;
+        return common;
+    }
+
+    static bool isFlagSet(const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+                          Flags::HardwareAccelerator flag) {
+        return desc.common.flags.hwAcceleratorMode == flag;
+    }
+
+    enum TupleIndex { HANDLE, DESCRIPTOR };
+    using EffectProxyTuple = std::tuple<std::shared_ptr<EffectProxy>, std::vector<Descriptor>>;
+
+    std::map<AudioUuid, EffectProxyTuple> createAllProxies() {
+        std::map<AudioUuid, EffectProxyTuple> proxyMap;
+        for (const auto& itor : mProxyDescs) {
+            const auto& uuid = itor.first.proxy.value();
+            if (proxyMap.end() == proxyMap.find(uuid)) {
+                std::get<TupleIndex::HANDLE>(proxyMap[uuid]) =
+                        ndk::SharedRefBase::make<EffectProxy>(itor.first, mFactory);
+            }
+        }
+        return proxyMap;
+    }
+
+    bool addAllSubEffects(std::map<AudioUuid, EffectProxyTuple> proxyMap) {
+        for (auto& itor : mProxyDescs) {
+            const auto& uuid = itor.first.proxy.value();
+            if (proxyMap.end() == proxyMap.find(uuid)) {
+                return false;
+            }
+            auto& proxy = std::get<TupleIndex::HANDLE>(proxyMap[uuid]);
+            if (!proxy->addSubEffect(itor.second).isOk()) {
+                return false;
+            }
+            std::get<TupleIndex::DESCRIPTOR>(proxyMap[uuid]).emplace_back(itor.second);
+        }
+        return true;
+    }
+
+    std::shared_ptr<IFactory> mFactory;
+    std::vector<Descriptor> mDescs;
+    std::map<Descriptor::Identity, Descriptor> mProxyDescs;
+};
+
+TEST_F(EffectProxyTest, createProxy) {
+    auto proxyMap = createAllProxies();
+    // if there are some descriptor defined with proxy, then proxyMap can not be empty
+    EXPECT_EQ(mProxyDescs.size() == 0, proxyMap.size() == 0);
+}
+
+TEST_F(EffectProxyTest, addSubEffectsCreateAndDestroy) {
+    auto proxyMap = createAllProxies();
+    ASSERT_TRUE(addAllSubEffects(proxyMap));
+
+    for (const auto& itor : proxyMap) {
+        auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+        EXPECT_TRUE(proxy->create().isOk());
+        EXPECT_TRUE(proxy->destroy().isOk());
+    }
+}
+
+TEST_F(EffectProxyTest, addSubEffectsCreateOpenCloseDestroy) {
+    auto proxyMap = createAllProxies();
+    EXPECT_TRUE(addAllSubEffects(proxyMap));
+
+    Parameter::Common common = createParamCommon();
+    IEffect::OpenEffectReturn ret;
+    for (const auto& itor : proxyMap) {
+        auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+        EXPECT_TRUE(proxy->create().isOk());
+        EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
+        EXPECT_TRUE(proxy->close().isOk());
+        EXPECT_TRUE(proxy->destroy().isOk());
+    }
+}
+
+// Add sub-effects, set active sub-effect with different checkers
+TEST_F(EffectProxyTest, setOffloadParam) {
+    auto proxyMap = createAllProxies();
+    EXPECT_TRUE(addAllSubEffects(proxyMap));
+
+    // Any flag exist should be able to set successfully
+    bool isNoneExist = false, isSimpleExist = false, isTunnelExist = false;
+    for (const auto& itor : mProxyDescs) {
+        isNoneExist = isNoneExist || isFlagSet(itor.second, Flags::HardwareAccelerator::NONE);
+        isSimpleExist = isSimpleExist || isFlagSet(itor.second, Flags::HardwareAccelerator::SIMPLE);
+        isTunnelExist = isTunnelExist || isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL);
+    }
+
+    Parameter::Common common = createParamCommon();
+    IEffect::OpenEffectReturn ret;
+    for (const auto& itor : proxyMap) {
+        auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+        EXPECT_TRUE(proxy->create().isOk());
+        EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
+        effect_offload_param_t offloadParam{false, 0};
+        EXPECT_EQ(isNoneExist || isSimpleExist, proxy->setOffloadParam(&offloadParam).isOk());
+        offloadParam.isOffload = true;
+        EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk());
+        EXPECT_TRUE(proxy->close().isOk());
+        EXPECT_TRUE(proxy->destroy().isOk());
+    }
+}
+TEST_F(EffectProxyTest, destroyWithoutCreate) {
+    auto proxyMap = createAllProxies();
+    ASSERT_TRUE(addAllSubEffects(proxyMap));
+
+    for (const auto& itor : proxyMap) {
+        auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+        EXPECT_TRUE(proxy->destroy().isOk());
+    }
+}
+
+TEST_F(EffectProxyTest, closeWithoutOpen) {
+    auto proxyMap = createAllProxies();
+    ASSERT_TRUE(addAllSubEffects(proxyMap));
+
+    for (const auto& itor : proxyMap) {
+        auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+        EXPECT_TRUE(proxy->create().isOk());
+
+        EXPECT_TRUE(proxy->close().isOk());
+        EXPECT_TRUE(proxy->destroy().isOk());
+    }
+}
+
+// Add sub-effects, set active sub-effect, create, open, and send command, expect success handling
+TEST_F(EffectProxyTest, normalSequency) {
+    auto proxyMap = createAllProxies();
+    ASSERT_TRUE(addAllSubEffects(proxyMap));
+
+    bool isTunnelExist = [&]() {
+        for (const auto& itor : mProxyDescs) {
+            if (isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL)) {
+                return true;
+            }
+        }
+        return false;
+    }();
+
+    Parameter::Common common = createParamCommon();
+    IEffect::OpenEffectReturn ret;
+    Parameter::VolumeStereo volumeStereo({.left = .1f, .right = -0.8f});
+    Parameter param = Parameter::make<Parameter::volumeStereo>(volumeStereo);
+    Parameter::Id id = Parameter::Id::make<Parameter::Id::commonTag>(Parameter::volumeStereo);
+    State state;
+    for (const auto& itor : proxyMap) {
+        Parameter expect;
+        auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+        effect_offload_param_t offloadParam{true, 0};
+        EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk());
+
+        EXPECT_TRUE(proxy->create().isOk());
+        EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
+
+        EXPECT_TRUE(proxy->setParameter(param).isOk());
+        EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
+        EXPECT_EQ(expect, param);
+
+        EXPECT_TRUE(proxy->command(CommandId::START).isOk());
+        EXPECT_TRUE(proxy->getState(&state).isOk());
+        EXPECT_EQ(State::PROCESSING, state);
+
+        EXPECT_TRUE(proxy->command(CommandId::STOP).isOk());
+        EXPECT_TRUE(proxy->getState(&state).isOk());
+        EXPECT_EQ(State::IDLE, state);
+
+        EXPECT_TRUE(proxy->close().isOk());
+        EXPECT_TRUE(proxy->destroy().isOk());
+    }
+}
+
+// setParameter, change active sub-effect, verify with getParameter
+TEST_F(EffectProxyTest, changeActiveSubAndVerifyParameter) {
+    auto proxyMap = createAllProxies();
+    EXPECT_TRUE(addAllSubEffects(proxyMap));
+
+    bool isNoneExist = false, isSimpleExist = false, isTunnelExist = false;
+    for (const auto& itor : mProxyDescs) {
+        isNoneExist = isNoneExist || isFlagSet(itor.second, Flags::HardwareAccelerator::NONE);
+        isSimpleExist = isSimpleExist || isFlagSet(itor.second, Flags::HardwareAccelerator::SIMPLE);
+        isTunnelExist = isTunnelExist || isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL);
+    }
+
+    Parameter::Common common = createParamCommon();
+    IEffect::OpenEffectReturn ret;
+    Parameter::VolumeStereo volumeStereo({.left = .5f, .right = .8f});
+    Parameter param = Parameter::make<Parameter::volumeStereo>(volumeStereo);
+    Parameter::Id id = Parameter::Id::make<Parameter::Id::commonTag>(Parameter::volumeStereo);
+    for (const auto& itor : proxyMap) {
+        Parameter expect;
+        auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+        EXPECT_TRUE(proxy->create().isOk());
+        EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
+        EXPECT_TRUE(proxy->setParameter(param).isOk());
+        EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
+        EXPECT_EQ(expect, param);
+
+        effect_offload_param_t offloadParam{false, 0};
+        EXPECT_EQ(isNoneExist || isSimpleExist, proxy->setOffloadParam(&offloadParam).isOk());
+        EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
+        EXPECT_EQ(expect, param);
+
+        offloadParam.isOffload = true;
+        EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk());
+        EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
+        EXPECT_EQ(expect, param);
+
+        EXPECT_TRUE(proxy->close().isOk());
+        EXPECT_TRUE(proxy->destroy().isOk());
+    }
+}
+
+// send command, change active sub-effect, then verify the state with getState
+TEST_F(EffectProxyTest, changeActiveSubAndVerifyState) {
+    auto proxyMap = createAllProxies();
+    ASSERT_TRUE(addAllSubEffects(proxyMap));
+
+    bool isNoneExist = false, isSimpleExist = false, isTunnelExist = false;
+    for (const auto& itor : mProxyDescs) {
+        isNoneExist = isNoneExist || isFlagSet(itor.second, Flags::HardwareAccelerator::NONE);
+        isSimpleExist = isSimpleExist || isFlagSet(itor.second, Flags::HardwareAccelerator::SIMPLE);
+        isTunnelExist = isTunnelExist || isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL);
+    }
+
+    Parameter::Common common = createParamCommon();
+    IEffect::OpenEffectReturn ret;
+    State state;
+    for (const auto& itor : proxyMap) {
+        Parameter expect;
+        auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+        EXPECT_TRUE(proxy->create().isOk());
+        EXPECT_TRUE(proxy->getState(&state).isOk());
+        EXPECT_EQ(State::INIT, state);
+        EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
+        EXPECT_TRUE(proxy->getState(&state).isOk());
+        EXPECT_EQ(State::IDLE, state);
+        EXPECT_TRUE(proxy->command(CommandId::START).isOk());
+        EXPECT_TRUE(proxy->getState(&state).isOk());
+        EXPECT_EQ(State::PROCESSING, state);
+
+        effect_offload_param_t offloadParam{false, 0};
+        EXPECT_EQ(isNoneExist || isSimpleExist, proxy->setOffloadParam(&offloadParam).isOk());
+        EXPECT_TRUE(proxy->getState(&state).isOk());
+        EXPECT_EQ(State::PROCESSING, state);
+
+        offloadParam.isOffload = true;
+        EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk());
+        EXPECT_TRUE(proxy->getState(&state).isOk());
+        EXPECT_EQ(State::PROCESSING, state);
+
+        EXPECT_TRUE(proxy->command(CommandId::STOP).isOk());
+        EXPECT_TRUE(proxy->getState(&state).isOk());
+        EXPECT_EQ(State::IDLE, state);
+
+        EXPECT_TRUE(proxy->close().isOk());
+        EXPECT_TRUE(proxy->getState(&state).isOk());
+        EXPECT_EQ(State::INIT, state);
+        EXPECT_TRUE(proxy->destroy().isOk());
+    }
+}
+
+} // namespace android
diff --git a/media/libeffects/dynamicsproc/Android.bp b/media/libeffects/dynamicsproc/Android.bp
index 736a086..7838117 100644
--- a/media/libeffects/dynamicsproc/Android.bp
+++ b/media/libeffects/dynamicsproc/Android.bp
@@ -92,6 +92,10 @@
         "dynamicsprocessingdefaults",
     ],
 
+    static_libs: [
+        "libaudioaidlranges",
+    ],
+
     visibility: [
         "//hardware/interfaces/audio/aidl/default",
     ],
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
index e508d48..1fed9a5 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
@@ -62,32 +62,135 @@
 
 const std::string DynamicsProcessingImpl::kEffectName = "DynamicsProcessing";
 
-const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMin =
+static const Range::DynamicsProcessingRange kEngineConfigRange = {
+        .min = DynamicsProcessing::make<
+                DynamicsProcessing::engineArchitecture>(DynamicsProcessing::EngineArchitecture(
+                {.resolutionPreference =
+                         DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
+                 .preferredProcessingDurationMs = 1.0f,
+                 .preEqStage = {.inUse = false, .bandCount = 0},
+                 .postEqStage = {.inUse = false, .bandCount = 0},
+                 .mbcStage = {.inUse = false, .bandCount = 0},
+                 .limiterInUse = false})),
+        .max = DynamicsProcessing::make<
+                DynamicsProcessing::engineArchitecture>(DynamicsProcessing::EngineArchitecture(
+                {.resolutionPreference =
+                         DynamicsProcessing::ResolutionPreference::FAVOR_TIME_RESOLUTION,
+                 .preferredProcessingDurationMs = 1000.0f,
+                 .preEqStage = {.inUse = true, .bandCount = 128},
+                 .postEqStage = {.inUse = true, .bandCount = 128},
+                 .mbcStage = {.inUse = true, .bandCount = 128},
+                 .limiterInUse = true}))};
+
+static const DynamicsProcessing::ChannelConfig kChannelConfigMin =
+        DynamicsProcessing::ChannelConfig({.channel = 0, .enable = false});
+
+static const DynamicsProcessing::ChannelConfig kChannelConfigMax =
+        DynamicsProcessing::ChannelConfig(
+                {.channel = std::numeric_limits<int>::max(), .enable = true});
+
+static const Range::DynamicsProcessingRange kPreEqChannelConfigRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::preEq>({kChannelConfigMin}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::preEq>({kChannelConfigMax})};
+
+static const Range::DynamicsProcessingRange kPostEqChannelConfigRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::postEq>({kChannelConfigMin}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::postEq>({kChannelConfigMax})};
+
+static const Range::DynamicsProcessingRange kMbcChannelConfigRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::mbc>({kChannelConfigMin}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::mbc>({kChannelConfigMax})};
+
+static const DynamicsProcessing::EqBandConfig kEqBandConfigMin =
         DynamicsProcessing::EqBandConfig({.channel = 0,
                                           .band = 0,
                                           .enable = false,
-                                          .cutoffFrequencyHz = 220,
-                                          .gainDb = std::numeric_limits<float>::min()});
-const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMax =
+                                          .cutoffFrequencyHz = 20,
+                                          .gainDb = -200});
+
+static const DynamicsProcessing::EqBandConfig kEqBandConfigMax =
         DynamicsProcessing::EqBandConfig({.channel = std::numeric_limits<int>::max(),
                                           .band = std::numeric_limits<int>::max(),
                                           .enable = true,
                                           .cutoffFrequencyHz = 20000,
-                                          .gainDb = std::numeric_limits<float>::max()});
-const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPreEqBandRange = {
-        .min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
-                {DynamicsProcessingImpl::kEqBandConfigMin}),
-        .max = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
-                {DynamicsProcessingImpl::kEqBandConfigMax})};
-const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPostEqBandRange = {
-        .min = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
-                {DynamicsProcessingImpl::kEqBandConfigMin}),
-        .max = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
-                {DynamicsProcessingImpl::kEqBandConfigMax})};
-const Range DynamicsProcessingImpl::kRange =
-        Range::make<Range::dynamicsProcessing>({DynamicsProcessingImpl::kPreEqBandRange});
+                                          .gainDb = 200});
 
-const Capability DynamicsProcessingImpl::kCapability = {.range = {DynamicsProcessingImpl::kRange}};
+static const Range::DynamicsProcessingRange kPreEqBandConfigRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>({kEqBandConfigMin}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::preEqBand>({kEqBandConfigMax})};
+
+static const Range::DynamicsProcessingRange kPostEqBandConfigRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::postEqBand>({kEqBandConfigMin}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::postEqBand>({kEqBandConfigMax})};
+
+static const Range::DynamicsProcessingRange kMbcBandConfigRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::mbcBand>(
+                {DynamicsProcessing::MbcBandConfig(
+                        {.channel = 0,
+                         .band = 0,
+                         .enable = false,
+                         .cutoffFrequencyHz = 20,
+                         .attackTimeMs = 0,
+                         .releaseTimeMs = 0,
+                         .ratio = 1,
+                         .thresholdDb = -200,
+                         .kneeWidthDb = 0,
+                         .noiseGateThresholdDb = -200,
+                         .expanderRatio = 1,
+                         .preGainDb = -200,
+                         .postGainDb = -200})}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::mbcBand>(
+                {DynamicsProcessing::MbcBandConfig(
+                        {.channel = std::numeric_limits<int>::max(),
+                         .band = std::numeric_limits<int>::max(),
+                         .enable = true,
+                         .cutoffFrequencyHz = 20000,
+                         .attackTimeMs = 60000,
+                         .releaseTimeMs = 60000,
+                         .ratio = 50,
+                         .thresholdDb = 200,
+                         .kneeWidthDb = 100,
+                         .noiseGateThresholdDb = 200,
+                         .expanderRatio = 50,
+                         .preGainDb = 200,
+                         .postGainDb = 200})})};
+
+static const Range::DynamicsProcessingRange kInputGainRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::inputGain>(
+                {DynamicsProcessing::InputGain(
+                        {.channel = 0, .gainDb = -200.0f})}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::inputGain>(
+                {DynamicsProcessing::InputGain({.channel = std::numeric_limits<int>::max(),
+                                                .gainDb = 200.0f})})};
+
+static const Range::DynamicsProcessingRange kLimiterRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::limiter>(
+                {DynamicsProcessing::LimiterConfig(
+                        {.channel = 0,
+                         .enable = false,
+                         .linkGroup = std::numeric_limits<int>::min(),
+                         .attackTimeMs = 0,
+                         .releaseTimeMs = 0,
+                         .ratio = 1,
+                         .thresholdDb = -200,
+                         .postGainDb = -200})}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::limiter>(
+                {DynamicsProcessing::LimiterConfig(
+                        {.channel = std::numeric_limits<int>::max(),
+                         .enable = true,
+                         .linkGroup = std::numeric_limits<int>::max(),
+                         .attackTimeMs = 60000,
+                         .releaseTimeMs = 60000,
+                         .ratio = 50,
+                         .thresholdDb = 200,
+                         .postGainDb = 200})})};
+
+const std::vector<Range::DynamicsProcessingRange> kRanges = {
+        kEngineConfigRange,     kPreEqChannelConfigRange, kPostEqChannelConfigRange,
+        kMbcChannelConfigRange, kPreEqBandConfigRange,    kPostEqBandConfigRange,
+        kMbcBandConfigRange,    kInputGainRange,          kLimiterRange};
+
+const Capability DynamicsProcessingImpl::kCapability = {.range = kRanges};
 
 const Descriptor DynamicsProcessingImpl::kDescriptor = {
         .common = {.id = {.type = getEffectTypeUuidDynamicsProcessing(),
@@ -158,14 +261,19 @@
     }
 }
 
+bool DynamicsProcessingImpl::isParamInRange(const Parameter::Specific& specific) {
+    auto& dp = specific.get<Parameter::Specific::dynamicsProcessing>();
+    return DynamicsProcessingRanges::isParamInRange(dp, kRanges);
+}
+
 ndk::ScopedAStatus DynamicsProcessingImpl::setParameterSpecific(
         const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::dynamicsProcessing != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
+    RETURN_IF(!isParamInRange(specific), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto& param = specific.get<Parameter::Specific::dynamicsProcessing>();
-    // TODO: check range here, dynamicsProcessing need customized method for nested parameters.
     auto tag = param.getTag();
 
     switch (tag) {
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
index d094c69..1e1e72e 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
@@ -18,8 +18,9 @@
 
 #include <aidl/android/hardware/audio/effect/BnEffect.h>
 
-#include "effect-impl/EffectImpl.h"
 #include "DynamicsProcessingContext.h"
+#include "EffectRangeSpecific.h"
+#include "effect-impl/EffectImpl.h"
 
 namespace aidl::android::hardware::audio::effect {
 
@@ -51,14 +52,10 @@
     std::string getEffectName() override { return kEffectName; }
 
   private:
-    static const DynamicsProcessing::EqBandConfig kEqBandConfigMin;
-    static const DynamicsProcessing::EqBandConfig kEqBandConfigMax;
-    static const Range::DynamicsProcessingRange kPreEqBandRange;
-    static const Range::DynamicsProcessingRange kPostEqBandRange;
-    static const Range kRange;
     std::shared_ptr<DynamicsProcessingContext> mContext;
     ndk::ScopedAStatus getParameterDynamicsProcessing(const DynamicsProcessing::Tag& tag,
                                                       Parameter::Specific* specific);
+    bool isParamInRange(const Parameter::Specific& specific);
 };
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
index 69ff522..9d77135 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
@@ -16,11 +16,11 @@
 
 #define LOG_TAG "AHAL_DPLibEffectsContext"
 
-#include "DynamicsProcessing.h"
 #include "DynamicsProcessingContext.h"
+#include "DynamicsProcessing.h"
 
-#include <functional>
 #include <sys/param.h>
+#include <functional>
 #include <unordered_set>
 
 namespace aidl::android::hardware::audio::effect {
@@ -83,7 +83,7 @@
     if (block < minBlockSize) {
         block = minBlockSize;
     } else if (!powerof2(block)) {
-        //find next highest power of 2.
+        // find next highest power of 2.
         block = 1 << (32 - __builtin_clz(block));
     }
     mDpFreq->configure(block, block >> 1, sampleRate);
@@ -91,9 +91,6 @@
 
 RetCode DynamicsProcessingContext::setEngineArchitecture(
         const DynamicsProcessing::EngineArchitecture& engineArchitecture) {
-    RETURN_VALUE_IF(!validateEngineConfig(engineArchitecture), RetCode::ERROR_ILLEGAL_PARAMETER,
-                    "illegalEngineConfig");
-
     std::lock_guard lg(mMutex);
     if (!mEngineInited || mEngineArchitecture != engineArchitecture) {
         if (engineArchitecture.resolutionPreference ==
@@ -134,10 +131,12 @@
 RetCode DynamicsProcessingContext::setPreEqBand(
         const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
     std::lock_guard lg(mMutex);
-    RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
-                    "postEqNotInUse");
-    return setBands_l<DynamicsProcessing::EqBandConfig>(
-            bands, mEngineArchitecture.preEqStage.bandCount, StageType::PREEQ);
+    RETURN_VALUE_IF(!mEngineArchitecture.preEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+                    "preEqNotInUse");
+    RETURN_VALUE_IF(
+            !validateBandConfig(bands, mChannelCount, mEngineArchitecture.preEqStage.bandCount),
+            RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
+    return setBands_l<DynamicsProcessing::EqBandConfig>(bands, StageType::PREEQ);
 }
 
 RetCode DynamicsProcessingContext::setPostEqBand(
@@ -145,8 +144,10 @@
     std::lock_guard lg(mMutex);
     RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
                     "postEqNotInUse");
-    return setBands_l<DynamicsProcessing::EqBandConfig>(
-            bands, mEngineArchitecture.postEqStage.bandCount, StageType::POSTEQ);
+    RETURN_VALUE_IF(
+            !validateBandConfig(bands, mChannelCount, mEngineArchitecture.postEqStage.bandCount),
+            RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
+    return setBands_l<DynamicsProcessing::EqBandConfig>(bands, StageType::POSTEQ);
 }
 
 RetCode DynamicsProcessingContext::setMbcBand(
@@ -154,8 +155,10 @@
     std::lock_guard lg(mMutex);
     RETURN_VALUE_IF(!mEngineArchitecture.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
                     "mbcNotInUse");
-    return setBands_l<DynamicsProcessing::MbcBandConfig>(
-            bands, mEngineArchitecture.preEqStage.bandCount, StageType::MBC);
+    RETURN_VALUE_IF(
+            !validateBandConfig(bands, mChannelCount, mEngineArchitecture.mbcStage.bandCount),
+            RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
+    return setBands_l<DynamicsProcessing::MbcBandConfig>(bands, StageType::MBC);
 }
 
 RetCode DynamicsProcessingContext::setLimiter(
@@ -163,13 +166,17 @@
     std::lock_guard lg(mMutex);
     RETURN_VALUE_IF(!mEngineArchitecture.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
                     "limiterNotInUse");
-    return setBands_l<DynamicsProcessing::LimiterConfig>(limiters, -1, StageType::LIMITER);
+    RETURN_VALUE_IF(!validateLimiterConfig(limiters, mChannelCount),
+                    RetCode::ERROR_ILLEGAL_PARAMETER, "limiterConfigNotValid");
+    return setBands_l<DynamicsProcessing::LimiterConfig>(limiters, StageType::LIMITER);
 }
 
 RetCode DynamicsProcessingContext::setInputGain(
         const std::vector<DynamicsProcessing::InputGain>& inputGains) {
     std::lock_guard lg(mMutex);
-    return setBands_l<DynamicsProcessing::InputGain>(inputGains, -1, StageType::INPUTGAIN);
+    RETURN_VALUE_IF(!validateInputGainConfig(inputGains, mChannelCount),
+                    RetCode::ERROR_ILLEGAL_PARAMETER, "inputGainNotValid");
+    return setBands_l<DynamicsProcessing::InputGain>(inputGains, StageType::INPUTGAIN);
 }
 
 DynamicsProcessing::EngineArchitecture DynamicsProcessingContext::getEngineArchitecture() {
@@ -406,45 +413,33 @@
     return eqBands;
 }
 
-/**
- * When StageEnablement is in use, bandCount needs to be positive.
- */
-bool DynamicsProcessingContext::validateStageEnablement(
-        const DynamicsProcessing::StageEnablement& enablement) {
-    return !enablement.inUse || (enablement.inUse && enablement.bandCount > 0);
-}
-
-bool DynamicsProcessingContext::validateEngineConfig(
-        const DynamicsProcessing::EngineArchitecture& engine) {
-    return engine.preferredProcessingDurationMs >= 0 &&
-           validateStageEnablement(engine.preEqStage) &&
-           validateStageEnablement(engine.postEqStage) && validateStageEnablement(engine.mbcStage);
-}
-
-bool DynamicsProcessingContext::validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band,
-                                                     int maxChannel, int maxBand) {
-    return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand);
-}
-
-bool DynamicsProcessingContext::validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band,
-                                                      int maxChannel, int maxBand) {
-    return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand) &&
-           validateTime(band.attackTimeMs) && validateTime(band.releaseTimeMs) &&
-           validateRatio(band.ratio) && validateBandDb(band.thresholdDb) &&
-           validateBandDb(band.kneeWidthDb) && validateBandDb(band.noiseGateThresholdDb) &&
-           validateRatio(band.expanderRatio);
+template <typename T>
+bool DynamicsProcessingContext::validateBandConfig(const std::vector<T>& bands, int maxChannel,
+                                                   int maxBand) {
+    std::vector<float> freqs(bands.size(), -1);
+    for (auto band : bands) {
+        if (!validateChannel(band.channel, maxChannel)) return false;
+        if (!validateBand(band.band, maxBand)) return false;
+        freqs[band.band] = band.cutoffFrequencyHz;
+    }
+    if (std::count(freqs.begin(), freqs.end(), -1)) return false;
+    return std::is_sorted(freqs.begin(), freqs.end());
 }
 
 bool DynamicsProcessingContext::validateLimiterConfig(
-        const DynamicsProcessing::LimiterConfig& limiter, int maxChannel) {
-    return validateChannel(limiter.channel, maxChannel) && validateTime(limiter.attackTimeMs) &&
-           validateTime(limiter.releaseTimeMs) && validateRatio(limiter.ratio) &&
-           validateBandDb(limiter.thresholdDb);
+        const std::vector<DynamicsProcessing::LimiterConfig>& cfgs, int maxChannel) {
+    for (auto cfg : cfgs) {
+        if (!validateChannel(cfg.channel, maxChannel)) return false;
+    }
+    return true;
 }
 
-bool DynamicsProcessingContext::validateInputGainConfig(const DynamicsProcessing::InputGain& gain,
-                                                        int maxChannel) {
-    return validateChannel(gain.channel, maxChannel);
+bool DynamicsProcessingContext::validateInputGainConfig(
+        const std::vector<DynamicsProcessing::InputGain>& cfgs, int maxChannel) {
+    for (auto cfg : cfgs) {
+        if (!validateChannel(cfg.channel, maxChannel)) return false;
+    }
+    return true;
 }
 
 template <typename D>
@@ -483,7 +478,6 @@
 }
 
 RetCode DynamicsProcessingContext::setDpChannelBand_l(const std::any& anyConfig, StageType type,
-                                                      int maxCh, int maxBand,
                                                       std::set<std::pair<int, int>>& chBandSet) {
     RETURN_VALUE_IF(!anyConfig.has_value(), RetCode::ERROR_ILLEGAL_PARAMETER, "bandInvalid");
     RetCode ret = RetCode::SUCCESS;
@@ -494,8 +488,6 @@
         case StageType::POSTEQ: {
             dp_fx::DPEq* dp;
             const auto& config = std::any_cast<DynamicsProcessing::EqBandConfig>(anyConfig);
-            RETURN_VALUE_IF(!validateEqBandConfig(config, maxCh, maxBand),
-                            RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
             RETURN_VALUE_IF(
                     nullptr == (dp = getEqWithType_l(type, config.channel)) || !dp->isEnabled(),
                     RetCode::ERROR_ILLEGAL_PARAMETER, "dpEqNotExist");
@@ -508,8 +500,6 @@
         case StageType::MBC: {
             dp_fx::DPMbc* dp;
             const auto& config = std::any_cast<DynamicsProcessing::MbcBandConfig>(anyConfig);
-            RETURN_VALUE_IF(!validateMbcBandConfig(config, maxCh, maxBand),
-                            RetCode::ERROR_ILLEGAL_PARAMETER, "mbcBandNotValid");
             RETURN_VALUE_IF(nullptr == (dp = getMbc_l(config.channel)) || !dp->isEnabled(),
                             RetCode::ERROR_ILLEGAL_PARAMETER, "dpMbcNotExist");
             dp_fx::DPMbcBand band;
@@ -524,8 +514,6 @@
         case StageType::LIMITER: {
             dp_fx::DPChannel* dp;
             const auto& config = std::any_cast<DynamicsProcessing::LimiterConfig>(anyConfig);
-            RETURN_VALUE_IF(!validateLimiterConfig(config, maxCh),
-                            RetCode::ERROR_ILLEGAL_PARAMETER, "limiterBandNotValid");
             RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
                             RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
             dp_fx::DPLimiter limiter;
@@ -539,8 +527,6 @@
         case StageType::INPUTGAIN: {
             dp_fx::DPChannel* dp;
             const auto& config = std::any_cast<DynamicsProcessing::InputGain>(anyConfig);
-            RETURN_VALUE_IF(!validateInputGainConfig(config, maxCh),
-                            RetCode::ERROR_ILLEGAL_PARAMETER, "inputGainNotValid");
             RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
                             RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
             dp->setInputGain(config.gainDb);
@@ -555,14 +541,12 @@
 }
 
 template <typename T /* BandConfig */>
-RetCode DynamicsProcessingContext::setBands_l(
-        const std::vector<T>& bands, int maxBand, StageType type) {
+RetCode DynamicsProcessingContext::setBands_l(const std::vector<T>& bands, StageType type) {
     RetCode ret = RetCode::SUCCESS;
     std::set<std::pair<int /* channel */, int /* band */>> bandSet;
 
     for (const auto& it : bands) {
-        if (RetCode::SUCCESS !=
-            setDpChannelBand_l(std::make_any<T>(it), type, mChannelCount, maxBand, bandSet)) {
+        if (RetCode::SUCCESS != setDpChannelBand_l(std::make_any<T>(it), type, bandSet)) {
             LOG(WARNING) << __func__ << " skipping band " << it.toString();
             ret = RetCode::ERROR_ILLEGAL_PARAMETER;
             continue;
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
index 8be784e..b8539f6 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
@@ -103,28 +103,22 @@
     RetCode setDpChannels_l(const std::vector<DynamicsProcessing::ChannelConfig>& channels,
                             bool stageInUse, StageType type) REQUIRES(mMutex);
     template <typename T /* BandConfig */>
-    RetCode setBands_l(const std::vector<T>& bands, int maxBand, StageType type) REQUIRES(mMutex);
-    RetCode setDpChannelBand_l(const std::any& anyConfig, StageType type, int maxCh, int maxBand,
+    RetCode setBands_l(const std::vector<T>& bands, StageType type) REQUIRES(mMutex);
+    RetCode setDpChannelBand_l(const std::any& anyConfig, StageType type,
                                std::set<std::pair<int, int>>& chBandSet) REQUIRES(mMutex);
 
     std::vector<DynamicsProcessing::EqBandConfig> getEqBandConfigs(StageType type);
     std::vector<DynamicsProcessing::ChannelConfig> getChannelConfig(StageType type);
 
-    bool validateStageEnablement(const DynamicsProcessing::StageEnablement& enablement);
-    bool validateEngineConfig(const DynamicsProcessing::EngineArchitecture& engine);
-    bool validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band, int maxChannel,
-                              int maxBand);
-    bool validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band, int maxChannel,
-                               int maxBand);
-    bool validateLimiterConfig(const DynamicsProcessing::LimiterConfig& limiter, int maxChannel);
-    bool validateInputGainConfig(const DynamicsProcessing::InputGain& gain, int maxChannel);
+    template <typename T /* BandConfig */>
+    bool validateBandConfig(const std::vector<T>& bands, int maxChannel, int maxBand);
+    bool validateLimiterConfig(const std::vector<DynamicsProcessing::LimiterConfig>& cfgs,
+                               int maxChannel);
+    bool validateInputGainConfig(const std::vector<DynamicsProcessing::InputGain>& cfgs,
+                                 int maxChannel);
 
-    inline bool validateCutoffFrequency(float freq);
     inline bool validateChannel(int ch, int maxCh) { return ch >= 0 && ch < maxCh; }
     inline bool validateBand(int band, int maxBand) { return band >= 0 && band < maxBand; }
-    inline bool validateTime(int time) { return time >= 0; }
-    inline bool validateRatio(int ratio) { return ratio >= 0; }
-    inline bool validateBandDb(int db) { return db <= 0; }
 };
 
 }  // namespace aidl::android::hardware::audio::effect
\ No newline at end of file
diff --git a/media/libheadtracking/PosePredictor.cpp b/media/libheadtracking/PosePredictor.cpp
index f67a966..5209d54 100644
--- a/media/libheadtracking/PosePredictor.cpp
+++ b/media/libheadtracking/PosePredictor.cpp
@@ -91,20 +91,23 @@
 
 // Formatting
 static inline std::vector<size_t> createDelimiterIdx(size_t predictors, size_t lookaheads) {
-    if (predictors == 0) return {};
-    --predictors;
-    std::vector<size_t> delimiterIdx(predictors);
-    for (size_t i = 0; i < predictors; ++i) {
-        delimiterIdx[i] = (i + 1) * lookaheads;
+    if (lookaheads == 0) return {};
+    --lookaheads;
+    std::vector<size_t> delimiterIdx(lookaheads);
+    for (size_t i = 0; i < lookaheads; ++i) {
+        delimiterIdx[i] = (i + 1) * predictors;
     }
     return delimiterIdx;
 }
 
 PosePredictor::PosePredictor()
-    : mPredictors{  // must match switch in getCurrentPredictor()
+    : mPredictors{
+            // First predictors must match switch in getCurrentPredictor()
             std::make_shared<LastPredictor>(),
             std::make_shared<TwistPredictor>(),
             std::make_shared<LeastSquaresPredictor>(),
+            // After this, can place additional predictors here for comparison such as
+            // std::make_shared<LeastSquaresPredictor>(0.25),
         }
     , mLookaheadMs(kLookAheadMs.begin(), kLookAheadMs.end())
     , mVerifiers(std::size(mLookaheadMs) * std::size(mPredictors))
@@ -195,7 +198,12 @@
     if constexpr (kEnableVerification) {
         // dump verification
         ss.append(prefixSpace)
-            .append(" Prediction abs error (L1) degrees [ type (last twist least-squares) x ( ");
+            .append(" Prediction abs error (L1) degrees [ type (");
+        for (size_t i = 0; i < mPredictors.size(); ++i) {
+            if (i > 0) ss.append(" , ");
+            ss.append(mPredictors[i]->name());
+        }
+        ss.append(" ) x ( ");
         for (size_t i = 0; i < mLookaheadMs.size(); ++i) {
             if (i > 0) ss.append(" : ");
             ss.append(std::to_string(mLookaheadMs[i]));
diff --git a/media/libheadtracking/PosePredictor.h b/media/libheadtracking/PosePredictor.h
index 06983cc..53211e3 100644
--- a/media/libheadtracking/PosePredictor.h
+++ b/media/libheadtracking/PosePredictor.h
@@ -32,6 +32,7 @@
     virtual void add(int64_t atNs, const Pose3f& pose, const Twist3f& twist) = 0;
     virtual Pose3f predict(int64_t atNs) const = 0;
     virtual void reset() = 0;
+    virtual std::string name() const = 0;
     virtual std::string toString(size_t index) const = 0;
 };
 
@@ -57,6 +58,10 @@
         mLastPose = {};
     }
 
+    std::string name() const override {
+        return "LAST";
+    }
+
     std::string toString(size_t index) const override {
         std::string s(index, ' ');
         s.append("LastPredictor using last pose: ")
@@ -92,6 +97,10 @@
         mLastTwist = {};
     }
 
+    std::string name() const override {
+        return "TWIST";
+    }
+
     std::string toString(size_t index) const override {
         std::string s(index, ' ');
         s.append("TwistPredictor using last pose: ")
@@ -130,13 +139,16 @@
     void add(int64_t atNs, const Pose3f& pose, const Twist3f& twist) override;
     Pose3f predict(int64_t atNs) const override;
     void reset() override;
+    std::string name() const override {
+        return "LEAST_SQUARES(" + std::to_string(mAlpha) + ")";
+    }
     std::string toString(size_t index) const override;
 
 private:
     const double mAlpha;
     int64_t mLastAtNs{};
     Pose3f mLastPose;
-    static constexpr double kDefaultAlphaEstimator = 0.5;
+    static constexpr double kDefaultAlphaEstimator = 0.2;
     static constexpr size_t kMinimumSamplesForPrediction = 4;
     audio_utils::LinearLeastSquaresFit<double> mRw;
     audio_utils::LinearLeastSquaresFit<double> mRx;
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index 1b8656d..2bdcdd2 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -26,7 +26,6 @@
 #include <binder/IMemory.h>
 #include <binder/MemoryDealer.h>
 #include <drm/drm_framework_common.h>
-#include <log/log.h>
 #include <media/mediametadataretriever.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ADebug.h>
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index 8a3b84e..86427ed 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -27,40 +27,6 @@
 #include <utils/String8.h>
 #include <utils/KeyedVector.h>
 
-// The binder is supposed to propagate the scheduler group across
-// the binder interface so that remote calls are executed with
-// the same priority as local calls. This is currently not working
-// so this change puts in a temporary hack to fix the issue with
-// metadata retrieval which can be a huge CPU hit if done on a
-// foreground thread.
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-
-#undef LOG_TAG
-#define LOG_TAG "IMediaMetadataRetriever"
-#include <utils/Log.h>
-#include <cutils/sched_policy.h>
-
-namespace android {
-
-static void sendSchedPolicy(Parcel& data)
-{
-    SchedPolicy policy;
-    get_sched_policy(gettid(), &policy);
-    data.writeInt32(policy);
-}
-
-static void setSchedPolicy(const Parcel& data)
-{
-    SchedPolicy policy = (SchedPolicy) data.readInt32();
-    set_sched_policy(gettid(), policy);
-}
-static void restoreSchedPolicy()
-{
-    set_sched_policy(gettid(), SP_FOREGROUND);
-}
-}; // end namespace android
-#endif
-
 namespace android {
 
 enum {
@@ -157,9 +123,6 @@
         data.writeInt32(option);
         data.writeInt32(colorFormat);
         data.writeInt32(metaOnly);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-        sendSchedPolicy(data);
-#endif
         remote()->transact(GET_FRAME_AT_TIME, data, &reply);
         status_t ret = reply.readInt32();
         if (ret != NO_ERROR) {
@@ -178,9 +141,6 @@
         data.writeInt32(colorFormat);
         data.writeInt32(metaOnly);
         data.writeInt32(thumbnail);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-        sendSchedPolicy(data);
-#endif
         remote()->transact(GET_IMAGE_AT_INDEX, data, &reply);
         status_t ret = reply.readInt32();
         if (ret != NO_ERROR) {
@@ -202,9 +162,6 @@
         data.writeInt32(top);
         data.writeInt32(right);
         data.writeInt32(bottom);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-        sendSchedPolicy(data);
-#endif
         remote()->transact(GET_IMAGE_RECT_AT_INDEX, data, &reply);
         status_t ret = reply.readInt32();
         if (ret != NO_ERROR) {
@@ -223,9 +180,6 @@
         data.writeInt32(index);
         data.writeInt32(colorFormat);
         data.writeInt32(metaOnly);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-        sendSchedPolicy(data);
-#endif
         remote()->transact(GET_FRAME_AT_INDEX, data, &reply);
         status_t ret = reply.readInt32();
         if (ret != NO_ERROR) {
@@ -238,9 +192,6 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-        sendSchedPolicy(data);
-#endif
         remote()->transact(EXTRACT_ALBUM_ART, data, &reply);
         status_t ret = reply.readInt32();
         if (ret != NO_ERROR) {
@@ -253,9 +204,6 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-        sendSchedPolicy(data);
-#endif
         data.writeInt32(keyCode);
         remote()->transact(EXTRACT_METADATA, data, &reply);
         status_t ret = reply.readInt32();
@@ -366,9 +314,6 @@
             bool metaOnly = (data.readInt32() != 0);
             ALOGV("getTimeAtTime: time(%" PRId64 " us), option(%d), colorFormat(%d), metaOnly(%d)",
                     timeUs, option, colorFormat, metaOnly);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-            setSchedPolicy(data);
-#endif
             sp<IMemory> bitmap = getFrameAtTime(timeUs, option, colorFormat, metaOnly);
             if (bitmap != 0) {  // Don't send NULL across the binder interface
                 reply->writeInt32(NO_ERROR);
@@ -376,9 +321,6 @@
             } else {
                 reply->writeInt32(UNKNOWN_ERROR);
             }
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-            restoreSchedPolicy();
-#endif
             return NO_ERROR;
         } break;
         case GET_IMAGE_AT_INDEX: {
@@ -389,9 +331,6 @@
             bool thumbnail = (data.readInt32() != 0);
             ALOGV("getImageAtIndex: index(%d), colorFormat(%d), metaOnly(%d), thumbnail(%d)",
                     index, colorFormat, metaOnly, thumbnail);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-            setSchedPolicy(data);
-#endif
             sp<IMemory> bitmap = getImageAtIndex(index, colorFormat, metaOnly, thumbnail);
             if (bitmap != 0) {  // Don't send NULL across the binder interface
                 reply->writeInt32(NO_ERROR);
@@ -399,9 +338,6 @@
             } else {
                 reply->writeInt32(UNKNOWN_ERROR);
             }
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-            restoreSchedPolicy();
-#endif
             return NO_ERROR;
         } break;
 
@@ -415,9 +351,6 @@
             int bottom = data.readInt32();
             ALOGV("getImageRectAtIndex: index(%d), colorFormat(%d), rect {%d, %d, %d, %d}",
                     index, colorFormat, left, top, right, bottom);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-            setSchedPolicy(data);
-#endif
             sp<IMemory> bitmap = getImageRectAtIndex(
                     index, colorFormat, left, top, right, bottom);
             if (bitmap != 0) {  // Don't send NULL across the binder interface
@@ -426,9 +359,6 @@
             } else {
                 reply->writeInt32(UNKNOWN_ERROR);
             }
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-            restoreSchedPolicy();
-#endif
             return NO_ERROR;
         } break;
 
@@ -439,9 +369,6 @@
             bool metaOnly = (data.readInt32() != 0);
             ALOGV("getFrameAtIndex: index(%d), colorFormat(%d), metaOnly(%d)",
                     index, colorFormat, metaOnly);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-            setSchedPolicy(data);
-#endif
             sp<IMemory> frame = getFrameAtIndex(index, colorFormat, metaOnly);
             if (frame != nullptr) {  // Don't send NULL across the binder interface
                 reply->writeInt32(NO_ERROR);
@@ -449,16 +376,10 @@
             } else {
                 reply->writeInt32(UNKNOWN_ERROR);
             }
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-            restoreSchedPolicy();
-#endif
             return NO_ERROR;
         } break;
         case EXTRACT_ALBUM_ART: {
             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-            setSchedPolicy(data);
-#endif
             sp<IMemory> albumArt = extractAlbumArt();
             if (albumArt != 0) {  // Don't send NULL across the binder interface
                 reply->writeInt32(NO_ERROR);
@@ -466,16 +387,10 @@
             } else {
                 reply->writeInt32(UNKNOWN_ERROR);
             }
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-            restoreSchedPolicy();
-#endif
             return NO_ERROR;
         } break;
         case EXTRACT_METADATA: {
             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-            setSchedPolicy(data);
-#endif
             int keyCode = data.readInt32();
             const char* value = extractMetadata(keyCode);
             if (value != NULL) {  // Don't send NULL across the binder interface
@@ -484,9 +399,6 @@
             } else {
                 reply->writeInt32(UNKNOWN_ERROR);
             }
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-            restoreSchedPolicy();
-#endif
             return NO_ERROR;
         } break;
         default:
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index a36f1d6..91216cb 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -46,6 +46,14 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libmediaplayerservice",
+        vector: "remote",
+        service_privilege: "privileged",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
 
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 32e40c3..fc49d69 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -238,6 +238,7 @@
         "CallbackMediaSource.cpp",
         "CameraSource.cpp",
         "CameraSourceTimeLapse.cpp",
+        "CodecErrorLog.cpp",
         "FrameDecoder.cpp",
         "HevcUtils.cpp",
         "InterfaceUtils.cpp",
diff --git a/media/libstagefright/CodecErrorLog.cpp b/media/libstagefright/CodecErrorLog.cpp
new file mode 100644
index 0000000..9785623
--- /dev/null
+++ b/media/libstagefright/CodecErrorLog.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CodecErrorLog"
+
+#include <log/log.h>
+#include <media/stagefright/CodecErrorLog.h>
+
+namespace android {
+
+void CodecErrorLog::log(const char *tag, const char *message) {
+    std::unique_lock lock(mLock);
+    ALOG(LOG_ERROR, tag, "%s", message);
+    mStream << message << std::endl;
+}
+
+void CodecErrorLog::log(const char *tag, const std::string &message) {
+    log(tag, message.c_str());
+}
+
+std::string CodecErrorLog::extract() {
+    std::unique_lock lock(mLock);
+    std::string msg = mStream.str();
+    mStream.str("");
+    return msg;
+}
+
+void CodecErrorLog::clear() {
+    std::unique_lock lock(mLock);
+    mStream.str("");
+}
+
+}  // namespace android
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 9b8cc5e..4a67876 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -41,6 +41,7 @@
 #include <android/binder_ibinder.h>
 #include <android/binder_manager.h>
 #include <android/dlext.h>
+#include <android-base/stringprintf.h>
 #include <binder/IMemory.h>
 #include <binder/IServiceManager.h>
 #include <binder/MemoryDealer.h>
@@ -874,10 +875,12 @@
         };
     }
     if (!mGetCodecInfo) {
-        mGetCodecInfo = [](const AString &name, sp<MediaCodecInfo> *info) -> status_t {
+        mGetCodecInfo = [&log = mErrorLog](const AString &name,
+                                           sp<MediaCodecInfo> *info) -> status_t {
             *info = nullptr;
             const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
             if (!mcl) {
+                log.log(LOG_TAG, "Fatal error: failed to initialize MediaCodecList");
                 return NO_INIT;  // if called from Java should raise IOException
             }
             AString tmp = name;
@@ -892,6 +895,8 @@
                 *info = mcl->getCodecInfo(codecIdx);
                 return OK;
             }
+            log.log(LOG_TAG, base::StringPrintf("Codec with name '%s' is not found on the device.",
+                                  name.c_str()));
             return NAME_NOT_FOUND;
         };
     }
@@ -947,6 +952,7 @@
 
 void MediaCodec::updateMediametrics() {
     if (mMetricsHandle == 0) {
+        ALOGW("no metrics handle found");
         return;
     }
 
@@ -1625,6 +1631,8 @@
 status_t MediaCodec::init(const AString &name) {
     status_t err = mResourceManagerProxy->init();
     if (err != OK) {
+        mErrorLog.log(LOG_TAG, base::StringPrintf(
+                "Fatal error: failed to initialize ResourceManager (err=%d)", err));
         mCodec = NULL; // remove the codec
         return err;
     }
@@ -1644,11 +1652,14 @@
     if (!name.startsWith("android.filter.")) {
         err = mGetCodecInfo(name, &mCodecInfo);
         if (err != OK) {
+            mErrorLog.log(LOG_TAG, base::StringPrintf(
+                    "Getting codec info with name '%s' failed (err=%d)", name.c_str(), err));
             mCodec = NULL;  // remove the codec.
             return err;
         }
         if (mCodecInfo == nullptr) {
-            ALOGE("Getting codec info with name '%s' failed", name.c_str());
+            mErrorLog.log(LOG_TAG, base::StringPrintf(
+                    "Getting codec info with name '%s' failed", name.c_str()));
             return NAME_NOT_FOUND;
         }
         secureCodec = name.endsWith(".secure");
@@ -1671,7 +1682,8 @@
 
     mCodec = mGetCodecBase(name, owner);
     if (mCodec == NULL) {
-        ALOGE("Getting codec base with name '%s' (owner='%s') failed", name.c_str(), owner);
+        mErrorLog.log(LOG_TAG, base::StringPrintf(
+                "Getting codec base with name '%s' (from '%s' HAL) failed", name.c_str(), owner));
         return NAME_NOT_FOUND;
     }
 
@@ -1683,7 +1695,7 @@
             mCodecLooper->setName("CodecLooper");
             err = mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
             if (OK != err) {
-                ALOGE("Codec Looper failed to start");
+                mErrorLog.log(LOG_TAG, "Fatal error: codec looper failed to start");
                 return err;
             }
         }
@@ -1860,7 +1872,8 @@
         // Prevent possible integer overflow in downstream code.
         if (mWidth < 0 || mHeight < 0 ||
                (uint64_t)mWidth * mHeight > (uint64_t)INT32_MAX / 4) {
-            ALOGE("Invalid size(s), width=%d, height=%d", mWidth, mHeight);
+            mErrorLog.log(LOG_TAG, base::StringPrintf(
+                    "Invalid size(s), width=%d, height=%d", mWidth, mHeight));
             return BAD_VALUE;
         }
 
@@ -3030,17 +3043,17 @@
         sp<MediaCodecBuffer> *buffer, sp<AMessage> *format) {
     // use mutex instead of a context switch
     if (mReleasedByResourceManager) {
-        ALOGE("getBufferAndFormat - resource already released");
+        mErrorLog.log(LOG_TAG, "resource already released");
         return DEAD_OBJECT;
     }
 
     if (buffer == NULL) {
-        ALOGE("getBufferAndFormat - null MediaCodecBuffer");
+        mErrorLog.log(LOG_TAG, "null buffer");
         return INVALID_OPERATION;
     }
 
     if (format == NULL) {
-        ALOGE("getBufferAndFormat - null AMessage");
+        mErrorLog.log(LOG_TAG, "null format");
         return INVALID_OPERATION;
     }
 
@@ -3048,7 +3061,9 @@
     format->clear();
 
     if (!isExecuting()) {
-        ALOGE("getBufferAndFormat - not executing");
+        mErrorLog.log(LOG_TAG, base::StringPrintf(
+                "Invalid to call %s; only valid in Executing states",
+                apiStateString().c_str()));
         return INVALID_OPERATION;
     }
 
@@ -3060,6 +3075,7 @@
     if (index >= buffers.size()) {
         ALOGE("getBufferAndFormat - trying to get buffer with "
               "bad index (index=%zu buffer_size=%zu)", index, buffers.size());
+        mErrorLog.log(LOG_TAG, base::StringPrintf("Bad index (index=%zu)", index));
         return INVALID_OPERATION;
     }
 
@@ -3067,6 +3083,7 @@
     if (!info.mOwnedByClient) {
         ALOGE("getBufferAndFormat - invalid operation "
               "(the index %zu is not owned by client)", index);
+        mErrorLog.log(LOG_TAG, base::StringPrintf("index %zu is not owned by client", index));
         return INVALID_OPERATION;
     }
 
@@ -3194,6 +3211,7 @@
 
 void MediaCodec::cancelPendingDequeueOperations() {
     if (mFlags & kFlagDequeueInputPending) {
+        mErrorLog.log(LOG_TAG, "Pending dequeue input buffer request cancelled");
         PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION);
 
         ++mDequeueInputTimeoutGeneration;
@@ -3202,6 +3220,7 @@
     }
 
     if (mFlags & kFlagDequeueOutputPending) {
+        mErrorLog.log(LOG_TAG, "Pending dequeue output buffer request cancelled");
         PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION);
 
         ++mDequeueOutputTimeoutGeneration;
@@ -3211,8 +3230,16 @@
 }
 
 bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
-    if (!isExecuting() || (mFlags & kFlagIsAsync)
-            || (newRequest && (mFlags & kFlagDequeueInputPending))) {
+    if (!isExecuting()) {
+        mErrorLog.log(LOG_TAG, base::StringPrintf(
+                "Invalid to call %s; only valid in executing state",
+                apiStateString().c_str()));
+        PostReplyWithError(replyID, INVALID_OPERATION);
+    } else if (mFlags & kFlagIsAsync) {
+        mErrorLog.log(LOG_TAG, "Invalid to call in async mode");
+        PostReplyWithError(replyID, INVALID_OPERATION);
+    } else if (newRequest && (mFlags & kFlagDequeueInputPending)) {
+        mErrorLog.log(LOG_TAG, "Invalid to call while another dequeue input request is pending");
         PostReplyWithError(replyID, INVALID_OPERATION);
         return true;
     } else if (mFlags & kFlagStickyError) {
@@ -3235,8 +3262,16 @@
 }
 
 bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
-    if (!isExecuting() || (mFlags & kFlagIsAsync)
-            || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
+    if (!isExecuting()) {
+        mErrorLog.log(LOG_TAG, base::StringPrintf(
+                "Invalid to call %s; only valid in executing state",
+                apiStateString().c_str()));
+        PostReplyWithError(replyID, INVALID_OPERATION);
+    } else if (mFlags & kFlagIsAsync) {
+        mErrorLog.log(LOG_TAG, "Invalid to call in async mode");
+        PostReplyWithError(replyID, INVALID_OPERATION);
+    } else if (newRequest && (mFlags & kFlagDequeueOutputPending)) {
+        mErrorLog.log(LOG_TAG, "Invalid to call while another dequeue output request is pending");
         PostReplyWithError(replyID, INVALID_OPERATION);
     } else if (mFlags & kFlagStickyError) {
         PostReplyWithError(replyID, getStickyError());
@@ -4027,6 +4062,9 @@
                 // callback can't be set after codec is executing,
                 // or before it's initialized (as the callback
                 // will be cleared when it goes to INITIALIZED)
+                mErrorLog.log(LOG_TAG, base::StringPrintf(
+                        "Invalid to call %s; only valid at Initialized state",
+                        apiStateString().c_str()));
                 PostReplyWithError(replyID, INVALID_OPERATION);
                 break;
             }
@@ -4058,6 +4096,9 @@
         case kWhatConfigure:
         {
             if (mState != INITIALIZED) {
+                mErrorLog.log(LOG_TAG, base::StringPrintf(
+                        "configure() is valid only at Initialized state; currently %s",
+                        apiStateString().c_str()));
                 PostReplyWithError(msg, INVALID_OPERATION);
                 break;
             }
@@ -4115,6 +4156,8 @@
             CHECK(msg->findInt32("flags", (int32_t *)&flags));
             if (flags & CONFIGURE_FLAG_USE_BLOCK_MODEL) {
                 if (!(mFlags & kFlagIsAsync)) {
+                    mErrorLog.log(
+                            LOG_TAG, "Block model is only valid with callback set (async mode)");
                     PostReplyWithError(replyID, INVALID_OPERATION);
                     break;
                 }
@@ -4187,9 +4230,13 @@
                     sp<Surface> surface = static_cast<Surface *>(obj.get());
                     if (mSurface == NULL) {
                         // do not support setting surface if it was not set
+                        mErrorLog.log(LOG_TAG,
+                                      "Cannot set surface if the codec is not configured with "
+                                      "a surface already");
                         err = INVALID_OPERATION;
                     } else if (obj == NULL) {
                         // do not support unsetting surface
+                        mErrorLog.log(LOG_TAG, "Unsetting surface is not supported");
                         err = BAD_VALUE;
                     } else {
                         err = connectToSurface(surface);
@@ -4220,6 +4267,9 @@
                 }
 
                 default:
+                    mErrorLog.log(LOG_TAG, base::StringPrintf(
+                            "setSurface() is valid only at Executing states; currently %s",
+                            apiStateString().c_str()));
                     err = INVALID_OPERATION;
                     break;
             }
@@ -4233,6 +4283,9 @@
         {
             // Must be configured, but can't have been started yet.
             if (mState != CONFIGURED) {
+                mErrorLog.log(LOG_TAG, base::StringPrintf(
+                        "setInputSurface() is valid only at Configured state; currently %s",
+                        apiStateString().c_str()));
                 PostReplyWithError(msg, INVALID_OPERATION);
                 break;
             }
@@ -4268,6 +4321,9 @@
                 PostReplyWithError(msg, OK);
                 break;
             } else if (mState != CONFIGURED) {
+                mErrorLog.log(LOG_TAG, base::StringPrintf(
+                        "start() is valid only at Configured state; currently %s",
+                        apiStateString().c_str()));
                 PostReplyWithError(msg, INVALID_OPERATION);
                 break;
             }
@@ -4345,6 +4401,7 @@
                     if (mFlags & kFlagIsAsync) {
                         onError(DEAD_OBJECT, ACTION_CODE_FATAL);
                     }
+                    mErrorLog.log(LOG_TAG, "Released by resource manager");
                     mReleasedByResourceManager = true;
                 }
 
@@ -4381,6 +4438,7 @@
                 // the previous stop/release completes and then reply with OK.
                 status_t err = mState == targetState ? OK : INVALID_OPERATION;
                 response->setInt32("err", err);
+                // TODO: mErrorLog
                 if (err == OK && targetState == UNINITIALIZED) {
                     mComponentName.clear();
                 }
@@ -4489,13 +4547,13 @@
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (mFlags & kFlagIsAsync) {
-                ALOGE("dequeueInputBuffer can't be used in async mode");
+                mErrorLog.log(LOG_TAG, "dequeueInputBuffer can't be used in async mode");
                 PostReplyWithError(replyID, INVALID_OPERATION);
                 break;
             }
 
             if (mHaveInputSurface) {
-                ALOGE("dequeueInputBuffer can't be used with input surface");
+                mErrorLog.log(LOG_TAG, "dequeueInputBuffer can't be used with input surface");
                 PostReplyWithError(replyID, INVALID_OPERATION);
                 break;
             }
@@ -4550,6 +4608,9 @@
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (!isExecuting()) {
+                mErrorLog.log(LOG_TAG, base::StringPrintf(
+                        "queueInputBuffer() is valid only at Executing states; currently %s",
+                        apiStateString().c_str()));
                 PostReplyWithError(replyID, INVALID_OPERATION);
                 break;
             } else if (mFlags & kFlagStickyError) {
@@ -4577,7 +4638,7 @@
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (mFlags & kFlagIsAsync) {
-                ALOGE("dequeueOutputBuffer can't be used in async mode");
+                mErrorLog.log(LOG_TAG, "dequeueOutputBuffer can't be used in async mode");
                 PostReplyWithError(replyID, INVALID_OPERATION);
                 break;
             }
@@ -4632,6 +4693,9 @@
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (!isExecuting()) {
+                mErrorLog.log(LOG_TAG, base::StringPrintf(
+                        "releaseOutputBuffer() is valid only at Executing states; currently %s",
+                        apiStateString().c_str()));
                 PostReplyWithError(replyID, INVALID_OPERATION);
                 break;
             } else if (mFlags & kFlagStickyError) {
@@ -4655,7 +4719,15 @@
 
         case kWhatSignalEndOfInputStream:
         {
-            if (!isExecuting() || !mHaveInputSurface) {
+            if (!isExecuting()) {
+                mErrorLog.log(LOG_TAG, base::StringPrintf(
+                        "signalEndOfInputStream() is valid only at Executing states; currently %s",
+                        apiStateString().c_str()));
+                PostReplyWithError(msg, INVALID_OPERATION);
+                break;
+            } else if (!mHaveInputSurface) {
+                mErrorLog.log(
+                        LOG_TAG, "signalEndOfInputStream() called without an input surface set");
                 PostReplyWithError(msg, INVALID_OPERATION);
                 break;
             } else if (mFlags & kFlagStickyError) {
@@ -4679,7 +4751,14 @@
         {
             sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
-            if (!isExecuting() || (mFlags & kFlagIsAsync)) {
+            if (!isExecuting()) {
+                mErrorLog.log(LOG_TAG, base::StringPrintf(
+                        "getInput/OutputBuffers() is valid only at Executing states; currently %s",
+                        apiStateString().c_str()));
+                PostReplyWithError(replyID, INVALID_OPERATION);
+                break;
+            } else if (mFlags & kFlagIsAsync) {
+                mErrorLog.log(LOG_TAG, "getInput/OutputBuffers() is not supported with callbacks");
                 PostReplyWithError(replyID, INVALID_OPERATION);
                 break;
             } else if (mFlags & kFlagStickyError) {
@@ -4712,6 +4791,9 @@
         case kWhatFlush:
         {
             if (!isExecuting()) {
+                mErrorLog.log(LOG_TAG, base::StringPrintf(
+                        "flush() is valid only at Executing states; currently %s",
+                        apiStateString().c_str()));
                 PostReplyWithError(msg, INVALID_OPERATION);
                 break;
             } else if (mFlags & kFlagStickyError) {
@@ -4751,10 +4833,17 @@
             sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
-            if ((mState != CONFIGURED && mState != STARTING &&
-                 mState != STARTED && mState != FLUSHING &&
-                 mState != FLUSHED)
-                    || format == NULL) {
+            if (mState != CONFIGURED && mState != STARTING &&
+                    mState != STARTED && mState != FLUSHING &&
+                    mState != FLUSHED) {
+                mErrorLog.log(LOG_TAG, base::StringPrintf(
+                        "getInput/OutputFormat() is valid at Executing states "
+                        "and Configured state; currently %s",
+                        apiStateString().c_str()));
+                PostReplyWithError(replyID, INVALID_OPERATION);
+                break;
+            } else if (format == NULL) {
+                mErrorLog.log(LOG_TAG, "Fatal error: format is not initialized");
                 PostReplyWithError(replyID, INVALID_OPERATION);
                 break;
             } else if (mFlags & kFlagStickyError) {
@@ -4789,6 +4878,7 @@
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (mComponentName.empty()) {
+                mErrorLog.log(LOG_TAG, "Fatal error: name is not set");
                 PostReplyWithError(replyID, INVALID_OPERATION);
                 break;
             }
@@ -4956,7 +5046,7 @@
     size_t i = 0;
     for (;;) {
         sp<ABuffer> csd;
-        if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
+        if (!format->findBuffer(base::StringPrintf("csd-%zu", i).c_str(), &csd)) {
             break;
         }
         if (csd->size() == 0) {
@@ -4991,7 +5081,7 @@
                 }
                 sDealer = new MemoryDealer(
                         newDealerCapacity,
-                        AStringPrintf("CSD(%dMB)", newDealerCapacity / 1048576).c_str());
+                        base::StringPrintf("CSD(%zuMB)", newDealerCapacity / 1048576).c_str());
                 mem = sDealer->allocate(csd->size());
             }
             memcpy(mem->unsecurePointer(), csd->data(), csd->size());
@@ -5002,9 +5092,14 @@
                 FetchLinearBlock(csd->size(), {std::string{mComponentName.c_str()}});
             C2WriteView view{block->map().get()};
             if (view.error() != C2_OK) {
+                mErrorLog.log(LOG_TAG, "Fatal error: failed to allocate and map a block");
                 return -EINVAL;
             }
             if (csd->size() > view.capacity()) {
+                mErrorLog.log(LOG_TAG, base::StringPrintf(
+                        "Fatal error: allocated block is too small "
+                        "(csd size %zu; block cap %u)",
+                        csd->size(), view.capacity()));
                 return -EINVAL;
             }
             memcpy(view.base(), csd->data(), csd->size());
@@ -5015,10 +5110,16 @@
         const sp<MediaCodecBuffer> &codecInputData = info.mData;
 
         if (csd->size() > codecInputData->capacity()) {
+            mErrorLog.log(LOG_TAG, base::StringPrintf(
+                    "CSD is too large to fit in input buffer "
+                    "(csd size %zu; buffer cap %zu)",
+                    csd->size(), codecInputData->capacity()));
             return -EINVAL;
         }
         if (codecInputData->data() == NULL) {
             ALOGV("Input buffer %zu is not properly allocated", bufferIndex);
+            mErrorLog.log(LOG_TAG, base::StringPrintf(
+                    "Fatal error: input buffer %zu is not properly allocated", bufferIndex));
             return -EINVAL;
         }
 
@@ -5071,6 +5172,7 @@
 
         mActivityNotify.clear();
         mCallback.clear();
+        mErrorLog.clear();
     }
 
     if (newState == UNINITIALIZED) {
@@ -5191,6 +5293,7 @@
         if (!hasCryptoOrDescrambler()) {
             ALOGE("[%s] queuing secure buffer without mCrypto or mDescrambler!",
                     mComponentName.c_str());
+            mErrorLog.log(LOG_TAG, "queuing secure buffer without mCrypto or mDescrambler!");
             return -EINVAL;
         }
 
@@ -5214,6 +5317,8 @@
     }
 
     if (index >= mPortBuffers[kPortIndexInput].size()) {
+        mErrorLog.log(LOG_TAG, base::StringPrintf(
+                "index out of range (index=%zu)", mPortBuffers[kPortIndexInput].size()));
         return -ERANGE;
     }
 
@@ -5234,6 +5339,7 @@
                     memory, (mFlags & kFlagIsSecure), key, iv, mode, pattern,
                     offset, subSamples, numSubSamples, buffer);
         } else {
+            mErrorLog.log(LOG_TAG, "Fatal error: invalid queue request without a buffer");
             err = UNKNOWN_ERROR;
         }
 
@@ -5256,17 +5362,28 @@
         offset = buffer->offset();
         size = buffer->size();
         if (err != OK) {
-            ALOGI("block model buffer attach failed: err = %s (%d)",
+            ALOGE("block model buffer attach failed: err = %s (%d)",
                   StrMediaError(err).c_str(), err);
             return err;
         }
     }
 
-    if (buffer == nullptr || !info->mOwnedByClient) {
+    if (buffer == nullptr) {
+        mErrorLog.log(LOG_TAG, base::StringPrintf(
+                "Fatal error: failed to fetch buffer for index %zu", index));
+        return -EACCES;
+    }
+    if (!info->mOwnedByClient) {
+        mErrorLog.log(LOG_TAG, base::StringPrintf(
+                "client does not own the buffer #%zu", index));
         return -EACCES;
     }
 
     if (offset + size > buffer->capacity()) {
+        mErrorLog.log(LOG_TAG, base::StringPrintf(
+                "buffer offset and size goes beyond the capacity: "
+                "offset=%zu, size=%zu, cap=%zu",
+                offset, size, buffer->capacity()));
         return -EINVAL;
     }
 
@@ -5371,8 +5488,8 @@
         if (it->getRenderTimeNs() < 0) {
             continue; // dropped frame from tracking
         }
-        msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
-        msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
+        msg->setInt64(base::StringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
+        msg->setInt64(base::StringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
         ++index;
     }
     return index;
@@ -5388,16 +5505,28 @@
     }
 
     if (!isExecuting()) {
+        mErrorLog.log(LOG_TAG, base::StringPrintf(
+                "releaseOutputBuffer() is valid at Executing states; currently %s",
+                apiStateString().c_str()));
         return -EINVAL;
     }
 
     if (index >= mPortBuffers[kPortIndexOutput].size()) {
+        mErrorLog.log(LOG_TAG, base::StringPrintf(
+                "index out of range (index=%zu)", mPortBuffers[kPortIndexOutput].size()));
         return -ERANGE;
     }
 
     BufferInfo *info = &mPortBuffers[kPortIndexOutput][index];
 
-    if (info->mData == nullptr || !info->mOwnedByClient) {
+    if (!info->mOwnedByClient) {
+        mErrorLog.log(LOG_TAG, base::StringPrintf(
+                "client does not own the buffer #%zu", index));
+        return -EACCES;
+    }
+    if (info->mData == nullptr) {
+        mErrorLog.log(LOG_TAG, base::StringPrintf(
+                "Fatal error: null buffer for index %zu", index));
         return -EACCES;
     }
 
@@ -5464,7 +5593,7 @@
         status_t err = mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
 
         if (err == NO_INIT) {
-            ALOGE("rendering to non-initilized(obsolete) surface");
+            mErrorLog.log(LOG_TAG, "rendering to non-initialized(obsolete) surface");
             return err;
         }
         if (err != OK) {
@@ -5737,12 +5866,14 @@
             memcpy(csd->data() + 4, nalStart, nalSize);
 
             mOutputFormat->setBuffer(
-                    AStringPrintf("csd-%u", csdIndex).c_str(), csd);
+                    base::StringPrintf("csd-%u", csdIndex).c_str(), csd);
 
             ++csdIndex;
         }
 
         if (csdIndex != 2) {
+            mErrorLog.log(LOG_TAG, base::StringPrintf(
+                    "codec config data contains %u NAL units; expected 2.", csdIndex));
             return ERROR_MALFORMED;
         }
     } else {
@@ -5784,6 +5915,32 @@
     mDeferredMessages.clear();
 }
 
+std::string MediaCodec::apiStateString() {
+    const char *rval = NULL;
+    char rawbuffer[16]; // room for "%d"
+
+    switch (mState) {
+        case UNINITIALIZED:
+            rval = (mFlags & kFlagStickyError) ? "at Error state" : "at Released state";
+            break;
+        case INITIALIZING: rval = "while constructing"; break;
+        case INITIALIZED: rval = "at Uninitialized state"; break;
+        case CONFIGURING: rval = "during configure()"; break;
+        case CONFIGURED: rval = "at Configured state"; break;
+        case STARTING: rval = "during start()"; break;
+        case STARTED: rval = "at Running state"; break;
+        case FLUSHING: rval = "during flush()"; break;
+        case FLUSHED: rval = "at Flushed state"; break;
+        case STOPPING: rval = "during stop()"; break;
+        case RELEASING: rval = "during release()"; break;
+        default:
+            snprintf(rawbuffer, sizeof(rawbuffer), "at %d", mState);
+            rval = rawbuffer;
+            break;
+    }
+    return rval;
+}
+
 std::string MediaCodec::stateString(State state) {
     const char *rval = NULL;
     char rawbuffer[16]; // room for "%d"
diff --git a/media/libstagefright/httplive/fuzzer/Android.bp b/media/libstagefright/httplive/fuzzer/Android.bp
index 85fd8b7..dd49714 100644
--- a/media/libstagefright/httplive/fuzzer/Android.bp
+++ b/media/libstagefright/httplive/fuzzer/Android.bp
@@ -62,5 +62,13 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libstagefright_httplive",
+        vector: "remote",
+        service_privilege: "privileged",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
diff --git a/media/libstagefright/include/media/stagefright/CodecErrorLog.h b/media/libstagefright/include/media/stagefright/CodecErrorLog.h
new file mode 100644
index 0000000..673117a
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/CodecErrorLog.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC_ERROR_LOG_H_
+
+#define CODEC_ERROR_LOG_H_
+
+#include <sstream>
+#include <string>
+
+#include <android-base/thread_annotations.h>
+
+#include <media/stagefright/foundation/AString.h>
+
+namespace android {
+
+/**
+ * CodecErrorLog gathers what happened during codec failures, and make them
+ * available to clients for debugging purpose.
+ */
+class CodecErrorLog {
+public:
+    CodecErrorLog() = default;
+
+    /**
+     * Log a line of message.
+     *
+     * \note the message should be readable to developers who may not be
+     *       familiar with MediaCodec internals
+     */
+    void log(const char *tag, const char *message);
+    void log(const char *tag, const std::string &message);
+
+    /**
+     * Extract the accumulated log as string. This operation clears the log.
+     */
+    std::string extract();
+
+    /**
+     * Clears the previous log.
+     */
+    void clear();
+
+private:
+    mutable std::mutex mLock;
+    std::stringstream mStream GUARDED_BY(mLock);
+};
+
+}  // namespace android
+
+#endif  // CODEC_ERROR_LOG_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 29b196f..ec2d13b 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -28,6 +28,7 @@
 #include <media/MediaMetrics.h>
 #include <media/MediaProfiles.h>
 #include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/CodecErrorLog.h>
 #include <media/stagefright/FrameRenderTracker.h>
 #include <utils/Vector.h>
 
@@ -297,6 +298,8 @@
         T value;
     };
 
+    inline CodecErrorLog &getErrorLog() { return mErrorLog; }
+
 protected:
     virtual ~MediaCodec();
     virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -321,6 +324,7 @@
         RELEASING,
     };
     std::string stateString(State state);
+    std::string apiStateString();
 
     enum {
         kPortIndexInput         = 0,
@@ -692,6 +696,8 @@
     std::function<status_t(const AString &, sp<MediaCodecInfo> *)> mGetCodecInfo;
     friend class MediaTestHelper;
 
+    CodecErrorLog mErrorLog;
+
     DISALLOW_EVIL_CONSTRUCTORS(MediaCodec);
 };
 
diff --git a/media/libstagefright/tests/HEVC/Android.bp b/media/libstagefright/tests/HEVC/Android.bp
index 7f2ff12..7a0ba52 100644
--- a/media/libstagefright/tests/HEVC/Android.bp
+++ b/media/libstagefright/tests/HEVC/Android.bp
@@ -56,7 +56,4 @@
             "signed-integer-overflow",
         ],
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/HEVCUtils/HEVCUtilsUnitTest.zip?unzip=true",
-    ],
 }
diff --git a/media/libstagefright/tests/extractorFactory/Android.bp b/media/libstagefright/tests/extractorFactory/Android.bp
index 20ebe44..a067284 100644
--- a/media/libstagefright/tests/extractorFactory/Android.bp
+++ b/media/libstagefright/tests/extractorFactory/Android.bp
@@ -66,7 +66,4 @@
             "signed-integer-overflow",
         ],
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip?unzip=true",
-    ],
 }
diff --git a/media/libstagefright/timedtext/test/Android.bp b/media/libstagefright/timedtext/test/Android.bp
index 953da79..ae97c50 100644
--- a/media/libstagefright/timedtext/test/Android.bp
+++ b/media/libstagefright/timedtext/test/Android.bp
@@ -62,7 +62,4 @@
             "signed-integer-overflow",
         ],
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/timedtext/test/TimedTextUnitTest.zip?unzip=true",
-    ],
 }
diff --git a/media/libstagefright/writer_fuzzers/Android.bp b/media/libstagefright/writer_fuzzers/Android.bp
index b81f27e..58aa7cd 100644
--- a/media/libstagefright/writer_fuzzers/Android.bp
+++ b/media/libstagefright/writer_fuzzers/Android.bp
@@ -57,6 +57,14 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzers target the APIs of all the various writers",
+        vector: "local_no_privileges_required",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
 
diff --git a/media/module/codecs/amrnb/dec/test/Android.bp b/media/module/codecs/amrnb/dec/test/Android.bp
index de69cfc..74258e0 100644
--- a/media/module/codecs/amrnb/dec/test/Android.bp
+++ b/media/module/codecs/amrnb/dec/test/Android.bp
@@ -58,7 +58,4 @@
             "signed-integer-overflow",
         ],
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.zip?unzip=true",
-    ],
 }
diff --git a/media/module/codecs/amrnb/enc/fuzzer/Android.bp b/media/module/codecs/amrnb/enc/fuzzer/Android.bp
index 2c041b7..bcbcee2 100644
--- a/media/module/codecs/amrnb/enc/fuzzer/Android.bp
+++ b/media/module/codecs/amrnb/enc/fuzzer/Android.bp
@@ -48,5 +48,13 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libstagefright_amrnbenc library",
+        vector: "local_no_privileges_required",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
diff --git a/media/module/codecs/amrnb/enc/test/Android.bp b/media/module/codecs/amrnb/enc/test/Android.bp
index 5871486..7e393e3 100644
--- a/media/module/codecs/amrnb/enc/test/Android.bp
+++ b/media/module/codecs/amrnb/enc/test/Android.bp
@@ -58,7 +58,4 @@
             "signed-integer-overflow",
         ],
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.zip?unzip=true",
-    ],
 }
diff --git a/media/module/codecs/amrnb/fuzzer/Android.bp b/media/module/codecs/amrnb/fuzzer/Android.bp
index 833a7ba..3f29267 100644
--- a/media/module/codecs/amrnb/fuzzer/Android.bp
+++ b/media/module/codecs/amrnb/fuzzer/Android.bp
@@ -48,5 +48,13 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libstagefright_amrnbdec library",
+        vector: "remote",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
diff --git a/media/module/codecs/amrwb/dec/fuzzer/Android.bp b/media/module/codecs/amrwb/dec/fuzzer/Android.bp
index 16f08fa..31a20ff 100644
--- a/media/module/codecs/amrwb/dec/fuzzer/Android.bp
+++ b/media/module/codecs/amrwb/dec/fuzzer/Android.bp
@@ -48,5 +48,13 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libstagefright_amrwbdec library",
+        vector: "remote",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
diff --git a/media/module/codecs/amrwb/dec/test/Android.bp b/media/module/codecs/amrwb/dec/test/Android.bp
index 7ea39ef..7d0c964 100644
--- a/media/module/codecs/amrwb/dec/test/Android.bp
+++ b/media/module/codecs/amrwb/dec/test/Android.bp
@@ -57,7 +57,4 @@
             "signed-integer-overflow",
         ],
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.zip?unzip=true",
-    ],
 }
diff --git a/media/module/codecs/amrwb/enc/fuzzer/Android.bp b/media/module/codecs/amrwb/enc/fuzzer/Android.bp
index f74fa4f..c2c13e1 100644
--- a/media/module/codecs/amrwb/enc/fuzzer/Android.bp
+++ b/media/module/codecs/amrwb/enc/fuzzer/Android.bp
@@ -48,5 +48,13 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libstagefright_amrwbenc library",
+        vector: "local_no_privileges_required",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
diff --git a/media/module/codecs/amrwb/enc/test/Android.bp b/media/module/codecs/amrwb/enc/test/Android.bp
index f095d62..942f6c9 100644
--- a/media/module/codecs/amrwb/enc/test/Android.bp
+++ b/media/module/codecs/amrwb/enc/test/Android.bp
@@ -57,7 +57,4 @@
             "signed-integer-overflow",
         ],
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.zip?unzip=true",
-    ],
 }
diff --git a/media/module/codecs/g711/fuzzer/Android.bp b/media/module/codecs/g711/fuzzer/Android.bp
index 376cce7..397fb9a 100644
--- a/media/module/codecs/g711/fuzzer/Android.bp
+++ b/media/module/codecs/g711/fuzzer/Android.bp
@@ -44,6 +44,14 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of codecs_g711dec library with a special focus on Alaw APIs",
+        vector: "remote",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
 
@@ -61,5 +69,13 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of codecs_g711dec library with a special focus on Mlaw APIs",
+        vector: "remote",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
diff --git a/media/module/codecs/m4v_h263/dec/test/Android.bp b/media/module/codecs/m4v_h263/dec/test/Android.bp
index 9dc756c..d8de569 100644
--- a/media/module/codecs/m4v_h263/dec/test/Android.bp
+++ b/media/module/codecs/m4v_h263/dec/test/Android.bp
@@ -76,7 +76,4 @@
         ],
         cfi: true,
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder-1.1.zip?unzip=true",
-    ],
 }
diff --git a/media/module/codecs/m4v_h263/enc/test/Android.bp b/media/module/codecs/m4v_h263/enc/test/Android.bp
index d75e2d1..2b5e49c 100644
--- a/media/module/codecs/m4v_h263/enc/test/Android.bp
+++ b/media/module/codecs/m4v_h263/enc/test/Android.bp
@@ -55,7 +55,4 @@
         ],
         cfi: true,
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip?unzip=true",
-    ],
 }
diff --git a/media/module/codecs/m4v_h263/fuzzer/Android.bp b/media/module/codecs/m4v_h263/fuzzer/Android.bp
index a052c11..4d0ed18 100644
--- a/media/module/codecs/m4v_h263/fuzzer/Android.bp
+++ b/media/module/codecs/m4v_h263/fuzzer/Android.bp
@@ -50,6 +50,14 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzers target the APIs of libstagefright_m4vh263dec library",
+        vector: "remote",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
 
@@ -98,6 +106,14 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzers target the APIs of libstagefright_m4vh263enc library",
+        vector: "local_no_privileges_required",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
 
diff --git a/media/module/codecs/mp3dec/fuzzer/Android.bp b/media/module/codecs/mp3dec/fuzzer/Android.bp
index 514a8a8..c5e0b1f 100644
--- a/media/module/codecs/mp3dec/fuzzer/Android.bp
+++ b/media/module/codecs/mp3dec/fuzzer/Android.bp
@@ -44,5 +44,13 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libstagefright_mp3dec",
+        vector: "remote",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
diff --git a/media/module/codecs/mp3dec/test/Android.bp b/media/module/codecs/mp3dec/test/Android.bp
index dd06bdc..f10b6ae 100644
--- a/media/module/codecs/mp3dec/test/Android.bp
+++ b/media/module/codecs/mp3dec/test/Android.bp
@@ -56,7 +56,4 @@
             "signed-integer-overflow",
         ],
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest-1.2.zip?unzip=true",
-    ],
 }
diff --git a/media/module/codecserviceregistrant/fuzzer/Android.bp b/media/module/codecserviceregistrant/fuzzer/Android.bp
index 0b9affd..1cb8c2b 100644
--- a/media/module/codecserviceregistrant/fuzzer/Android.bp
+++ b/media/module/codecserviceregistrant/fuzzer/Android.bp
@@ -41,5 +41,13 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libmedia_codecserviceregistrant",
+        vector: "local_no_privileges_required",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
diff --git a/media/module/extractors/fuzzers/Android.bp b/media/module/extractors/fuzzers/Android.bp
index b3e34d2..91ca7b1 100644
--- a/media/module/extractors/fuzzers/Android.bp
+++ b/media/module/extractors/fuzzers/Android.bp
@@ -72,6 +72,14 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzers targets the APIs of all the various extractors",
+        vector: "remote",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
 
diff --git a/media/module/extractors/tests/Android.bp b/media/module/extractors/tests/Android.bp
index f5eadbd..d6e79c7 100644
--- a/media/module/extractors/tests/Android.bp
+++ b/media/module/extractors/tests/Android.bp
@@ -100,7 +100,4 @@
             "signed-integer-overflow",
         ],
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.4.zip?unzip=true",
-    ],
 }
diff --git a/media/module/foundation/tests/OpusHeader/Android.bp b/media/module/foundation/tests/OpusHeader/Android.bp
index f052650..fa2b40e 100644
--- a/media/module/foundation/tests/OpusHeader/Android.bp
+++ b/media/module/foundation/tests/OpusHeader/Android.bp
@@ -54,7 +54,4 @@
         ],
         cfi: true,
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/OpusHeader/OpusHeader.zip?unzip=true",
-    ],
 }
diff --git a/media/module/id3/test/Android.bp b/media/module/id3/test/Android.bp
index 0481e48..52cdfa5 100644
--- a/media/module/id3/test/Android.bp
+++ b/media/module/id3/test/Android.bp
@@ -57,7 +57,4 @@
             "signed-integer-overflow",
         ],
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test-1.2.zip?unzip=true",
-    ],
 }
diff --git a/media/module/libmediatranscoding/transcoder/benchmark/Android.bp b/media/module/libmediatranscoding/transcoder/benchmark/Android.bp
index f98b27d..459f0ae 100644
--- a/media/module/libmediatranscoding/transcoder/benchmark/Android.bp
+++ b/media/module/libmediatranscoding/transcoder/benchmark/Android.bp
@@ -26,25 +26,16 @@
     name: "MediaTranscoderBenchmark",
     srcs: ["MediaTranscoderBenchmark.cpp"],
     defaults: ["benchmarkdefaults"],
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
-    ],
 }
 
 cc_test {
     name: "MediaSampleReaderBenchmark",
     srcs: ["MediaSampleReaderBenchmark.cpp"],
     defaults: ["benchmarkdefaults"],
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
-    ],
 }
 
 cc_test {
     name: "MediaTrackTranscoderBenchmark",
     srcs: ["MediaTrackTranscoderBenchmark.cpp"],
     defaults: ["benchmarkdefaults"],
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
-    ],
 }
diff --git a/media/module/mpeg2ts/test/Android.bp b/media/module/mpeg2ts/test/Android.bp
index 4b1bacd..34a8d3e 100644
--- a/media/module/mpeg2ts/test/Android.bp
+++ b/media/module/mpeg2ts/test/Android.bp
@@ -74,7 +74,4 @@
             "signed-integer-overflow",
         ],
     },
-    data: [
-        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.zip?unzip=true",
-    ],
 }
diff --git a/media/utils/include/mediautils/MethodStatistics.h b/media/utils/include/mediautils/MethodStatistics.h
index 6d7e990..c8b36d8 100644
--- a/media/utils/include/mediautils/MethodStatistics.h
+++ b/media/utils/include/mediautils/MethodStatistics.h
@@ -59,7 +59,7 @@
     void event(C&& code, FloatType executeMs) {
         std::lock_guard lg(mLock);
         auto it = mStatisticsMap.lower_bound(code);
-        if (it != mStatisticsMap.end() && it->first == code) {
+        if (it != mStatisticsMap.end() && it->first == static_cast<Code>(code)) {
             it->second.add(executeMs);
         } else {
             // StatsType ctor takes an optional array of data for initialization.
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 6d4c3a3..f1797e6 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -19,11 +19,127 @@
     ],
 }
 
+tidy_errors = [
+    // https://clang.llvm.org/extra/clang-tidy/checks/list.html
+    // For many categories, the checks are too many to specify individually.
+    // Feel free to disable as needed - as warnings are generally ignored,
+    // we treat warnings as errors.
+    "android-*",
+    "bugprone-*",
+    "cert-*",
+    "clang-analyzer-security*",
+    "google-*",
+    "misc-*",
+    //"modernize-*",  // explicitly list the modernize as they can be subjective.
+    "modernize-avoid-bind",
+    //"modernize-avoid-c-arrays", // std::array<> can be verbose
+    "modernize-concat-nested-namespaces",
+    //"modernize-deprecated-headers", // C headers still ok even if there is C++ equivalent.
+    "modernize-deprecated-ios-base-aliases",
+    "modernize-loop-convert",
+    "modernize-make-shared",
+    "modernize-make-unique",
+    // "modernize-pass-by-value",
+    "modernize-raw-string-literal",
+    "modernize-redundant-void-arg",
+    "modernize-replace-auto-ptr",
+    "modernize-replace-random-shuffle",
+    "modernize-return-braced-init-list",
+    "modernize-shrink-to-fit",
+    "modernize-unary-static-assert",
+    // "modernize-use-auto",  // found in MediaMetricsService.h, debatable - auto can obscure type
+    "modernize-use-bool-literals",
+    "modernize-use-default-member-init",
+    "modernize-use-emplace",
+    "modernize-use-equals-default",
+    "modernize-use-equals-delete",
+    // "modernize-use-nodiscard",
+    "modernize-use-noexcept",
+    "modernize-use-nullptr",
+    "modernize-use-override",
+    //"modernize-use-trailing-return-type", // not necessarily more readable
+    "modernize-use-transparent-functors",
+    "modernize-use-uncaught-exceptions",
+    "modernize-use-using",
+    "performance-*",
+
+    // Remove some pedantic stylistic requirements.
+    "-google-readability-casting", // C++ casts not always necessary and may be verbose
+    "-google-readability-todo",    // do not require TODO(info)
+
+    "-bugprone-unhandled-self-assignment",
+    "-bugprone-suspicious-string-compare",
+    "-cert-oop54-cpp", // found in TransactionLog.h
+    "-bugprone-narrowing-conversions", // b/182410845
+
+    // TODO(b/275642749) Reenable these warnings
+    "-bugprone-assignment-in-if-condition",
+    "-bugprone-forward-declaration-namespace",
+    "-bugprone-parent-virtual-call",
+    "-cert-dcl59-cpp",
+    "-cert-err34-c",
+    "-google-build-namespaces",
+    "-google-build-using-namespace",
+    "-google-default-arguments",
+    "-google-runtime-int",
+    "-misc-const-correctness",
+    "-misc-non-private-member-variables-in-classes",
+    "-modernize-concat-nested-namespaces",
+    "-modernize-loop-convert",
+    "-modernize-use-default-member-init",
+    "-modernize-use-equals-default",
+    "-modernize-use-nullptr",
+    "-modernize-use-override",
+    "-modernize-use-using",
+    "-performance-no-int-to-ptr",
+]
+
+// Eventually use common tidy defaults
+cc_defaults {
+    name: "audioflinger_flags_defaults",
+    // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+    // https://clang.llvm.org/docs/DiagnosticsReference.html
+    cflags: [
+        "-Wall",
+        "-Wdeprecated",
+        "-Werror",
+        "-Werror=implicit-fallthrough",
+        "-Werror=sometimes-uninitialized",
+        "-Werror=conditional-uninitialized",
+        "-Wextra",
+
+        // suppress some warning chatter.
+        "-Wno-deprecated-copy-with-dtor",
+        "-Wno-deprecated-copy-with-user-provided-dtor",
+
+        "-Wredundant-decls",
+        "-Wshadow",
+        "-Wstrict-aliasing",
+        "-fstrict-aliasing",
+        "-Wthread-safety",
+        //"-Wthread-safety-negative", // experimental - looks broken in R.
+        "-Wunreachable-code",
+        "-Wunreachable-code-break",
+        "-Wunreachable-code-return",
+        "-Wunused",
+        "-Wused-but-marked-unused",
+        "-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS",
+    ],
+    // https://clang.llvm.org/extra/clang-tidy/
+    tidy: true,
+    tidy_checks: tidy_errors,
+    tidy_checks_as_errors: tidy_errors,
+    tidy_flags: [
+      "-format-style=file",
+    ],
+}
+
 cc_library_shared {
     name: "libaudioflinger",
 
     defaults: [
         "latest_android_media_audio_common_types_cpp_shared",
+        "audioflinger_flags_defaults",
     ],
 
     srcs: [
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index ba7c6b6..2ef4feb 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -229,6 +229,7 @@
 BINDER_METHOD_ENTRY(getAAudioMixerBurstCount) \
 BINDER_METHOD_ENTRY(getAAudioHardwareBurstMinUsec) \
 BINDER_METHOD_ENTRY(setDeviceConnectedState) \
+BINDER_METHOD_ENTRY(setSimulateDeviceConnections) \
 BINDER_METHOD_ENTRY(setRequestedLatencyMode) \
 BINDER_METHOD_ENTRY(getSupportedLatencyModes) \
 BINDER_METHOD_ENTRY(setBluetoothVariableLatencyEnabled) \
@@ -499,6 +500,25 @@
     return final_result;
 }
 
+status_t AudioFlinger::setSimulateDeviceConnections(bool enabled) {
+    bool at_least_one_succeeded = false;
+    status_t last_error = INVALID_OPERATION;
+    Mutex::Autolock _l(mLock);
+    AutoMutex lock(mHardwareLock);
+    mHardwareStatus = AUDIO_HW_SET_SIMULATE_CONNECTIONS;
+    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+        sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
+        status_t result = dev->setSimulateDeviceConnections(enabled);
+        if (result == OK) {
+            at_least_one_succeeded = true;
+        } else {
+            last_error = result;
+        }
+    }
+    mHardwareStatus = AUDIO_HW_IDLE;
+    return at_least_one_succeeded ? OK : last_error;
+}
+
 // getDefaultVibratorInfo_l must be called with AudioFlinger lock held.
 std::optional<media::AudioVibratorInfo> AudioFlinger::getDefaultVibratorInfo_l() {
     if (mAudioVibratorInfos.empty()) {
@@ -694,7 +714,7 @@
 }
 
 status_t AudioFlinger::addEffectToHal(audio_port_handle_t deviceId,
-        audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+        audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
     AutoMutex lock(mHardwareLock);
     AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(hwModuleId);
     if (audioHwDevice == nullptr) {
@@ -704,7 +724,7 @@
 }
 
 status_t AudioFlinger::removeEffectFromHal(audio_port_handle_t deviceId,
-        audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+        audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
     AutoMutex lock(mHardwareLock);
     AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(hwModuleId);
     if (audioHwDevice == nullptr) {
@@ -822,6 +842,7 @@
 }
 
 status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
+NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
     if (!dumpAllowed()) {
         dumpPermissionDenial(fd, args);
@@ -924,7 +945,6 @@
         // to lookup the service if it's not running, as it will block for a second
         if (sMediaLogServiceAsBinder != 0) {
             dprintf(fd, "\nmedia.log:\n");
-            Vector<String16> args;
             sMediaLogServiceAsBinder->dump(fd, args);
         }
 
@@ -1421,8 +1441,9 @@
     if (NO_ERROR == ret) {
         Mutex::Autolock _l(mLock);
         mMode = mode;
-        for (size_t i = 0; i < mPlaybackThreads.size(); i++)
+        for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
             mPlaybackThreads.valueAt(i)->setMode(mode);
+        }
     }
 
     mediametrics::LogItem(mMetricsId)
@@ -1760,7 +1781,7 @@
 // forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mLock held
 void AudioFlinger::forwardParametersToDownstreamPatches_l(
         audio_io_handle_t upStream, const String8& keyValuePairs,
-        std::function<bool(const sp<PlaybackThread>&)> useThread)
+        const std::function<bool(const sp<PlaybackThread>&)>& useThread)
 {
     std::vector<PatchPanel::SoftwarePatch> swPatches;
     if (mPatchPanel.getDownstreamSoftwarePatches(upStream, &swPatches) != OK) return;
@@ -1776,7 +1797,7 @@
 
 // Update downstream patches for all playback threads attached to an MSD module
 void AudioFlinger::updateDownStreamPatches_l(const struct audio_patch *patch,
-                                             const std::set<audio_io_handle_t> streams)
+                                             const std::set<audio_io_handle_t>& streams)
 {
     for (const audio_io_handle_t stream : streams) {
         PlaybackThread *playbackThread = checkPlaybackThread_l(stream);
@@ -1982,24 +2003,29 @@
     mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
 
     sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+
     std::vector<audio_channel_mask_t> channelMasks = {channelMask};
-    if (channelMask != AUDIO_CHANNEL_IN_MONO)
+    if (channelMask != AUDIO_CHANNEL_IN_MONO) {
         channelMasks.push_back(AUDIO_CHANNEL_IN_MONO);
-    if (channelMask != AUDIO_CHANNEL_IN_STEREO)
+    }
+    if (channelMask != AUDIO_CHANNEL_IN_STEREO) {
         channelMasks.push_back(AUDIO_CHANNEL_IN_STEREO);
+    }
 
     std::vector<audio_format_t> formats = {format};
-    if (format != AUDIO_FORMAT_PCM_16_BIT)
+    if (format != AUDIO_FORMAT_PCM_16_BIT) {
         formats.push_back(AUDIO_FORMAT_PCM_16_BIT);
+    }
 
     std::vector<uint32_t> sampleRates = {sampleRate};
     static const uint32_t SR_44100 = 44100;
     static const uint32_t SR_48000 = 48000;
-
-    if (sampleRate != SR_48000)
+    if (sampleRate != SR_48000) {
         sampleRates.push_back(SR_48000);
-    if (sampleRate != SR_44100)
+    }
+    if (sampleRate != SR_44100) {
         sampleRates.push_back(SR_44100);
+    }
 
     mHardwareStatus = AUDIO_HW_IDLE;
 
@@ -2468,7 +2494,7 @@
         // session and move it to this thread.
         sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
         if (chain != 0) {
-            Mutex::Autolock _l(thread->mLock);
+            Mutex::Autolock _l2(thread->mLock);
             thread->addEffectChain_l(chain);
         }
         break;
@@ -2848,7 +2874,7 @@
 sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
                                                         audio_io_handle_t *output,
                                                         audio_config_t *halConfig,
-                                                        audio_config_base_t *mixerConfig __unused,
+                                                        audio_config_base_t *mixerConfig,
                                                         audio_devices_t deviceType,
                                                         const String8& address,
                                                         audio_output_flags_t flags)
@@ -2970,7 +2996,6 @@
             aidl2legacy_int32_t_audio_output_flags_t_mask(request.flags));
 
     audio_io_handle_t output;
-    uint32_t latencyMs;
 
     ALOGI("openOutput() this %p, module %d Device %s, SamplingRate %d, Format %#08x, "
               "Channels %#x, flags %#x",
@@ -2993,6 +3018,7 @@
     sp<ThreadBase> thread = openOutput_l(module, &output, &halConfig,
             &mixerConfig, deviceType, address, flags);
     if (thread != 0) {
+        uint32_t latencyMs = 0;
         if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0) {
             PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
             latencyMs = playbackThread->latency();
@@ -3341,7 +3367,7 @@
                         continue;
                     }
                     if (t->hasAudioSession(chain->sessionId()) != 0) {
-                        Mutex::Autolock _l(t->mLock);
+                        Mutex::Autolock _l2(t->mLock);
                         ALOGV("closeInput() found thread %d for effect session %d",
                               t->id(), chain->sessionId());
                         t->addEffectChain_l(chain);
@@ -3546,7 +3572,8 @@
     }
 
     for (size_t i = 0; i < chains.size(); i++) {
-        sp<EffectChain> ec = chains[i];
+         // clang-tidy suggests const ref
+        sp<EffectChain> ec = chains[i];  // NOLINT(performance-unnecessary-copy-initialization)
         int sessionid = ec->sessionId();
         sp<ThreadBase> t = ec->thread().promote();
         if (t == 0) {
@@ -3715,7 +3742,7 @@
     PlaybackThread *thread = primaryPlaybackThread_l();
 
     if (thread == NULL) {
-        return DeviceTypeSet();
+        return {};
     }
 
     return thread->outDeviceTypes();
@@ -4227,7 +4254,7 @@
             // session and used it instead of creating a new one.
             sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
             if (chain != 0) {
-                Mutex::Autolock _l(thread->mLock);
+                Mutex::Autolock _l2(thread->mLock);
                 thread->addEffectChain_l(chain);
             }
         }
@@ -4345,6 +4372,7 @@
 status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
                                    AudioFlinger::PlaybackThread *srcThread,
                                    AudioFlinger::PlaybackThread *dstThread)
+NO_THREAD_SAFETY_ANALYSIS // requires srcThread and dstThread locks
 {
     ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
             sessionId, srcThread, dstThread);
@@ -4374,11 +4402,12 @@
     // transfer all effects one by one so that new effect chain is created on new thread with
     // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
     sp<EffectChain> dstChain;
-    sp<EffectModule> effect = chain->getEffectFromId_l(0);
     Vector< sp<EffectModule> > removed;
     status_t status = NO_ERROR;
     std::string errorString;
-    while (effect != nullptr) {
+    // process effects one by one.
+    for (sp<EffectModule> effect = chain->getEffectFromId_l(0); effect != nullptr;
+            effect = chain->getEffectFromId_l(0)) {
         srcThread->removeEffect_l(effect);
         removed.add(effect);
         status = dstThread->addEffect_l(effect);
@@ -4399,7 +4428,6 @@
                 break;
             }
         }
-        effect = chain->getEffectFromId_l(0);
     }
 
     size_t restored = 0;
@@ -4503,6 +4531,7 @@
 }
 
 bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l()
+NO_THREAD_SAFETY_ANALYSIS  // thread lock for getEffectChain_l.
 {
     if (mGlobalEffectEnableTime != 0 &&
             ((systemTime() - mGlobalEffectEnableTime) < kMinGlobalEffectEnabletimeNs)) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index ebfe32c..9079be9 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -293,6 +293,8 @@
 
     virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected);
 
+    virtual status_t setSimulateDeviceConnections(bool enabled);
+
     virtual status_t setRequestedLatencyMode(
             audio_io_handle_t output, audio_latency_mode_t mode);
 
@@ -328,12 +330,12 @@
     static void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration);
 
     status_t addEffectToHal(audio_port_handle_t deviceId,
-            audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect);
+            audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect);
     status_t removeEffectFromHal(audio_port_handle_t deviceId,
-            audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect);
+            audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect);
 
     void updateDownStreamPatches_l(const struct audio_patch *patch,
-                                   const std::set<audio_io_handle_t> streams);
+                                   const std::set<audio_io_handle_t>& streams);
 
     std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l();
 
@@ -376,7 +378,7 @@
                   audio_session_t triggerSession,
                   audio_session_t listenerSession,
                   sync_event_callback_t callBack,
-                  wp<RefBase> cookie)
+                  const wp<RefBase>& cookie)
         : mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession),
           mCallback(callBack), mCookie(cookie)
         {}
@@ -848,7 +850,7 @@
                 void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices);
                 void forwardParametersToDownstreamPatches_l(
                         audio_io_handle_t upStream, const String8& keyValuePairs,
-                        std::function<bool(const sp<PlaybackThread>&)> useThread = nullptr);
+                        const std::function<bool(const sp<PlaybackThread>&)>& useThread = nullptr);
 
     // AudioStreamIn is immutable, so their fields are const.
     // For emphasis, we could also make all pointers to them be "const *",
@@ -861,7 +863,8 @@
 
         sp<DeviceHalInterface> hwDev() const { return audioHwDev->hwDevice(); }
 
-        AudioStreamIn(AudioHwDevice *dev, sp<StreamInHalInterface> in, audio_input_flags_t flags) :
+        AudioStreamIn(AudioHwDevice *dev, const sp<StreamInHalInterface>& in,
+                audio_input_flags_t flags) :
             audioHwDev(dev), stream(in), flags(flags) {}
         status_t read(void *buffer, size_t bytes, size_t *read) override {
             return stream->read(buffer, bytes, read);
@@ -932,6 +935,7 @@
         AUDIO_HW_GET_MASTER_MUTE,       // get_master_mute
         AUDIO_HW_GET_MICROPHONES,       // getMicrophones
         AUDIO_HW_SET_CONNECTED_STATE,   // setConnectedState
+        AUDIO_HW_SET_SIMULATE_CONNECTIONS, // setSimulateDeviceConnections
     };
 
     mutable     hardware_call_state                 mHardwareStatus;    // for dump only
diff --git a/services/audioflinger/AudioHwDevice.h b/services/audioflinger/AudioHwDevice.h
index 1749f3f..d071922 100644
--- a/services/audioflinger/AudioHwDevice.h
+++ b/services/audioflinger/AudioHwDevice.h
@@ -46,7 +46,7 @@
 
     AudioHwDevice(audio_module_handle_t handle,
                   const char *moduleName,
-                  sp<DeviceHalInterface> hwDevice,
+                  const sp<DeviceHalInterface>& hwDevice,
                   Flags flags)
         : mHandle(handle)
         , mModuleName(strdup(moduleName))
diff --git a/services/audioflinger/AutoPark.h b/services/audioflinger/AutoPark.h
index 9ac7b65..83f6b7d 100644
--- a/services/audioflinger/AutoPark.h
+++ b/services/audioflinger/AutoPark.h
@@ -58,4 +58,4 @@
     FastThreadState::Command    mPreviousCommand;
 };  // class AutoPark
 
-}   // namespace
+}   // namespace android
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index 3a8c1bc..8484f95 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -160,7 +160,9 @@
     return status;
 }
 
-void AudioFlinger::DeviceEffectManager::dump(int fd) {
+void AudioFlinger::DeviceEffectManager::dump(int fd)
+NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
+{
     const bool locked = dumpTryLock(mLock);
     if (!locked) {
         String8 result("DeviceEffectManager may be deadlocked\n");
@@ -264,7 +266,7 @@
     return false;
 }
 
-void AudioFlinger::DeviceEffectManager::CommandThread::sendCommand(sp<Command> command) {
+void AudioFlinger::DeviceEffectManager::CommandThread::sendCommand(const sp<Command>& command) {
     Mutex::Autolock _l(mLock);
     mCommands.push_back(command);
     mWaitWorkCV.signal();
diff --git a/services/audioflinger/DeviceEffectManager.h b/services/audioflinger/DeviceEffectManager.h
index d2faa70..493800e 100644
--- a/services/audioflinger/DeviceEffectManager.h
+++ b/services/audioflinger/DeviceEffectManager.h
@@ -47,11 +47,11 @@
            int32_t sessionId, int32_t deviceId,
            sp<EffectHalInterface> *effect);
     status_t addEffectToHal(audio_port_handle_t deviceId, audio_module_handle_t hwModuleId,
-            sp<EffectHalInterface> effect) {
+            const sp<EffectHalInterface>& effect) {
         return mAudioFlinger.addEffectToHal(deviceId, hwModuleId, effect);
     };
     status_t removeEffectFromHal(audio_port_handle_t deviceId, audio_module_handle_t hwModuleId,
-            sp<EffectHalInterface> effect) {
+            const sp<EffectHalInterface>& effect) {
         return mAudioFlinger.removeEffectFromHal(deviceId, hwModuleId, effect);
     };
 
@@ -73,7 +73,7 @@
             RELEASE_AUDIO_PATCH,
         };
 
-        CommandThread(DeviceEffectManager& manager)
+        explicit CommandThread(DeviceEffectManager& manager)
             : Thread(false), mManager(manager) {}
         ~CommandThread() override;
 
@@ -94,7 +94,7 @@
         class Command: public RefBase {
         public:
             Command() = default;
-            Command(int command, sp<CommandData> data)
+            Command(int command, const sp<CommandData>& data)
                 : mCommand(command), mData(data) {}
 
             int mCommand = -1;
@@ -117,13 +117,13 @@
 
         class ReleaseAudioPatchData : public CommandData {
         public:
-            ReleaseAudioPatchData(audio_patch_handle_t handle)
+            explicit ReleaseAudioPatchData(audio_patch_handle_t handle)
                 :   mHandle(handle) {}
 
             audio_patch_handle_t mHandle;
         };
 
-        void sendCommand(sp<Command> command);
+        void sendCommand(const sp<Command>& command);
 
         Mutex   mLock;
         Condition mWaitWorkCV;
@@ -145,7 +145,7 @@
 
 class DeviceEffectManagerCallback :  public EffectCallbackInterface {
 public:
-            DeviceEffectManagerCallback(DeviceEffectManager *manager)
+    explicit DeviceEffectManagerCallback(DeviceEffectManager *manager)
                 : mManager(*manager) {}
 
     status_t createEffectHal(const effect_uuid_t *pEffectUuid,
@@ -176,10 +176,10 @@
     size_t    frameCount() const override  { return 0; }
     uint32_t  latency() const override  { return 0; }
 
-    status_t addEffectToHal(sp<EffectHalInterface> effect __unused) override {
+    status_t addEffectToHal(const sp<EffectHalInterface>& /* effect */) override {
         return NO_ERROR;
     }
-    status_t removeEffectFromHal(sp<EffectHalInterface> effect __unused) override {
+    status_t removeEffectFromHal(const sp<EffectHalInterface>& /* effect */) override {
         return NO_ERROR;
     }
 
@@ -204,11 +204,11 @@
     int newEffectId() { return mManager.audioFlinger().nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT); }
 
     status_t addEffectToHal(audio_port_handle_t deviceId,
-            audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+            audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
         return mManager.addEffectToHal(deviceId, hwModuleId, effect);
     }
     status_t removeEffectFromHal(audio_port_handle_t deviceId,
-            audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+            audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
         return mManager.removeEffectFromHal(deviceId, hwModuleId, effect);
     }
 private:
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 98829d0..e912bff 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -498,6 +498,7 @@
 }
 
 void AudioFlinger::EffectBase::dump(int fd, const Vector<String16>& args __unused)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
 {
     String8 result;
 
@@ -1249,13 +1250,13 @@
         return -EINVAL;
     }
     if (cmdCode == EFFECT_CMD_GET_PARAM &&
-            (maxReplySize < sizeof(effect_param_t) ||
+            (maxReplySize < static_cast<signed>(sizeof(effect_param_t)) ||
                    param->psize > maxReplySize - sizeof(effect_param_t))) {
         android_errorWriteLog(0x534e4554, "29251553");
         return -EINVAL;
     }
     if (cmdCode == EFFECT_CMD_GET_PARAM &&
-            (sizeof(effect_param_t) > maxReplySize
+            (static_cast<signed>(sizeof(effect_param_t)) > maxReplySize
                     || param->psize > maxReplySize - sizeof(effect_param_t)
                     || param->vsize > maxReplySize - sizeof(effect_param_t)
                             - param->psize
@@ -1685,6 +1686,7 @@
 }
 
 void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
+NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
     EffectBase::dump(fd, args);
 
@@ -1939,7 +1941,7 @@
         }
         mCblkMemory.clear();    // free the shared memory before releasing the heap it belongs to
         // Client destructor must run with AudioFlinger client mutex locked
-        Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
+        Mutex::Autolock _l2(mClient->audioFlinger()->mClientLock);
         mClient.clear();
     }
 }
@@ -2003,14 +2005,14 @@
     }
 
     if (cmdCode == EFFECT_CMD_ENABLE) {
-        if (maxResponseSize < sizeof(int)) {
+        if (maxResponseSize < static_cast<signed>(sizeof(int))) {
             android_errorWriteLog(0x534e4554, "32095713");
             RETURN(BAD_VALUE);
         }
         writeToBuffer(NO_ERROR, response);
         return enable(_aidl_return);
     } else if (cmdCode == EFFECT_CMD_DISABLE) {
-        if (maxResponseSize < sizeof(int)) {
+        if (maxResponseSize < static_cast<signed>(sizeof(int))) {
             android_errorWriteLog(0x534e4554, "32095713");
             RETURN(BAD_VALUE);
         }
@@ -2034,7 +2036,7 @@
             RETURN(INVALID_OPERATION);
         }
 
-        if (maxResponseSize < sizeof(int)) {
+        if (maxResponseSize < (signed)sizeof(int)) {
             android_errorWriteLog(0x534e4554, "32095713");
             RETURN(BAD_VALUE);
         }
@@ -2043,7 +2045,7 @@
         // No need to trylock() here as this function is executed in the binder thread serving a
         // particular client process:  no risk to block the whole media server process or mixer
         // threads if we are stuck here
-        Mutex::Autolock _l(mCblk->lock);
+        Mutex::Autolock _l2(mCblk->lock);
         // keep local copy of index in case of client corruption b/32220769
         const uint32_t clientIndex = mCblk->clientIndex;
         const uint32_t serverIndex = mCblk->serverIndex;
@@ -2146,6 +2148,7 @@
 }
 
 void AudioFlinger::EffectHandle::dumpToBuffer(char* buffer, size_t size)
+NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
     bool locked = mCblk != NULL && AudioFlinger::dumpTryLock(mCblk->lock);
 
@@ -2400,7 +2403,7 @@
             }
         } else {
             effect->setInBuffer(mInBuffer);
-            if (idx_insert == previousSize) {
+            if (idx_insert == static_cast<ssize_t>(previousSize)) {
                 if (idx_insert != 0) {
                     mEffects[idx_insert-1]->configure();
                     mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
@@ -2460,7 +2463,7 @@
             }
             // remember position of first insert effect and by default
             // select this as insert position for new effect
-            if (idx_insert == size) {
+            if (idx_insert == static_cast<ssize_t>(size)) {
                 idx_insert = i;
             }
             // remember position of last insert effect claiming
@@ -2690,6 +2693,7 @@
 }
 
 void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
+NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
     String8 result;
 
@@ -3027,7 +3031,7 @@
 }
 
 status_t AudioFlinger::EffectChain::EffectCallback::addEffectToHal(
-        sp<EffectHalInterface> effect) {
+        const sp<EffectHalInterface>& effect) {
     status_t result = NO_INIT;
     sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
@@ -3043,7 +3047,7 @@
 }
 
 status_t AudioFlinger::EffectChain::EffectCallback::removeEffectFromHal(
-        sp<EffectHalInterface> effect) {
+        const sp<EffectHalInterface>& effect) {
     status_t result = NO_INIT;
     sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
@@ -3185,15 +3189,20 @@
     return t->frameCount();
 }
 
-uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const {
+uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const
+NO_THREAD_SAFETY_ANALYSIS  // latency_l() access
+{
     sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
+    // TODO(b/275956781) - this requires the thread lock.
     return t->latency_l();
 }
 
-void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const {
+void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const
+NO_THREAD_SAFETY_ANALYSIS  // setVolumeForOutput_l() access
+{
     sp<ThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
@@ -3437,7 +3446,7 @@
 }
 
 status_t AudioFlinger::DeviceEffectProxy::addEffectToHal(
-    sp<EffectHalInterface> effect) {
+        const sp<EffectHalInterface>& effect) {
     if (mHalEffect == nullptr) {
         return NO_INIT;
     }
@@ -3446,7 +3455,7 @@
 }
 
 status_t AudioFlinger::DeviceEffectProxy::removeEffectFromHal(
-    sp<EffectHalInterface> effect) {
+        const sp<EffectHalInterface>& effect) {
     if (mHalEffect == nullptr) {
         return NO_INIT;
     }
@@ -3484,7 +3493,9 @@
     return audio_channel_count_from_in_mask(channelMask());
 }
 
-void AudioFlinger::DeviceEffectProxy::dump(int fd, int spaces) {
+void AudioFlinger::DeviceEffectProxy::dump(int fd, int spaces)
+NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
+{
     const Vector<String16> args;
     EffectBase::dump(fd, args);
 
@@ -3563,7 +3574,7 @@
 }
 
 status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::addEffectToHal(
-        sp<EffectHalInterface> effect) {
+        const sp<EffectHalInterface>& effect) {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
         return NO_INIT;
@@ -3572,7 +3583,7 @@
 }
 
 status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::removeEffectFromHal(
-        sp<EffectHalInterface> effect) {
+        const sp<EffectHalInterface>& effect) {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
         return NO_INIT;
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 78788df..bad86bc 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -45,8 +45,8 @@
     // Non trivial methods usually implemented with help from ThreadBase:
     //   pay attention to mutex locking order
     virtual uint32_t latency() const { return 0; }
-    virtual status_t addEffectToHal(sp<EffectHalInterface> effect) = 0;
-    virtual status_t removeEffectFromHal(sp<EffectHalInterface> effect) = 0;
+    virtual status_t addEffectToHal(const sp<EffectHalInterface>& effect) = 0;
+    virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
     virtual void setVolumeForOutput(float left, float right) const = 0;
     virtual bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) = 0;
     virtual void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect,
@@ -159,8 +159,8 @@
     bool             isPinned() const { return mPinned; }
     void             unPin() { mPinned = false; }
 
-    void             lock() { mLock.lock(); }
-    void             unlock() { mLock.unlock(); }
+    void             lock() ACQUIRE(mLock) { mLock.lock(); }
+    void             unlock() RELEASE(mLock) { mLock.unlock(); }
 
     status_t         updatePolicyState();
 
@@ -459,10 +459,10 @@
 
     void process_l();
 
-    void lock() {
+    void lock() ACQUIRE(mLock) {
         mLock.lock();
     }
-    void unlock() {
+    void unlock() RELEASE(mLock) {
         mLock.unlock();
     }
 
@@ -605,8 +605,8 @@
         size_t frameCount() const override;
         uint32_t latency() const override;
 
-        status_t addEffectToHal(sp<EffectHalInterface> effect) override;
-        status_t removeEffectFromHal(sp<EffectHalInterface> effect) override;
+        status_t addEffectToHal(const sp<EffectHalInterface>& effect) override;
+        status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override;
         bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
         void setVolumeForOutput(float left, float right) const override;
 
@@ -721,8 +721,8 @@
 
     size_t removeEffect(const sp<EffectModule>& effect);
 
-    status_t addEffectToHal(sp<EffectHalInterface> effect);
-    status_t removeEffectFromHal(sp<EffectHalInterface> effect);
+    status_t addEffectToHal(const sp<EffectHalInterface>& effect);
+    status_t removeEffectFromHal(const sp<EffectHalInterface>& effect);
 
     const AudioDeviceTypeAddr& device() { return mDevice; };
     bool isOutput() const;
@@ -766,8 +766,8 @@
         size_t frameCount() const override  { return 0; }
         uint32_t latency() const override  { return 0; }
 
-        status_t addEffectToHal(sp<EffectHalInterface> effect) override;
-        status_t removeEffectFromHal(sp<EffectHalInterface> effect) override;
+        status_t addEffectToHal(const sp<EffectHalInterface>& effect) override;
+        status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override;
 
         bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
         void setVolumeForOutput(float left __unused, float right __unused) const override {}
diff --git a/services/audioflinger/FastCaptureDumpState.cpp b/services/audioflinger/FastCaptureDumpState.cpp
index b8b3866..243dfa5 100644
--- a/services/audioflinger/FastCaptureDumpState.cpp
+++ b/services/audioflinger/FastCaptureDumpState.cpp
@@ -51,4 +51,4 @@
                 periodSec * 1e3, mSilenced ? "true" : "false");
 }
 
-}   // android
+}  // namespace android
diff --git a/services/audioflinger/FastCaptureDumpState.h b/services/audioflinger/FastCaptureDumpState.h
index a1b8706..34ce456 100644
--- a/services/audioflinger/FastCaptureDumpState.h
+++ b/services/audioflinger/FastCaptureDumpState.h
@@ -38,6 +38,6 @@
     bool     mSilenced = false; // capture is silenced
 };
 
-}   // android
+}  // namespace android
 
 #endif  // ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
diff --git a/services/audioflinger/FastCaptureState.cpp b/services/audioflinger/FastCaptureState.cpp
index c4d5e45..918ba9c 100644
--- a/services/audioflinger/FastCaptureState.cpp
+++ b/services/audioflinger/FastCaptureState.cpp
@@ -42,4 +42,4 @@
     LOG_ALWAYS_FATAL("%s", __func__);
 }
 
-}   // android
+}  // namespace android
diff --git a/services/audioflinger/FastMixerDumpState.cpp b/services/audioflinger/FastMixerDumpState.cpp
index 3f20282..d041882 100644
--- a/services/audioflinger/FastMixerDumpState.cpp
+++ b/services/audioflinger/FastMixerDumpState.cpp
@@ -203,4 +203,4 @@
     }
 }
 
-}   // android
+}  // namespace android
diff --git a/services/audioflinger/FastMixerDumpState.h b/services/audioflinger/FastMixerDumpState.h
index 9b91cbc..294ef78 100644
--- a/services/audioflinger/FastMixerDumpState.h
+++ b/services/audioflinger/FastMixerDumpState.h
@@ -81,6 +81,6 @@
     TimestampVerifier<int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
 };
 
-}   // android
+}  // namespace android
 
 #endif  // ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
diff --git a/services/audioflinger/FastThread.h b/services/audioflinger/FastThread.h
index 3f6b206..2f0f73f 100644
--- a/services/audioflinger/FastThread.h
+++ b/services/audioflinger/FastThread.h
@@ -92,6 +92,6 @@
 
 };  // class FastThread
 
-}   // android
+}  // namespace android
 
 #endif  // ANDROID_AUDIO_FAST_THREAD_H
diff --git a/services/audioflinger/FastThreadDumpState.cpp b/services/audioflinger/FastThreadDumpState.cpp
index 964a725..e91073f 100644
--- a/services/audioflinger/FastThreadDumpState.cpp
+++ b/services/audioflinger/FastThreadDumpState.cpp
@@ -56,4 +56,4 @@
 }
 #endif
 
-}   // android
+}  // namespace android
diff --git a/services/audioflinger/FastThreadDumpState.h b/services/audioflinger/FastThreadDumpState.h
index 1ce0914..0b20e55 100644
--- a/services/audioflinger/FastThreadDumpState.h
+++ b/services/audioflinger/FastThreadDumpState.h
@@ -67,6 +67,6 @@
 
 };  // struct FastThreadDumpState
 
-}   // android
+}  // namespace android
 
 #endif  // ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
diff --git a/services/audioflinger/FastThreadState.h b/services/audioflinger/FastThreadState.h
index 54c0dc6..9fb4e06 100644
--- a/services/audioflinger/FastThreadState.h
+++ b/services/audioflinger/FastThreadState.h
@@ -50,6 +50,6 @@
     static const char *commandToString(Command command);
 };  // struct FastThreadState
 
-}   // android
+}  // namespace android
 
 #endif  // ANDROID_AUDIO_FAST_THREAD_STATE_H
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 68a3800..5555766 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -199,7 +199,7 @@
             return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE ||
                     mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE; }
 
-        void setThread(sp<ThreadBase> thread) { mThread = thread; }
+        void setThread(const sp<ThreadBase>& thread) { mThread = thread; }
         wp<ThreadBase> thread() const { return mThread; }
 
         // returns the latency of the patch (from record to playback).
diff --git a/services/audioflinger/StateQueue.cpp b/services/audioflinger/StateQueue.cpp
index 9d4188f..38ce2c2 100644
--- a/services/audioflinger/StateQueue.cpp
+++ b/services/audioflinger/StateQueue.cpp
@@ -187,7 +187,9 @@
 
 }   // namespace android
 
-// hack for gcc
+// Hack to avoid explicit template instantiation of
+// template class StateQueue<FastCaptureState>;
+// template class StateQueue<FastMixerState>;
 #ifdef STATE_QUEUE_INSTANTIATIONS
-#include STATE_QUEUE_INSTANTIATIONS
+#include STATE_QUEUE_INSTANTIATIONS  // NOLINT(bugprone-suspicious-include)
 #endif
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 37b8fe8..9e68cd3 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -374,7 +374,7 @@
         // try three times to get the clock offset, choose the one
         // with the minimum gap in measurements.
         const int tries = 3;
-        nsecs_t bestGap, measured;
+        nsecs_t bestGap = 0, measured = 0; // not required, initialized for clang-tidy
         for (int i = 0; i < tries; ++i) {
             const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC);
             const nsecs_t tbase = systemTime(clockbase);
@@ -623,6 +623,7 @@
 // sendConfigEvent_l() must be called with ThreadBase::mLock held
 // Can temporarily release the lock if waiting for a reply from processConfigEvents_l().
 status_t AudioFlinger::ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event)
+NO_THREAD_SAFETY_ANALYSIS  // condition variable
 {
     status_t status = NO_ERROR;
 
@@ -936,6 +937,7 @@
 }
 
 void AudioFlinger::ThreadBase::dump(int fd, const Vector<String16>& args)
+NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
     dprintf(fd, "\n%s thread %p, name %s, tid %d, type %d (%s):\n", isOutput() ? "Output" : "Input",
             this, mThreadName, getTid(), type(), threadTypeToString(type()));
@@ -1304,7 +1306,9 @@
 
 void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(bool enabled,
                                                            audio_session_t sessionId,
-                                                           bool threadLocked) {
+                                                           bool threadLocked)
+NO_THREAD_SAFETY_ANALYSIS  // manual locking
+{
     if (!threadLocked) {
         mLock.lock();
     }
@@ -1768,6 +1772,7 @@
 
 void AudioFlinger::ThreadBase::lockEffectChains_l(
         Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+NO_THREAD_SAFETY_ANALYSIS  // calls EffectChain::lock()
 {
     effectChains = mEffectChains;
     for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -1777,6 +1782,7 @@
 
 void AudioFlinger::ThreadBase::unlockEffectChains(
         const Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+NO_THREAD_SAFETY_ANALYSIS  // calls EffectChain::unlock()
 {
     for (size_t i = 0; i < effectChains.size(); i++) {
         effectChains[i]->unlock();
@@ -1884,7 +1890,7 @@
 
 template <typename T>
 void AudioFlinger::ThreadBase::ActiveTracks<T>::updatePowerState(
-        sp<ThreadBase> thread, bool force) {
+        const sp<ThreadBase>& thread, bool force) {
     // Updates ActiveTracks client uids to the thread wakelock.
     if (mActiveTracksGeneration != mLastActiveTracksGeneration || force) {
         thread->updateWakeLockUids_l(getWakeLockUids());
@@ -2716,6 +2722,7 @@
 
 // addTrack_l() must be called with ThreadBase::mLock held
 status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
+NO_THREAD_SAFETY_ANALYSIS  // release and re-acquire mLock
 {
     status_t status = ALREADY_EXISTS;
 
@@ -2825,6 +2832,9 @@
     if (!trackActive) {
         removeTrack_l(track);
     } else if (track->isFastTrack() || track->isOffloaded() || track->isDirect()) {
+        if (track->isPausePending()) {
+            track->pauseAck();
+        }
         track->mState = TrackBase::STOPPING_1;
     }
 
@@ -2865,7 +2875,7 @@
     if (initCheck() == NO_ERROR && mOutput->stream->getParameters(keys, &out_s8) == OK) {
         return out_s8;
     }
-    return String8();
+    return {};
 }
 
 status_t AudioFlinger::DirectOutputThread::selectPresentation(int presentationId, int programId) {
@@ -3575,10 +3585,10 @@
                 size_t numSamples = mNormalFrameCount
                         * (audio_channel_count_from_out_mask(mMixerChannelMask)
                                                              + mHapticChannelCount);
-                status_t result = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
+                const status_t allocateStatus = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
                         numSamples * sizeof(effect_buffer_t),
                         &halInBuffer);
-                if (result != OK) return result;
+                if (allocateStatus != OK) return allocateStatus;
 #ifdef FLOAT_EFFECT_CHAIN
                 buffer = halInBuffer ? halInBuffer->audioBuffer()->f32 : buffer;
 #else
@@ -3664,8 +3674,8 @@
             }
 
             // detach all tracks with same session ID from this chain
-            for (size_t i = 0; i < mTracks.size(); ++i) {
-                sp<Track> track = mTracks[i];
+            for (size_t j = 0; j < mTracks.size(); ++j) {
+                sp<Track> track = mTracks[j];
                 if (session == track->sessionId()) {
                     track->setMainBuffer(reinterpret_cast<effect_buffer_t*>(mSinkBuffer));
                     chain->decTrackCnt();
@@ -3718,6 +3728,7 @@
 }
 
 bool AudioFlinger::PlaybackThread::threadLoop()
+NO_THREAD_SAFETY_ANALYSIS  // manual locking of AudioFlinger
 {
     tlNBLogWriter = mNBLogWriter.get();
 
@@ -3786,7 +3797,7 @@
             // is more informational.
             if (mAudioFlinger->mLock.tryLock() == NO_ERROR) {
                 std::vector<PatchPanel::SoftwarePatch> swPatches;
-                double latencyMs;
+                double latencyMs = 0.; // not required; initialized for clang-tidy
                 status_t status = INVALID_OPERATION;
                 audio_patch_handle_t downstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
                 if (mAudioFlinger->mPatchPanel.getDownstreamSoftwarePatches(id(), &swPatches) == OK
@@ -3806,8 +3817,7 @@
                         ALOGVV("new downstream latency %lf ms", latencyMs);
                     } else {
                         ALOGD("out of range downstream latency %lf ms", latencyMs);
-                        if (latencyMs < minLatency) latencyMs = minLatency;
-                        else if (latencyMs > maxLatency) latencyMs = maxLatency;
+                        latencyMs = std::clamp(latencyMs, minLatency, maxLatency);
                     }
                     mDownstreamLatencyStatMs.add(latencyMs);
                 }
@@ -4489,6 +4499,7 @@
 
 // removeTracks_l() must be called with ThreadBase::mLock held
 void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp<Track> >& tracksToRemove)
+NO_THREAD_SAFETY_ANALYSIS  // release and re-acquire mLock
 {
     for (const auto& track : tracksToRemove) {
         mActiveTracks.remove(track);
@@ -4609,8 +4620,8 @@
                             "as it does not support audio patches",
                             patch->sinks[i].ext.device.type);
         type = static_cast<audio_devices_t>(type | patch->sinks[i].ext.device.type);
-        deviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
-                patch->sinks[i].ext.device.address));
+        deviceTypeAddrs.emplace_back(patch->sinks[i].ext.device.type,
+                patch->sinks[i].ext.device.address);
     }
 
     audio_port_handle_t sinkPortId = patch->sinks[0].id;
@@ -4818,14 +4829,15 @@
         // When it wakes up after a maximum latency, it runs a few cycles quickly before
         // finally blocking.  Note the pipe implementation rounds up the request to a power of 2.
         MonoPipe *monoPipe = new MonoPipe(mNormalFrameCount * 4, format, true /*writeCanBlock*/);
-        const NBAIO_Format offers[1] = {format};
-        size_t numCounterOffers = 0;
+        const NBAIO_Format offersFast[1] = {format};
+        size_t numCounterOffersFast = 0;
 #if !LOG_NDEBUG
         ssize_t index =
 #else
         (void)
 #endif
-                monoPipe->negotiate(offers, 1, NULL, numCounterOffers);
+                monoPipe->negotiate(offersFast, std::size(offersFast),
+                        nullptr /* counterOffers */, numCounterOffersFast);
         ALOG_ASSERT(index == 0);
         monoPipe->setAvgFrames((mScreenState & 1) ?
                 (monoPipe->maxFrames() * 7) / 8 : mNormalFrameCount * 2);
@@ -5237,7 +5249,7 @@
         // tallyUnderrunFrames() is called to update the track counters
         // with the number of underrun frames for a particular mixer period.
         // We defer tallying until we know the final mixer status.
-        void tallyUnderrunFrames(sp<Track> track, size_t underrunFrames) {
+        void tallyUnderrunFrames(const sp<Track>& track, size_t underrunFrames) {
             mUnderrunFrames.emplace_back(track, underrunFrames);
         }
 
@@ -5486,7 +5498,7 @@
         // during last round
         size_t desiredFrames;
         const uint32_t sampleRate = track->mAudioTrackServerProxy->getSampleRate();
-        AudioPlaybackRate playbackRate = track->mAudioTrackServerProxy->getPlaybackRate();
+        const AudioPlaybackRate playbackRate = track->mAudioTrackServerProxy->getPlaybackRate();
 
         desiredFrames = sourceFramesNeededWithTimestretch(
                 sampleRate, mNormalFrameCount, mSampleRate, playbackRate.mSpeed);
@@ -5670,12 +5682,12 @@
                 AudioMixer::SAMPLE_RATE,
                 (void *)(uintptr_t)reqSampleRate);
 
-            AudioPlaybackRate playbackRate = proxy->getPlaybackRate();
             mAudioMixer->setParameter(
                 trackId,
                 AudioMixer::TIMESTRETCH,
                 AudioMixer::PLAYBACK_RATE,
-                &playbackRate);
+                // cast away constness for this generic API.
+                const_cast<void *>(reinterpret_cast<const void *>(&playbackRate)));
 
             /*
              * Select the appropriate output buffer for the track.
@@ -6059,12 +6071,12 @@
             mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
             for (const auto &track : mTracks) {
                 const int trackId = track->id();
-                status_t status = mAudioMixer->create(
+                const status_t createStatus = mAudioMixer->create(
                         trackId,
                         track->mChannelMask,
                         track->mFormat,
                         track->mSessionId);
-                ALOGW_IF(status != NO_ERROR,
+                ALOGW_IF(createStatus != NO_ERROR,
                         "%s(): AudioMixer cannot create track(%d)"
                         " mask %#x, format %#x, sessionId %d",
                         __func__,
@@ -6193,12 +6205,17 @@
         if (left > GAIN_FLOAT_UNITY) {
             left = GAIN_FLOAT_UNITY;
         }
-        left *= v * mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
         right = float_from_gain(gain_minifloat_unpack_right(vlr));
         if (right > GAIN_FLOAT_UNITY) {
             right = GAIN_FLOAT_UNITY;
         }
-        right *= v * mMasterBalanceRight;
+        left *= v;
+        right *= v;
+        if (mAudioFlinger->getMode() != AUDIO_MODE_IN_COMMUNICATION
+                || audio_channel_count_from_out_mask(mChannelMask) > 1) {
+            left *= mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
+            right *= mMasterBalanceRight;
+        }
     }
 
     if (lastTrack) {
@@ -6236,7 +6253,8 @@
                 mFlushPending = true;
             }
         } else /* mType == OFFLOAD */ {
-            if (previousTrack->sessionId() != latestTrack->sessionId()) {
+            if (previousTrack->sessionId() != latestTrack->sessionId() ||
+                previousTrack->isFlushPending()) {
                 mFlushPending = true;
             }
         }
@@ -7111,7 +7129,7 @@
 void AudioFlinger::DuplicatingThread::threadLoop_mix()
 {
     // mix buffers...
-    if (outputsReady(outputTracks)) {
+    if (outputsReady()) {
         mAudioMixer->process();
     } else {
         if (mMixerBufferValid) {
@@ -7182,7 +7200,7 @@
     }
 }
 
-void AudioFlinger::DuplicatingThread::dumpInternals_l(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::DuplicatingThread::dumpInternals_l(int fd, const Vector<String16>& args)
 {
     MixerThread::dumpInternals_l(fd, args);
 
@@ -7286,9 +7304,7 @@
     }
 }
 
-
-bool AudioFlinger::DuplicatingThread::outputsReady(
-        const SortedVector< sp<OutputTrack> > &outputTracks)
+bool AudioFlinger::DuplicatingThread::outputsReady()
 {
     for (size_t i = 0; i < outputTracks.size(); i++) {
         sp<ThreadBase> thread = outputTracks[i]->thread().promote();
@@ -7617,14 +7633,16 @@
         // pipe will be shared directly with fast clients, so clear to avoid leaking old information
         memset(pipeBuffer, 0, pipeSize);
         Pipe *pipe = new Pipe(pipeFramesP2, format, pipeBuffer);
-        const NBAIO_Format offers[1] = {format};
-        size_t numCounterOffers = 0;
-        [[maybe_unused]] ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
+        const NBAIO_Format offersFast[1] = {format};
+        size_t numCounterOffersFast = 0;
+        [[maybe_unused]] ssize_t index = pipe->negotiate(offersFast, std::size(offersFast),
+                nullptr /* counterOffers */, numCounterOffersFast);
         ALOG_ASSERT(index == 0);
         mPipeSink = pipe;
         PipeReader *pipeReader = new PipeReader(*pipe);
-        numCounterOffers = 0;
-        index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers);
+        numCounterOffersFast = 0;
+        index = pipeReader->negotiate(offersFast, std::size(offersFast),
+                nullptr /* counterOffers */, numCounterOffersFast);
         ALOG_ASSERT(index == 0);
         mPipeSource = pipeReader;
         mPipeFramesP2 = pipeFramesP2;
@@ -7972,7 +7990,7 @@
         // copy to the right place.  Permitted because mRsmpInBuffer was over-allocated.
 
         int32_t rear = mRsmpInRear & (mRsmpInFramesP2 - 1);
-        ssize_t framesRead;
+        ssize_t framesRead = 0; // not needed, remove clang-tidy warning.
         const int64_t lastIoBeginNs = systemTime(); // start IO timing
 
         // If an NBAIO source is present, use it to read the normal capture's data
@@ -8165,8 +8183,9 @@
                     // straight from RecordThread buffer to RecordTrack buffer.
                     AudioBufferProvider::Buffer buffer;
                     buffer.frameCount = framesOut;
-                    status_t status = activeTrack->mResamplerBufferProvider->getNextBuffer(&buffer);
-                    if (status == OK && buffer.frameCount != 0) {
+                    const status_t getNextBufferStatus =
+                            activeTrack->mResamplerBufferProvider->getNextBuffer(&buffer);
+                    if (getNextBufferStatus == OK && buffer.frameCount != 0) {
                         ALOGV_IF(buffer.frameCount != framesOut,
                                 "%s() read less than expected (%zu vs %zu)",
                                 __func__, buffer.frameCount, framesOut);
@@ -8176,7 +8195,7 @@
                     } else {
                         framesOut = 0;
                         ALOGE("%s() cannot fill request, status: %d, frameCount: %zu",
-                            __func__, status, buffer.frameCount);
+                            __func__, getNextBufferStatus, buffer.frameCount);
                     }
                 } else {
                     // process frames from the RecordThread buffer provider to the RecordTrack
@@ -8596,7 +8615,6 @@
         //      or using a separate command thread
         recordTrack->mState = TrackBase::STARTING_1;
         mActiveTracks.add(recordTrack);
-        status_t status = NO_ERROR;
         if (recordTrack->isExternalTrack()) {
             mLock.unlock();
             status = AudioSystem::startInput(recordTrack->portId());
@@ -8787,7 +8805,7 @@
     // "best effort" behavior of the API.
     if (sharedOffset < 0) {
         sharedAudioStartFrames = mRsmpInRear;
-    } else if (sharedOffset > mRsmpInFrames) {
+    } else if (sharedOffset > static_cast<signed>(mRsmpInFrames)) {
         sharedAudioStartFrames =
                 audio_utils::safe_sub_overflow(mRsmpInRear, (int32_t)mRsmpInFrames);
     }
@@ -9162,7 +9180,7 @@
             return out_s8;
         }
     }
-    return String8();
+    return {};
 }
 
 void AudioFlinger::RecordThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
@@ -9397,7 +9415,7 @@
             maxFilled = filled;
         }
     }
-    if (maxFilled > mRsmpInFrames) {
+    if (maxFilled > static_cast<signed>(mRsmpInFrames)) {
         (void)__builtin_sub_overflow(mRsmpInRear, mRsmpInFrames, &oldestFront);
     }
     return oldestFront;
@@ -9589,7 +9607,7 @@
 
 AudioFlinger::MmapThread::MmapThread(
         const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
-        AudioHwDevice *hwDev, sp<StreamHalInterface> stream, bool systemReady, bool isOut)
+        AudioHwDevice *hwDev, const sp<StreamHalInterface>& stream, bool systemReady, bool isOut)
     : ThreadBase(audioFlinger, id, (isOut ? MMAP_PLAYBACK : MMAP_CAPTURE), systemReady, isOut),
       mSessionId(AUDIO_SESSION_NONE),
       mPortId(AUDIO_PORT_HANDLE_NONE),
@@ -9794,8 +9812,10 @@
         mHalVolFloat = -1.0f;
     } else if (!track->isSilenced_l()) {
         for (const sp<MmapTrack> &t : mActiveTracks) {
-            if (t->isSilenced_l() && t->uid() != client.attributionSource.uid)
+            if (t->isSilenced_l()
+                    && t->uid() != static_cast<uid_t>(client.attributionSource.uid)) {
                 t->invalidate();
+            }
         }
     }
 
@@ -10021,7 +10041,7 @@
     if (initCheck() == NO_ERROR && mHalStream->getParameters(keys, &out_s8) == OK) {
         return out_s8;
     }
-    return String8();
+    return {};
 }
 
 void AudioFlinger::MmapThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
@@ -10051,6 +10071,7 @@
 
 status_t AudioFlinger::MmapThread::createAudioPatch_l(const struct audio_patch *patch,
                                                           audio_patch_handle_t *handle)
+NO_THREAD_SAFETY_ANALYSIS  // elease and re-acquire mLock
 {
     status_t status = NO_ERROR;
 
@@ -10068,8 +10089,8 @@
                                 "as it does not support audio patches",
                                 patch->sinks[i].ext.device.type);
             type = static_cast<audio_devices_t>(type | patch->sinks[i].ext.device.type);
-            sinkDeviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
-                    patch->sinks[i].ext.device.address));
+            sinkDeviceTypeAddrs.emplace_back(patch->sinks[i].ext.device.type,
+                    patch->sinks[i].ext.device.address);
         }
         deviceId = patch->sinks[0].id;
         numDevices = mPatch.num_sinks;
@@ -10272,6 +10293,7 @@
 }
 
 void AudioFlinger::MmapThread::checkInvalidTracks_l()
+NO_THREAD_SAFETY_ANALYSIS  // release and re-acquire mLock
 {
     sp<MmapStreamCallback> callback;
     for (const sp<MmapTrack> &track : mActiveTracks) {
@@ -10426,6 +10448,7 @@
 }
 
 void AudioFlinger::MmapPlaybackThread::processVolume_l()
+NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l
 {
     float volume;
 
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index ce90767..63ad4e6 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -163,7 +163,7 @@
 
     class SetParameterConfigEventData : public ConfigEventData {
     public:
-        explicit SetParameterConfigEventData(String8 keyValuePairs) :
+        explicit SetParameterConfigEventData(const String8& keyValuePairs) :
             mKeyValuePairs(keyValuePairs) {}
 
         virtual  void dump(char *buffer, size_t size) {
@@ -175,7 +175,7 @@
 
     class SetParameterConfigEvent : public ConfigEvent {
     public:
-        explicit SetParameterConfigEvent(String8 keyValuePairs) :
+        explicit SetParameterConfigEvent(const String8& keyValuePairs) :
             ConfigEvent(CFG_EVENT_SET_PARAMETER) {
             mData = new SetParameterConfigEventData(keyValuePairs);
             mWaitStatus = true;
@@ -789,7 +789,7 @@
                     // ThreadBase thread.
                     void            clear();
                     // periodically called in the threadLoop() to update power state uids.
-                    void            updatePowerState(sp<ThreadBase> thread, bool force = false);
+                    void updatePowerState(const sp<ThreadBase>& thread, bool force = false);
 
                     /** @return true if one or move active tracks was added or removed since the
                      *          last time this function was called or the vector was created.
@@ -1260,7 +1260,7 @@
     template <typename T>
     class Tracks {
     public:
-        Tracks(bool saveDeletedTrackIds) :
+        explicit Tracks(bool saveDeletedTrackIds) :
             mSaveDeletedTrackIds(saveDeletedTrackIds) { }
 
         // SortedVector methods
@@ -1289,7 +1289,7 @@
             return mTracks.end();
         }
 
-        size_t          processDeletedTrackIds(std::function<void(int)> f) {
+        size_t          processDeletedTrackIds(const std::function<void(int)>& f) {
             for (const int trackId : mDeletedTrackIds) {
                 f(trackId);
             }
@@ -1411,7 +1411,7 @@
                 class IsTimestampAdvancing {
                 public:
                     // The timestamp will not be checked any faster than the specified time.
-                    IsTimestampAdvancing(nsecs_t minimumTimeBetweenChecksNs)
+                    explicit IsTimestampAdvancing(nsecs_t minimumTimeBetweenChecksNs)
                         :   mMinimumTimeBetweenChecksNs(minimumTimeBetweenChecksNs)
                     {
                         clear();
@@ -1700,7 +1700,7 @@
                 void        dumpInternals_l(int fd, const Vector<String16>& args) override;
 
 private:
-                bool        outputsReady(const SortedVector< sp<OutputTrack> > &outputTracks);
+                bool        outputsReady();
 protected:
     // threadLoop snippets
     virtual     void        threadLoop_mix();
@@ -2066,7 +2066,7 @@
 #include "MmapTracks.h"
 
     MmapThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
-               AudioHwDevice *hwDev, sp<StreamHalInterface> stream, bool systemReady,
+               AudioHwDevice *hwDev, const sp<StreamHalInterface>& stream, bool systemReady,
                bool isOut);
     virtual     ~MmapThread();
 
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 20bfbb0..42f7b47 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -122,7 +122,7 @@
              * This may be called without the thread lock.
              */
     virtual double      bufferLatencyMs() const {
-                            return mServerProxy->framesReadySafe() * 1000 / sampleRate();
+                            return mServerProxy->framesReadySafe() * 1000. / sampleRate();
                         }
 
             /** returns whether the track supports server latency computation.
@@ -430,7 +430,7 @@
 {
 public:
     using Timeout = std::optional<std::chrono::nanoseconds>;
-                        PatchTrackBase(sp<ClientProxy> proxy, const ThreadBase& thread,
+                        PatchTrackBase(const sp<ClientProxy>& proxy, const ThreadBase& thread,
                                        const Timeout& timeout);
             void        setPeerTimeout(std::chrono::nanoseconds timeout);
             template <typename T>
diff --git a/services/audioflinger/TrackMetrics.h b/services/audioflinger/TrackMetrics.h
index 6fc70d6..ed3928a 100644
--- a/services/audioflinger/TrackMetrics.h
+++ b/services/audioflinger/TrackMetrics.h
@@ -113,7 +113,8 @@
         mDeviceStartupMs.add(startupMs);
     }
 
-    void updateMinMaxVolume(int64_t durationNs, double deviceVolume) {
+    void updateMinMaxVolume_l(int64_t durationNs, double deviceVolume)
+            REQUIRES(mLock) {
         if (deviceVolume > mMaxVolume) {
             mMaxVolume = deviceVolume;
             mMaxVolumeDurationNs = durationNs;
@@ -165,7 +166,7 @@
             mDeviceTimeNs += durationNs;
             mCumulativeTimeNs += durationNs;
         }
-        updateMinMaxVolume(durationNs, mVolume); // always update.
+        updateMinMaxVolume_l(durationNs, mVolume); // always update.
         mVolume = volume;
         mLastVolumeChangeTimeNs = timeNs;
     }
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 300ad9f..123d5a9 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -303,7 +303,7 @@
     return NO_ERROR;
 }
 
-AudioFlinger::ThreadBase::PatchTrackBase::PatchTrackBase(sp<ClientProxy> proxy,
+AudioFlinger::ThreadBase::PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
                                                          const ThreadBase& thread,
                                                          const Timeout& timeout)
     : mProxy(proxy)
@@ -1298,8 +1298,9 @@
 // must be called with thread lock held
 void AudioFlinger::PlaybackThread::Track::flushAck()
 {
-    if (!isOffloaded() && !isDirect())
+    if (!isOffloaded() && !isDirect()) {
         return;
+    }
 
     // Clear the client ring buffer so that the app can prime the buffer while paused.
     // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
@@ -1812,23 +1813,23 @@
 
 //To be called with thread lock held
 bool AudioFlinger::PlaybackThread::Track::isResumePending() {
-
-    if (mState == RESUMING)
+    if (mState == RESUMING) {
         return true;
+    }
     /* Resume is pending if track was stopping before pause was called */
     if (mState == STOPPING_1 &&
-        mResumeToStopping)
+        mResumeToStopping) {
         return true;
+    }
 
     return false;
 }
 
 //To be called with thread lock held
 void AudioFlinger::PlaybackThread::Track::resumeAck() {
-
-
-    if (mState == RESUMING)
+    if (mState == RESUMING) {
         mState = ACTIVE;
+    }
 
     // Other possibility of  pending resume is stopping_1 state
     // Do not update the state from stopping as this prevents
@@ -2094,7 +2095,10 @@
         if (thread != 0 && !thread->standby()) {
             if (mBufferQueue.size() < kMaxOverFlowBuffers) {
                 pInBuffer = new Buffer;
-                pInBuffer->mBuffer = malloc(inBuffer.frameCount * mFrameSize);
+                const size_t bufferSize = inBuffer.frameCount * mFrameSize;
+                pInBuffer->mBuffer = malloc(bufferSize);
+                LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
+                        "%s: Unable to malloc size %zu", __func__, bufferSize);
                 pInBuffer->frameCount = inBuffer.frameCount;
                 pInBuffer->raw = pInBuffer->mBuffer;
                 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
@@ -2258,7 +2262,7 @@
     buf.mFrameCount = buffer->frameCount;
     buf.mRaw = buffer->raw;
     mPeerProxy->releaseBuffer(&buf);
-    TrackBase::releaseBuffer(buffer);
+    TrackBase::releaseBuffer(buffer); // Note: this is the base class.
 }
 
 status_t AudioFlinger::PlaybackThread::PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
@@ -2872,7 +2876,7 @@
 {
     void *ptr = nullptr;
     (void)posix_memalign(&ptr, alignment, size);
-    return std::unique_ptr<void, decltype(free)*>(ptr, free);
+    return {ptr, free};
 }
 
 AudioFlinger::RecordThread::PassthruPatchRecord::PassthruPatchRecord(
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 496591a..7ad9f6c 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -245,6 +245,8 @@
                                     unsigned int *num_ports,
                                     struct audio_port_v7 *ports,
                                     unsigned int *generation) = 0;
+    virtual status_t listDeclaredDevicePorts(media::AudioPortRole role,
+                                             std::vector<media::AudioPortFw>* result) = 0;
     virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
     virtual status_t createAudioPatch(const struct audio_patch *patch,
                                        audio_patch_handle_t *handle,
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index 7d21ae0..de501ee 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -162,6 +162,10 @@
 
     DeviceVector getActiveMediaDevices(const DeviceVector& availableDevices) const override;
 
+    void initializeDeviceSelectionCache() override;
+
+    void updateDeviceSelectionCache() override;
+
 private:
     /**
      * Get media devices as the given role
@@ -190,6 +194,28 @@
 
     /** current forced use configuration. */
     audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT] = {};
+
+protected:
+    /**
+     * Set the device information for a given strategy.
+     *
+     * @param strategy the strategy to set devices information
+     * @param devices the devices selected for the strategy
+     */
+    virtual void setStrategyDevices(const sp<ProductStrategy>& /*strategy*/,
+                                    const DeviceVector& /*devices*/) {
+        // In EngineBase, do nothing. It is up to the actual engine to decide if it is needed to
+        // set devices information for the given strategy.
+    }
+
+    /**
+     * Get devices that will be used for the given product strategy.
+     *
+     * @param strategy the strategy to query
+     */
+    virtual DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const = 0;
+
+    DeviceStrategyMap mDevicesForStrategies;
 };
 
 } // namespace audio_policy
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 99507ee..83a8e4d 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -627,6 +627,26 @@
     return activeDevices;
 }
 
+void EngineBase::initializeDeviceSelectionCache() {
+    // Initializing the device selection cache with default device won't be harmful, it will be
+    // updated after the audio modules are initialized.
+    auto defaultDevices = DeviceVector(getApmObserver()->getDefaultOutputDevice());
+    for (const auto &iter : getProductStrategies()) {
+        const auto &strategy = iter.second;
+        mDevicesForStrategies[strategy->getId()] = defaultDevices;
+        setStrategyDevices(strategy, defaultDevices);
+    }
+}
+
+void EngineBase::updateDeviceSelectionCache() {
+    for (const auto &iter : getProductStrategies()) {
+        const auto& strategy = iter.second;
+        auto devices = getDevicesForProductStrategy(strategy->getId());
+        mDevicesForStrategies[strategy->getId()] = devices;
+        setStrategyDevices(strategy, devices);
+    }
+}
+
 void EngineBase::dumpCapturePresetDevicesRoleMap(String8 *dst, int spaces) const
 {
     dst->appendFormat("\n%*sDevice role per capture preset dump:", spaces, "");
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index 518f86e..57174c7 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -421,6 +421,16 @@
      */
     virtual DeviceVector getActiveMediaDevices(const DeviceVector& availableDevices) const = 0;
 
+    /**
+     * @brief initializeDeviceSelectionCache. Device selection for AudioAttribute / Streams is
+     * cached in the engine in order to speed up process when the audio system is stable. When the
+     * audio system is initializing, not all audio devices information will be available. In that
+     * case, calling this function can allow the engine to initialize the device selection cache
+     * with default values.
+     * This must only be called when audio policy manager is initializing.
+     */
+    virtual void initializeDeviceSelectionCache() = 0;
+
     virtual void dump(String8 *dst) const = 0;
 
 protected:
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 2831a9b..a802646 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -354,14 +354,6 @@
     return availableInputDevices.getDevice(deviceType, String8(address.c_str()), AUDIO_FORMAT_DEFAULT);
 }
 
-void Engine::updateDeviceSelectionCache()
-{
-    for (const auto &iter : getProductStrategies()) {
-        const auto &strategy = iter.second;
-        mDevicesForStrategies[strategy->getId()] = getDevicesForProductStrategy(strategy->getId());
-    }
-}
-
 void Engine::setDeviceAddressForProductStrategy(product_strategy_t strategy,
                                                 const std::string &address)
 {
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 4b559f0..001dde9 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -66,8 +66,6 @@
                                                      sp<AudioPolicyMix> *mix = nullptr)
                                                      const override;
 
-    void updateDeviceSelectionCache() override;
-
     ///
     /// from AudioPolicyPluginInterface
     ///
@@ -122,15 +120,17 @@
 
     status_t loadAudioPolicyEngineConfig();
 
-    DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const;
     DeviceVector getCachedDevices(product_strategy_t ps) const;
 
+    ///
+    /// from EngineBase
+    ///
+    DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const override;
+
     /**
      * Policy Parameter Manager hidden through a wrapper.
      */
     ParameterManagerWrapper *mPolicyParameterMgr;
-
-    DeviceStrategyMap mDevicesForStrategies;
 };
 
 } // namespace audio_policy
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 45c5eac..e72249f 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -279,7 +279,8 @@
                         getLastRemovableMediaDevices(GROUP_NONE, {AUDIO_DEVICE_OUT_BLE_HEADSET}));
         if (!devices.isEmpty()) break;
         devices = availableOutputDevices.getFirstDevicesFromTypes({
-                AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_EARPIECE});
+                AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_EARPIECE,
+                AUDIO_DEVICE_OUT_SPEAKER});
     } break;
 
     case STRATEGY_SONIFICATION:
@@ -641,15 +642,9 @@
     return device;
 }
 
-void Engine::updateDeviceSelectionCache()
-{
-    for (const auto &iter : getProductStrategies()) {
-        const auto& strategy = iter.second;
-        auto devices = getDevicesForProductStrategy(strategy->getId());
-        mDevicesForStrategies[strategy->getId()] = devices;
-        strategy->setDeviceTypes(devices.types());
-        strategy->setDeviceAddress(devices.getFirstValidAddress().c_str());
-    }
+void Engine::setStrategyDevices(const sp<ProductStrategy>& strategy, const DeviceVector &devices) {
+    strategy->setDeviceTypes(devices.types());
+    strategy->setDeviceAddress(devices.getFirstValidAddress().c_str());
 }
 
 product_strategy_t Engine::getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const {
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 595e289..be9f4cc 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -67,7 +67,10 @@
                                                      sp<AudioPolicyMix> *mix = nullptr)
                                                      const override;
 
-    void updateDeviceSelectionCache() override;
+    void setStrategyDevices(const sp<ProductStrategy>& strategy,
+                            const DeviceVector& devices) override;
+
+    DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const override;
 
 private:
     /* Copy facilities are put private to disable copy. */
@@ -87,8 +90,6 @@
                                           DeviceVector availableOutputDevices,
                                           const SwAudioOutputCollection &outputs) const;
 
-    DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const;
-
     sp<DeviceDescriptor> getDeviceForInputSource(audio_source_t inputSource) const;
 
     product_strategy_t getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const;
@@ -97,8 +98,6 @@
     DeviceVector getPreferredAvailableDevicesForProductStrategy(
         const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
 
-    DeviceStrategyMap mDevicesForStrategies;
-
     std::map<product_strategy_t, legacy_strategy> mLegacyStrategyMap;
 };
 } // namespace audio_policy
diff --git a/services/audiopolicy/fuzzer/Android.bp b/services/audiopolicy/fuzzer/Android.bp
index 9f6b703..621f643 100644
--- a/services/audiopolicy/fuzzer/Android.bp
+++ b/services/audiopolicy/fuzzer/Android.bp
@@ -63,6 +63,15 @@
     ],
     data: [":audiopolicyfuzzer_configuration_files"],
     fuzz_config: {
-       cc: ["mnaganov@google.com"],
+        cc: ["mnaganov@google.com"],
+        componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libaudiopolicy",
+        vector: "local_no_privileges_required",
+        service_privilege: "privileged",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c64497f..0239627 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -4242,6 +4242,28 @@
     return NO_ERROR;
 }
 
+status_t AudioPolicyManager::listDeclaredDevicePorts(media::AudioPortRole role,
+        std::vector<media::AudioPortFw>* _aidl_return) {
+    auto pushPort = [&](const sp<DeviceDescriptor>& dev) -> status_t {
+        audio_port_v7 port;
+        dev->toAudioPort(&port);
+        auto aidlPort = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_v7_AudioPortFw(port));
+        _aidl_return->push_back(std::move(aidlPort));
+        return OK;
+    };
+
+    for (const auto& module : mHwModulesAll) {
+        for (const auto& dev : module->getDeclaredDevices()) {
+            if (role == media::AudioPortRole::NONE ||
+                    ((role == media::AudioPortRole::SOURCE)
+                            == audio_is_input_device(dev->type()))) {
+                RETURN_STATUS_IF_ERROR(pushPort(dev));
+            }
+        }
+    }
+    return OK;
+}
+
 status_t AudioPolicyManager::getAudioPort(struct audio_port_v7 *port)
 {
     if (port == nullptr || port->id == AUDIO_PORT_HANDLE_NONE) {
@@ -5652,7 +5674,9 @@
         }
     }
 
-    mEngine->updateDeviceSelectionCache();
+    // 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));
 
@@ -6058,6 +6082,14 @@
     }
 
     if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+        // first call getAudioPort to get the supported attributes from the HAL
+        struct audio_port_v7 port = {};
+        device->toAudioPort(&port);
+        status_t status = mpClientInterface->getAudioPort(&port);
+        if (status == NO_ERROR) {
+            device->importAudioPort(port);
+        }
+
         // look for input profiles that can be routed to this device
         SortedVector< sp<IOProfile> > profiles;
         for (const auto& hwModule : mHwModules) {
@@ -6109,11 +6141,7 @@
 
             desc = new AudioInputDescriptor(profile, mpClientInterface);
             audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
-            status_t status = desc->open(nullptr,
-                                         device,
-                                         AUDIO_SOURCE_MIC,
-                                         AUDIO_INPUT_FLAG_NONE,
-                                         &input);
+            status = desc->open(nullptr, device, AUDIO_SOURCE_MIC, AUDIO_INPUT_FLAG_NONE, &input);
 
             if (status == NO_ERROR) {
                 const String8& address = String8(device->address().c_str());
@@ -7684,12 +7712,17 @@
                 ioHandle, String8(AudioParameter::keyStreamSupportedFormats));
         ALOGV("%s: supported formats %d, %s", __FUNCTION__, ioHandle, reply.string());
         AudioParameter repliedParameters(reply);
+        FormatVector formats;
         if (repliedParameters.get(
-                String8(AudioParameter::keyStreamSupportedFormats), reply) != NO_ERROR) {
-            ALOGE("%s: failed to retrieve format, bailing out", __FUNCTION__);
+                String8(AudioParameter::keyStreamSupportedFormats), reply) == NO_ERROR) {
+            formats = formatsFromString(reply.string());
+        } else if (devDesc->hasValidAudioProfile()) {
+            ALOGD("%s: using the device profiles", __func__);
+            formats = devDesc->getAudioProfiles().getSupportedFormats();
+        } else {
+            ALOGE("%s: failed to retrieve format, bailing out", __func__);
             return;
         }
-        FormatVector formats = formatsFromString(reply.string());
         mReportedFormatsMap[devDesc] = formats;
         if (device == AUDIO_DEVICE_OUT_HDMI
                 || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD)) {
@@ -7699,7 +7732,7 @@
     }
 
     for (audio_format_t format : profiles.getSupportedFormats()) {
-        ChannelMaskSet channelMasks;
+        std::optional<ChannelMaskSet> channelMasks;
         SampleRateSet samplingRates;
         AudioParameter requestedParameters;
         requestedParameters.addInt(String8(AudioParameter::keyFormat), format);
@@ -7714,6 +7747,8 @@
             if (repliedParameters.get(
                     String8(AudioParameter::keyStreamSupportedSamplingRates), reply) == NO_ERROR) {
                 samplingRates = samplingRatesFromString(reply.string());
+            } else {
+                samplingRates = devDesc->getAudioProfiles().getSampleRatesFor(format);
             }
         }
         if (profiles.hasDynamicChannelsFor(format)) {
@@ -7725,14 +7760,17 @@
             if (repliedParameters.get(
                     String8(AudioParameter::keyStreamSupportedChannels), reply) == NO_ERROR) {
                 channelMasks = channelMasksFromString(reply.string());
-                if (device == AUDIO_DEVICE_OUT_HDMI
-                        || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD)) {
-                    modifySurroundChannelMasks(&channelMasks);
-                }
+            } else {
+                channelMasks = devDesc->getAudioProfiles().getChannelMasksFor(format);
+            }
+            if (channelMasks.has_value() && (device == AUDIO_DEVICE_OUT_HDMI
+                    || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD))) {
+                modifySurroundChannelMasks(&channelMasks.value());
             }
         }
         addDynamicAudioProfileAndSort(
-                profiles, new AudioProfile(format, channelMasks, samplingRates));
+                profiles, new AudioProfile(
+                        format, channelMasks.value_or(ChannelMaskSet()), samplingRates));
     }
 }
 
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 8466d097..e0411ab 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -261,6 +261,8 @@
                                         unsigned int *num_ports,
                                         struct audio_port_v7 *ports,
                                         unsigned int *generation);
+                status_t listDeclaredDevicePorts(media::AudioPortRole role,
+                                                 std::vector<media::AudioPortFw>* result) override;
         virtual status_t getAudioPort(struct audio_port_v7 *port);
         virtual status_t createAudioPatch(const struct audio_patch *patch,
                                            audio_patch_handle_t *handle,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index fdf5787..f34427c 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1516,6 +1516,17 @@
     return Status::ok();
 }
 
+Status AudioPolicyService::listDeclaredDevicePorts(media::AudioPortRole role,
+                                                    std::vector<media::AudioPortFw>* _aidl_return) {
+    Mutex::Autolock _l(mLock);
+    if (mAudioPolicyManager == NULL) {
+        return binderStatusFromStatusT(NO_INIT);
+    }
+    AutoCallerClear acc;
+    return binderStatusFromStatusT(mAudioPolicyManager->listDeclaredDevicePorts(
+                    role, _aidl_return));
+}
+
 Status AudioPolicyService::getAudioPort(int portId,
                                         media::AudioPortFw* _aidl_return) {
     audio_port_v7 port{ .id = portId };
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 09b6f3b..281785e 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1816,14 +1816,12 @@
 void AudioPolicyService::SensorPrivacyPolicy::registerSelf() {
     SensorPrivacyManager spm;
     mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled();
-    (void)spm.addToggleSensorPrivacyListener(this);
     spm.addSensorPrivacyListener(this);
 }
 
 void AudioPolicyService::SensorPrivacyPolicy::unregisterSelf() {
     SensorPrivacyManager spm;
     spm.removeSensorPrivacyListener(this);
-    spm.removeToggleSensorPrivacyListener(this);
 }
 
 bool AudioPolicyService::SensorPrivacyPolicy::isSensorPrivacyEnabled() {
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 860bd18..7f682c8 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -174,6 +174,8 @@
     binder::Status listAudioPorts(media::AudioPortRole role, media::AudioPortType type,
                                   Int* count, std::vector<media::AudioPortFw>* ports,
                                   int32_t* _aidl_return) override;
+    binder::Status listDeclaredDevicePorts(media::AudioPortRole role,
+                                           std::vector<media::AudioPortFw>* _aidl_return) override;
     binder::Status getAudioPort(int portId,
                                 media::AudioPortFw* _aidl_return) override;
     binder::Status createAudioPatch(const media::AudioPatchFw& patch, int32_t handle,
diff --git a/services/audiopolicy/service/SpatializerPoseController.cpp b/services/audiopolicy/service/SpatializerPoseController.cpp
index 63f53b7..4cba8cc 100644
--- a/services/audiopolicy/service/SpatializerPoseController.cpp
+++ b/services/audiopolicy/service/SpatializerPoseController.cpp
@@ -108,8 +108,8 @@
               .freshnessTimeout = Ticks(kFreshnessTimeout).count(),
               .predictionDuration = []() -> float {
                   const int duration_ms =
-                          property_get_int32("audio.spatializer.prediction_duration_ms", 0);
-                  if (duration_ms > 0) {
+                          property_get_int32("audio.spatializer.prediction_duration_ms", -1);
+                  if (duration_ms >= 0) {
                       return duration_ms * 1'000'000LL;
                   } else {
                       return Ticks(kPredictionDuration).count();
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 1c40cfd..3821f97 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -1681,19 +1681,19 @@
     // Connecting a valid output device with valid parameters should trigger a routing update
     ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
             AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
-            "a", "b", AUDIO_FORMAT_DEFAULT));
+            "00:11:22:33:44:55", "b", AUDIO_FORMAT_DEFAULT));
     ASSERT_EQ(1, mClient->getRoutingUpdatedCounter());
 
     // Disconnecting a connected device should succeed and trigger a routing update
     ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
             AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-            "a", "b", AUDIO_FORMAT_DEFAULT));
+            "00:11:22:33:44:55", "b", AUDIO_FORMAT_DEFAULT));
     ASSERT_EQ(2, mClient->getRoutingUpdatedCounter());
 
     // Disconnecting a disconnected device should fail and not trigger a routing update
     ASSERT_EQ(INVALID_OPERATION, mManager->setDeviceConnectionState(
             AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-            "a", "b",  AUDIO_FORMAT_DEFAULT));
+            "00:11:22:33:44:55", "b",  AUDIO_FORMAT_DEFAULT));
     ASSERT_EQ(2, mClient->getRoutingUpdatedCounter());
 
     // Changing force use should trigger an update
@@ -1820,9 +1820,9 @@
                 DeviceConnectionTestParams({AUDIO_DEVICE_OUT_HDMI, "test_out_hdmi",
                                             "audio_policy_test_out_hdmi"}),
                 DeviceConnectionTestParams({AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, "bt_hfp_in",
-                                            "hfp_client_in"}),
+                                            "00:11:22:33:44:55"}),
                 DeviceConnectionTestParams({AUDIO_DEVICE_OUT_BLUETOOTH_SCO, "bt_hfp_out",
-                                            "hfp_client_out"})
+                                            "00:11:22:33:44:55"})
                 )
         );
 
diff --git a/services/medialog/fuzzer/Android.bp b/services/medialog/fuzzer/Android.bp
index 9ff0ce4..c96c37b 100644
--- a/services/medialog/fuzzer/Android.bp
+++ b/services/medialog/fuzzer/Android.bp
@@ -38,5 +38,13 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libmedialogservice library",
+        vector: "local_privileges_required",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "future_version",
     },
 }
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
index 8b33f10..20a6378 100644
--- a/services/mediametrics/fuzzer/Android.bp
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -68,5 +68,13 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libmediametricsservice",
+        vector: "local_no_privileges_required",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
diff --git a/services/mediametrics/statsd_drm.cpp b/services/mediametrics/statsd_drm.cpp
index 9f08eca..e5f7190 100644
--- a/services/mediametrics/statsd_drm.cpp
+++ b/services/mediametrics/statsd_drm.cpp
@@ -281,9 +281,9 @@
     const int32_t uid = IPCThreadState::self()->getCallingUid();
     int32_t frontend = 0;
     if (!item->getInt32("frontend", &frontend)) return false;
-    int32_t requested_security_level = -1;
+    int32_t requested_security_level = 0;
     if (!item->getInt32("requested_security_level", &requested_security_level)) return false;
-    int32_t opened_security_level = -1;
+    int32_t opened_security_level = 0;
     if (!item->getInt32("opened_security_level", &opened_security_level)) return false;
 
     // Optional to be included
@@ -325,12 +325,10 @@
     if (!item->getInt32("frontend", &frontend)) return false;
     std::string object_nonce = "";
     if (!item->getString("object_nonce", &object_nonce)) return false;
-    int32_t security_level = -1;
-    if (!item->getInt32("security_level", &security_level)) return false;
     std::string api_str = "";
     if (!item->getString("api", &api_str)) return false;
     const int32_t api = MediaDrmStatsdHelper::findDrmApi(api_str);
-    int32_t error_code = -1;
+    int32_t error_code = 0;
     if (!item->getInt32("error_code", &error_code)) return false;
 
     // Optional to be included
@@ -338,12 +336,14 @@
     item->getString("version", &version);
     std::string session_nonce = "";
     item->getString("session_nonce", &session_nonce);
+    int32_t security_level = 0;
+    item->getInt32("security_level", &security_level);
 
     int32_t cdm_err = 0;
     item->getInt32("cdm_err", &cdm_err);
     int32_t oem_err = 0;
     item->getInt32("oem_err", &oem_err);
-    int32_t error_context = -1;
+    int32_t error_context = 0;
     item->getInt32("error_context", &error_context);
 
     const int result = stats_write(stats::media_metrics::MEDIA_DRM_ERRORED, scheme, uuid_lsb,
diff --git a/services/mediaresourcemanager/OWNERS b/services/mediaresourcemanager/OWNERS
index 82abf8f..4fc3728 100644
--- a/services/mediaresourcemanager/OWNERS
+++ b/services/mediaresourcemanager/OWNERS
@@ -1 +1,3 @@
-dwkang@google.com
+girishshetty@google.com
+lajos@google.com
+wonsik@google.com
diff --git a/services/tuner/mediatuner.rc b/services/tuner/mediatuner.rc
index 6a3e199..d813b7d 100644
--- a/services/tuner/mediatuner.rc
+++ b/services/tuner/mediatuner.rc
@@ -1,6 +1,7 @@
 service media.tuner /system/bin/mediatuner
     class main
     group media
+    user root
     ioprio rt 4
     onrestart restart vendor.tuner-hal-1-0
     onrestart restart vendor.tuner-hal-1-1