Merge "Updated fuzz_config in Android.bp file"
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/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/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/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/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index 5d2856a..9c054f0 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -356,7 +356,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..56e6e8a 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -362,7 +362,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/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/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..cb1a67d 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -2484,11 +2484,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 +2517,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/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/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..9901fc0 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",
@@ -297,3 +298,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..3894cbf 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,7 +935,7 @@
     TIME_CHECK();
     if (!mModule) return NO_INIT;
     return mModule->dump(fd, Args(args).args(), args.size());
-};
+}
 
 int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
     TIME_CHECK();
@@ -772,6 +943,73 @@
     return INVALID_OPERATION;
 }
 
+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) {
     if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
     return p.ext.get<AudioPortExt::Tag::device>().device == device;
@@ -865,7 +1103,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 +1112,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 +1122,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 +1158,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 +1176,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 +1209,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 +1257,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 +1285,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..5ab7c84 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -29,6 +29,7 @@
 #include <utils/Log.h>
 
 #include "EffectConversionHelperAidl.h"
+#include "EffectProxy.h"
 
 namespace android {
 namespace effect {
@@ -37,7 +38,9 @@
 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;
@@ -72,7 +75,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 +101,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,
@@ -154,22 +159,55 @@
     }
 
     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", __func__,
+              android::internal::ToString(state).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);
+        }
+        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 +225,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 +330,20 @@
               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 *static_cast<int32_t*>(pReplyData) = OK;
 }
 
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 54df1b8..1200264 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,15 @@
     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; }
 
   protected:
     const int32_t mSessionId;
@@ -42,7 +48,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 +64,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 +81,9 @@
                                                                    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;
 
     status_t handleInit(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
                         void* pReplyData);
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index 0c19ac8..d6135af 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);
     }
 }
 
@@ -160,34 +164,49 @@
 
 // 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();
+    if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ ||
+        !outputQ->isValid()) {
+        ALOGE("%s invalid FMQ [Status %d I %d O %d]", __func__, statusQ ? statusQ->isValid() : 0,
+              inputQ ? inputQ->isValid() : 0, outputQ ? outputQ->isValid() : 0);
+        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;
     }
 
     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 +229,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..8966363 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -31,11 +31,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 +78,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 +93,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..c4d85e5
--- /dev/null
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -0,0 +1,292 @@
+/*
+ * 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..3048580 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -40,6 +40,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 {
@@ -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;
 }
 
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 157e8bb..147c131 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 {
@@ -181,6 +207,8 @@
 
     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..f1619a8 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 = 0,
+                 .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_FREQUENCY_RESOLUTION,
+                 .preferredProcessingDurationMs = std::numeric_limits<float>::max(),
+                 .preEqStage = {.inUse = true, .bandCount = std::numeric_limits<int>::max()},
+                 .postEqStage = {.inUse = true, .bandCount = std::numeric_limits<int>::max()},
+                 .mbcStage = {.inUse = true, .bandCount = std::numeric_limits<int>::max()},
+                 .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 =
+                                          .gainDb = std::numeric_limits<float>::lowest()});
+
+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});
 
-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 = 220,
+                         .attackTimeMs = 0,
+                         .releaseTimeMs = 0,
+                         .ratio = 0,
+                         .thresholdDb = std::numeric_limits<float>::lowest(),
+                         .kneeWidthDb = 0,
+                         .noiseGateThresholdDb = std::numeric_limits<float>::lowest(),
+                         .expanderRatio = 0,
+                         .preGainDb = std::numeric_limits<float>::lowest(),
+                         .postGainDb = std::numeric_limits<float>::lowest()})}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::mbcBand>(
+                {DynamicsProcessing::MbcBandConfig(
+                        {.channel = std::numeric_limits<int>::max(),
+                         .band = std::numeric_limits<int>::max(),
+                         .enable = true,
+                         .cutoffFrequencyHz = 20000,
+                         .attackTimeMs = std::numeric_limits<float>::max(),
+                         .releaseTimeMs = std::numeric_limits<float>::max(),
+                         .ratio = std::numeric_limits<float>::max(),
+                         .thresholdDb = 0,
+                         .kneeWidthDb = std::numeric_limits<float>::max(),
+                         .noiseGateThresholdDb = 0,
+                         .expanderRatio = std::numeric_limits<float>::max(),
+                         .preGainDb = std::numeric_limits<float>::max(),
+                         .postGainDb = std::numeric_limits<float>::max()})})};
+
+static const Range::DynamicsProcessingRange kInputGainRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::inputGain>(
+                {DynamicsProcessing::InputGain(
+                        {.channel = 0, .gainDb = std::numeric_limits<float>::lowest()})}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::inputGain>(
+                {DynamicsProcessing::InputGain({.channel = std::numeric_limits<int>::max(),
+                                                .gainDb = std::numeric_limits<float>::max()})})};
+
+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 = 0,
+                         .thresholdDb = std::numeric_limits<float>::min(),
+                         .postGainDb = std::numeric_limits<float>::min()})}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::limiter>(
+                {DynamicsProcessing::LimiterConfig(
+                        {.channel = std::numeric_limits<int>::max(),
+                         .enable = true,
+                         .linkGroup = std::numeric_limits<int>::max(),
+                         .attackTimeMs = std::numeric_limits<float>::max(),
+                         .releaseTimeMs = std::numeric_limits<float>::max(),
+                         .ratio = std::numeric_limits<float>::max(),
+                         .thresholdDb = 0,
+                         .postGainDb = std::numeric_limits<float>::max()})})};
+
+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/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/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/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/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index ba7c6b6..9a3dd98 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()) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index ebfe32c..4b8bfbd 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);
 
@@ -932,6 +934,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/Threads.cpp b/services/audioflinger/Threads.cpp
index 37b8fe8..16c72cc 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2825,6 +2825,9 @@
     if (!trackActive) {
         removeTrack_l(track);
     } else if (track->isFastTrack() || track->isOffloaded() || track->isDirect()) {
+        if (track->isPausePending()) {
+            track->pauseAck();
+        }
         track->mState = TrackBase::STOPPING_1;
     }
 
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/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..f7a3273 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) {
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.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