Merge "CCodecConfig: round frame rate instead of truncating to increase the accuracy"
diff --git a/Android.bp b/Android.bp
index 0e0ea1f..5aa2029 100644
--- a/Android.bp
+++ b/Android.bp
@@ -75,10 +75,10 @@
         "av-types-aidl-cpp",
     ],
     header_libs: [
-        "libaudioclient_aidl_conversion_util",
+        "libaudio_aidl_conversion_common_util_cpp",
     ],
     export_header_lib_headers: [
-        "libaudioclient_aidl_conversion_util",
+        "libaudio_aidl_conversion_common_util_cpp",
     ],
     host_supported: true,
     vendor_available: true,
diff --git a/apex/Android.bp b/apex/Android.bp
index 570ca01..b0d7c02 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -67,13 +67,15 @@
     // Use a custom AndroidManifest.xml used for API targeting.
     androidManifest: ":com.android.media-androidManifest",
 
-    // IMPORTANT: q-launched-apex-module enables the build system to make
-    // sure the package compatible to Android 10 in two ways:
+    // IMPORTANT: q-launched-dcla-enabled-apex-module enables the build system to make
+    // sure the package compatible to Android 10 in two ways(if flag APEX_BUILD_FOR_PRE_S_DEVICES=1
+    // is set):
     // - build the APEX package compatible to Android 10
     //   so that the package can be installed.
     // - build artifacts (lib/javalib/bin) against Android 10 SDK
     //   so that the artifacts can run.
-    defaults: ["q-launched-apex-module"],
+    // If the flag is not set, the package is built to be compatible with Android 12.
+    defaults: ["q-launched-dcla-enabled-apex-module"],
     // Indicates that pre-installed version of this apex can be compressed.
     // Whether it actually will be compressed is controlled on per-device basis.
     compressible: true,
@@ -191,13 +193,15 @@
     // Use a custom AndroidManifest.xml used for API targeting.
     androidManifest: ":com.android.media.swcodec-androidManifest",
 
-    // IMPORTANT: q-launched-apex-module enables the build system to make
-    // sure the package compatible to Android 10 in two ways:
+    // IMPORTANT: q-launched-dcla-enabled-apex-module enables the build system to make
+    // sure the package compatible to Android 10 in two ways(if flag APEX_BUILD_FOR_PRE_S_DEVICES=1
+    // is set):
     // - build the APEX package compatible to Android 10
     //   so that the package can be installed.
     // - build artifacts (lib/javalib/bin) against Android 10 SDK
     //   so that the artifacts can run.
-    defaults: ["q-launched-apex-module"],
+    // If the flag is not set, the package is built to be compatible with Android 12.
+    defaults: ["q-launched-dcla-enabled-apex-module"],
     // Indicates that pre-installed version of this apex can be compressed.
     // Whether it actually will be compressed is controlled on per-device basis.
     compressible: true,
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 408d216..1e1a49d 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -35,6 +35,7 @@
         "CryptoHalAidl.cpp",
         "DrmUtils.cpp",
         "DrmHalListener.cpp",
+        "DrmStatus.cpp",
     ],
 
     local_include_dirs: [
@@ -74,6 +75,7 @@
     static_libs: [
         "resourcemanager_aidl_interface-ndk",
         "libaidlcommonsupport",
+        "libjsoncpp",
     ],
 
     export_shared_lib_headers: [
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index f95d527..fc1780d 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -71,7 +71,7 @@
     mCryptoHalHidl->notifyResolution(width, height);
 }
 
-status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+DrmStatus CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
     // This requires plugin to be created.
     if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->setMediaDrmSession(sessionId);
     return mCryptoHalHidl->setMediaDrmSession(sessionId);
diff --git a/drm/libmediadrm/CryptoHalAidl.cpp b/drm/libmediadrm/CryptoHalAidl.cpp
index f01ecb3..c1fd797 100644
--- a/drm/libmediadrm/CryptoHalAidl.cpp
+++ b/drm/libmediadrm/CryptoHalAidl.cpp
@@ -260,7 +260,7 @@
     }
 }
 
-status_t CryptoHalAidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+DrmStatus CryptoHalAidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
diff --git a/drm/libmediadrm/CryptoHalHidl.cpp b/drm/libmediadrm/CryptoHalHidl.cpp
index 55364b5..458a1ae 100644
--- a/drm/libmediadrm/CryptoHalHidl.cpp
+++ b/drm/libmediadrm/CryptoHalHidl.cpp
@@ -386,7 +386,7 @@
     ALOGE_IF(!hResult.isOk(), "notifyResolution txn failed %s", hResult.description().c_str());
 }
 
-status_t CryptoHalHidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+DrmStatus CryptoHalHidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
diff --git a/drm/libmediadrm/DrmStatus.cpp b/drm/libmediadrm/DrmStatus.cpp
new file mode 100644
index 0000000..0258801
--- /dev/null
+++ b/drm/libmediadrm/DrmStatus.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 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 <mediadrm/DrmStatus.h>
+#include <json/json.h>
+
+namespace android {
+
+DrmStatus::DrmStatus(status_t err, const char *msg) : mStatus(err) {
+    Json::Value errorDetails;
+    Json::Reader reader;
+    if (!reader.parse(msg, errorDetails)) {
+        mErrMsg = msg;
+        return;
+    }
+
+    std::string errMsg;
+    auto val = errorDetails["cdmError"];
+    if (!val.isNull()) {
+        mCdmErr = val.asInt();
+    }
+    val = errorDetails["oemError"];
+    if (!val.isNull()) {
+        mOemErr = val.asInt();
+    }
+    val = errorDetails["context"];
+    if (!val.isNull()) {
+        mCtx = val.asInt();
+    }
+    val = errorDetails["errorMessage"];
+    if (!val.isNull()) {
+        mErrMsg = val.asString();
+    } else {
+        mErrMsg = msg;
+    }
+}
+
+}  // namespace android
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index be0cd4b..cb103f7 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -32,6 +32,7 @@
 #include <android/hardware/drm/1.4/IDrmFactory.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
 #include <hidl/HidlSupport.h>
+#include <json/json.h>
 
 #include <cutils/properties.h>
 #include <utils/Errors.h>
@@ -362,18 +363,23 @@
 }
 }  // namespace
 
-std::string GetExceptionMessage(status_t err, const char* msg,
+std::string GetExceptionMessage(const DrmStatus &err, const char* defaultMsg,
                                 const Vector<::V1_4::LogMessage>& logs) {
     std::string ruler("==============================");
     std::string header("Beginning of DRM Plugin Log");
     std::string footer("End of DRM Plugin Log");
+    std::string msg(err.getErrorMessage());
     String8 msg8;
-    if (msg) {
-        msg8 += msg;
+    if (!msg.empty()) {
+        msg8 += msg.c_str();
+        msg8 += ": ";
+    } else if (defaultMsg) {
+        msg8 += defaultMsg;
         msg8 += ": ";
     }
-    auto errStr = StrCryptoError(err);
-    msg8 += errStr.c_str();
+    msg8 += StrCryptoError(err).c_str();
+    msg8 += String8::format("\ncdm err: %d, oem err: %d, ctx: %d",
+                            err.getCdmErr(), err.getOemErr(), err.getContext());
     msg8 += String8::format("\n%s %s %s", ruler.c_str(), header.c_str(), ruler.c_str());
 
     for (auto log : logs) {
@@ -410,6 +416,141 @@
     return logs;
 }
 
+DrmStatus statusAidlToDrmStatus(::ndk::ScopedAStatus& statusAidl) {
+    if (statusAidl.isOk()) return OK;
+    if (statusAidl.getExceptionCode() != EX_SERVICE_SPECIFIC) return DEAD_OBJECT;
+    auto astatus = static_cast<StatusAidl>(statusAidl.getServiceSpecificError());
+    status_t status{};
+    switch (astatus) {
+    case StatusAidl::OK:
+        status = OK;
+        break;
+    case StatusAidl::BAD_VALUE:
+        status = BAD_VALUE;
+        break;
+    case StatusAidl::ERROR_DRM_CANNOT_HANDLE:
+        status = ERROR_DRM_CANNOT_HANDLE;
+        break;
+    case StatusAidl::ERROR_DRM_DECRYPT:
+        status = ERROR_DRM_DECRYPT;
+        break;
+    case StatusAidl::ERROR_DRM_DEVICE_REVOKED:
+        status = ERROR_DRM_DEVICE_REVOKED;
+        break;
+    case StatusAidl::ERROR_DRM_FRAME_TOO_LARGE:
+        status = ERROR_DRM_FRAME_TOO_LARGE;
+        break;
+    case StatusAidl::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+        status = ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+        break;
+    case StatusAidl::ERROR_DRM_INSUFFICIENT_SECURITY:
+        status = ERROR_DRM_INSUFFICIENT_SECURITY;
+        break;
+    case StatusAidl::ERROR_DRM_INVALID_STATE:
+        status = ERROR_DRM_INVALID_STATE;
+        break;
+    case StatusAidl::ERROR_DRM_LICENSE_EXPIRED:
+        status = ERROR_DRM_LICENSE_EXPIRED;
+        break;
+    case StatusAidl::ERROR_DRM_NO_LICENSE:
+        status = ERROR_DRM_NO_LICENSE;
+        break;
+    case StatusAidl::ERROR_DRM_NOT_PROVISIONED:
+        status = ERROR_DRM_NOT_PROVISIONED;
+        break;
+    case StatusAidl::ERROR_DRM_RESOURCE_BUSY:
+        status = ERROR_DRM_RESOURCE_BUSY;
+        break;
+    case StatusAidl::ERROR_DRM_RESOURCE_CONTENTION:
+        status = ERROR_DRM_RESOURCE_CONTENTION;
+        break;
+    case StatusAidl::ERROR_DRM_SESSION_LOST_STATE:
+        status = ERROR_DRM_SESSION_LOST_STATE;
+        break;
+    case StatusAidl::ERROR_DRM_SESSION_NOT_OPENED:
+        status = ERROR_DRM_SESSION_NOT_OPENED;
+        break;
+
+    // New in S / drm@1.4:
+    case StatusAidl::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
+        status = ERROR_DRM_ZERO_SUBSAMPLES;
+        break;
+    case StatusAidl::CRYPTO_LIBRARY_ERROR:
+        status = ERROR_DRM_CRYPTO_LIBRARY;
+        break;
+    case StatusAidl::GENERAL_OEM_ERROR:
+        status = ERROR_DRM_GENERIC_OEM;
+        break;
+    case StatusAidl::GENERAL_PLUGIN_ERROR:
+        status = ERROR_DRM_GENERIC_PLUGIN;
+        break;
+    case StatusAidl::INIT_DATA_INVALID:
+        status = ERROR_DRM_INIT_DATA;
+        break;
+    case StatusAidl::KEY_NOT_LOADED:
+        status = ERROR_DRM_KEY_NOT_LOADED;
+        break;
+    case StatusAidl::LICENSE_PARSE_ERROR:
+        status = ERROR_DRM_LICENSE_PARSE;
+        break;
+    case StatusAidl::LICENSE_POLICY_ERROR:
+        status = ERROR_DRM_LICENSE_POLICY;
+        break;
+    case StatusAidl::LICENSE_RELEASE_ERROR:
+        status = ERROR_DRM_LICENSE_RELEASE;
+        break;
+    case StatusAidl::LICENSE_REQUEST_REJECTED:
+        status = ERROR_DRM_LICENSE_REQUEST_REJECTED;
+        break;
+    case StatusAidl::LICENSE_RESTORE_ERROR:
+        status = ERROR_DRM_LICENSE_RESTORE;
+        break;
+    case StatusAidl::LICENSE_STATE_ERROR:
+        status = ERROR_DRM_LICENSE_STATE;
+        break;
+    case StatusAidl::MALFORMED_CERTIFICATE:
+        status = ERROR_DRM_CERTIFICATE_MALFORMED;
+        break;
+    case StatusAidl::MEDIA_FRAMEWORK_ERROR:
+        status = ERROR_DRM_MEDIA_FRAMEWORK;
+        break;
+    case StatusAidl::MISSING_CERTIFICATE:
+        status = ERROR_DRM_CERTIFICATE_MISSING;
+        break;
+    case StatusAidl::PROVISIONING_CERTIFICATE_ERROR:
+        status = ERROR_DRM_PROVISIONING_CERTIFICATE;
+        break;
+    case StatusAidl::PROVISIONING_CONFIGURATION_ERROR:
+        status = ERROR_DRM_PROVISIONING_CONFIG;
+        break;
+    case StatusAidl::PROVISIONING_PARSE_ERROR:
+        status = ERROR_DRM_PROVISIONING_PARSE;
+        break;
+    case StatusAidl::PROVISIONING_REQUEST_REJECTED:
+        status = ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
+        break;
+    case StatusAidl::RETRYABLE_PROVISIONING_ERROR:
+        status = ERROR_DRM_PROVISIONING_RETRY;
+        break;
+    case StatusAidl::SECURE_STOP_RELEASE_ERROR:
+        status = ERROR_DRM_SECURE_STOP_RELEASE;
+        break;
+    case StatusAidl::STORAGE_READ_FAILURE:
+        status = ERROR_DRM_STORAGE_READ;
+        break;
+    case StatusAidl::STORAGE_WRITE_FAILURE:
+        status = ERROR_DRM_STORAGE_WRITE;
+        break;
+
+    case StatusAidl::ERROR_DRM_UNKNOWN:
+    default:
+        status = ERROR_DRM_UNKNOWN;
+        break;
+    }
+
+    return DrmStatus(status, statusAidl.getMessage());
+}
+
 LogBuffer gLogBuf;
 }  // namespace DrmUtils
 }  // namespace android
diff --git a/drm/libmediadrm/fuzzer/Android.bp b/drm/libmediadrm/fuzzer/Android.bp
index a85e3cf..deda9ef 100644
--- a/drm/libmediadrm/fuzzer/Android.bp
+++ b/drm/libmediadrm/fuzzer/Android.bp
@@ -37,6 +37,7 @@
         "liblog",
         "resourcemanager_aidl_interface-ndk",
         "libaidlcommonsupport",
+        "libjsoncpp",
     ],
     header_libs: [
         "libmedia_headers",
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHal.h b/drm/libmediadrm/include/mediadrm/CryptoHal.h
index 32a6741..60cbbf8 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHal.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHal.h
@@ -38,7 +38,7 @@
     virtual bool requiresSecureDecoderComponent(
             const char *mime) const;
     virtual void notifyResolution(uint32_t width, uint32_t height);
-    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
+    virtual DrmStatus setMediaDrmSession(const Vector<uint8_t> &sessionId);
     virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
             CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
             const drm::V1_0::SharedBuffer &source, size_t offset,
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h b/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
index 50878a6..eec4585 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
@@ -49,7 +49,7 @@
     virtual status_t destroyPlugin();
     virtual bool requiresSecureDecoderComponent(const char* mime) const;
     virtual void notifyResolution(uint32_t width, uint32_t height);
-    virtual status_t setMediaDrmSession(const Vector<uint8_t>& sessionId);
+    virtual DrmStatus setMediaDrmSession(const Vector<uint8_t>& sessionId);
     virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode,
                             const CryptoPlugin::Pattern& pattern, const ::SharedBuffer& source,
                             size_t offset, const CryptoPlugin::SubSample* subSamples,
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h b/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
index 6db1e89..0150d7c 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
@@ -57,7 +57,7 @@
 
     virtual void notifyResolution(uint32_t width, uint32_t height);
 
-    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
+    virtual DrmStatus setMediaDrmSession(const Vector<uint8_t> &sessionId);
 
     virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
             CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
diff --git a/drm/libmediadrm/include/mediadrm/DrmStatus.h b/drm/libmediadrm/interface/mediadrm/DrmStatus.h
similarity index 65%
rename from drm/libmediadrm/include/mediadrm/DrmStatus.h
rename to drm/libmediadrm/interface/mediadrm/DrmStatus.h
index 4f29a5a..15826ca 100644
--- a/drm/libmediadrm/include/mediadrm/DrmStatus.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmStatus.h
@@ -16,27 +16,35 @@
 
 #ifndef DRM_STATUS_
 #define DRM_STATUS_
-#include <stdint.h>
 
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/MediaErrors.h>
 #include <utils/Errors.h>
 
+#include <stdint.h>
+#include <string>
+
 namespace android {
 
 struct DrmStatus {
   public:
-    DrmStatus(status_t status, int32_t cdmerr = 0, int32_t oemerr = 0)
-        : mStatus(status), mCdmErr(cdmerr), mOemErr(oemerr) {}
+    DrmStatus(status_t status, int32_t cdmErr = 0, int32_t oemErr = 0,
+              int32_t ctx = 0, std::string errMsg = "")
+        : mStatus(status), mCdmErr(cdmErr), mOemErr(oemErr),
+          mCtx(ctx), mErrMsg(errMsg) {}
+    DrmStatus(status_t err, const char *msg);
     operator status_t() const { return mStatus; }
-    int32_t cdmErr() const { return mCdmErr; }
-    int32_t oemErr() const { return mOemErr; }
+    int32_t getCdmErr() const { return mCdmErr; }
+    int32_t getOemErr() const { return mOemErr; }
+    int32_t getContext() const { return mCtx; }
+    std::string getErrorMessage() const { return mErrMsg; }
     bool operator==(status_t other) const { return mStatus == other; }
     bool operator!=(status_t other) const { return mStatus != other; }
 
   private:
-    status_t mStatus;
-    int32_t mCdmErr{}, mOemErr{};
+    status_t mStatus{};
+    int32_t mCdmErr{}, mOemErr{}, mCtx{};
+    std::string mErrMsg;
 };
 
 }  // namespace android
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
index 32390d6..2632ebd 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -199,98 +199,7 @@
     return toStatusT_1_4(err);
 }
 
-inline DrmStatus statusAidlToDrmStatus(::ndk::ScopedAStatus& statusAidl) {
-    if (statusAidl.isOk()) return OK;
-    if (statusAidl.getExceptionCode() != EX_SERVICE_SPECIFIC) return DEAD_OBJECT;
-    auto status = static_cast<StatusAidl>(statusAidl.getServiceSpecificError());
-    switch (status) {
-    case StatusAidl::OK:
-        return OK;
-    case StatusAidl::BAD_VALUE:
-        return BAD_VALUE;
-    case StatusAidl::ERROR_DRM_CANNOT_HANDLE:
-        return ERROR_DRM_CANNOT_HANDLE;
-    case StatusAidl::ERROR_DRM_DECRYPT:
-        return ERROR_DRM_DECRYPT;
-    case StatusAidl::ERROR_DRM_DEVICE_REVOKED:
-        return ERROR_DRM_DEVICE_REVOKED;
-    case StatusAidl::ERROR_DRM_FRAME_TOO_LARGE:
-        return ERROR_DRM_FRAME_TOO_LARGE;
-    case StatusAidl::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
-        return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
-    case StatusAidl::ERROR_DRM_INSUFFICIENT_SECURITY:
-        return ERROR_DRM_INSUFFICIENT_SECURITY;
-    case StatusAidl::ERROR_DRM_INVALID_STATE:
-        return ERROR_DRM_INVALID_STATE;
-    case StatusAidl::ERROR_DRM_LICENSE_EXPIRED:
-        return ERROR_DRM_LICENSE_EXPIRED;
-    case StatusAidl::ERROR_DRM_NO_LICENSE:
-        return ERROR_DRM_NO_LICENSE;
-    case StatusAidl::ERROR_DRM_NOT_PROVISIONED:
-        return ERROR_DRM_NOT_PROVISIONED;
-    case StatusAidl::ERROR_DRM_RESOURCE_BUSY:
-        return ERROR_DRM_RESOURCE_BUSY;
-    case StatusAidl::ERROR_DRM_RESOURCE_CONTENTION:
-        return ERROR_DRM_RESOURCE_CONTENTION;
-    case StatusAidl::ERROR_DRM_SESSION_LOST_STATE:
-        return ERROR_DRM_SESSION_LOST_STATE;
-    case StatusAidl::ERROR_DRM_SESSION_NOT_OPENED:
-        return ERROR_DRM_SESSION_NOT_OPENED;
-
-    // New in S / drm@1.4:
-    case StatusAidl::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
-        return ERROR_DRM_ZERO_SUBSAMPLES;
-    case StatusAidl::CRYPTO_LIBRARY_ERROR:
-        return ERROR_DRM_CRYPTO_LIBRARY;
-    case StatusAidl::GENERAL_OEM_ERROR:
-        return ERROR_DRM_GENERIC_OEM;
-    case StatusAidl::GENERAL_PLUGIN_ERROR:
-        return ERROR_DRM_GENERIC_PLUGIN;
-    case StatusAidl::INIT_DATA_INVALID:
-        return ERROR_DRM_INIT_DATA;
-    case StatusAidl::KEY_NOT_LOADED:
-        return ERROR_DRM_KEY_NOT_LOADED;
-    case StatusAidl::LICENSE_PARSE_ERROR:
-        return ERROR_DRM_LICENSE_PARSE;
-    case StatusAidl::LICENSE_POLICY_ERROR:
-        return ERROR_DRM_LICENSE_POLICY;
-    case StatusAidl::LICENSE_RELEASE_ERROR:
-        return ERROR_DRM_LICENSE_RELEASE;
-    case StatusAidl::LICENSE_REQUEST_REJECTED:
-        return ERROR_DRM_LICENSE_REQUEST_REJECTED;
-    case StatusAidl::LICENSE_RESTORE_ERROR:
-        return ERROR_DRM_LICENSE_RESTORE;
-    case StatusAidl::LICENSE_STATE_ERROR:
-        return ERROR_DRM_LICENSE_STATE;
-    case StatusAidl::MALFORMED_CERTIFICATE:
-        return ERROR_DRM_CERTIFICATE_MALFORMED;
-    case StatusAidl::MEDIA_FRAMEWORK_ERROR:
-        return ERROR_DRM_MEDIA_FRAMEWORK;
-    case StatusAidl::MISSING_CERTIFICATE:
-        return ERROR_DRM_CERTIFICATE_MISSING;
-    case StatusAidl::PROVISIONING_CERTIFICATE_ERROR:
-        return ERROR_DRM_PROVISIONING_CERTIFICATE;
-    case StatusAidl::PROVISIONING_CONFIGURATION_ERROR:
-        return ERROR_DRM_PROVISIONING_CONFIG;
-    case StatusAidl::PROVISIONING_PARSE_ERROR:
-        return ERROR_DRM_PROVISIONING_PARSE;
-    case StatusAidl::PROVISIONING_REQUEST_REJECTED:
-        return ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
-    case StatusAidl::RETRYABLE_PROVISIONING_ERROR:
-        return ERROR_DRM_PROVISIONING_RETRY;
-    case StatusAidl::SECURE_STOP_RELEASE_ERROR:
-        return ERROR_DRM_SECURE_STOP_RELEASE;
-    case StatusAidl::STORAGE_READ_FAILURE:
-        return ERROR_DRM_STORAGE_READ;
-    case StatusAidl::STORAGE_WRITE_FAILURE:
-        return ERROR_DRM_STORAGE_WRITE;
-
-    case StatusAidl::ERROR_DRM_UNKNOWN:
-    default:
-        return ERROR_DRM_UNKNOWN;
-    }
-    return ERROR_DRM_UNKNOWN;
-}
+DrmStatus statusAidlToDrmStatus(::ndk::ScopedAStatus& statusAidl);
 
 template<typename T, typename U>
 status_t GetLogMessagesAidl(const std::shared_ptr<U> &obj, Vector<::V1_4::LogMessage> &logs) {
@@ -374,14 +283,16 @@
     return OK;
 }
 
-std::string GetExceptionMessage(status_t err, const char *msg,
+std::string GetExceptionMessage(const DrmStatus & err, const char *defaultMsg,
                                 const Vector<::V1_4::LogMessage> &logs);
 
 template<typename T>
-std::string GetExceptionMessage(status_t err, const char *msg, const sp<T> &iface) {
+std::string GetExceptionMessage(const DrmStatus &err, const char *defaultMsg, const sp<T> &iface) {
     Vector<::V1_4::LogMessage> logs;
-    iface->getLogMessages(logs);
-    return GetExceptionMessage(err, msg, logs);
+    if (iface != NULL) {
+        iface->getLogMessages(logs);
+    }
+    return GetExceptionMessage(err, defaultMsg, logs);
 }
 
 } // namespace DrmUtils
diff --git a/drm/libmediadrm/interface/mediadrm/ICrypto.h b/drm/libmediadrm/interface/mediadrm/ICrypto.h
index 2c4df60..4087186 100644
--- a/drm/libmediadrm/interface/mediadrm/ICrypto.h
+++ b/drm/libmediadrm/interface/mediadrm/ICrypto.h
@@ -17,6 +17,7 @@
 #include <cutils/native_handle.h>
 #include <media/hardware/CryptoAPI.h>
 #include <media/stagefright/foundation/ABase.h>
+#include <mediadrm/DrmStatus.h>
 #include <utils/RefBase.h>
 #include <utils/StrongPointer.h>
 
@@ -65,7 +66,7 @@
 
     virtual void notifyResolution(uint32_t width, uint32_t height) = 0;
 
-    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
+    virtual DrmStatus setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
 
     enum DestinationType {
         kDestinationTypeSharedMemory, // non-secure
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
new file mode 100644
index 0000000..7d8a859
--- /dev/null
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -0,0 +1,2266 @@
+/*
+ * Copyright (C) 2022 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 <map>
+#include <utility>
+#include <vector>
+
+#define LOG_TAG "AidlConversionCppNdk"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "media/AidlConversionCppNdk.h"
+
+#include <media/ShmemCompat.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Utilities
+
+#if defined(BACKEND_NDK)
+/* AIDL String generated in NDK is different than CPP */
+#define GET_DEVICE_DESC_CONNECTION(x)  AudioDeviceDescription::CONNECTION_##x
+namespace aidl {
+#else
+#define GET_DEVICE_DESC_CONNECTION(x)  AudioDeviceDescription::CONNECTION_##x()
+#endif
+
+namespace android {
+
+using ::android::BAD_VALUE;
+using ::android::OK;
+using ::android::base::unexpected;
+
+using media::audio::common::AudioChannelLayout;
+using media::audio::common::AudioConfig;
+using media::audio::common::AudioConfigBase;
+using media::audio::common::AudioContentType;
+using media::audio::common::AudioDevice;
+using media::audio::common::AudioDeviceAddress;
+using media::audio::common::AudioDeviceDescription;
+using media::audio::common::AudioDeviceType;
+using media::audio::common::AudioDualMonoMode;
+using media::audio::common::AudioEncapsulationMetadataType;
+using media::audio::common::AudioEncapsulationMode;
+using media::audio::common::AudioEncapsulationType;
+using media::audio::common::AudioFormatDescription;
+using media::audio::common::AudioFormatType;
+using media::audio::common::AudioGain;
+using media::audio::common::AudioGainConfig;
+using media::audio::common::AudioGainMode;
+using media::audio::common::AudioInputFlags;
+using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioLatencyMode;
+using media::audio::common::AudioMode;
+using media::audio::common::AudioOffloadInfo;
+using media::audio::common::AudioOutputFlags;
+using media::audio::common::AudioPlaybackRate;
+using media::audio::common::AudioPortDeviceExt;
+using media::audio::common::AudioPortExt;
+using media::audio::common::AudioPortMixExt;
+using media::audio::common::AudioPortMixExtUseCase;
+using media::audio::common::AudioProfile;
+using media::audio::common::AudioSource;
+using media::audio::common::AudioStandard;
+using media::audio::common::AudioStreamType;
+using media::audio::common::AudioUsage;
+using media::audio::common::AudioUuid;
+using media::audio::common::ExtraAudioDescriptor;
+using media::audio::common::Int;
+using media::audio::common::PcmType;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Converters
+
+::android::status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize) {
+    if (aidl.size() > maxSize - 1) {
+        return BAD_VALUE;
+    }
+    aidl.copy(dest, aidl.size());
+    dest[aidl.size()] = '\0';
+    return OK;
+}
+
+ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize) {
+    if (legacy == nullptr) {
+        return unexpected(BAD_VALUE);
+    }
+    if (strnlen(legacy, maxSize) == maxSize) {
+        // No null-terminator.
+        return unexpected(BAD_VALUE);
+    }
+    return std::string(legacy);
+}
+
+ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl) {
+    return convertReinterpret<audio_module_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl) {
+    return convertReinterpret<audio_io_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl) {
+    return convertReinterpret<audio_port_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl) {
+    return convertReinterpret<audio_patch_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl) {
+    return convertReinterpret<audio_unique_id_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl) {
+    return convertReinterpret<audio_hw_sync_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl) {
+    return convertReinterpret<pid_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl) {
+    return convertReinterpret<uid_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl) {
+    return String16(aidl.data(), aidl.size());
+}
+
+ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy) {
+    return std::string(String8(legacy).c_str());
+}
+
+// TODO b/182392769: create an optional -> optional util
+ConversionResult<std::optional<String16>>
+aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl) {
+    if (!aidl.has_value()) {
+        return std::nullopt;
+    }
+    ConversionResult<String16> conversion =
+        VALUE_OR_RETURN(aidl2legacy_string_view_String16(aidl.value()));
+    return conversion.value();
+}
+
+ConversionResult<std::optional<std::string_view>>
+legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy) {
+  if (!legacy.has_value()) {
+    return std::nullopt;
+  }
+  ConversionResult<std::string> conversion =
+      VALUE_OR_RETURN(legacy2aidl_String16_string(legacy.value()));
+  return conversion.value();
+}
+
+ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl) {
+    return String8(aidl.data(), aidl.size());
+}
+
+ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy) {
+    return std::string(legacy.c_str());
+}
+
+namespace {
+
+namespace detail {
+using AudioChannelBitPair = std::pair<audio_channel_mask_t, int>;
+using AudioChannelBitPairs = std::vector<AudioChannelBitPair>;
+using AudioChannelPair = std::pair<audio_channel_mask_t, AudioChannelLayout>;
+using AudioChannelPairs = std::vector<AudioChannelPair>;
+using AudioDevicePair = std::pair<audio_devices_t, AudioDeviceDescription>;
+using AudioDevicePairs = std::vector<AudioDevicePair>;
+using AudioFormatPair = std::pair<audio_format_t, AudioFormatDescription>;
+using AudioFormatPairs = std::vector<AudioFormatPair>;
+}
+
+const detail::AudioChannelBitPairs& getInAudioChannelBits() {
+    static const detail::AudioChannelBitPairs pairs = {
+        { AUDIO_CHANNEL_IN_LEFT, AudioChannelLayout::CHANNEL_FRONT_LEFT },
+        { AUDIO_CHANNEL_IN_RIGHT, AudioChannelLayout::CHANNEL_FRONT_RIGHT },
+        // AUDIO_CHANNEL_IN_FRONT is at the end
+        { AUDIO_CHANNEL_IN_BACK, AudioChannelLayout::CHANNEL_BACK_CENTER },
+        // AUDIO_CHANNEL_IN_*_PROCESSED not supported
+        // AUDIO_CHANNEL_IN_PRESSURE not supported
+        // AUDIO_CHANNEL_IN_*_AXIS not supported
+        // AUDIO_CHANNEL_IN_VOICE_* not supported
+        { AUDIO_CHANNEL_IN_BACK_LEFT, AudioChannelLayout::CHANNEL_BACK_LEFT },
+        { AUDIO_CHANNEL_IN_BACK_RIGHT, AudioChannelLayout::CHANNEL_BACK_RIGHT },
+        { AUDIO_CHANNEL_IN_CENTER, AudioChannelLayout::CHANNEL_FRONT_CENTER },
+        { AUDIO_CHANNEL_IN_LOW_FREQUENCY, AudioChannelLayout::CHANNEL_LOW_FREQUENCY },
+        { AUDIO_CHANNEL_IN_TOP_LEFT, AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT },
+        { AUDIO_CHANNEL_IN_TOP_RIGHT, AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT },
+        // When going from aidl to legacy, IN_CENTER is used
+        { AUDIO_CHANNEL_IN_FRONT, AudioChannelLayout::CHANNEL_FRONT_CENTER }
+    };
+    return pairs;
+}
+
+const detail::AudioChannelPairs& getInAudioChannelPairs() {
+    static const detail::AudioChannelPairs pairs = {
+#define DEFINE_INPUT_LAYOUT(n)                                                 \
+            {                                                                  \
+                AUDIO_CHANNEL_IN_##n,                                          \
+                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
+                        AudioChannelLayout::LAYOUT_##n)                        \
+            }
+
+        DEFINE_INPUT_LAYOUT(MONO),
+        DEFINE_INPUT_LAYOUT(STEREO),
+        DEFINE_INPUT_LAYOUT(FRONT_BACK),
+        // AUDIO_CHANNEL_IN_6 not supported
+        DEFINE_INPUT_LAYOUT(2POINT0POINT2),
+        DEFINE_INPUT_LAYOUT(2POINT1POINT2),
+        DEFINE_INPUT_LAYOUT(3POINT0POINT2),
+        DEFINE_INPUT_LAYOUT(3POINT1POINT2),
+        DEFINE_INPUT_LAYOUT(5POINT1)
+#undef DEFINE_INPUT_LAYOUT
+    };
+    return pairs;
+}
+
+const detail::AudioChannelBitPairs& getOutAudioChannelBits() {
+    static const detail::AudioChannelBitPairs pairs = {
+#define DEFINE_OUTPUT_BITS(n)                                                  \
+            { AUDIO_CHANNEL_OUT_##n, AudioChannelLayout::CHANNEL_##n }
+
+        DEFINE_OUTPUT_BITS(FRONT_LEFT),
+        DEFINE_OUTPUT_BITS(FRONT_RIGHT),
+        DEFINE_OUTPUT_BITS(FRONT_CENTER),
+        DEFINE_OUTPUT_BITS(LOW_FREQUENCY),
+        DEFINE_OUTPUT_BITS(BACK_LEFT),
+        DEFINE_OUTPUT_BITS(BACK_RIGHT),
+        DEFINE_OUTPUT_BITS(FRONT_LEFT_OF_CENTER),
+        DEFINE_OUTPUT_BITS(FRONT_RIGHT_OF_CENTER),
+        DEFINE_OUTPUT_BITS(BACK_CENTER),
+        DEFINE_OUTPUT_BITS(SIDE_LEFT),
+        DEFINE_OUTPUT_BITS(SIDE_RIGHT),
+        DEFINE_OUTPUT_BITS(TOP_CENTER),
+        DEFINE_OUTPUT_BITS(TOP_FRONT_LEFT),
+        DEFINE_OUTPUT_BITS(TOP_FRONT_CENTER),
+        DEFINE_OUTPUT_BITS(TOP_FRONT_RIGHT),
+        DEFINE_OUTPUT_BITS(TOP_BACK_LEFT),
+        DEFINE_OUTPUT_BITS(TOP_BACK_CENTER),
+        DEFINE_OUTPUT_BITS(TOP_BACK_RIGHT),
+        DEFINE_OUTPUT_BITS(TOP_SIDE_LEFT),
+        DEFINE_OUTPUT_BITS(TOP_SIDE_RIGHT),
+        DEFINE_OUTPUT_BITS(BOTTOM_FRONT_LEFT),
+        DEFINE_OUTPUT_BITS(BOTTOM_FRONT_CENTER),
+        DEFINE_OUTPUT_BITS(BOTTOM_FRONT_RIGHT),
+        DEFINE_OUTPUT_BITS(LOW_FREQUENCY_2),
+        DEFINE_OUTPUT_BITS(FRONT_WIDE_LEFT),
+        DEFINE_OUTPUT_BITS(FRONT_WIDE_RIGHT),
+#undef DEFINE_OUTPUT_BITS
+        { AUDIO_CHANNEL_OUT_HAPTIC_A, AudioChannelLayout::CHANNEL_HAPTIC_A },
+        { AUDIO_CHANNEL_OUT_HAPTIC_B, AudioChannelLayout::CHANNEL_HAPTIC_B }
+    };
+    return pairs;
+}
+
+const detail::AudioChannelPairs& getOutAudioChannelPairs() {
+    static const detail::AudioChannelPairs pairs = {
+#define DEFINE_OUTPUT_LAYOUT(n)                                                \
+            {                                                                  \
+                AUDIO_CHANNEL_OUT_##n,                                         \
+                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
+                        AudioChannelLayout::LAYOUT_##n)                        \
+            }
+
+        DEFINE_OUTPUT_LAYOUT(MONO),
+        DEFINE_OUTPUT_LAYOUT(STEREO),
+        DEFINE_OUTPUT_LAYOUT(2POINT1),
+        DEFINE_OUTPUT_LAYOUT(TRI),
+        DEFINE_OUTPUT_LAYOUT(TRI_BACK),
+        DEFINE_OUTPUT_LAYOUT(3POINT1),
+        DEFINE_OUTPUT_LAYOUT(2POINT0POINT2),
+        DEFINE_OUTPUT_LAYOUT(2POINT1POINT2),
+        DEFINE_OUTPUT_LAYOUT(3POINT0POINT2),
+        DEFINE_OUTPUT_LAYOUT(3POINT1POINT2),
+        DEFINE_OUTPUT_LAYOUT(QUAD),
+        DEFINE_OUTPUT_LAYOUT(QUAD_SIDE),
+        DEFINE_OUTPUT_LAYOUT(SURROUND),
+        DEFINE_OUTPUT_LAYOUT(PENTA),
+        DEFINE_OUTPUT_LAYOUT(5POINT1),
+        DEFINE_OUTPUT_LAYOUT(5POINT1_SIDE),
+        DEFINE_OUTPUT_LAYOUT(5POINT1POINT2),
+        DEFINE_OUTPUT_LAYOUT(5POINT1POINT4),
+        DEFINE_OUTPUT_LAYOUT(6POINT1),
+        DEFINE_OUTPUT_LAYOUT(7POINT1),
+        DEFINE_OUTPUT_LAYOUT(7POINT1POINT2),
+        DEFINE_OUTPUT_LAYOUT(7POINT1POINT4),
+        DEFINE_OUTPUT_LAYOUT(13POINT_360RA),
+        DEFINE_OUTPUT_LAYOUT(22POINT2),
+        DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_A),
+        DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_A),
+        DEFINE_OUTPUT_LAYOUT(HAPTIC_AB),
+        DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_AB),
+        DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_AB)
+#undef DEFINE_OUTPUT_LAYOUT
+    };
+    return pairs;
+}
+
+const detail::AudioChannelPairs& getVoiceAudioChannelPairs() {
+    static const detail::AudioChannelPairs pairs = {
+#define DEFINE_VOICE_LAYOUT(n)                                                 \
+            {                                                                  \
+                AUDIO_CHANNEL_IN_VOICE_##n,                                    \
+                AudioChannelLayout::make<AudioChannelLayout::Tag::voiceMask>(  \
+                        AudioChannelLayout::VOICE_##n)                         \
+            }
+        DEFINE_VOICE_LAYOUT(UPLINK_MONO),
+        DEFINE_VOICE_LAYOUT(DNLINK_MONO),
+        DEFINE_VOICE_LAYOUT(CALL_MONO)
+#undef DEFINE_VOICE_LAYOUT
+    };
+    return pairs;
+}
+
+AudioDeviceDescription make_AudioDeviceDescription(AudioDeviceType type,
+        const std::string& connection = "") {
+    AudioDeviceDescription result;
+    result.type = type;
+    result.connection = connection;
+    return result;
+}
+
+void append_AudioDeviceDescription(detail::AudioDevicePairs& pairs,
+        audio_devices_t inputType, audio_devices_t outputType,
+        AudioDeviceType inType, AudioDeviceType outType,
+        const std::string& connection = "") {
+    pairs.push_back(std::make_pair(inputType, make_AudioDeviceDescription(inType, connection)));
+    pairs.push_back(std::make_pair(outputType, make_AudioDeviceDescription(outType, connection)));
+}
+
+const detail::AudioDevicePairs& getAudioDevicePairs() {
+    static const detail::AudioDevicePairs pairs = []() {
+        detail::AudioDevicePairs pairs = {{
+            {
+                AUDIO_DEVICE_NONE, AudioDeviceDescription{}
+            },
+            {
+                AUDIO_DEVICE_OUT_EARPIECE, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_SPEAKER_EARPIECE)
+            },
+            {
+                AUDIO_DEVICE_OUT_SPEAKER, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_SPEAKER)
+            },
+            {
+                AUDIO_DEVICE_OUT_WIRED_HEADPHONE, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_HEADPHONE,
+                        GET_DEVICE_DESC_CONNECTION(ANALOG))
+            },
+            {
+                AUDIO_DEVICE_OUT_BLUETOOTH_SCO, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_DEVICE,
+                        GET_DEVICE_DESC_CONNECTION(BT_SCO))
+            },
+            {
+                AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_CARKIT,
+                        GET_DEVICE_DESC_CONNECTION(BT_SCO))
+            },
+            {
+                AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_HEADPHONE,
+                        GET_DEVICE_DESC_CONNECTION(BT_A2DP))
+            },
+            {
+                AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_SPEAKER,
+                        GET_DEVICE_DESC_CONNECTION(BT_A2DP))
+            },
+            {
+                AUDIO_DEVICE_OUT_TELEPHONY_TX, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_TELEPHONY_TX)
+            },
+            {
+                AUDIO_DEVICE_OUT_AUX_LINE, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_LINE_AUX)
+            },
+            {
+                AUDIO_DEVICE_OUT_SPEAKER_SAFE, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_SPEAKER_SAFE)
+            },
+            {
+                AUDIO_DEVICE_OUT_HEARING_AID, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_HEARING_AID,
+                        GET_DEVICE_DESC_CONNECTION(WIRELESS))
+            },
+            {
+                AUDIO_DEVICE_OUT_ECHO_CANCELLER, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_ECHO_CANCELLER)
+            },
+            {
+                AUDIO_DEVICE_OUT_BLE_SPEAKER, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_SPEAKER,
+                        GET_DEVICE_DESC_CONNECTION(BT_LE))
+            },
+            {
+                AUDIO_DEVICE_OUT_BLE_BROADCAST, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_BROADCAST,
+                        GET_DEVICE_DESC_CONNECTION(BT_LE))
+            },
+            // AUDIO_DEVICE_IN_AMBIENT and IN_COMMUNICATION are removed since they were deprecated.
+            {
+                AUDIO_DEVICE_IN_BUILTIN_MIC, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_MICROPHONE)
+            },
+            {
+                AUDIO_DEVICE_IN_BACK_MIC, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_MICROPHONE_BACK)
+            },
+            {
+                AUDIO_DEVICE_IN_TELEPHONY_RX, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_TELEPHONY_RX)
+            },
+            {
+                AUDIO_DEVICE_IN_TV_TUNER, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_TV_TUNER)
+            },
+            {
+                AUDIO_DEVICE_IN_LOOPBACK, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_LOOPBACK)
+            },
+            {
+                AUDIO_DEVICE_IN_BLUETOOTH_BLE, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_DEVICE,
+                        GET_DEVICE_DESC_CONNECTION(BT_LE))
+            },
+            {
+                AUDIO_DEVICE_IN_ECHO_REFERENCE, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_ECHO_REFERENCE)
+            }
+        }};
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT,
+                AudioDeviceType::IN_DEFAULT, AudioDeviceType::OUT_DEFAULT);
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET,
+                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+                GET_DEVICE_DESC_CONNECTION(ANALOG));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
+                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+                GET_DEVICE_DESC_CONNECTION(BT_SCO));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_HDMI, AUDIO_DEVICE_OUT_HDMI,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(HDMI));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+                AudioDeviceType::IN_SUBMIX, AudioDeviceType::OUT_SUBMIX);
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET,
+                AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
+                GET_DEVICE_DESC_CONNECTION(ANALOG));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
+                AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
+                GET_DEVICE_DESC_CONNECTION(USB));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_ACCESSORY,
+                AudioDeviceType::IN_ACCESSORY, AudioDeviceType::OUT_ACCESSORY,
+                GET_DEVICE_DESC_CONNECTION(USB));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_OUT_USB_DEVICE,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(USB));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_FM_TUNER, AUDIO_DEVICE_OUT_FM,
+                AudioDeviceType::IN_FM_TUNER, AudioDeviceType::OUT_FM);
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_LINE, AUDIO_DEVICE_OUT_LINE,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(ANALOG));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_SPDIF, AUDIO_DEVICE_OUT_SPDIF,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(SPDIF));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(BT_A2DP));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_IP, AUDIO_DEVICE_OUT_IP,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(IP_V4));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_BUS, AUDIO_DEVICE_OUT_BUS,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(BUS));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_PROXY, AUDIO_DEVICE_OUT_PROXY,
+                AudioDeviceType::IN_AFE_PROXY, AudioDeviceType::OUT_AFE_PROXY);
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
+                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+                GET_DEVICE_DESC_CONNECTION(USB));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_HDMI_ARC, AUDIO_DEVICE_OUT_HDMI_ARC,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(HDMI_ARC));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_HDMI_EARC, AUDIO_DEVICE_OUT_HDMI_EARC,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(HDMI_EARC));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_OUT_BLE_HEADSET,
+                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+                GET_DEVICE_DESC_CONNECTION(BT_LE));
+        return pairs;
+    }();
+#undef GET_DEVICE_DESC_CONNECTION
+    return pairs;
+}
+
+AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
+    AudioFormatDescription result;
+    result.type = type;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
+    auto result = make_AudioFormatDescription(AudioFormatType::PCM);
+    result.pcm = pcm;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(const std::string& encoding) {
+    AudioFormatDescription result;
+    result.encoding = encoding;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType transport,
+        const std::string& encoding) {
+    auto result = make_AudioFormatDescription(encoding);
+    result.pcm = transport;
+    return result;
+}
+
+const detail::AudioFormatPairs& getAudioFormatPairs() {
+    static const detail::AudioFormatPairs pairs = {{
+            {AUDIO_FORMAT_INVALID,
+             make_AudioFormatDescription(AudioFormatType::SYS_RESERVED_INVALID)},
+            {AUDIO_FORMAT_DEFAULT, AudioFormatDescription{}},
+            {AUDIO_FORMAT_PCM_16_BIT, make_AudioFormatDescription(PcmType::INT_16_BIT)},
+            {AUDIO_FORMAT_PCM_8_BIT, make_AudioFormatDescription(PcmType::UINT_8_BIT)},
+            {AUDIO_FORMAT_PCM_32_BIT, make_AudioFormatDescription(PcmType::INT_32_BIT)},
+            {AUDIO_FORMAT_PCM_8_24_BIT, make_AudioFormatDescription(PcmType::FIXED_Q_8_24)},
+            {AUDIO_FORMAT_PCM_FLOAT, make_AudioFormatDescription(PcmType::FLOAT_32_BIT)},
+            {AUDIO_FORMAT_PCM_24_BIT_PACKED, make_AudioFormatDescription(PcmType::INT_24_BIT)},
+            {AUDIO_FORMAT_MP3, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEG)},
+            {AUDIO_FORMAT_AMR_NB,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AMR_NB)},
+            {AUDIO_FORMAT_AMR_WB,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AMR_WB)},
+            {AUDIO_FORMAT_AAC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_MP4)},
+            {AUDIO_FORMAT_AAC_MAIN,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_MAIN)},
+            {AUDIO_FORMAT_AAC_LC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LC)},
+            {AUDIO_FORMAT_AAC_SSR,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_SSR)},
+            {AUDIO_FORMAT_AAC_LTP,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LTP)},
+            {AUDIO_FORMAT_AAC_HE_V1,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_HE_V1)},
+            {AUDIO_FORMAT_AAC_SCALABLE,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_SCALABLE)},
+            {AUDIO_FORMAT_AAC_ERLC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ERLC)},
+            {AUDIO_FORMAT_AAC_LD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LD)},
+            {AUDIO_FORMAT_AAC_HE_V2,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_HE_V2)},
+            {AUDIO_FORMAT_AAC_ELD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ELD)},
+            {AUDIO_FORMAT_AAC_XHE,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_XHE)
+
+            },
+            // AUDIO_FORMAT_HE_AAC_V1 and HE_AAC_V2 are removed since they were deprecated long time
+            // ago.
+            {AUDIO_FORMAT_VORBIS,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_VORBIS)},
+            {AUDIO_FORMAT_OPUS, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_OPUS)},
+            {AUDIO_FORMAT_AC3, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AC3)},
+            {AUDIO_FORMAT_E_AC3, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EAC3)},
+            {AUDIO_FORMAT_E_AC3_JOC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EAC3_JOC)},
+            {AUDIO_FORMAT_DTS, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS)},
+            {AUDIO_FORMAT_DTS_HD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_HD)},
+            {AUDIO_FORMAT_DTS_HD_MA,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_HD_MA)},
+            {AUDIO_FORMAT_DTS_UHD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1)},
+            {AUDIO_FORMAT_DTS_UHD_P2,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2)},
+            // In the future, we would like to represent encapsulated bitstreams as
+            // nested AudioFormatDescriptions. The legacy 'AUDIO_FORMAT_IEC61937' type doesn't
+            // specify the format of the encapsulated bitstream.
+            {AUDIO_FORMAT_IEC61937,
+             make_AudioFormatDescription(PcmType::INT_16_BIT,
+                                         ::android::MEDIA_MIMETYPE_AUDIO_IEC61937)},
+            {AUDIO_FORMAT_DOLBY_TRUEHD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD)},
+            {AUDIO_FORMAT_EVRC, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRC)},
+            {AUDIO_FORMAT_EVRCB,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRCB)},
+            {AUDIO_FORMAT_EVRCWB,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRCWB)},
+            {AUDIO_FORMAT_EVRCNW,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRCNW)},
+            {AUDIO_FORMAT_AAC_ADIF,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADIF)},
+            {AUDIO_FORMAT_WMA, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_WMA)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_WMA_PRO, make_AudioFormatDescription("audio/x-ms-wma.pro")},
+            {AUDIO_FORMAT_AMR_WB_PLUS,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)},
+            {AUDIO_FORMAT_MP2,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II)},
+            {AUDIO_FORMAT_QCELP,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_QCELP)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_DSD, make_AudioFormatDescription("audio/vnd.sony.dsd")},
+            {AUDIO_FORMAT_FLAC, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_FLAC)},
+            {AUDIO_FORMAT_ALAC, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_ALAC)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_APE, make_AudioFormatDescription("audio/x-ape")},
+            {AUDIO_FORMAT_AAC_ADTS,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS)},
+            {AUDIO_FORMAT_AAC_ADTS_MAIN,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_MAIN)},
+            {AUDIO_FORMAT_AAC_ADTS_LC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LC)},
+            {AUDIO_FORMAT_AAC_ADTS_SSR,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SSR)},
+            {AUDIO_FORMAT_AAC_ADTS_LTP,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LTP)},
+            {AUDIO_FORMAT_AAC_ADTS_HE_V1,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V1)},
+            {AUDIO_FORMAT_AAC_ADTS_SCALABLE,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SCALABLE)},
+            {AUDIO_FORMAT_AAC_ADTS_ERLC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ERLC)},
+            {AUDIO_FORMAT_AAC_ADTS_LD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LD)},
+            {AUDIO_FORMAT_AAC_ADTS_HE_V2,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V2)},
+            {AUDIO_FORMAT_AAC_ADTS_ELD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ELD)},
+            {AUDIO_FORMAT_AAC_ADTS_XHE,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_XHE)},
+            {// Note: not in the IANA registry. "vnd.octel.sbc" is not BT SBC.
+             AUDIO_FORMAT_SBC, make_AudioFormatDescription("audio/x-sbc")},
+            {AUDIO_FORMAT_APTX, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_APTX)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_APTX_HD, make_AudioFormatDescription("audio/vnd.qcom.aptx.hd")},
+            {AUDIO_FORMAT_AC4, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AC4)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_LDAC, make_AudioFormatDescription("audio/vnd.sony.ldac")},
+            {AUDIO_FORMAT_MAT,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_MAT_1_0,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT +
+                                         std::string(".1.0"))},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_MAT_2_0,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT +
+                                         std::string(".2.0"))},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_MAT_2_1,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT +
+                                         std::string(".2.1"))},
+            {AUDIO_FORMAT_AAC_LATM,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC)},
+            {AUDIO_FORMAT_AAC_LATM_LC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LATM_LC)},
+            {AUDIO_FORMAT_AAC_LATM_HE_V1,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V1)},
+            {AUDIO_FORMAT_AAC_LATM_HE_V2,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V2)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_CELT, make_AudioFormatDescription("audio/x-celt")},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_APTX_ADAPTIVE,
+             make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive")},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_LHDC, make_AudioFormatDescription("audio/vnd.savitech.lhdc")},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_LHDC_LL, make_AudioFormatDescription("audio/vnd.savitech.lhdc.ll")},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_APTX_TWSP, make_AudioFormatDescription("audio/vnd.qcom.aptx.twsp")},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_LC3, make_AudioFormatDescription("audio/x-lc3")},
+            {AUDIO_FORMAT_MPEGH,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1)},
+            {AUDIO_FORMAT_MPEGH_BL_L3,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L3)},
+            {AUDIO_FORMAT_MPEGH_BL_L4,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L4)},
+            {AUDIO_FORMAT_MPEGH_LC_L3,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L3)},
+            {AUDIO_FORMAT_MPEGH_LC_L4,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L4)},
+            {AUDIO_FORMAT_IEC60958,
+             make_AudioFormatDescription(PcmType::INT_24_BIT,
+                                         ::android::MEDIA_MIMETYPE_AUDIO_IEC60958)},
+            {AUDIO_FORMAT_DRA, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DRA)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_APTX_ADAPTIVE_QLEA,
+             make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive.r3")},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_APTX_ADAPTIVE_R4,
+             make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive.r4")},
+    }};
+    return pairs;
+}
+
+template<typename S, typename T>
+std::map<S, T> make_DirectMap(const std::vector<std::pair<S, T>>& v) {
+    std::map<S, T> result(v.begin(), v.end());
+    LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
+    return result;
+}
+
+template<typename S, typename T>
+std::map<S, T> make_DirectMap(
+        const std::vector<std::pair<S, T>>& v1, const std::vector<std::pair<S, T>>& v2) {
+    std::map<S, T> result(v1.begin(), v1.end());
+    LOG_ALWAYS_FATAL_IF(result.size() != v1.size(), "Duplicate key elements detected in v1");
+    result.insert(v2.begin(), v2.end());
+    LOG_ALWAYS_FATAL_IF(result.size() != v1.size() + v2.size(),
+            "Duplicate key elements detected in v1+v2");
+    return result;
+}
+
+template<typename S, typename T>
+std::map<T, S> make_ReverseMap(const std::vector<std::pair<S, T>>& v) {
+    std::map<T, S> result;
+    std::transform(v.begin(), v.end(), std::inserter(result, result.begin()),
+            [](const std::pair<S, T>& p) {
+                return std::make_pair(p.second, p.first);
+            });
+    LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
+    return result;
+}
+
+}  // namespace
+
+audio_channel_mask_t aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+        int aidlLayout, bool isInput) {
+    auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
+    const int aidlLayoutInitial = aidlLayout; // for error message
+    audio_channel_mask_t legacy = AUDIO_CHANNEL_NONE;
+    for (const auto& bitPair : bitMapping) {
+        if ((aidlLayout & bitPair.second) == bitPair.second) {
+            legacy = static_cast<audio_channel_mask_t>(legacy | bitPair.first);
+            aidlLayout &= ~bitPair.second;
+            if (aidlLayout == 0) {
+                return legacy;
+            }
+        }
+    }
+    ALOGE("%s: aidl layout 0x%x contains bits 0x%x that have no match to legacy %s bits",
+            __func__, aidlLayoutInitial, aidlLayout, isInput ? "input" : "output");
+    return AUDIO_CHANNEL_NONE;
+}
+
+ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+        const AudioChannelLayout& aidl, bool isInput) {
+    using ReverseMap = std::map<AudioChannelLayout, audio_channel_mask_t>;
+    using Tag = AudioChannelLayout::Tag;
+    static const ReverseMap mIn = make_ReverseMap(getInAudioChannelPairs());
+    static const ReverseMap mOut = make_ReverseMap(getOutAudioChannelPairs());
+    static const ReverseMap mVoice = make_ReverseMap(getVoiceAudioChannelPairs());
+
+    auto convert = [](const AudioChannelLayout& aidl, const ReverseMap& m,
+            const char* func, const char* type) -> ConversionResult<audio_channel_mask_t> {
+        if (auto it = m.find(aidl); it != m.end()) {
+            return it->second;
+        } else {
+            ALOGW("%s: no legacy %s audio_channel_mask_t found for %s", func, type,
+                    aidl.toString().c_str());
+            return unexpected(BAD_VALUE);
+        }
+    };
+
+    switch (aidl.getTag()) {
+        case Tag::none:
+            return AUDIO_CHANNEL_NONE;
+        case Tag::invalid:
+            return AUDIO_CHANNEL_INVALID;
+        case Tag::indexMask:
+            // Index masks do not have pre-defined values.
+            if (const int bits = aidl.get<Tag::indexMask>();
+                    __builtin_popcount(bits) != 0 &&
+                    __builtin_popcount(bits) <= AUDIO_CHANNEL_COUNT_MAX) {
+                return audio_channel_mask_from_representation_and_bits(
+                        AUDIO_CHANNEL_REPRESENTATION_INDEX, bits);
+            } else {
+                ALOGE("%s: invalid indexMask value 0x%x in %s",
+                        __func__, bits, aidl.toString().c_str());
+                return unexpected(BAD_VALUE);
+            }
+        case Tag::layoutMask:
+            // The fast path is to find a direct match for some known layout mask.
+            if (const auto layoutMatch = convert(aidl, isInput ? mIn : mOut, __func__,
+                    isInput ? "input" : "output");
+                    layoutMatch.ok()) {
+                return layoutMatch;
+            }
+            // If a match for a predefined layout wasn't found, make a custom one from bits.
+            if (audio_channel_mask_t bitMask =
+                    aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+                            aidl.get<Tag::layoutMask>(), isInput);
+                    bitMask != AUDIO_CHANNEL_NONE) {
+                return bitMask;
+            }
+            return unexpected(BAD_VALUE);
+        case Tag::voiceMask:
+            return convert(aidl, mVoice, __func__, "voice");
+    }
+    ALOGE("%s: unexpected tag value %d", __func__, aidl.getTag());
+    return unexpected(BAD_VALUE);
+}
+
+int legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
+        audio_channel_mask_t legacy, bool isInput) {
+    auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
+    const int legacyInitial = legacy; // for error message
+    int aidlLayout = 0;
+    for (const auto& bitPair : bitMapping) {
+        if ((legacy & bitPair.first) == bitPair.first) {
+            aidlLayout |= bitPair.second;
+            legacy = static_cast<audio_channel_mask_t>(legacy & ~bitPair.first);
+            if (legacy == 0) {
+                return aidlLayout;
+            }
+        }
+    }
+    ALOGE("%s: legacy %s audio_channel_mask_t 0x%x contains unrecognized bits 0x%x",
+            __func__, isInput ? "input" : "output", legacyInitial, legacy);
+    return 0;
+}
+
+ConversionResult<AudioChannelLayout> legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+        audio_channel_mask_t legacy, bool isInput) {
+    using DirectMap = std::map<audio_channel_mask_t, AudioChannelLayout>;
+    using Tag = AudioChannelLayout::Tag;
+    static const DirectMap mInAndVoice = make_DirectMap(
+            getInAudioChannelPairs(), getVoiceAudioChannelPairs());
+    static const DirectMap mOut = make_DirectMap(getOutAudioChannelPairs());
+
+    auto convert = [](const audio_channel_mask_t legacy, const DirectMap& m,
+            const char* func, const char* type) -> ConversionResult<AudioChannelLayout> {
+        if (auto it = m.find(legacy); it != m.end()) {
+            return it->second;
+        } else {
+            ALOGW("%s: no AudioChannelLayout found for legacy %s audio_channel_mask_t value 0x%x",
+                    func, type, legacy);
+            return unexpected(BAD_VALUE);
+        }
+    };
+
+    if (legacy == AUDIO_CHANNEL_NONE) {
+        return AudioChannelLayout{};
+    } else if (legacy == AUDIO_CHANNEL_INVALID) {
+        return AudioChannelLayout::make<Tag::invalid>(0);
+    }
+
+    const audio_channel_representation_t repr = audio_channel_mask_get_representation(legacy);
+    if (repr == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+        if (audio_channel_mask_is_valid(legacy)) {
+            const int indexMask = VALUE_OR_RETURN(
+                    convertIntegral<int>(audio_channel_mask_get_bits(legacy)));
+            return AudioChannelLayout::make<Tag::indexMask>(indexMask);
+        } else {
+            ALOGE("%s: legacy audio_channel_mask_t value 0x%x is invalid", __func__, legacy);
+            return unexpected(BAD_VALUE);
+        }
+    } else if (repr == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
+        // The fast path is to find a direct match for some known layout mask.
+        if (const auto layoutMatch = convert(legacy, isInput ? mInAndVoice : mOut, __func__,
+                isInput ? "input / voice" : "output");
+                layoutMatch.ok()) {
+            return layoutMatch;
+        }
+        // If a match for a predefined layout wasn't found, make a custom one from bits,
+        // rejecting those with voice channel bits.
+        if (!isInput ||
+                (legacy & (AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK)) == 0) {
+            if (int bitMaskLayout =
+                    legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
+                            legacy, isInput);
+                    bitMaskLayout != 0) {
+                return AudioChannelLayout::make<Tag::layoutMask>(bitMaskLayout);
+            }
+        } else {
+            ALOGE("%s: legacy audio_channel_mask_t value 0x%x contains voice bits",
+                    __func__, legacy);
+        }
+        return unexpected(BAD_VALUE);
+    }
+
+    ALOGE("%s: unknown representation %d in audio_channel_mask_t value 0x%x",
+            __func__, repr, legacy);
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
+        const AudioDeviceDescription& aidl) {
+    static const std::map<AudioDeviceDescription, audio_devices_t> m =
+            make_ReverseMap(getAudioDevicePairs());
+    if (auto it = m.find(aidl); it != m.end()) {
+        return it->second;
+    } else {
+        ALOGE("%s: no legacy audio_devices_t found for %s", __func__, aidl.toString().c_str());
+        return unexpected(BAD_VALUE);
+    }
+}
+
+ConversionResult<AudioDeviceDescription> legacy2aidl_audio_devices_t_AudioDeviceDescription(
+        audio_devices_t legacy) {
+    static const std::map<audio_devices_t, AudioDeviceDescription> m =
+            make_DirectMap(getAudioDevicePairs());
+    if (auto it = m.find(legacy); it != m.end()) {
+        return it->second;
+    } else {
+        ALOGE("%s: no AudioDeviceDescription found for legacy audio_devices_t value 0x%x",
+                __func__, legacy);
+        return unexpected(BAD_VALUE);
+    }
+}
+
+::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);
+}
+
+::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>()));
+    return OK;
+}
+
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+        const AudioDevice& aidl,
+        audio_devices_t* legacyType, std::string* legacyAddress) {
+    *legacyType = VALUE_OR_RETURN_STATUS(
+            aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
+    *legacyAddress = aidl.address.get<AudioDeviceAddress::id>();
+    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(
+            legacy2aidl_string(legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN));
+    aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
+    return aidl;
+}
+
+ConversionResult<AudioDevice>
+legacy2aidl_audio_device_AudioDevice(
+        audio_devices_t legacyType, const String8& legacyAddress) {
+    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);
+    return aidl;
+}
+
+ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
+        const AudioFormatDescription& aidl) {
+    static const std::map<AudioFormatDescription, audio_format_t> m =
+            make_ReverseMap(getAudioFormatPairs());
+    if (auto it = m.find(aidl); it != m.end()) {
+        return it->second;
+    } else {
+        ALOGE("%s: no legacy audio_format_t found for %s", __func__, aidl.toString().c_str());
+        return unexpected(BAD_VALUE);
+    }
+}
+
+ConversionResult<AudioFormatDescription> legacy2aidl_audio_format_t_AudioFormatDescription(
+        audio_format_t legacy) {
+    static const std::map<audio_format_t, AudioFormatDescription> m =
+            make_DirectMap(getAudioFormatPairs());
+    if (auto it = m.find(legacy); it != m.end()) {
+        return it->second;
+    } else {
+        ALOGE("%s: no AudioFormatDescription found for legacy audio_format_t value 0x%x",
+                __func__, legacy);
+        return unexpected(BAD_VALUE);
+    }
+}
+
+ConversionResult<audio_gain_mode_t> aidl2legacy_AudioGainMode_audio_gain_mode_t(
+        AudioGainMode aidl) {
+    switch (aidl) {
+        case AudioGainMode::JOINT:
+            return AUDIO_GAIN_MODE_JOINT;
+        case AudioGainMode::CHANNELS:
+            return AUDIO_GAIN_MODE_CHANNELS;
+        case AudioGainMode::RAMP:
+            return AUDIO_GAIN_MODE_RAMP;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioGainMode> legacy2aidl_audio_gain_mode_t_AudioGainMode(
+        audio_gain_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_GAIN_MODE_JOINT:
+            return AudioGainMode::JOINT;
+        case AUDIO_GAIN_MODE_CHANNELS:
+            return AudioGainMode::CHANNELS;
+        case AUDIO_GAIN_MODE_RAMP:
+            return AudioGainMode::RAMP;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl) {
+    return convertBitmask<audio_gain_mode_t, int32_t, audio_gain_mode_t, AudioGainMode>(
+            aidl, aidl2legacy_AudioGainMode_audio_gain_mode_t,
+            // AudioGainMode is index-based.
+            indexToEnum_index<AudioGainMode>,
+            // AUDIO_GAIN_MODE_* constants are mask-based.
+            enumToMask_bitmask<audio_gain_mode_t, audio_gain_mode_t>);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy) {
+    return convertBitmask<int32_t, audio_gain_mode_t, AudioGainMode, audio_gain_mode_t>(
+            legacy, legacy2aidl_audio_gain_mode_t_AudioGainMode,
+            // AUDIO_GAIN_MODE_* constants are mask-based.
+            indexToEnum_bitmask<audio_gain_mode_t>,
+            // AudioGainMode is index-based.
+            enumToMask_index<int32_t, AudioGainMode>);
+}
+
+ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
+        const AudioGainConfig& aidl, bool isInput) {
+    audio_gain_config legacy;
+    legacy.index = VALUE_OR_RETURN(convertIntegral<int>(aidl.index));
+    legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
+    legacy.channel_mask = VALUE_OR_RETURN(
+            aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
+    const bool isJoint = bitmaskIsSet(aidl.mode, AudioGainMode::JOINT);
+    size_t numValues = isJoint ? 1
+                               : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
+                                         : audio_channel_count_from_out_mask(legacy.channel_mask);
+    if (aidl.values.size() != numValues || aidl.values.size() > std::size(legacy.values)) {
+        return unexpected(BAD_VALUE);
+    }
+    for (size_t i = 0; i < numValues; ++i) {
+        legacy.values[i] = VALUE_OR_RETURN(convertIntegral<int>(aidl.values[i]));
+    }
+    legacy.ramp_duration_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.rampDurationMs));
+    return legacy;
+}
+
+ConversionResult<AudioGainConfig> legacy2aidl_audio_gain_config_AudioGainConfig(
+        const audio_gain_config& legacy, bool isInput) {
+    AudioGainConfig aidl;
+    aidl.index = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.index));
+    aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
+    aidl.channelMask = VALUE_OR_RETURN(
+            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+    const bool isJoint = (legacy.mode & AUDIO_GAIN_MODE_JOINT) != 0;
+    size_t numValues = isJoint ? 1
+                               : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
+                                         : audio_channel_count_from_out_mask(legacy.channel_mask);
+    aidl.values.resize(numValues);
+    for (size_t i = 0; i < numValues; ++i) {
+        aidl.values[i] = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.values[i]));
+    }
+    aidl.rampDurationMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.ramp_duration_ms));
+    return aidl;
+}
+
+ConversionResult<audio_input_flags_t> aidl2legacy_AudioInputFlags_audio_input_flags_t(
+        AudioInputFlags aidl) {
+    switch (aidl) {
+        case AudioInputFlags::FAST:
+            return AUDIO_INPUT_FLAG_FAST;
+        case AudioInputFlags::HW_HOTWORD:
+            return AUDIO_INPUT_FLAG_HW_HOTWORD;
+        case AudioInputFlags::RAW:
+            return AUDIO_INPUT_FLAG_RAW;
+        case AudioInputFlags::SYNC:
+            return AUDIO_INPUT_FLAG_SYNC;
+        case AudioInputFlags::MMAP_NOIRQ:
+            return AUDIO_INPUT_FLAG_MMAP_NOIRQ;
+        case AudioInputFlags::VOIP_TX:
+            return AUDIO_INPUT_FLAG_VOIP_TX;
+        case AudioInputFlags::HW_AV_SYNC:
+            return AUDIO_INPUT_FLAG_HW_AV_SYNC;
+        case AudioInputFlags::DIRECT:
+            return AUDIO_INPUT_FLAG_DIRECT;
+        case AudioInputFlags::ULTRASOUND:
+            return AUDIO_INPUT_FLAG_ULTRASOUND;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
+        audio_input_flags_t legacy) {
+    switch (legacy) {
+        case AUDIO_INPUT_FLAG_NONE:
+            break; // shouldn't get here. must be listed  -Werror,-Wswitch
+        case AUDIO_INPUT_FLAG_FAST:
+            return AudioInputFlags::FAST;
+        case AUDIO_INPUT_FLAG_HW_HOTWORD:
+            return AudioInputFlags::HW_HOTWORD;
+        case AUDIO_INPUT_FLAG_RAW:
+            return AudioInputFlags::RAW;
+        case AUDIO_INPUT_FLAG_SYNC:
+            return AudioInputFlags::SYNC;
+        case AUDIO_INPUT_FLAG_MMAP_NOIRQ:
+            return AudioInputFlags::MMAP_NOIRQ;
+        case AUDIO_INPUT_FLAG_VOIP_TX:
+            return AudioInputFlags::VOIP_TX;
+        case AUDIO_INPUT_FLAG_HW_AV_SYNC:
+            return AudioInputFlags::HW_AV_SYNC;
+        case AUDIO_INPUT_FLAG_DIRECT:
+            return AudioInputFlags::DIRECT;
+        case AUDIO_INPUT_FLAG_ULTRASOUND:
+            return AudioInputFlags::ULTRASOUND;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
+        AudioOutputFlags aidl) {
+    switch (aidl) {
+        case AudioOutputFlags::DIRECT:
+            return AUDIO_OUTPUT_FLAG_DIRECT;
+        case AudioOutputFlags::PRIMARY:
+            return AUDIO_OUTPUT_FLAG_PRIMARY;
+        case AudioOutputFlags::FAST:
+            return AUDIO_OUTPUT_FLAG_FAST;
+        case AudioOutputFlags::DEEP_BUFFER:
+            return AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+        case AudioOutputFlags::COMPRESS_OFFLOAD:
+            return AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+        case AudioOutputFlags::NON_BLOCKING:
+            return AUDIO_OUTPUT_FLAG_NON_BLOCKING;
+        case AudioOutputFlags::HW_AV_SYNC:
+            return AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
+        case AudioOutputFlags::TTS:
+            return AUDIO_OUTPUT_FLAG_TTS;
+        case AudioOutputFlags::RAW:
+            return AUDIO_OUTPUT_FLAG_RAW;
+        case AudioOutputFlags::SYNC:
+            return AUDIO_OUTPUT_FLAG_SYNC;
+        case AudioOutputFlags::IEC958_NONAUDIO:
+            return AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
+        case AudioOutputFlags::DIRECT_PCM:
+            return AUDIO_OUTPUT_FLAG_DIRECT_PCM;
+        case AudioOutputFlags::MMAP_NOIRQ:
+            return AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+        case AudioOutputFlags::VOIP_RX:
+            return AUDIO_OUTPUT_FLAG_VOIP_RX;
+        case AudioOutputFlags::INCALL_MUSIC:
+            return AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
+        case AudioOutputFlags::GAPLESS_OFFLOAD:
+            return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
+        case AudioOutputFlags::ULTRASOUND:
+            return AUDIO_OUTPUT_FLAG_ULTRASOUND;
+        case AudioOutputFlags::SPATIALIZER:
+            return AUDIO_OUTPUT_FLAG_SPATIALIZER;
+        case AudioOutputFlags::BIT_PERFECT:
+            return AUDIO_OUTPUT_FLAG_BIT_PERFECT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
+        audio_output_flags_t legacy) {
+    switch (legacy) {
+        case AUDIO_OUTPUT_FLAG_NONE:
+            break; // shouldn't get here. must be listed  -Werror,-Wswitch
+        case AUDIO_OUTPUT_FLAG_DIRECT:
+            return AudioOutputFlags::DIRECT;
+        case AUDIO_OUTPUT_FLAG_PRIMARY:
+            return AudioOutputFlags::PRIMARY;
+        case AUDIO_OUTPUT_FLAG_FAST:
+            return AudioOutputFlags::FAST;
+        case AUDIO_OUTPUT_FLAG_DEEP_BUFFER:
+            return AudioOutputFlags::DEEP_BUFFER;
+        case AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD:
+            return AudioOutputFlags::COMPRESS_OFFLOAD;
+        case AUDIO_OUTPUT_FLAG_NON_BLOCKING:
+            return AudioOutputFlags::NON_BLOCKING;
+        case AUDIO_OUTPUT_FLAG_HW_AV_SYNC:
+            return AudioOutputFlags::HW_AV_SYNC;
+        case AUDIO_OUTPUT_FLAG_TTS:
+            return AudioOutputFlags::TTS;
+        case AUDIO_OUTPUT_FLAG_RAW:
+            return AudioOutputFlags::RAW;
+        case AUDIO_OUTPUT_FLAG_SYNC:
+            return AudioOutputFlags::SYNC;
+        case AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO:
+            return AudioOutputFlags::IEC958_NONAUDIO;
+        case AUDIO_OUTPUT_FLAG_DIRECT_PCM:
+            return AudioOutputFlags::DIRECT_PCM;
+        case AUDIO_OUTPUT_FLAG_MMAP_NOIRQ:
+            return AudioOutputFlags::MMAP_NOIRQ;
+        case AUDIO_OUTPUT_FLAG_VOIP_RX:
+            return AudioOutputFlags::VOIP_RX;
+        case AUDIO_OUTPUT_FLAG_INCALL_MUSIC:
+            return AudioOutputFlags::INCALL_MUSIC;
+        case AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD:
+            return AudioOutputFlags::GAPLESS_OFFLOAD;
+        case AUDIO_OUTPUT_FLAG_ULTRASOUND:
+            return AudioOutputFlags::ULTRASOUND;
+        case AUDIO_OUTPUT_FLAG_SPATIALIZER:
+            return AudioOutputFlags::SPATIALIZER;
+        case AUDIO_OUTPUT_FLAG_BIT_PERFECT:
+            return AudioOutputFlags::BIT_PERFECT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
+        int32_t aidl) {
+    using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
+
+    LegacyMask converted = VALUE_OR_RETURN(
+            (convertBitmask<LegacyMask, int32_t, audio_input_flags_t, AudioInputFlags>(
+                    aidl, aidl2legacy_AudioInputFlags_audio_input_flags_t,
+                    indexToEnum_index<AudioInputFlags>,
+                    enumToMask_bitmask<LegacyMask, audio_input_flags_t>)));
+    return static_cast<audio_input_flags_t>(converted);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
+        audio_input_flags_t legacy) {
+    using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
+
+    LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
+    return convertBitmask<int32_t, LegacyMask, AudioInputFlags, audio_input_flags_t>(
+            legacyMask, legacy2aidl_audio_input_flags_t_AudioInputFlags,
+            indexToEnum_bitmask<audio_input_flags_t>,
+            enumToMask_index<int32_t, AudioInputFlags>);
+}
+
+ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
+        int32_t aidl) {
+    return convertBitmask<audio_output_flags_t,
+            int32_t,
+            audio_output_flags_t,
+            AudioOutputFlags>(
+            aidl, aidl2legacy_AudioOutputFlags_audio_output_flags_t,
+            indexToEnum_index<AudioOutputFlags>,
+            enumToMask_bitmask<audio_output_flags_t, audio_output_flags_t>);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
+        audio_output_flags_t legacy) {
+    using LegacyMask = std::underlying_type_t<audio_output_flags_t>;
+
+    LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
+    return convertBitmask<int32_t, LegacyMask, AudioOutputFlags, audio_output_flags_t>(
+            legacyMask, legacy2aidl_audio_output_flags_t_AudioOutputFlags,
+            indexToEnum_bitmask<audio_output_flags_t>,
+            enumToMask_index<int32_t, AudioOutputFlags>);
+}
+
+ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
+        const AudioIoFlags& aidl, bool isInput) {
+    audio_io_flags legacy;
+    if (isInput) {
+        legacy.input = VALUE_OR_RETURN(
+                aidl2legacy_int32_t_audio_input_flags_t_mask(
+                        VALUE_OR_RETURN(UNION_GET(aidl, input))));
+    } else {
+        legacy.output = VALUE_OR_RETURN(
+                aidl2legacy_int32_t_audio_output_flags_t_mask(
+                        VALUE_OR_RETURN(UNION_GET(aidl, output))));
+    }
+    return legacy;
+}
+
+ConversionResult<AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
+        const audio_io_flags& legacy, bool isInput) {
+    AudioIoFlags aidl;
+    if (isInput) {
+        UNION_SET(aidl, input,
+                VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(legacy.input)));
+    } else {
+        UNION_SET(aidl, output,
+                VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(legacy.output)));
+    }
+    return aidl;
+}
+
+ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
+        AudioStreamType aidl) {
+    switch (aidl) {
+        case AudioStreamType::INVALID:
+            break;  // return error
+        case AudioStreamType::SYS_RESERVED_DEFAULT:
+            return AUDIO_STREAM_DEFAULT;
+        case AudioStreamType::VOICE_CALL:
+            return AUDIO_STREAM_VOICE_CALL;
+        case AudioStreamType::SYSTEM:
+            return AUDIO_STREAM_SYSTEM;
+        case AudioStreamType::RING:
+            return AUDIO_STREAM_RING;
+        case AudioStreamType::MUSIC:
+            return AUDIO_STREAM_MUSIC;
+        case AudioStreamType::ALARM:
+            return AUDIO_STREAM_ALARM;
+        case AudioStreamType::NOTIFICATION:
+            return AUDIO_STREAM_NOTIFICATION;
+        case AudioStreamType::BLUETOOTH_SCO:
+            return AUDIO_STREAM_BLUETOOTH_SCO;
+        case AudioStreamType::ENFORCED_AUDIBLE:
+            return AUDIO_STREAM_ENFORCED_AUDIBLE;
+        case AudioStreamType::DTMF:
+            return AUDIO_STREAM_DTMF;
+        case AudioStreamType::TTS:
+            return AUDIO_STREAM_TTS;
+        case AudioStreamType::ACCESSIBILITY:
+            return AUDIO_STREAM_ACCESSIBILITY;
+        case AudioStreamType::ASSISTANT:
+            return AUDIO_STREAM_ASSISTANT;
+        case AudioStreamType::SYS_RESERVED_REROUTING:
+            return AUDIO_STREAM_REROUTING;
+        case AudioStreamType::SYS_RESERVED_PATCH:
+            return AUDIO_STREAM_PATCH;
+        case AudioStreamType::CALL_ASSISTANT:
+            return AUDIO_STREAM_CALL_ASSISTANT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioStreamType> legacy2aidl_audio_stream_type_t_AudioStreamType(
+        audio_stream_type_t legacy) {
+    switch (legacy) {
+        case AUDIO_STREAM_DEFAULT:
+            return AudioStreamType::SYS_RESERVED_DEFAULT;
+        case AUDIO_STREAM_VOICE_CALL:
+            return AudioStreamType::VOICE_CALL;
+        case AUDIO_STREAM_SYSTEM:
+            return AudioStreamType::SYSTEM;
+        case AUDIO_STREAM_RING:
+            return AudioStreamType::RING;
+        case AUDIO_STREAM_MUSIC:
+            return AudioStreamType::MUSIC;
+        case AUDIO_STREAM_ALARM:
+            return AudioStreamType::ALARM;
+        case AUDIO_STREAM_NOTIFICATION:
+            return AudioStreamType::NOTIFICATION;
+        case AUDIO_STREAM_BLUETOOTH_SCO:
+            return AudioStreamType::BLUETOOTH_SCO;
+        case AUDIO_STREAM_ENFORCED_AUDIBLE:
+            return AudioStreamType::ENFORCED_AUDIBLE;
+        case AUDIO_STREAM_DTMF:
+            return AudioStreamType::DTMF;
+        case AUDIO_STREAM_TTS:
+            return AudioStreamType::TTS;
+        case AUDIO_STREAM_ACCESSIBILITY:
+            return AudioStreamType::ACCESSIBILITY;
+        case AUDIO_STREAM_ASSISTANT:
+            return AudioStreamType::ASSISTANT;
+        case AUDIO_STREAM_REROUTING:
+            return AudioStreamType::SYS_RESERVED_REROUTING;
+        case AUDIO_STREAM_PATCH:
+            return AudioStreamType::SYS_RESERVED_PATCH;
+        case AUDIO_STREAM_CALL_ASSISTANT:
+            return AudioStreamType::CALL_ASSISTANT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
+        AudioSource aidl) {
+    switch (aidl) {
+        case AudioSource::SYS_RESERVED_INVALID:
+            return AUDIO_SOURCE_INVALID;
+        case AudioSource::DEFAULT:
+            return AUDIO_SOURCE_DEFAULT;
+        case AudioSource::MIC:
+            return AUDIO_SOURCE_MIC;
+        case AudioSource::VOICE_UPLINK:
+            return AUDIO_SOURCE_VOICE_UPLINK;
+        case AudioSource::VOICE_DOWNLINK:
+            return AUDIO_SOURCE_VOICE_DOWNLINK;
+        case AudioSource::VOICE_CALL:
+            return AUDIO_SOURCE_VOICE_CALL;
+        case AudioSource::CAMCORDER:
+            return AUDIO_SOURCE_CAMCORDER;
+        case AudioSource::VOICE_RECOGNITION:
+            return AUDIO_SOURCE_VOICE_RECOGNITION;
+        case AudioSource::VOICE_COMMUNICATION:
+            return AUDIO_SOURCE_VOICE_COMMUNICATION;
+        case AudioSource::REMOTE_SUBMIX:
+            return AUDIO_SOURCE_REMOTE_SUBMIX;
+        case AudioSource::UNPROCESSED:
+            return AUDIO_SOURCE_UNPROCESSED;
+        case AudioSource::VOICE_PERFORMANCE:
+            return AUDIO_SOURCE_VOICE_PERFORMANCE;
+        case AudioSource::ULTRASOUND:
+            return AUDIO_SOURCE_ULTRASOUND;
+        case AudioSource::ECHO_REFERENCE:
+            return AUDIO_SOURCE_ECHO_REFERENCE;
+        case AudioSource::FM_TUNER:
+            return AUDIO_SOURCE_FM_TUNER;
+        case AudioSource::HOTWORD:
+            return AUDIO_SOURCE_HOTWORD;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioSource> legacy2aidl_audio_source_t_AudioSource(
+        audio_source_t legacy) {
+    switch (legacy) {
+        case AUDIO_SOURCE_INVALID:
+            return AudioSource::SYS_RESERVED_INVALID;
+        case AUDIO_SOURCE_DEFAULT:
+            return AudioSource::DEFAULT;
+        case AUDIO_SOURCE_MIC:
+            return AudioSource::MIC;
+        case AUDIO_SOURCE_VOICE_UPLINK:
+            return AudioSource::VOICE_UPLINK;
+        case AUDIO_SOURCE_VOICE_DOWNLINK:
+            return AudioSource::VOICE_DOWNLINK;
+        case AUDIO_SOURCE_VOICE_CALL:
+            return AudioSource::VOICE_CALL;
+        case AUDIO_SOURCE_CAMCORDER:
+            return AudioSource::CAMCORDER;
+        case AUDIO_SOURCE_VOICE_RECOGNITION:
+            return AudioSource::VOICE_RECOGNITION;
+        case AUDIO_SOURCE_VOICE_COMMUNICATION:
+            return AudioSource::VOICE_COMMUNICATION;
+        case AUDIO_SOURCE_REMOTE_SUBMIX:
+            return AudioSource::REMOTE_SUBMIX;
+        case AUDIO_SOURCE_UNPROCESSED:
+            return AudioSource::UNPROCESSED;
+        case AUDIO_SOURCE_VOICE_PERFORMANCE:
+            return AudioSource::VOICE_PERFORMANCE;
+        case AUDIO_SOURCE_ULTRASOUND:
+            return AudioSource::ULTRASOUND;
+        case AUDIO_SOURCE_ECHO_REFERENCE:
+            return AudioSource::ECHO_REFERENCE;
+        case AUDIO_SOURCE_FM_TUNER:
+            return AudioSource::FM_TUNER;
+        case AUDIO_SOURCE_HOTWORD:
+            return AudioSource::HOTWORD;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl) {
+    return convertReinterpret<audio_session_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_content_type_t>
+aidl2legacy_AudioContentType_audio_content_type_t(AudioContentType aidl) {
+    switch (aidl) {
+        case AudioContentType::UNKNOWN:
+            return AUDIO_CONTENT_TYPE_UNKNOWN;
+        case AudioContentType::SPEECH:
+            return AUDIO_CONTENT_TYPE_SPEECH;
+        case AudioContentType::MUSIC:
+            return AUDIO_CONTENT_TYPE_MUSIC;
+        case AudioContentType::MOVIE:
+            return AUDIO_CONTENT_TYPE_MOVIE;
+        case AudioContentType::SONIFICATION:
+            return AUDIO_CONTENT_TYPE_SONIFICATION;
+        case AudioContentType::ULTRASOUND:
+            return AUDIO_CONTENT_TYPE_ULTRASOUND;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioContentType>
+legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy) {
+    switch (legacy) {
+        case AUDIO_CONTENT_TYPE_UNKNOWN:
+            return AudioContentType::UNKNOWN;
+        case AUDIO_CONTENT_TYPE_SPEECH:
+            return AudioContentType::SPEECH;
+        case AUDIO_CONTENT_TYPE_MUSIC:
+            return AudioContentType::MUSIC;
+        case AUDIO_CONTENT_TYPE_MOVIE:
+            return AudioContentType::MOVIE;
+        case AUDIO_CONTENT_TYPE_SONIFICATION:
+            return AudioContentType::SONIFICATION;
+        case AUDIO_CONTENT_TYPE_ULTRASOUND:
+            return AudioContentType::ULTRASOUND;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_usage_t>
+aidl2legacy_AudioUsage_audio_usage_t(AudioUsage aidl) {
+    switch (aidl) {
+        case AudioUsage::INVALID:
+            break;  // return error
+        case AudioUsage::UNKNOWN:
+            return AUDIO_USAGE_UNKNOWN;
+        case AudioUsage::MEDIA:
+            return AUDIO_USAGE_MEDIA;
+        case AudioUsage::VOICE_COMMUNICATION:
+            return AUDIO_USAGE_VOICE_COMMUNICATION;
+        case AudioUsage::VOICE_COMMUNICATION_SIGNALLING:
+            return AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+        case AudioUsage::ALARM:
+            return AUDIO_USAGE_ALARM;
+        case AudioUsage::NOTIFICATION:
+            return AUDIO_USAGE_NOTIFICATION;
+        case AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE:
+            return AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+        case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST:
+            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
+        case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT:
+            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT;
+        case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED:
+            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED;
+        case AudioUsage::NOTIFICATION_EVENT:
+            return AUDIO_USAGE_NOTIFICATION_EVENT;
+        case AudioUsage::ASSISTANCE_ACCESSIBILITY:
+            return AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+        case AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE:
+            return AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
+        case AudioUsage::ASSISTANCE_SONIFICATION:
+            return AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+        case AudioUsage::GAME:
+            return AUDIO_USAGE_GAME;
+        case AudioUsage::VIRTUAL_SOURCE:
+            return AUDIO_USAGE_VIRTUAL_SOURCE;
+        case AudioUsage::ASSISTANT:
+            return AUDIO_USAGE_ASSISTANT;
+        case AudioUsage::CALL_ASSISTANT:
+            return AUDIO_USAGE_CALL_ASSISTANT;
+        case AudioUsage::EMERGENCY:
+            return AUDIO_USAGE_EMERGENCY;
+        case AudioUsage::SAFETY:
+            return AUDIO_USAGE_SAFETY;
+        case AudioUsage::VEHICLE_STATUS:
+            return AUDIO_USAGE_VEHICLE_STATUS;
+        case AudioUsage::ANNOUNCEMENT:
+            return AUDIO_USAGE_ANNOUNCEMENT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioUsage>
+legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy) {
+    switch (legacy) {
+        case AUDIO_USAGE_UNKNOWN:
+            return AudioUsage::UNKNOWN;
+        case AUDIO_USAGE_MEDIA:
+            return AudioUsage::MEDIA;
+        case AUDIO_USAGE_VOICE_COMMUNICATION:
+            return AudioUsage::VOICE_COMMUNICATION;
+        case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
+            return AudioUsage::VOICE_COMMUNICATION_SIGNALLING;
+        case AUDIO_USAGE_ALARM:
+            return AudioUsage::ALARM;
+        case AUDIO_USAGE_NOTIFICATION:
+            return AudioUsage::NOTIFICATION;
+        case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
+            return AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE;
+        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+            return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST;
+        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+            return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT;
+        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+            return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED;
+        case AUDIO_USAGE_NOTIFICATION_EVENT:
+            return AudioUsage::NOTIFICATION_EVENT;
+        case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+            return AudioUsage::ASSISTANCE_ACCESSIBILITY;
+        case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+            return AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE;
+        case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
+            return AudioUsage::ASSISTANCE_SONIFICATION;
+        case AUDIO_USAGE_GAME:
+            return AudioUsage::GAME;
+        case AUDIO_USAGE_VIRTUAL_SOURCE:
+            return AudioUsage::VIRTUAL_SOURCE;
+        case AUDIO_USAGE_ASSISTANT:
+            return AudioUsage::ASSISTANT;
+        case AUDIO_USAGE_CALL_ASSISTANT:
+            return AudioUsage::CALL_ASSISTANT;
+        case AUDIO_USAGE_EMERGENCY:
+            return AudioUsage::EMERGENCY;
+        case AUDIO_USAGE_SAFETY:
+            return AudioUsage::SAFETY;
+        case AUDIO_USAGE_VEHICLE_STATUS:
+            return AudioUsage::VEHICLE_STATUS;
+        case AUDIO_USAGE_ANNOUNCEMENT:
+            return AudioUsage::ANNOUNCEMENT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+
+ConversionResult<audio_encapsulation_mode_t>
+aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(AudioEncapsulationMode aidl) {
+    switch (aidl) {
+        case AudioEncapsulationMode::INVALID:
+            break;  // return error
+        case AudioEncapsulationMode::NONE:
+            return AUDIO_ENCAPSULATION_MODE_NONE;
+        case AudioEncapsulationMode::ELEMENTARY_STREAM:
+            return AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM;
+        case AudioEncapsulationMode::HANDLE:
+            return AUDIO_ENCAPSULATION_MODE_HANDLE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioEncapsulationMode>
+legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_ENCAPSULATION_MODE_NONE:
+            return AudioEncapsulationMode::NONE;
+        case AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM:
+            return AudioEncapsulationMode::ELEMENTARY_STREAM;
+        case AUDIO_ENCAPSULATION_MODE_HANDLE:
+            return AudioEncapsulationMode::HANDLE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_offload_info_t>
+aidl2legacy_AudioOffloadInfo_audio_offload_info_t(const AudioOffloadInfo& aidl) {
+    audio_offload_info_t legacy = AUDIO_INFO_INITIALIZER;
+    audio_config_base_t base = VALUE_OR_RETURN(
+            aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, false /*isInput*/));
+    legacy.sample_rate = base.sample_rate;
+    legacy.channel_mask = base.channel_mask;
+    legacy.format = base.format;
+    legacy.stream_type = VALUE_OR_RETURN(
+            aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
+    legacy.bit_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitRatePerSecond));
+    legacy.duration_us = VALUE_OR_RETURN(convertIntegral<int64_t>(aidl.durationUs));
+    legacy.has_video = aidl.hasVideo;
+    legacy.is_streaming = aidl.isStreaming;
+    legacy.bit_width = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitWidth));
+    legacy.offload_buffer_size = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.offloadBufferSize));
+    legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
+    legacy.encapsulation_mode = VALUE_OR_RETURN(
+            aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(aidl.encapsulationMode));
+    legacy.content_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.contentId));
+    legacy.sync_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.syncId));
+    return legacy;
+}
+
+ConversionResult<AudioOffloadInfo>
+legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy) {
+    AudioOffloadInfo aidl;
+    // Version 0.1 fields.
+    if (legacy.size < offsetof(audio_offload_info_t, usage) + sizeof(audio_offload_info_t::usage)) {
+        return unexpected(BAD_VALUE);
+    }
+    const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
+        .channel_mask = legacy.channel_mask, .format = legacy.format };
+    aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(
+                    base, false /*isInput*/));
+    aidl.streamType = VALUE_OR_RETURN(
+            legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream_type));
+    aidl.bitRatePerSecond = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_rate));
+    aidl.durationUs = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.duration_us));
+    aidl.hasVideo = legacy.has_video;
+    aidl.isStreaming = legacy.is_streaming;
+    aidl.bitWidth = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_width));
+    aidl.offloadBufferSize = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.offload_buffer_size));
+    aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
+
+    // Version 0.2 fields.
+    if (legacy.version >= AUDIO_OFFLOAD_INFO_VERSION_0_2) {
+        if (legacy.size <
+            offsetof(audio_offload_info_t, sync_id) + sizeof(audio_offload_info_t::sync_id)) {
+            return unexpected(BAD_VALUE);
+        }
+        aidl.encapsulationMode = VALUE_OR_RETURN(
+                legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(
+                        legacy.encapsulation_mode));
+        aidl.contentId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.content_id));
+        aidl.syncId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.sync_id));
+    }
+    return aidl;
+}
+
+ConversionResult<audio_config_t>
+aidl2legacy_AudioConfig_audio_config_t(const AudioConfig& aidl, bool isInput) {
+    const audio_config_base_t legacyBase = VALUE_OR_RETURN(
+            aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, isInput));
+    audio_config_t legacy = AUDIO_CONFIG_INITIALIZER;
+    legacy.sample_rate = legacyBase.sample_rate;
+    legacy.channel_mask = legacyBase.channel_mask;
+    legacy.format = legacyBase.format;
+    legacy.offload_info = VALUE_OR_RETURN(
+            aidl2legacy_AudioOffloadInfo_audio_offload_info_t(aidl.offloadInfo));
+    legacy.frame_count = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.frameCount));
+    return legacy;
+}
+
+ConversionResult<AudioConfig>
+legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput) {
+    const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
+        .channel_mask = legacy.channel_mask, .format = legacy.format };
+    AudioConfig aidl;
+    aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(base, isInput));
+    aidl.offloadInfo = VALUE_OR_RETURN(
+            legacy2aidl_audio_offload_info_t_AudioOffloadInfo(legacy.offload_info));
+    aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.frame_count));
+    return aidl;
+}
+
+ConversionResult<audio_config_base_t>
+aidl2legacy_AudioConfigBase_audio_config_base_t(const AudioConfigBase& aidl, bool isInput) {
+    audio_config_base_t legacy;
+    legacy.sample_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
+    legacy.channel_mask = VALUE_OR_RETURN(
+            aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
+    legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
+    return legacy;
+}
+
+ConversionResult<AudioConfigBase>
+legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput) {
+    AudioConfigBase aidl;
+    aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
+    aidl.channelMask = VALUE_OR_RETURN(
+            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+    aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
+    return aidl;
+}
+
+ConversionResult<audio_uuid_t>
+aidl2legacy_AudioUuid_audio_uuid_t(const AudioUuid& aidl) {
+    audio_uuid_t legacy;
+    legacy.timeLow = VALUE_OR_RETURN(convertReinterpret<uint32_t>(aidl.timeLow));
+    legacy.timeMid = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeMid));
+    legacy.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeHiAndVersion));
+    legacy.clockSeq = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.clockSeq));
+    if (aidl.node.size() != std::size(legacy.node)) {
+        return unexpected(BAD_VALUE);
+    }
+    std::copy(aidl.node.begin(), aidl.node.end(), legacy.node);
+    return legacy;
+}
+
+ConversionResult<AudioUuid>
+legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy) {
+    AudioUuid aidl;
+    aidl.timeLow = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.timeLow));
+    aidl.timeMid = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeMid));
+    aidl.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeHiAndVersion));
+    aidl.clockSeq = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.clockSeq));
+    std::copy(legacy.node, legacy.node + std::size(legacy.node), std::back_inserter(aidl.node));
+    return aidl;
+}
+
+ConversionResult<audio_encapsulation_metadata_type_t>
+aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
+        AudioEncapsulationMetadataType aidl) {
+    switch (aidl) {
+        case AudioEncapsulationMetadataType::NONE:
+            return AUDIO_ENCAPSULATION_METADATA_TYPE_NONE;
+        case AudioEncapsulationMetadataType::FRAMEWORK_TUNER:
+            return AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER;
+        case AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR:
+            return AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioEncapsulationMetadataType>
+legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
+        audio_encapsulation_metadata_type_t legacy) {
+    switch (legacy) {
+        case AUDIO_ENCAPSULATION_METADATA_TYPE_NONE:
+            return AudioEncapsulationMetadataType::NONE;
+        case AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER:
+            return AudioEncapsulationMetadataType::FRAMEWORK_TUNER;
+        case AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR:
+            return AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<uint32_t>
+aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl) {
+    return convertBitmask<uint32_t,
+            int32_t,
+            audio_encapsulation_mode_t,
+            AudioEncapsulationMode>(
+            aidl, aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t,
+            indexToEnum_index<AudioEncapsulationMode>,
+            enumToMask_index<uint32_t, audio_encapsulation_mode_t>);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy) {
+    return convertBitmask<int32_t,
+            uint32_t,
+            AudioEncapsulationMode,
+            audio_encapsulation_mode_t>(
+            legacy, legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode,
+            indexToEnum_index<audio_encapsulation_mode_t>,
+            enumToMask_index<int32_t, AudioEncapsulationMode>);
+}
+
+ConversionResult<uint32_t>
+aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl) {
+    return convertBitmask<uint32_t,
+            int32_t,
+            audio_encapsulation_metadata_type_t,
+            AudioEncapsulationMetadataType>(
+            aidl, aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t,
+            indexToEnum_index<AudioEncapsulationMetadataType>,
+            enumToMask_index<uint32_t, audio_encapsulation_metadata_type_t>);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy) {
+    return convertBitmask<int32_t,
+            uint32_t,
+            AudioEncapsulationMetadataType,
+            audio_encapsulation_metadata_type_t>(
+            legacy, legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType,
+            indexToEnum_index<audio_encapsulation_metadata_type_t>,
+            enumToMask_index<int32_t, AudioEncapsulationMetadataType>);
+}
+
+ConversionResult<audio_profile>
+aidl2legacy_AudioProfile_audio_profile(const AudioProfile& aidl, bool isInput) {
+    audio_profile legacy;
+    legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
+
+    if (aidl.sampleRates.size() > std::size(legacy.sample_rates)) {
+        return unexpected(BAD_VALUE);
+    }
+    RETURN_IF_ERROR(
+            convertRange(aidl.sampleRates.begin(), aidl.sampleRates.end(), legacy.sample_rates,
+                         convertIntegral<int32_t, unsigned int>));
+    legacy.num_sample_rates = aidl.sampleRates.size();
+
+    if (aidl.channelMasks.size() > std::size(legacy.channel_masks)) {
+        return unexpected(BAD_VALUE);
+    }
+    RETURN_IF_ERROR(
+            convertRange(aidl.channelMasks.begin(), aidl.channelMasks.end(), legacy.channel_masks,
+                    [isInput](const AudioChannelLayout& l) {
+                        return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
+                    }));
+    legacy.num_channel_masks = aidl.channelMasks.size();
+
+    legacy.encapsulation_type = VALUE_OR_RETURN(
+            aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(aidl.encapsulationType));
+    return legacy;
+}
+
+ConversionResult<AudioProfile>
+legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput) {
+    AudioProfile aidl;
+    aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
+
+    if (legacy.num_sample_rates > std::size(legacy.sample_rates)) {
+        return unexpected(BAD_VALUE);
+    }
+    RETURN_IF_ERROR(
+            convertRange(legacy.sample_rates, legacy.sample_rates + legacy.num_sample_rates,
+                         std::back_inserter(aidl.sampleRates),
+                         convertIntegral<unsigned int, int32_t>));
+
+    if (legacy.num_channel_masks > std::size(legacy.channel_masks)) {
+        return unexpected(BAD_VALUE);
+    }
+    RETURN_IF_ERROR(
+            convertRange(legacy.channel_masks, legacy.channel_masks + legacy.num_channel_masks,
+                         std::back_inserter(aidl.channelMasks),
+                    [isInput](audio_channel_mask_t m) {
+                        return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
+                    }));
+
+    aidl.encapsulationType = VALUE_OR_RETURN(
+            legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+                    legacy.encapsulation_type));
+    return aidl;
+}
+
+ConversionResult<audio_gain>
+aidl2legacy_AudioGain_audio_gain(const AudioGain& aidl, bool isInput) {
+    audio_gain legacy;
+    legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
+    legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+                    aidl.channelMask, isInput));
+    legacy.min_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.minValue));
+    legacy.max_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.maxValue));
+    legacy.default_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.defaultValue));
+    legacy.step_value = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.stepValue));
+    legacy.min_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.minRampMs));
+    legacy.max_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.maxRampMs));
+    return legacy;
+}
+
+ConversionResult<AudioGain>
+legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput) {
+    AudioGain aidl;
+    aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
+    aidl.channelMask = VALUE_OR_RETURN(
+            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+    aidl.minValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_value));
+    aidl.maxValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_value));
+    aidl.defaultValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.default_value));
+    aidl.stepValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.step_value));
+    aidl.minRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_ramp_ms));
+    aidl.maxRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_ramp_ms));
+    return aidl;
+}
+
+ConversionResult<audio_mode_t>
+aidl2legacy_AudioMode_audio_mode_t(AudioMode aidl) {
+    switch (aidl) {
+        case AudioMode::SYS_RESERVED_INVALID:
+            return AUDIO_MODE_INVALID;
+        case AudioMode::SYS_RESERVED_CURRENT:
+            return AUDIO_MODE_CURRENT;
+        case AudioMode::NORMAL:
+            return AUDIO_MODE_NORMAL;
+        case AudioMode::RINGTONE:
+            return AUDIO_MODE_RINGTONE;
+        case AudioMode::IN_CALL:
+            return AUDIO_MODE_IN_CALL;
+        case AudioMode::IN_COMMUNICATION:
+            return AUDIO_MODE_IN_COMMUNICATION;
+        case AudioMode::CALL_SCREEN:
+            return AUDIO_MODE_CALL_SCREEN;
+        case AudioMode::SYS_RESERVED_CALL_REDIRECT:
+            return AUDIO_MODE_CALL_REDIRECT;
+        case AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT:
+            return AUDIO_MODE_COMMUNICATION_REDIRECT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioMode>
+legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_MODE_INVALID:
+            return AudioMode::SYS_RESERVED_INVALID;
+        case AUDIO_MODE_CURRENT:
+            return AudioMode::SYS_RESERVED_CURRENT;
+        case AUDIO_MODE_NORMAL:
+            return AudioMode::NORMAL;
+        case AUDIO_MODE_RINGTONE:
+            return AudioMode::RINGTONE;
+        case AUDIO_MODE_IN_CALL:
+            return AudioMode::IN_CALL;
+        case AUDIO_MODE_IN_COMMUNICATION:
+            return AudioMode::IN_COMMUNICATION;
+        case AUDIO_MODE_CALL_SCREEN:
+            return AudioMode::CALL_SCREEN;
+        case AUDIO_MODE_CALL_REDIRECT:
+            return AudioMode::SYS_RESERVED_CALL_REDIRECT;
+        case AUDIO_MODE_COMMUNICATION_REDIRECT:
+            return AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT;
+        case AUDIO_MODE_CNT:
+            break;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_standard_t>
+aidl2legacy_AudioStandard_audio_standard_t(AudioStandard aidl) {
+    switch (aidl) {
+        case AudioStandard::NONE:
+            return AUDIO_STANDARD_NONE;
+        case AudioStandard::EDID:
+            return AUDIO_STANDARD_EDID;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioStandard>
+legacy2aidl_audio_standard_t_AudioStandard(audio_standard_t legacy) {
+    switch (legacy) {
+        case AUDIO_STANDARD_NONE:
+            return AudioStandard::NONE;
+        case AUDIO_STANDARD_EDID:
+            return AudioStandard::EDID;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_extra_audio_descriptor>
+aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
+        const ExtraAudioDescriptor& aidl) {
+    audio_extra_audio_descriptor legacy;
+    legacy.standard = VALUE_OR_RETURN(aidl2legacy_AudioStandard_audio_standard_t(aidl.standard));
+    if (aidl.audioDescriptor.size() > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
+        return unexpected(BAD_VALUE);
+    }
+    legacy.descriptor_length = aidl.audioDescriptor.size();
+    std::copy(aidl.audioDescriptor.begin(), aidl.audioDescriptor.end(),
+              std::begin(legacy.descriptor));
+    legacy.encapsulation_type =
+            VALUE_OR_RETURN(aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
+                    aidl.encapsulationType));
+    return legacy;
+}
+
+ConversionResult<ExtraAudioDescriptor>
+legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
+        const audio_extra_audio_descriptor& legacy) {
+    ExtraAudioDescriptor aidl;
+    aidl.standard = VALUE_OR_RETURN(legacy2aidl_audio_standard_t_AudioStandard(legacy.standard));
+    if (legacy.descriptor_length > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
+        return unexpected(BAD_VALUE);
+    }
+    aidl.audioDescriptor.resize(legacy.descriptor_length);
+    std::copy(legacy.descriptor, legacy.descriptor + legacy.descriptor_length,
+              aidl.audioDescriptor.begin());
+    aidl.encapsulationType =
+            VALUE_OR_RETURN(legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+                    legacy.encapsulation_type));
+    return aidl;
+}
+
+ConversionResult<audio_encapsulation_type_t>
+aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
+        const AudioEncapsulationType& aidl) {
+    switch (aidl) {
+        case AudioEncapsulationType::NONE:
+            return AUDIO_ENCAPSULATION_TYPE_NONE;
+        case AudioEncapsulationType::IEC61937:
+            return AUDIO_ENCAPSULATION_TYPE_IEC61937;
+        case AudioEncapsulationType::PCM:
+            return AUDIO_ENCAPSULATION_TYPE_PCM;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioEncapsulationType>
+legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+        const audio_encapsulation_type_t & legacy) {
+    switch (legacy) {
+        case AUDIO_ENCAPSULATION_TYPE_NONE:
+            return AudioEncapsulationType::NONE;
+        case AUDIO_ENCAPSULATION_TYPE_IEC61937:
+            return AudioEncapsulationType::IEC61937;
+        case AUDIO_ENCAPSULATION_TYPE_PCM:
+            return AudioEncapsulationType::PCM;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(AudioDualMonoMode aidl) {
+    switch (aidl) {
+        case AudioDualMonoMode::OFF:
+            return AUDIO_DUAL_MONO_MODE_OFF;
+        case AudioDualMonoMode::LR:
+            return AUDIO_DUAL_MONO_MODE_LR;
+        case AudioDualMonoMode::LL:
+            return AUDIO_DUAL_MONO_MODE_LL;
+        case AudioDualMonoMode::RR:
+            return AUDIO_DUAL_MONO_MODE_RR;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_DUAL_MONO_MODE_OFF:
+            return AudioDualMonoMode::OFF;
+        case AUDIO_DUAL_MONO_MODE_LR:
+            return AudioDualMonoMode::LR;
+        case AUDIO_DUAL_MONO_MODE_LL:
+            return AudioDualMonoMode::LL;
+        case AUDIO_DUAL_MONO_MODE_RR:
+            return AudioDualMonoMode::RR;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+        AudioPlaybackRate::TimestretchFallbackMode aidl) {
+    switch (aidl) {
+        case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT:
+            return AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT;
+        case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT:
+            return AUDIO_TIMESTRETCH_FALLBACK_DEFAULT;
+        case AudioPlaybackRate::TimestretchFallbackMode::MUTE:
+            return AUDIO_TIMESTRETCH_FALLBACK_MUTE;
+        case AudioPlaybackRate::TimestretchFallbackMode::FAIL:
+            return AUDIO_TIMESTRETCH_FALLBACK_FAIL;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+        audio_timestretch_fallback_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
+            return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT;
+        case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
+            return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT;
+        case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
+            return AudioPlaybackRate::TimestretchFallbackMode::MUTE;
+        case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
+            return AudioPlaybackRate::TimestretchFallbackMode::FAIL;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+        AudioPlaybackRate::TimestretchMode aidl) {
+    switch (aidl) {
+        case AudioPlaybackRate::TimestretchMode::DEFAULT:
+            return AUDIO_TIMESTRETCH_STRETCH_DEFAULT;
+        case AudioPlaybackRate::TimestretchMode::VOICE:
+            return AUDIO_TIMESTRETCH_STRETCH_VOICE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+        audio_timestretch_stretch_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_TIMESTRETCH_STRETCH_DEFAULT:
+            return AudioPlaybackRate::TimestretchMode::DEFAULT;
+        case AUDIO_TIMESTRETCH_STRETCH_VOICE:
+            return AudioPlaybackRate::TimestretchMode::VOICE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const AudioPlaybackRate& aidl) {
+    audio_playback_rate_t legacy;
+    legacy.mSpeed = aidl.speed;
+    legacy.mPitch = aidl.pitch;
+    legacy.mFallbackMode = VALUE_OR_RETURN(
+            aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+                    aidl.fallbackMode));
+    legacy.mStretchMode = VALUE_OR_RETURN(
+            aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(aidl.timestretchMode));
+    return legacy;
+}
+
+ConversionResult<AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
+    AudioPlaybackRate aidl;
+    aidl.speed = legacy.mSpeed;
+    aidl.pitch = legacy.mPitch;
+    aidl.fallbackMode = VALUE_OR_RETURN(
+            legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+                    legacy.mFallbackMode));
+    aidl.timestretchMode = VALUE_OR_RETURN(
+            legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(legacy.mStretchMode));
+    return aidl;
+}
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(AudioLatencyMode aidl) {
+    switch (aidl) {
+        case AudioLatencyMode::FREE:
+            return AUDIO_LATENCY_MODE_FREE;
+        case AudioLatencyMode::LOW:
+            return AUDIO_LATENCY_MODE_LOW;
+    }
+    return unexpected(BAD_VALUE);
+}
+ConversionResult<AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_LATENCY_MODE_FREE:
+            return AudioLatencyMode::FREE;
+        case AUDIO_LATENCY_MODE_LOW:
+            return AudioLatencyMode::LOW;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+}  // namespace android
+
+#if defined(BACKEND_NDK)
+}  // aidl
+#endif
\ No newline at end of file
diff --git a/media/audioaidlconversion/Android.bp b/media/audioaidlconversion/Android.bp
new file mode 100644
index 0000000..4a1df3a
--- /dev/null
+++ b/media/audioaidlconversion/Android.bp
@@ -0,0 +1,140 @@
+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
+    default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_defaults {
+    name: "audio_aidl_conversion_common_util_default",
+    host_supported: true,
+    vendor_available: true,
+    double_loadable: true,
+    min_sdk_version: "29",
+    export_include_dirs: [
+        "include",
+    ],
+    header_libs: [
+        "libbase_headers",
+        "liberror_headers",
+    ],
+    export_header_lib_headers: [
+        "libbase_headers",
+        "liberror_headers",
+    ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.btservices",
+        "com.android.media",
+        "com.android.media.swcodec",
+    ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
+
+// This is intended for clients needing to include AidlConversionUtil.h, without extra dependencies.
+cc_library_headers {
+    name: "libaudio_aidl_conversion_common_util_cpp",
+    defaults: [
+        "audio_aidl_conversion_common_util_default",
+    ],
+}
+
+cc_library_headers {
+    name: "libaudio_aidl_conversion_common_util_ndk",
+    defaults: [
+        "audio_aidl_conversion_common_util_default",
+    ],
+    cflags: [
+        "-DBACKEND_NDK",
+    ],
+}
+
+cc_defaults {
+    name: "audio_aidl_conversion_common_default",
+    export_include_dirs: ["include"],
+    host_supported: true,
+    vendor_available: true,
+    double_loadable: true,
+    min_sdk_version: "29",
+    header_libs: [
+        "libaudio_system_headers",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "liblog",
+        "libshmemcompat",
+        "libstagefright_foundation",
+        "libutils",
+        "shared-file-region-aidl-cpp",
+        "framework-permission-aidl-cpp",
+    ],
+    export_shared_lib_headers: [
+        "libbase",
+        "shared-file-region-aidl-cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+    ],
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
+
+/**
+ * Only AIDL CPP backend conversion supported.
+ */
+cc_library {
+    name: "libaudio_aidl_conversion_common_cpp",
+    srcs: ["AidlConversionCppNdk.cpp"],
+    header_libs: [
+        "libaudio_aidl_conversion_common_util_cpp",
+    ],
+    export_header_lib_headers: [
+        "libaudio_aidl_conversion_common_util_cpp",
+    ],
+    defaults: [
+        "audio_aidl_conversion_common_default",
+        "latest_android_media_audio_common_types_cpp_export_shared",
+    ],
+}
+
+/**
+ * Only AIDL NDK backend conversion supported.
+ */
+cc_library {
+    name: "libaudio_aidl_conversion_common_ndk",
+    srcs: ["AidlConversionCppNdk.cpp"],
+    header_libs: [
+        "libaudio_aidl_conversion_common_util_ndk",
+    ],
+    export_header_lib_headers: [
+        "libaudio_aidl_conversion_common_util_ndk",
+    ],
+    defaults: [
+        "audio_aidl_conversion_common_default",
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+    cflags: [
+        "-DBACKEND_NDK",
+    ],
+}
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
new file mode 100644
index 0000000..c25ddb1
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2022 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 <limits>
+#include <type_traits>
+#include <system/audio.h>
+
+/**
+ * Can handle conversion between AIDL (both CPP and NDK backend) and legacy type.
+ * Controlled by the cflags preprocessor in Android.bp.
+ */
+#if defined(BACKEND_NDK)
+#define PREFIX(f) <aidl/f>
+#else
+#define PREFIX(f) <f>
+#endif
+
+#include PREFIX(android/media/audio/common/AudioChannelLayout.h)
+#include PREFIX(android/media/audio/common/AudioConfig.h)
+#include PREFIX(android/media/audio/common/AudioConfigBase.h)
+#include PREFIX(android/media/audio/common/AudioContentType.h)
+#include PREFIX(android/media/audio/common/AudioDeviceDescription.h)
+#include PREFIX(android/media/audio/common/AudioDualMonoMode.h)
+#include PREFIX(android/media/audio/common/AudioEncapsulationMetadataType.h)
+#include PREFIX(android/media/audio/common/AudioEncapsulationMode.h)
+#include PREFIX(android/media/audio/common/AudioEncapsulationType.h)
+#include PREFIX(android/media/audio/common/AudioFormatDescription.h)
+#include PREFIX(android/media/audio/common/AudioGain.h)
+#include PREFIX(android/media/audio/common/AudioGainConfig.h)
+#include PREFIX(android/media/audio/common/AudioGainMode.h)
+#include PREFIX(android/media/audio/common/AudioInputFlags.h)
+#include PREFIX(android/media/audio/common/AudioIoFlags.h)
+#include PREFIX(android/media/audio/common/AudioLatencyMode.h)
+#include PREFIX(android/media/audio/common/AudioMode.h)
+#include PREFIX(android/media/audio/common/AudioOffloadInfo.h)
+#include PREFIX(android/media/audio/common/AudioOutputFlags.h)
+#include PREFIX(android/media/audio/common/AudioPortExt.h)
+#include PREFIX(android/media/audio/common/AudioPortMixExt.h)
+#include PREFIX(android/media/audio/common/AudioPlaybackRate.h)
+#include PREFIX(android/media/audio/common/AudioProfile.h)
+#include PREFIX(android/media/audio/common/AudioSource.h)
+#include PREFIX(android/media/audio/common/AudioStandard.h)
+#include PREFIX(android/media/audio/common/AudioUsage.h)
+#include PREFIX(android/media/audio/common/AudioUuid.h)
+#include PREFIX(android/media/audio/common/ExtraAudioDescriptor.h)
+#include PREFIX(android/media/audio/common/Int.h)
+#undef PREFIX
+
+#include <media/AidlConversionUtil.h>
+#include <system/audio.h>
+#include <system/audio_effect.h>
+
+using ::android::String16;
+using ::android::String8;
+
+#if defined(BACKEND_NDK)
+namespace aidl {
+#endif
+
+namespace android {
+
+// maxSize is the size of the C-string buffer (including the 0-terminator), NOT the max length of
+// the string.
+::android::status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize);
+ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize);
+
+ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy);
+
+ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy);
+
+ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy);
+
+ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy);
+
+ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy);
+
+ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy);
+
+ConversionResult<unsigned int> aidl2legacy_int32_t_config_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_config_mask_int32_t(unsigned int legacy);
+
+ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy);
+
+ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy);
+
+ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl);
+ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy);
+
+ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl);
+ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy);
+
+ConversionResult<std::optional<String16>>
+aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl);
+ConversionResult<std::optional<std::string_view>>
+legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy);
+
+ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+        const media::audio::common::AudioChannelLayout& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioChannelLayout>
+legacy2aidl_audio_channel_mask_t_AudioChannelLayout(audio_channel_mask_t legacy, bool isInput);
+
+ConversionResult<audio_config_t>
+aidl2legacy_AudioConfig_audio_config_t(const media::audio::common::AudioConfig& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioConfig>
+legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput);
+
+ConversionResult<audio_config_base_t>
+aidl2legacy_AudioConfigBase_audio_config_base_t(
+        const media::audio::common::AudioConfigBase& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioConfigBase>
+legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput);
+
+ConversionResult<audio_input_flags_t>
+aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
+ConversionResult<media::audio::common::AudioInputFlags>
+legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
+
+ConversionResult<audio_output_flags_t>
+aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
+ConversionResult<media::audio::common::AudioOutputFlags>
+legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
+
+ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
+        int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
+        audio_input_flags_t legacy);
+
+ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
+        int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
+        audio_output_flags_t legacy);
+
+ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
+        const media::audio::common::AudioIoFlags& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
+        const audio_io_flags& legacy, bool isInput);
+
+ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy);
+
+ConversionResult<audio_content_type_t>
+aidl2legacy_AudioContentType_audio_content_type_t(
+        media::audio::common::AudioContentType aidl);
+ConversionResult<media::audio::common::AudioContentType>
+legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy);
+
+ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
+        const media::audio::common::AudioDeviceDescription& aidl);
+ConversionResult<media::audio::common::AudioDeviceDescription>
+legacy2aidl_audio_devices_t_AudioDeviceDescription(audio_devices_t legacy);
+
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+        const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
+        char* legacyAddress);
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+        const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
+        String8* legacyAddress);
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+        const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
+        std::string* legacyAddress);
+
+ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
+        audio_devices_t legacyType, const char* legacyAddress);
+ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
+        audio_devices_t legacyType, const String8& legacyAddress);
+
+ConversionResult<audio_extra_audio_descriptor>
+aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
+        const media::audio::common::ExtraAudioDescriptor& aidl);
+
+ConversionResult<media::audio::common::ExtraAudioDescriptor>
+legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
+        const audio_extra_audio_descriptor& legacy);
+
+ConversionResult<audio_encapsulation_metadata_type_t>
+aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
+        media::audio::common::AudioEncapsulationMetadataType aidl);
+ConversionResult<media::audio::common::AudioEncapsulationMetadataType>
+legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
+        audio_encapsulation_metadata_type_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy);
+
+ConversionResult<audio_encapsulation_mode_t>
+aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(
+        media::audio::common::AudioEncapsulationMode aidl);
+ConversionResult<media::audio::common::AudioEncapsulationMode>
+legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy);
+
+ConversionResult<audio_encapsulation_type_t>
+aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
+        const media::audio::common::AudioEncapsulationType& aidl);
+ConversionResult<media::audio::common::AudioEncapsulationType>
+legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+        const audio_encapsulation_type_t& legacy);
+
+ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
+        const media::audio::common::AudioFormatDescription& aidl);
+ConversionResult<media::audio::common::AudioFormatDescription>
+legacy2aidl_audio_format_t_AudioFormatDescription(audio_format_t legacy);
+
+ConversionResult<audio_gain_mode_t>
+aidl2legacy_AudioGainMode_audio_gain_mode_t(media::audio::common::AudioGainMode aidl);
+ConversionResult<media::audio::common::AudioGainMode>
+legacy2aidl_audio_gain_mode_t_AudioGainMode(audio_gain_mode_t legacy);
+
+ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy);
+
+ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
+        const media::audio::common::AudioGainConfig& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioGainConfig>
+legacy2aidl_audio_gain_config_AudioGainConfig(const audio_gain_config& legacy, bool isInput);
+
+ConversionResult<audio_gain>
+aidl2legacy_AudioGain_audio_gain(const media::audio::common::AudioGain& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioGain>
+legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput);
+
+ConversionResult<audio_input_flags_t>
+aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
+ConversionResult<media::audio::common::AudioInputFlags>
+legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
+
+ConversionResult<audio_mode_t>
+aidl2legacy_AudioMode_audio_mode_t(media::audio::common::AudioMode aidl);
+ConversionResult<media::audio::common::AudioMode>
+legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy);
+
+ConversionResult<audio_offload_info_t>
+aidl2legacy_AudioOffloadInfo_audio_offload_info_t(
+        const media::audio::common::AudioOffloadInfo& aidl);
+ConversionResult<media::audio::common::AudioOffloadInfo>
+legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy);
+
+ConversionResult<audio_output_flags_t>
+aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
+ConversionResult<media::audio::common::AudioOutputFlags>
+legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
+
+ConversionResult<audio_profile> aidl2legacy_AudioProfile_audio_profile(
+        const media::audio::common::AudioProfile& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioProfile> legacy2aidl_audio_profile_AudioProfile(
+        const audio_profile& legacy, bool isInput);
+
+ConversionResult<audio_standard_t> aidl2legacy_AudioStandard_audio_standard_t(
+        media::audio::common::AudioStandard aidl);
+ConversionResult<media::audio::common::AudioStandard> legacy2aidl_audio_standard_t_AudioStandard(
+        audio_standard_t legacy);
+
+ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
+        media::audio::common::AudioSource aidl);
+ConversionResult<media::audio::common::AudioSource> legacy2aidl_audio_source_t_AudioSource(
+        audio_source_t legacy);
+
+ConversionResult<audio_usage_t> aidl2legacy_AudioUsage_audio_usage_t(
+        media::audio::common::AudioUsage aidl);
+ConversionResult<media::audio::common::AudioUsage> legacy2aidl_audio_usage_t_AudioUsage(
+        audio_usage_t legacy);
+
+ConversionResult<audio_uuid_t> aidl2legacy_AudioUuid_audio_uuid_t(
+        const media::audio::common::AudioUuid &aidl);
+ConversionResult<media::audio::common::AudioUuid> legacy2aidl_audio_uuid_t_AudioUuid(
+        const audio_uuid_t& legacy);
+
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::audio::common::AudioDualMonoMode aidl);
+ConversionResult<media::audio::common::AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+        media::audio::common::AudioPlaybackRate::TimestretchFallbackMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+        audio_timestretch_fallback_mode_t legacy);
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+        media::audio::common::AudioPlaybackRate::TimestretchMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+        audio_timestretch_stretch_mode_t legacy);
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(
+        const media::audio::common::AudioPlaybackRate& aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(media::audio::common::AudioLatencyMode aidl);
+ConversionResult<media::audio::common::AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy);
+
+}  // namespace android
+
+#if defined(BACKEND_NDK)
+} // aidl
+#endif
diff --git a/media/libaudioclient/include/media/AidlConversionUtil.h b/media/audioaidlconversion/include/media/AidlConversionUtil.h
similarity index 80%
rename from media/libaudioclient/include/media/AidlConversionUtil.h
rename to media/audioaidlconversion/include/media/AidlConversionUtil.h
index 8817c35..95daa4a 100644
--- a/media/libaudioclient/include/media/AidlConversionUtil.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil.h
@@ -20,15 +20,21 @@
 #include <type_traits>
 #include <utility>
 
-#include <binder/Enums.h>
+#include <android-base/expected.h>
 #include <binder/Status.h>
 #include <error/Result.h>
 
-namespace android {
+#if defined(BACKEND_NDK)
+#include <android/binder_status.h>
+namespace aidl {
+#else
+#include <binder/Enums.h>
+#endif
 
 template <typename T>
-using ConversionResult = error::Result<T>;
+using ConversionResult = ::android::error::Result<T>;
 
+namespace android {
 /**
  * A generic template to safely cast between integral types, respecting limits of the destination
  * type.
@@ -39,15 +45,15 @@
     // have the signed converted to unsigned and produce wrong results.
     if (std::is_signed_v<From> && !std::is_signed_v<To>) {
         if (from < 0 || from > std::numeric_limits<To>::max()) {
-            return base::unexpected(BAD_VALUE);
+            return ::android::base::unexpected(::android::BAD_VALUE);
         }
     } else if (std::is_signed_v<To> && !std::is_signed_v<From>) {
         if (from > std::numeric_limits<To>::max()) {
-            return base::unexpected(BAD_VALUE);
+            return ::android::base::unexpected(::android::BAD_VALUE);
         }
     } else {
         if (from < std::numeric_limits<To>::min() || from > std::numeric_limits<To>::max()) {
-            return base::unexpected(BAD_VALUE);
+            return ::android::base::unexpected(::android::BAD_VALUE);
         }
     }
     return static_cast<To>(from);
@@ -67,14 +73,14 @@
  * A generic template that helps convert containers of convertible types, using iterators.
  */
 template<typename InputIterator, typename OutputIterator, typename Func>
-status_t convertRange(InputIterator start,
+::android::status_t convertRange(InputIterator start,
                       InputIterator end,
                       OutputIterator out,
                       const Func& itemConversion) {
     for (InputIterator iter = start; iter != end; ++iter, ++out) {
         *out = VALUE_OR_RETURN_STATUS(itemConversion(*iter));
     }
-    return OK;
+    return ::android::OK;
 }
 
 /**
@@ -82,7 +88,7 @@
  * Uses a limit as maximum conversion items.
  */
 template<typename InputIterator, typename OutputIterator, typename Func>
-status_t convertRangeWithLimit(InputIterator start,
+::android::status_t convertRangeWithLimit(InputIterator start,
                       InputIterator end,
                       OutputIterator out,
                       const Func& itemConversion,
@@ -94,7 +100,7 @@
     for (InputIterator iter = start; (iter != last); ++iter, ++out) {
         *out = VALUE_OR_RETURN_STATUS(itemConversion(*iter));
     }
-    return OK;
+    return ::android::OK;
 }
 
 /**
@@ -140,7 +146,7 @@
     OutputContainer output;
     auto ins = std::inserter(output, output.begin());
     for (const auto& item1 : input1) {
-        RETURN_IF_ERROR(iter2 != input2.end() ? OK : BAD_VALUE);
+        RETURN_IF_ERROR(iter2 != input2.end() ? ::android::OK : ::android::BAD_VALUE);
         *ins = VALUE_OR_RETURN(itemConversion(item1, *iter2++));
     }
     return output;
@@ -248,7 +254,8 @@
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Utilities for working with AIDL unions.
 // UNION_GET(obj, fieldname) returns a ConversionResult<T> containing either the strongly-typed
-//   value of the respective field, or BAD_VALUE if the union is not set to the requested field.
+//   value of the respective field, or ::android::BAD_VALUE if the union is not set to the requested
+//   field.
 // UNION_SET(obj, fieldname, value) sets the requested field to the given value.
 
 template<typename T, typename T::Tag tag>
@@ -257,7 +264,7 @@
 template<typename T, typename T::Tag tag>
 ConversionResult<UnionFieldType<T, tag>> unionGetField(const T& u) {
     if (u.getTag() != tag) {
-        return base::unexpected(BAD_VALUE);
+        return ::android::base::unexpected(::android::BAD_VALUE);
     }
     return u.template get<tag>();
 }
@@ -275,7 +282,11 @@
  */
 template <typename T>
 bool isValidEnum(T value) {
-    constexpr android::enum_range<T> er{};
+#if defined(BACKEND_NDK)
+    constexpr ndk::enum_range<T> er{};
+#else
+    constexpr ::android::enum_range<T> er{};
+#endif
     return std::find(er.begin(), er.end(), value) != er.end();
 }
 
@@ -294,7 +305,7 @@
 }
 
 /**
- * Return the equivalent Android status_t from a binder exception code.
+ * Return the equivalent Android ::android::status_t from a binder exception code.
  *
  * Generally one should use statusTFromBinderStatus() instead.
  *
@@ -304,33 +315,33 @@
  * Note: for EX_TRANSACTION_FAILED and EX_SERVICE_SPECIFIC a more detailed error code
  * can be found from transactionError() or serviceSpecificErrorCode().
  */
-static inline status_t statusTFromExceptionCode(int32_t exceptionCode) {
+static inline ::android::status_t statusTFromExceptionCode(int32_t exceptionCode) {
     using namespace ::android::binder;
     switch (exceptionCode) {
         case Status::EX_NONE:
-            return OK;
-        case Status::EX_SECURITY: // Java SecurityException, rethrows locally in Java
-            return PERMISSION_DENIED;
-        case Status::EX_BAD_PARCELABLE: // Java BadParcelableException, rethrows in Java
-        case Status::EX_ILLEGAL_ARGUMENT: // Java IllegalArgumentException, rethrows in Java
-        case Status::EX_NULL_POINTER: // Java NullPointerException, rethrows in Java
-            return BAD_VALUE;
-        case Status::EX_ILLEGAL_STATE: // Java IllegalStateException, rethrows in Java
-        case Status::EX_UNSUPPORTED_OPERATION: // Java UnsupportedOperationException, rethrows
-            return INVALID_OPERATION;
+            return ::android::OK;
+        case Status::EX_SECURITY:  // Java SecurityException, rethrows locally in Java
+            return ::android::PERMISSION_DENIED;
+        case Status::EX_BAD_PARCELABLE:  // Java BadParcelableException, rethrows in Java
+        case Status::EX_ILLEGAL_ARGUMENT:  // Java IllegalArgumentException, rethrows in Java
+        case Status::EX_NULL_POINTER:  // Java NullPointerException, rethrows in Java
+            return ::android::BAD_VALUE;
+        case Status::EX_ILLEGAL_STATE:  // Java IllegalStateException, rethrows in Java
+        case Status::EX_UNSUPPORTED_OPERATION:  // Java UnsupportedOperationException, rethrows
+            return ::android::INVALID_OPERATION;
         case Status::EX_HAS_REPLY_HEADER: // Native strictmode violation
-        case Status::EX_PARCELABLE: // Java bootclass loader (not standard exception), rethrows
-        case Status::EX_NETWORK_MAIN_THREAD: // Java NetworkOnMainThreadException, rethrows
+        case Status::EX_PARCELABLE:  // Java bootclass loader (not standard exception), rethrows
+        case Status::EX_NETWORK_MAIN_THREAD:  // Java NetworkOnMainThreadException, rethrows
         case Status::EX_TRANSACTION_FAILED: // Native - see error code
-        case Status::EX_SERVICE_SPECIFIC:  // Java ServiceSpecificException,
-                                           // rethrows in Java with integer error code
-            return UNKNOWN_ERROR;
+        case Status::EX_SERVICE_SPECIFIC:   // Java ServiceSpecificException,
+                                            // rethrows in Java with integer error code
+            return ::android::UNKNOWN_ERROR;
     }
-    return UNKNOWN_ERROR;
+    return ::android::UNKNOWN_ERROR;
 }
 
 /**
- * Return the equivalent Android status_t from a binder status.
+ * Return the equivalent Android ::android::status_t from a binder status.
  *
  * Used to handle errors from a AIDL method declaration
  *
@@ -340,8 +351,8 @@
  *
  * return_type method(type0 param0, ...)
  */
-static inline status_t statusTFromBinderStatus(const ::android::binder::Status &status) {
-    return status.isOk() ? OK // check OK,
+static inline ::android::status_t statusTFromBinderStatus(const ::android::binder::Status &status) {
+    return status.isOk() ? ::android::OK // check ::android::OK,
         : status.serviceSpecificErrorCode() // service-side error, not standard Java exception
                                             // (fromServiceSpecificError)
         ?: status.transactionError() // a native binder transaction error (fromStatusT)
@@ -356,23 +367,23 @@
  * where Java callers expect an exception, not an integer return value.
  */
 static inline ::android::binder::Status binderStatusFromStatusT(
-        status_t status, const char *optionalMessage = nullptr) {
+        ::android::status_t status, const char *optionalMessage = nullptr) {
     const char * const emptyIfNull = optionalMessage == nullptr ? "" : optionalMessage;
     // From binder::Status instructions:
     //  Prefer a generic exception code when possible, then a service specific
-    //  code, and finally a status_t for low level failures or legacy support.
+    //  code, and finally a ::android::status_t for low level failures or legacy support.
     //  Exception codes and service specific errors map to nicer exceptions for
     //  Java clients.
 
     using namespace ::android::binder;
     switch (status) {
-        case OK:
+        case ::android::OK:
             return Status::ok();
-        case PERMISSION_DENIED: // throw SecurityException on Java side
+        case ::android::PERMISSION_DENIED: // throw SecurityException on Java side
             return Status::fromExceptionCode(Status::EX_SECURITY, emptyIfNull);
-        case BAD_VALUE: // throw IllegalArgumentException on Java side
+        case ::android::BAD_VALUE: // throw IllegalArgumentException on Java side
             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, emptyIfNull);
-        case INVALID_OPERATION: // throw IllegalStateException on Java side
+        case ::android::INVALID_OPERATION: // throw IllegalStateException on Java side
             return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, emptyIfNull);
     }
 
@@ -387,3 +398,7 @@
 } // namespace aidl_utils
 
 }  // namespace android
+
+#if defined(BACKEND_NDK)
+}  // namespace aidl
+#endif
\ No newline at end of file
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 90d51fd..f75e58d 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -42,9 +42,6 @@
 using media::audio::common::AudioDeviceAddress;
 using media::audio::common::AudioDeviceDescription;
 using media::audio::common::AudioDeviceType;
-using media::audio::common::AudioEncapsulationMetadataType;
-using media::audio::common::AudioEncapsulationMode;
-using media::audio::common::AudioEncapsulationType;
 using media::audio::common::AudioFormatDescription;
 using media::audio::common::AudioFormatType;
 using media::audio::common::AudioGain;
@@ -138,127 +135,6 @@
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Converters
 
-status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize) {
-    if (aidl.size() > maxSize - 1) {
-        return BAD_VALUE;
-    }
-    aidl.copy(dest, aidl.size());
-    dest[aidl.size()] = '\0';
-    return OK;
-}
-
-ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize) {
-    if (legacy == nullptr) {
-        return unexpected(BAD_VALUE);
-    }
-    if (strnlen(legacy, maxSize) == maxSize) {
-        // No null-terminator.
-        return unexpected(BAD_VALUE);
-    }
-    return std::string(legacy);
-}
-
-ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl) {
-    return convertReinterpret<audio_module_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl) {
-    return convertReinterpret<audio_io_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl) {
-    return convertReinterpret<audio_port_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl) {
-    return convertReinterpret<audio_patch_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl) {
-    return convertReinterpret<audio_unique_id_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl) {
-    return convertReinterpret<audio_hw_sync_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl) {
-    return convertReinterpret<pid_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl) {
-    return convertReinterpret<uid_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl) {
-    return String16(aidl.data(), aidl.size());
-}
-
-ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy) {
-    return std::string(String8(legacy).c_str());
-}
-
-// TODO b/182392769: create an optional -> optional util
-ConversionResult<std::optional<String16>>
-aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl) {
-    if (!aidl.has_value()) {
-        return std::nullopt;
-    }
-    ConversionResult<String16> conversion =
-        VALUE_OR_RETURN(aidl2legacy_string_view_String16(aidl.value()));
-    return conversion.value();
-}
-
-ConversionResult<std::optional<std::string_view>>
-legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy) {
-  if (!legacy.has_value()) {
-    return std::nullopt;
-  }
-  ConversionResult<std::string> conversion =
-      VALUE_OR_RETURN(legacy2aidl_String16_string(legacy.value()));
-  return conversion.value();
-}
-
-ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl) {
-    return String8(aidl.data(), aidl.size());
-}
-
-ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy) {
-    return std::string(legacy.c_str());
-}
-
 ConversionResult<audio_io_config_event_t> aidl2legacy_AudioIoConfigEvent_audio_io_config_event_t(
         media::AudioIoConfigEvent aidl) {
     switch (aidl) {
@@ -365,1477 +241,6 @@
     return unexpected(BAD_VALUE);
 }
 
-namespace {
-
-namespace detail {
-using AudioChannelBitPair = std::pair<audio_channel_mask_t, int>;
-using AudioChannelBitPairs = std::vector<AudioChannelBitPair>;
-using AudioChannelPair = std::pair<audio_channel_mask_t, AudioChannelLayout>;
-using AudioChannelPairs = std::vector<AudioChannelPair>;
-using AudioDevicePair = std::pair<audio_devices_t, AudioDeviceDescription>;
-using AudioDevicePairs = std::vector<AudioDevicePair>;
-using AudioFormatPair = std::pair<audio_format_t, AudioFormatDescription>;
-using AudioFormatPairs = std::vector<AudioFormatPair>;
-}
-
-const detail::AudioChannelBitPairs& getInAudioChannelBits() {
-    static const detail::AudioChannelBitPairs pairs = {
-        { AUDIO_CHANNEL_IN_LEFT, AudioChannelLayout::CHANNEL_FRONT_LEFT },
-        { AUDIO_CHANNEL_IN_RIGHT, AudioChannelLayout::CHANNEL_FRONT_RIGHT },
-        // AUDIO_CHANNEL_IN_FRONT is at the end
-        { AUDIO_CHANNEL_IN_BACK, AudioChannelLayout::CHANNEL_BACK_CENTER },
-        // AUDIO_CHANNEL_IN_*_PROCESSED not supported
-        // AUDIO_CHANNEL_IN_PRESSURE not supported
-        // AUDIO_CHANNEL_IN_*_AXIS not supported
-        // AUDIO_CHANNEL_IN_VOICE_* not supported
-        { AUDIO_CHANNEL_IN_BACK_LEFT, AudioChannelLayout::CHANNEL_BACK_LEFT },
-        { AUDIO_CHANNEL_IN_BACK_RIGHT, AudioChannelLayout::CHANNEL_BACK_RIGHT },
-        { AUDIO_CHANNEL_IN_CENTER, AudioChannelLayout::CHANNEL_FRONT_CENTER },
-        { AUDIO_CHANNEL_IN_LOW_FREQUENCY, AudioChannelLayout::CHANNEL_LOW_FREQUENCY },
-        { AUDIO_CHANNEL_IN_TOP_LEFT, AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT },
-        { AUDIO_CHANNEL_IN_TOP_RIGHT, AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT },
-        // When going from aidl to legacy, IN_CENTER is used
-        { AUDIO_CHANNEL_IN_FRONT, AudioChannelLayout::CHANNEL_FRONT_CENTER }
-    };
-    return pairs;
-}
-
-const detail::AudioChannelPairs& getInAudioChannelPairs() {
-    static const detail::AudioChannelPairs pairs = {
-#define DEFINE_INPUT_LAYOUT(n)                                                 \
-            {                                                                  \
-                AUDIO_CHANNEL_IN_##n,                                          \
-                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
-                        AudioChannelLayout::LAYOUT_##n)                        \
-            }
-
-        DEFINE_INPUT_LAYOUT(MONO),
-        DEFINE_INPUT_LAYOUT(STEREO),
-        DEFINE_INPUT_LAYOUT(FRONT_BACK),
-        // AUDIO_CHANNEL_IN_6 not supported
-        DEFINE_INPUT_LAYOUT(2POINT0POINT2),
-        DEFINE_INPUT_LAYOUT(2POINT1POINT2),
-        DEFINE_INPUT_LAYOUT(3POINT0POINT2),
-        DEFINE_INPUT_LAYOUT(3POINT1POINT2),
-        DEFINE_INPUT_LAYOUT(5POINT1)
-#undef DEFINE_INPUT_LAYOUT
-    };
-    return pairs;
-}
-
-const detail::AudioChannelBitPairs& getOutAudioChannelBits() {
-    static const detail::AudioChannelBitPairs pairs = {
-#define DEFINE_OUTPUT_BITS(n)                                                  \
-            { AUDIO_CHANNEL_OUT_##n, AudioChannelLayout::CHANNEL_##n }
-
-        DEFINE_OUTPUT_BITS(FRONT_LEFT),
-        DEFINE_OUTPUT_BITS(FRONT_RIGHT),
-        DEFINE_OUTPUT_BITS(FRONT_CENTER),
-        DEFINE_OUTPUT_BITS(LOW_FREQUENCY),
-        DEFINE_OUTPUT_BITS(BACK_LEFT),
-        DEFINE_OUTPUT_BITS(BACK_RIGHT),
-        DEFINE_OUTPUT_BITS(FRONT_LEFT_OF_CENTER),
-        DEFINE_OUTPUT_BITS(FRONT_RIGHT_OF_CENTER),
-        DEFINE_OUTPUT_BITS(BACK_CENTER),
-        DEFINE_OUTPUT_BITS(SIDE_LEFT),
-        DEFINE_OUTPUT_BITS(SIDE_RIGHT),
-        DEFINE_OUTPUT_BITS(TOP_CENTER),
-        DEFINE_OUTPUT_BITS(TOP_FRONT_LEFT),
-        DEFINE_OUTPUT_BITS(TOP_FRONT_CENTER),
-        DEFINE_OUTPUT_BITS(TOP_FRONT_RIGHT),
-        DEFINE_OUTPUT_BITS(TOP_BACK_LEFT),
-        DEFINE_OUTPUT_BITS(TOP_BACK_CENTER),
-        DEFINE_OUTPUT_BITS(TOP_BACK_RIGHT),
-        DEFINE_OUTPUT_BITS(TOP_SIDE_LEFT),
-        DEFINE_OUTPUT_BITS(TOP_SIDE_RIGHT),
-        DEFINE_OUTPUT_BITS(BOTTOM_FRONT_LEFT),
-        DEFINE_OUTPUT_BITS(BOTTOM_FRONT_CENTER),
-        DEFINE_OUTPUT_BITS(BOTTOM_FRONT_RIGHT),
-        DEFINE_OUTPUT_BITS(LOW_FREQUENCY_2),
-        DEFINE_OUTPUT_BITS(FRONT_WIDE_LEFT),
-        DEFINE_OUTPUT_BITS(FRONT_WIDE_RIGHT),
-#undef DEFINE_OUTPUT_BITS
-        { AUDIO_CHANNEL_OUT_HAPTIC_A, AudioChannelLayout::CHANNEL_HAPTIC_A },
-        { AUDIO_CHANNEL_OUT_HAPTIC_B, AudioChannelLayout::CHANNEL_HAPTIC_B }
-    };
-    return pairs;
-}
-
-const detail::AudioChannelPairs& getOutAudioChannelPairs() {
-    static const detail::AudioChannelPairs pairs = {
-#define DEFINE_OUTPUT_LAYOUT(n)                                                \
-            {                                                                  \
-                AUDIO_CHANNEL_OUT_##n,                                         \
-                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
-                        AudioChannelLayout::LAYOUT_##n)                        \
-            }
-
-        DEFINE_OUTPUT_LAYOUT(MONO),
-        DEFINE_OUTPUT_LAYOUT(STEREO),
-        DEFINE_OUTPUT_LAYOUT(2POINT1),
-        DEFINE_OUTPUT_LAYOUT(TRI),
-        DEFINE_OUTPUT_LAYOUT(TRI_BACK),
-        DEFINE_OUTPUT_LAYOUT(3POINT1),
-        DEFINE_OUTPUT_LAYOUT(2POINT0POINT2),
-        DEFINE_OUTPUT_LAYOUT(2POINT1POINT2),
-        DEFINE_OUTPUT_LAYOUT(3POINT0POINT2),
-        DEFINE_OUTPUT_LAYOUT(3POINT1POINT2),
-        DEFINE_OUTPUT_LAYOUT(QUAD),
-        DEFINE_OUTPUT_LAYOUT(QUAD_SIDE),
-        DEFINE_OUTPUT_LAYOUT(SURROUND),
-        DEFINE_OUTPUT_LAYOUT(PENTA),
-        DEFINE_OUTPUT_LAYOUT(5POINT1),
-        DEFINE_OUTPUT_LAYOUT(5POINT1_SIDE),
-        DEFINE_OUTPUT_LAYOUT(5POINT1POINT2),
-        DEFINE_OUTPUT_LAYOUT(5POINT1POINT4),
-        DEFINE_OUTPUT_LAYOUT(6POINT1),
-        DEFINE_OUTPUT_LAYOUT(7POINT1),
-        DEFINE_OUTPUT_LAYOUT(7POINT1POINT2),
-        DEFINE_OUTPUT_LAYOUT(7POINT1POINT4),
-        DEFINE_OUTPUT_LAYOUT(13POINT_360RA),
-        DEFINE_OUTPUT_LAYOUT(22POINT2),
-        DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_A),
-        DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_A),
-        DEFINE_OUTPUT_LAYOUT(HAPTIC_AB),
-        DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_AB),
-        DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_AB)
-#undef DEFINE_OUTPUT_LAYOUT
-    };
-    return pairs;
-}
-
-const detail::AudioChannelPairs& getVoiceAudioChannelPairs() {
-    static const detail::AudioChannelPairs pairs = {
-#define DEFINE_VOICE_LAYOUT(n)                                                 \
-            {                                                                  \
-                AUDIO_CHANNEL_IN_VOICE_##n,                                    \
-                AudioChannelLayout::make<AudioChannelLayout::Tag::voiceMask>(  \
-                        AudioChannelLayout::VOICE_##n)                         \
-            }
-        DEFINE_VOICE_LAYOUT(UPLINK_MONO),
-        DEFINE_VOICE_LAYOUT(DNLINK_MONO),
-        DEFINE_VOICE_LAYOUT(CALL_MONO)
-#undef DEFINE_VOICE_LAYOUT
-    };
-    return pairs;
-}
-
-AudioDeviceDescription make_AudioDeviceDescription(AudioDeviceType type,
-        const std::string& connection = "") {
-    AudioDeviceDescription result;
-    result.type = type;
-    result.connection = connection;
-    return result;
-}
-
-void append_AudioDeviceDescription(detail::AudioDevicePairs& pairs,
-        audio_devices_t inputType, audio_devices_t outputType,
-        AudioDeviceType inType, AudioDeviceType outType,
-        const std::string& connection = "") {
-    pairs.push_back(std::make_pair(inputType, make_AudioDeviceDescription(inType, connection)));
-    pairs.push_back(std::make_pair(outputType, make_AudioDeviceDescription(outType, connection)));
-}
-
-const detail::AudioDevicePairs& getAudioDevicePairs() {
-    static const detail::AudioDevicePairs pairs = []() {
-        detail::AudioDevicePairs pairs = {{
-            {
-                AUDIO_DEVICE_NONE, AudioDeviceDescription{}
-            },
-            {
-                AUDIO_DEVICE_OUT_EARPIECE, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_SPEAKER_EARPIECE)
-            },
-            {
-                AUDIO_DEVICE_OUT_SPEAKER, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_SPEAKER)
-            },
-            {
-                AUDIO_DEVICE_OUT_WIRED_HEADPHONE, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_HEADPHONE,
-                        AudioDeviceDescription::CONNECTION_ANALOG())
-            },
-            {
-                AUDIO_DEVICE_OUT_BLUETOOTH_SCO, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_DEVICE,
-                        AudioDeviceDescription::CONNECTION_BT_SCO())
-            },
-            {
-                AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_CARKIT,
-                        AudioDeviceDescription::CONNECTION_BT_SCO())
-            },
-            {
-                AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_HEADPHONE,
-                        AudioDeviceDescription::CONNECTION_BT_A2DP())
-            },
-            {
-                AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_SPEAKER,
-                        AudioDeviceDescription::CONNECTION_BT_A2DP())
-            },
-            {
-                AUDIO_DEVICE_OUT_TELEPHONY_TX, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_TELEPHONY_TX)
-            },
-            {
-                AUDIO_DEVICE_OUT_AUX_LINE, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_LINE_AUX)
-            },
-            {
-                AUDIO_DEVICE_OUT_SPEAKER_SAFE, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_SPEAKER_SAFE)
-            },
-            {
-                AUDIO_DEVICE_OUT_HEARING_AID, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_HEARING_AID,
-                        AudioDeviceDescription::CONNECTION_WIRELESS())
-            },
-            {
-                AUDIO_DEVICE_OUT_ECHO_CANCELLER, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_ECHO_CANCELLER)
-            },
-            {
-                AUDIO_DEVICE_OUT_BLE_SPEAKER, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_SPEAKER,
-                        AudioDeviceDescription::CONNECTION_BT_LE())
-            },
-            {
-                AUDIO_DEVICE_OUT_BLE_BROADCAST, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_BROADCAST,
-                        AudioDeviceDescription::CONNECTION_BT_LE())
-            },
-            // AUDIO_DEVICE_IN_AMBIENT and IN_COMMUNICATION are removed since they were deprecated.
-            {
-                AUDIO_DEVICE_IN_BUILTIN_MIC, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_MICROPHONE)
-            },
-            {
-                AUDIO_DEVICE_IN_BACK_MIC, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_MICROPHONE_BACK)
-            },
-            {
-                AUDIO_DEVICE_IN_TELEPHONY_RX, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_TELEPHONY_RX)
-            },
-            {
-                AUDIO_DEVICE_IN_TV_TUNER, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_TV_TUNER)
-            },
-            {
-                AUDIO_DEVICE_IN_LOOPBACK, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_LOOPBACK)
-            },
-            {
-                AUDIO_DEVICE_IN_BLUETOOTH_BLE, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_DEVICE,
-                        AudioDeviceDescription::CONNECTION_BT_LE())
-            },
-            {
-                AUDIO_DEVICE_IN_ECHO_REFERENCE, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_ECHO_REFERENCE)
-            }
-        }};
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT,
-                AudioDeviceType::IN_DEFAULT, AudioDeviceType::OUT_DEFAULT);
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET,
-                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
-                AudioDeviceDescription::CONNECTION_ANALOG());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
-                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
-                AudioDeviceDescription::CONNECTION_BT_SCO());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_HDMI, AUDIO_DEVICE_OUT_HDMI,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_HDMI());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
-                AudioDeviceType::IN_SUBMIX, AudioDeviceType::OUT_SUBMIX);
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET,
-                AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
-                AudioDeviceDescription::CONNECTION_ANALOG());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
-                AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
-                AudioDeviceDescription::CONNECTION_USB());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_ACCESSORY,
-                AudioDeviceType::IN_ACCESSORY, AudioDeviceType::OUT_ACCESSORY,
-                AudioDeviceDescription::CONNECTION_USB());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_OUT_USB_DEVICE,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_USB());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_FM_TUNER, AUDIO_DEVICE_OUT_FM,
-                AudioDeviceType::IN_FM_TUNER, AudioDeviceType::OUT_FM);
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_LINE, AUDIO_DEVICE_OUT_LINE,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_ANALOG());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_SPDIF, AUDIO_DEVICE_OUT_SPDIF,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_SPDIF());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_BT_A2DP());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_IP, AUDIO_DEVICE_OUT_IP,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_IP_V4());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_BUS, AUDIO_DEVICE_OUT_BUS,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_BUS());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_PROXY, AUDIO_DEVICE_OUT_PROXY,
-                AudioDeviceType::IN_AFE_PROXY, AudioDeviceType::OUT_AFE_PROXY);
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
-                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
-                AudioDeviceDescription::CONNECTION_USB());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_HDMI_ARC, AUDIO_DEVICE_OUT_HDMI_ARC,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_HDMI_ARC());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_HDMI_EARC, AUDIO_DEVICE_OUT_HDMI_EARC,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_HDMI_EARC());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_OUT_BLE_HEADSET,
-                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
-                AudioDeviceDescription::CONNECTION_BT_LE());
-        return pairs;
-    }();
-    return pairs;
-}
-
-AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
-    AudioFormatDescription result;
-    result.type = type;
-    return result;
-}
-
-AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
-    auto result = make_AudioFormatDescription(AudioFormatType::PCM);
-    result.pcm = pcm;
-    return result;
-}
-
-AudioFormatDescription make_AudioFormatDescription(const std::string& encoding) {
-    AudioFormatDescription result;
-    result.encoding = encoding;
-    return result;
-}
-
-AudioFormatDescription make_AudioFormatDescription(PcmType transport,
-        const std::string& encoding) {
-    auto result = make_AudioFormatDescription(encoding);
-    result.pcm = transport;
-    return result;
-}
-
-const detail::AudioFormatPairs& getAudioFormatPairs() {
-    static const detail::AudioFormatPairs pairs = {{
-        {
-            AUDIO_FORMAT_INVALID,
-            make_AudioFormatDescription(AudioFormatType::SYS_RESERVED_INVALID)
-        },
-        {
-            AUDIO_FORMAT_DEFAULT, AudioFormatDescription{}
-        },
-        {
-            AUDIO_FORMAT_PCM_16_BIT, make_AudioFormatDescription(PcmType::INT_16_BIT)
-        },
-        {
-            AUDIO_FORMAT_PCM_8_BIT, make_AudioFormatDescription(PcmType::UINT_8_BIT)
-        },
-        {
-            AUDIO_FORMAT_PCM_32_BIT, make_AudioFormatDescription(PcmType::INT_32_BIT)
-        },
-        {
-            AUDIO_FORMAT_PCM_8_24_BIT, make_AudioFormatDescription(PcmType::FIXED_Q_8_24)
-        },
-        {
-            AUDIO_FORMAT_PCM_FLOAT, make_AudioFormatDescription(PcmType::FLOAT_32_BIT)
-        },
-        {
-            AUDIO_FORMAT_PCM_24_BIT_PACKED, make_AudioFormatDescription(PcmType::INT_24_BIT)
-        },
-        {
-            AUDIO_FORMAT_MP3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEG)
-        },
-        {
-            AUDIO_FORMAT_AMR_NB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_NB)
-        },
-        {
-            AUDIO_FORMAT_AMR_WB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_WB)
-        },
-        {
-            AUDIO_FORMAT_AAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_MP4)
-        },
-        {
-            AUDIO_FORMAT_AAC_MAIN, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_MAIN)
-        },
-        {
-            AUDIO_FORMAT_AAC_LC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LC)
-        },
-        {
-            AUDIO_FORMAT_AAC_SSR, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_SSR)
-        },
-        {
-            AUDIO_FORMAT_AAC_LTP, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LTP)
-        },
-        {
-            AUDIO_FORMAT_AAC_HE_V1, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_HE_V1)
-        },
-        {
-            AUDIO_FORMAT_AAC_SCALABLE,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_SCALABLE)
-        },
-        {
-            AUDIO_FORMAT_AAC_ERLC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ERLC)
-        },
-        {
-            AUDIO_FORMAT_AAC_LD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LD)
-        },
-        {
-            AUDIO_FORMAT_AAC_HE_V2, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_HE_V2)
-        },
-        {
-            AUDIO_FORMAT_AAC_ELD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ELD)
-        },
-        {
-            AUDIO_FORMAT_AAC_XHE, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_XHE)
-        },
-        // AUDIO_FORMAT_HE_AAC_V1 and HE_AAC_V2 are removed since they were deprecated long time
-        // ago.
-        {
-            AUDIO_FORMAT_VORBIS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_VORBIS)
-        },
-        {
-            AUDIO_FORMAT_OPUS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_OPUS)
-        },
-        {
-            AUDIO_FORMAT_AC3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AC3)
-        },
-        {
-            AUDIO_FORMAT_E_AC3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EAC3)
-        },
-        {
-            AUDIO_FORMAT_E_AC3_JOC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EAC3_JOC)
-        },
-        {
-            AUDIO_FORMAT_DTS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS)
-        },
-        {
-            AUDIO_FORMAT_DTS_HD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_HD)
-        },
-        {
-            AUDIO_FORMAT_DTS_HD_MA, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_HD_MA)
-        },
-        {
-            AUDIO_FORMAT_DTS_UHD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1)
-        },
-        {
-            AUDIO_FORMAT_DTS_UHD_P2, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2)
-        },
-        // In the future, we would like to represent encapsulated bitstreams as
-        // nested AudioFormatDescriptions. The legacy 'AUDIO_FORMAT_IEC61937' type doesn't
-        // specify the format of the encapsulated bitstream.
-        {
-            AUDIO_FORMAT_IEC61937,
-            make_AudioFormatDescription(PcmType::INT_16_BIT, MEDIA_MIMETYPE_AUDIO_IEC61937)
-        },
-        {
-            AUDIO_FORMAT_DOLBY_TRUEHD,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD)
-        },
-        {
-            AUDIO_FORMAT_EVRC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRC)
-        },
-        {
-            AUDIO_FORMAT_EVRCB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCB)
-        },
-        {
-            AUDIO_FORMAT_EVRCWB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCWB)
-        },
-        {
-            AUDIO_FORMAT_EVRCNW, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCNW)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADIF, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADIF)
-        },
-        {
-            AUDIO_FORMAT_WMA, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_WMA)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_WMA_PRO, make_AudioFormatDescription("audio/x-ms-wma.pro")
-        },
-        {
-            AUDIO_FORMAT_AMR_WB_PLUS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)
-        },
-        {
-            AUDIO_FORMAT_MP2, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II)
-        },
-        {
-            AUDIO_FORMAT_QCELP, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_QCELP)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_DSD, make_AudioFormatDescription("audio/vnd.sony.dsd")
-        },
-        {
-            AUDIO_FORMAT_FLAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_FLAC)
-        },
-        {
-            AUDIO_FORMAT_ALAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_ALAC)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_APE, make_AudioFormatDescription("audio/x-ape")
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_MAIN,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_MAIN)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_LC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LC)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_SSR,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SSR)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_LTP,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LTP)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_HE_V1,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V1)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_SCALABLE,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SCALABLE)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_ERLC,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ERLC)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_LD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LD)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_HE_V2,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V2)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_ELD,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ELD)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_XHE,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_XHE)
-        },
-        {
-            // Note: not in the IANA registry. "vnd.octel.sbc" is not BT SBC.
-            AUDIO_FORMAT_SBC, make_AudioFormatDescription("audio/x-sbc")
-        },
-        {
-            AUDIO_FORMAT_APTX, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_APTX)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_APTX_HD, make_AudioFormatDescription("audio/vnd.qcom.aptx.hd")
-        },
-        {
-            AUDIO_FORMAT_AC4, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AC4)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_LDAC, make_AudioFormatDescription("audio/vnd.sony.ldac")
-        },
-        {
-            AUDIO_FORMAT_MAT, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_MAT_1_0,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT + std::string(".1.0"))
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_MAT_2_0,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT + std::string(".2.0"))
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_MAT_2_1,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT + std::string(".2.1"))
-        },
-        {
-            AUDIO_FORMAT_AAC_LATM, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC)
-        },
-        {
-            AUDIO_FORMAT_AAC_LATM_LC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LATM_LC)
-        },
-        {
-            AUDIO_FORMAT_AAC_LATM_HE_V1,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V1)
-        },
-        {
-            AUDIO_FORMAT_AAC_LATM_HE_V2,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V2)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_CELT, make_AudioFormatDescription("audio/x-celt")
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_APTX_ADAPTIVE, make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive")
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_LHDC, make_AudioFormatDescription("audio/vnd.savitech.lhdc")
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_LHDC_LL, make_AudioFormatDescription("audio/vnd.savitech.lhdc.ll")
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_APTX_TWSP, make_AudioFormatDescription("audio/vnd.qcom.aptx.twsp")
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_LC3, make_AudioFormatDescription("audio/x-lc3")
-        },
-        {
-            AUDIO_FORMAT_MPEGH, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1)
-        },
-        {
-            AUDIO_FORMAT_MPEGH_BL_L3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L3)
-        },
-        {
-            AUDIO_FORMAT_MPEGH_BL_L4, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L4)
-        },
-        {
-            AUDIO_FORMAT_MPEGH_LC_L3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L3)
-        },
-        {
-            AUDIO_FORMAT_MPEGH_LC_L4, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L4)
-        },
-        {
-            AUDIO_FORMAT_IEC60958,
-            make_AudioFormatDescription(PcmType::INT_24_BIT, MEDIA_MIMETYPE_AUDIO_IEC60958)
-        },
-        {
-            AUDIO_FORMAT_DRA, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DRA)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_APTX_ADAPTIVE_QLEA,
-            make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive.r3")
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_APTX_ADAPTIVE_R4,
-            make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive.r4")
-        },
-    }};
-    return pairs;
-}
-
-template<typename S, typename T>
-std::unordered_map<S, T> make_DirectMap(const std::vector<std::pair<S, T>>& v) {
-    std::unordered_map<S, T> result(v.begin(), v.end());
-    LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
-    return result;
-}
-
-template<typename S, typename T>
-std::unordered_map<S, T> make_DirectMap(
-        const std::vector<std::pair<S, T>>& v1, const std::vector<std::pair<S, T>>& v2) {
-    std::unordered_map<S, T> result(v1.begin(), v1.end());
-    LOG_ALWAYS_FATAL_IF(result.size() != v1.size(), "Duplicate key elements detected in v1");
-    result.insert(v2.begin(), v2.end());
-    LOG_ALWAYS_FATAL_IF(result.size() != v1.size() + v2.size(),
-            "Duplicate key elements detected in v1+v2");
-    return result;
-}
-
-template<typename S, typename T>
-std::unordered_map<T, S> make_ReverseMap(const std::vector<std::pair<S, T>>& v) {
-    std::unordered_map<T, S> result;
-    std::transform(v.begin(), v.end(), std::inserter(result, result.begin()),
-            [](const std::pair<S, T>& p) {
-                return std::make_pair(p.second, p.first);
-            });
-    LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
-    return result;
-}
-
-}  // namespace
-
-audio_channel_mask_t aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
-        int aidlLayout, bool isInput) {
-    auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
-    const int aidlLayoutInitial = aidlLayout; // for error message
-    audio_channel_mask_t legacy = AUDIO_CHANNEL_NONE;
-    for (const auto& bitPair : bitMapping) {
-        if ((aidlLayout & bitPair.second) == bitPair.second) {
-            legacy = static_cast<audio_channel_mask_t>(legacy | bitPair.first);
-            aidlLayout &= ~bitPair.second;
-            if (aidlLayout == 0) {
-                return legacy;
-            }
-        }
-    }
-    ALOGE("%s: aidl layout 0x%x contains bits 0x%x that have no match to legacy %s bits",
-            __func__, aidlLayoutInitial, aidlLayout, isInput ? "input" : "output");
-    return AUDIO_CHANNEL_NONE;
-}
-
-ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
-        const AudioChannelLayout& aidl, bool isInput) {
-    using ReverseMap = std::unordered_map<AudioChannelLayout, audio_channel_mask_t>;
-    using Tag = AudioChannelLayout::Tag;
-    static const ReverseMap mIn = make_ReverseMap(getInAudioChannelPairs());
-    static const ReverseMap mOut = make_ReverseMap(getOutAudioChannelPairs());
-    static const ReverseMap mVoice = make_ReverseMap(getVoiceAudioChannelPairs());
-
-    auto convert = [](const AudioChannelLayout& aidl, const ReverseMap& m,
-            const char* func, const char* type) -> ConversionResult<audio_channel_mask_t> {
-        if (auto it = m.find(aidl); it != m.end()) {
-            return it->second;
-        } else {
-            ALOGW("%s: no legacy %s audio_channel_mask_t found for %s", func, type,
-                    aidl.toString().c_str());
-            return unexpected(BAD_VALUE);
-        }
-    };
-
-    switch (aidl.getTag()) {
-        case Tag::none:
-            return AUDIO_CHANNEL_NONE;
-        case Tag::invalid:
-            return AUDIO_CHANNEL_INVALID;
-        case Tag::indexMask:
-            // Index masks do not have pre-defined values.
-            if (const int bits = aidl.get<Tag::indexMask>();
-                    __builtin_popcount(bits) != 0 &&
-                    __builtin_popcount(bits) <= AUDIO_CHANNEL_COUNT_MAX) {
-                return audio_channel_mask_from_representation_and_bits(
-                        AUDIO_CHANNEL_REPRESENTATION_INDEX, bits);
-            } else {
-                ALOGE("%s: invalid indexMask value 0x%x in %s",
-                        __func__, bits, aidl.toString().c_str());
-                return unexpected(BAD_VALUE);
-            }
-        case Tag::layoutMask:
-            // The fast path is to find a direct match for some known layout mask.
-            if (const auto layoutMatch = convert(aidl, isInput ? mIn : mOut, __func__,
-                    isInput ? "input" : "output");
-                    layoutMatch.ok()) {
-                return layoutMatch;
-            }
-            // If a match for a predefined layout wasn't found, make a custom one from bits.
-            if (audio_channel_mask_t bitMask =
-                    aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
-                            aidl.get<Tag::layoutMask>(), isInput);
-                    bitMask != AUDIO_CHANNEL_NONE) {
-                return bitMask;
-            }
-            return unexpected(BAD_VALUE);
-        case Tag::voiceMask:
-            return convert(aidl, mVoice, __func__, "voice");
-    }
-    ALOGE("%s: unexpected tag value %d", __func__, aidl.getTag());
-    return unexpected(BAD_VALUE);
-}
-
-int legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
-        audio_channel_mask_t legacy, bool isInput) {
-    auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
-    const int legacyInitial = legacy; // for error message
-    int aidlLayout = 0;
-    for (const auto& bitPair : bitMapping) {
-        if ((legacy & bitPair.first) == bitPair.first) {
-            aidlLayout |= bitPair.second;
-            legacy = static_cast<audio_channel_mask_t>(legacy & ~bitPair.first);
-            if (legacy == 0) {
-                return aidlLayout;
-            }
-        }
-    }
-    ALOGE("%s: legacy %s audio_channel_mask_t 0x%x contains unrecognized bits 0x%x",
-            __func__, isInput ? "input" : "output", legacyInitial, legacy);
-    return 0;
-}
-
-ConversionResult<AudioChannelLayout> legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
-        audio_channel_mask_t legacy, bool isInput) {
-    using DirectMap = std::unordered_map<audio_channel_mask_t, AudioChannelLayout>;
-    using Tag = AudioChannelLayout::Tag;
-    static const DirectMap mInAndVoice = make_DirectMap(
-            getInAudioChannelPairs(), getVoiceAudioChannelPairs());
-    static const DirectMap mOut = make_DirectMap(getOutAudioChannelPairs());
-
-    auto convert = [](const audio_channel_mask_t legacy, const DirectMap& m,
-            const char* func, const char* type) -> ConversionResult<AudioChannelLayout> {
-        if (auto it = m.find(legacy); it != m.end()) {
-            return it->second;
-        } else {
-            ALOGW("%s: no AudioChannelLayout found for legacy %s audio_channel_mask_t value 0x%x",
-                    func, type, legacy);
-            return unexpected(BAD_VALUE);
-        }
-    };
-
-    if (legacy == AUDIO_CHANNEL_NONE) {
-        return AudioChannelLayout{};
-    } else if (legacy == AUDIO_CHANNEL_INVALID) {
-        return AudioChannelLayout::make<Tag::invalid>(0);
-    }
-
-    const audio_channel_representation_t repr = audio_channel_mask_get_representation(legacy);
-    if (repr == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
-        if (audio_channel_mask_is_valid(legacy)) {
-            const int indexMask = VALUE_OR_RETURN(
-                    convertIntegral<int>(audio_channel_mask_get_bits(legacy)));
-            return AudioChannelLayout::make<Tag::indexMask>(indexMask);
-        } else {
-            ALOGE("%s: legacy audio_channel_mask_t value 0x%x is invalid", __func__, legacy);
-            return unexpected(BAD_VALUE);
-        }
-    } else if (repr == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
-        // The fast path is to find a direct match for some known layout mask.
-        if (const auto layoutMatch = convert(legacy, isInput ? mInAndVoice : mOut, __func__,
-                isInput ? "input / voice" : "output");
-                layoutMatch.ok()) {
-            return layoutMatch;
-        }
-        // If a match for a predefined layout wasn't found, make a custom one from bits,
-        // rejecting those with voice channel bits.
-        if (!isInput ||
-                (legacy & (AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK)) == 0) {
-            if (int bitMaskLayout =
-                    legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
-                            legacy, isInput);
-                    bitMaskLayout != 0) {
-                return AudioChannelLayout::make<Tag::layoutMask>(bitMaskLayout);
-            }
-        } else {
-            ALOGE("%s: legacy audio_channel_mask_t value 0x%x contains voice bits",
-                    __func__, legacy);
-        }
-        return unexpected(BAD_VALUE);
-    }
-
-    ALOGE("%s: unknown representation %d in audio_channel_mask_t value 0x%x",
-            __func__, repr, legacy);
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
-        const AudioDeviceDescription& aidl) {
-    static const std::unordered_map<AudioDeviceDescription, audio_devices_t> m =
-            make_ReverseMap(getAudioDevicePairs());
-    if (auto it = m.find(aidl); it != m.end()) {
-        return it->second;
-    } else {
-        ALOGE("%s: no legacy audio_devices_t found for %s", __func__, aidl.toString().c_str());
-        return unexpected(BAD_VALUE);
-    }
-}
-
-ConversionResult<AudioDeviceDescription> legacy2aidl_audio_devices_t_AudioDeviceDescription(
-        audio_devices_t legacy) {
-    static const std::unordered_map<audio_devices_t, AudioDeviceDescription> m =
-            make_DirectMap(getAudioDevicePairs());
-    if (auto it = m.find(legacy); it != m.end()) {
-        return it->second;
-    } else {
-        ALOGE("%s: no AudioDeviceDescription found for legacy audio_devices_t value 0x%x",
-                __func__, legacy);
-        return unexpected(BAD_VALUE);
-    }
-}
-
-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);
-}
-
-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>()));
-    return OK;
-}
-
-status_t aidl2legacy_AudioDevice_audio_device(
-        const AudioDevice& aidl,
-        audio_devices_t* legacyType, std::string* legacyAddress) {
-    *legacyType = VALUE_OR_RETURN_STATUS(
-            aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
-    *legacyAddress = aidl.address.get<AudioDeviceAddress::id>();
-    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(
-            legacy2aidl_string(legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN));
-    aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
-    return aidl;
-}
-
-ConversionResult<AudioDevice>
-legacy2aidl_audio_device_AudioDevice(
-        audio_devices_t legacyType, const String8& legacyAddress) {
-    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);
-    return aidl;
-}
-
-ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
-        const AudioFormatDescription& aidl) {
-    static const std::unordered_map<AudioFormatDescription, audio_format_t> m =
-            make_ReverseMap(getAudioFormatPairs());
-    if (auto it = m.find(aidl); it != m.end()) {
-        return it->second;
-    } else {
-        ALOGE("%s: no legacy audio_format_t found for %s", __func__, aidl.toString().c_str());
-        return unexpected(BAD_VALUE);
-    }
-}
-
-ConversionResult<AudioFormatDescription> legacy2aidl_audio_format_t_AudioFormatDescription(
-        audio_format_t legacy) {
-    static const std::unordered_map<audio_format_t, AudioFormatDescription> m =
-            make_DirectMap(getAudioFormatPairs());
-    if (auto it = m.find(legacy); it != m.end()) {
-        return it->second;
-    } else {
-        ALOGE("%s: no AudioFormatDescription found for legacy audio_format_t value 0x%x",
-                __func__, legacy);
-        return unexpected(BAD_VALUE);
-    }
-}
-
-ConversionResult<audio_gain_mode_t> aidl2legacy_AudioGainMode_audio_gain_mode_t(
-        AudioGainMode aidl) {
-    switch (aidl) {
-        case AudioGainMode::JOINT:
-            return AUDIO_GAIN_MODE_JOINT;
-        case AudioGainMode::CHANNELS:
-            return AUDIO_GAIN_MODE_CHANNELS;
-        case AudioGainMode::RAMP:
-            return AUDIO_GAIN_MODE_RAMP;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioGainMode> legacy2aidl_audio_gain_mode_t_AudioGainMode(
-        audio_gain_mode_t legacy) {
-    switch (legacy) {
-        case AUDIO_GAIN_MODE_JOINT:
-            return AudioGainMode::JOINT;
-        case AUDIO_GAIN_MODE_CHANNELS:
-            return AudioGainMode::CHANNELS;
-        case AUDIO_GAIN_MODE_RAMP:
-            return AudioGainMode::RAMP;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl) {
-    return convertBitmask<audio_gain_mode_t, int32_t, audio_gain_mode_t, AudioGainMode>(
-            aidl, aidl2legacy_AudioGainMode_audio_gain_mode_t,
-            // AudioGainMode is index-based.
-            indexToEnum_index<AudioGainMode>,
-            // AUDIO_GAIN_MODE_* constants are mask-based.
-            enumToMask_bitmask<audio_gain_mode_t, audio_gain_mode_t>);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy) {
-    return convertBitmask<int32_t, audio_gain_mode_t, AudioGainMode, audio_gain_mode_t>(
-            legacy, legacy2aidl_audio_gain_mode_t_AudioGainMode,
-            // AUDIO_GAIN_MODE_* constants are mask-based.
-            indexToEnum_bitmask<audio_gain_mode_t>,
-            // AudioGainMode is index-based.
-            enumToMask_index<int32_t, AudioGainMode>);
-}
-
-ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
-        const AudioGainConfig& aidl, bool isInput) {
-    audio_gain_config legacy;
-    legacy.index = VALUE_OR_RETURN(convertIntegral<int>(aidl.index));
-    legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
-    legacy.channel_mask = VALUE_OR_RETURN(
-            aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
-    const bool isJoint = bitmaskIsSet(aidl.mode, AudioGainMode::JOINT);
-    size_t numValues = isJoint ? 1
-                               : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
-                                         : audio_channel_count_from_out_mask(legacy.channel_mask);
-    if (aidl.values.size() != numValues || aidl.values.size() > std::size(legacy.values)) {
-        return unexpected(BAD_VALUE);
-    }
-    for (size_t i = 0; i < numValues; ++i) {
-        legacy.values[i] = VALUE_OR_RETURN(convertIntegral<int>(aidl.values[i]));
-    }
-    legacy.ramp_duration_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.rampDurationMs));
-    return legacy;
-}
-
-ConversionResult<AudioGainConfig> legacy2aidl_audio_gain_config_AudioGainConfig(
-        const audio_gain_config& legacy, bool isInput) {
-    AudioGainConfig aidl;
-    aidl.index = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.index));
-    aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
-    aidl.channelMask = VALUE_OR_RETURN(
-            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
-    const bool isJoint = (legacy.mode & AUDIO_GAIN_MODE_JOINT) != 0;
-    size_t numValues = isJoint ? 1
-                               : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
-                                         : audio_channel_count_from_out_mask(legacy.channel_mask);
-    aidl.values.resize(numValues);
-    for (size_t i = 0; i < numValues; ++i) {
-        aidl.values[i] = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.values[i]));
-    }
-    aidl.rampDurationMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.ramp_duration_ms));
-    return aidl;
-}
-
-ConversionResult<audio_input_flags_t> aidl2legacy_AudioInputFlags_audio_input_flags_t(
-        AudioInputFlags aidl) {
-    switch (aidl) {
-        case AudioInputFlags::FAST:
-            return AUDIO_INPUT_FLAG_FAST;
-        case AudioInputFlags::HW_HOTWORD:
-            return AUDIO_INPUT_FLAG_HW_HOTWORD;
-        case AudioInputFlags::RAW:
-            return AUDIO_INPUT_FLAG_RAW;
-        case AudioInputFlags::SYNC:
-            return AUDIO_INPUT_FLAG_SYNC;
-        case AudioInputFlags::MMAP_NOIRQ:
-            return AUDIO_INPUT_FLAG_MMAP_NOIRQ;
-        case AudioInputFlags::VOIP_TX:
-            return AUDIO_INPUT_FLAG_VOIP_TX;
-        case AudioInputFlags::HW_AV_SYNC:
-            return AUDIO_INPUT_FLAG_HW_AV_SYNC;
-        case AudioInputFlags::DIRECT:
-            return AUDIO_INPUT_FLAG_DIRECT;
-        case AudioInputFlags::ULTRASOUND:
-            return AUDIO_INPUT_FLAG_ULTRASOUND;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
-        audio_input_flags_t legacy) {
-    switch (legacy) {
-        case AUDIO_INPUT_FLAG_NONE:
-            break; // shouldn't get here. must be listed  -Werror,-Wswitch
-        case AUDIO_INPUT_FLAG_FAST:
-            return AudioInputFlags::FAST;
-        case AUDIO_INPUT_FLAG_HW_HOTWORD:
-            return AudioInputFlags::HW_HOTWORD;
-        case AUDIO_INPUT_FLAG_RAW:
-            return AudioInputFlags::RAW;
-        case AUDIO_INPUT_FLAG_SYNC:
-            return AudioInputFlags::SYNC;
-        case AUDIO_INPUT_FLAG_MMAP_NOIRQ:
-            return AudioInputFlags::MMAP_NOIRQ;
-        case AUDIO_INPUT_FLAG_VOIP_TX:
-            return AudioInputFlags::VOIP_TX;
-        case AUDIO_INPUT_FLAG_HW_AV_SYNC:
-            return AudioInputFlags::HW_AV_SYNC;
-        case AUDIO_INPUT_FLAG_DIRECT:
-            return AudioInputFlags::DIRECT;
-        case AUDIO_INPUT_FLAG_ULTRASOUND:
-            return AudioInputFlags::ULTRASOUND;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
-        AudioOutputFlags aidl) {
-    switch (aidl) {
-        case AudioOutputFlags::DIRECT:
-            return AUDIO_OUTPUT_FLAG_DIRECT;
-        case AudioOutputFlags::PRIMARY:
-            return AUDIO_OUTPUT_FLAG_PRIMARY;
-        case AudioOutputFlags::FAST:
-            return AUDIO_OUTPUT_FLAG_FAST;
-        case AudioOutputFlags::DEEP_BUFFER:
-            return AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
-        case AudioOutputFlags::COMPRESS_OFFLOAD:
-            return AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
-        case AudioOutputFlags::NON_BLOCKING:
-            return AUDIO_OUTPUT_FLAG_NON_BLOCKING;
-        case AudioOutputFlags::HW_AV_SYNC:
-            return AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
-        case AudioOutputFlags::TTS:
-            return AUDIO_OUTPUT_FLAG_TTS;
-        case AudioOutputFlags::RAW:
-            return AUDIO_OUTPUT_FLAG_RAW;
-        case AudioOutputFlags::SYNC:
-            return AUDIO_OUTPUT_FLAG_SYNC;
-        case AudioOutputFlags::IEC958_NONAUDIO:
-            return AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
-        case AudioOutputFlags::DIRECT_PCM:
-            return AUDIO_OUTPUT_FLAG_DIRECT_PCM;
-        case AudioOutputFlags::MMAP_NOIRQ:
-            return AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
-        case AudioOutputFlags::VOIP_RX:
-            return AUDIO_OUTPUT_FLAG_VOIP_RX;
-        case AudioOutputFlags::INCALL_MUSIC:
-            return AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
-        case AudioOutputFlags::GAPLESS_OFFLOAD:
-            return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
-        case AudioOutputFlags::ULTRASOUND:
-            return AUDIO_OUTPUT_FLAG_ULTRASOUND;
-        case AudioOutputFlags::SPATIALIZER:
-            return AUDIO_OUTPUT_FLAG_SPATIALIZER;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
-        audio_output_flags_t legacy) {
-    switch (legacy) {
-        case AUDIO_OUTPUT_FLAG_NONE:
-            break; // shouldn't get here. must be listed  -Werror,-Wswitch
-        case AUDIO_OUTPUT_FLAG_DIRECT:
-            return AudioOutputFlags::DIRECT;
-        case AUDIO_OUTPUT_FLAG_PRIMARY:
-            return AudioOutputFlags::PRIMARY;
-        case AUDIO_OUTPUT_FLAG_FAST:
-            return AudioOutputFlags::FAST;
-        case AUDIO_OUTPUT_FLAG_DEEP_BUFFER:
-            return AudioOutputFlags::DEEP_BUFFER;
-        case AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD:
-            return AudioOutputFlags::COMPRESS_OFFLOAD;
-        case AUDIO_OUTPUT_FLAG_NON_BLOCKING:
-            return AudioOutputFlags::NON_BLOCKING;
-        case AUDIO_OUTPUT_FLAG_HW_AV_SYNC:
-            return AudioOutputFlags::HW_AV_SYNC;
-        case AUDIO_OUTPUT_FLAG_TTS:
-            return AudioOutputFlags::TTS;
-        case AUDIO_OUTPUT_FLAG_RAW:
-            return AudioOutputFlags::RAW;
-        case AUDIO_OUTPUT_FLAG_SYNC:
-            return AudioOutputFlags::SYNC;
-        case AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO:
-            return AudioOutputFlags::IEC958_NONAUDIO;
-        case AUDIO_OUTPUT_FLAG_DIRECT_PCM:
-            return AudioOutputFlags::DIRECT_PCM;
-        case AUDIO_OUTPUT_FLAG_MMAP_NOIRQ:
-            return AudioOutputFlags::MMAP_NOIRQ;
-        case AUDIO_OUTPUT_FLAG_VOIP_RX:
-            return AudioOutputFlags::VOIP_RX;
-        case AUDIO_OUTPUT_FLAG_INCALL_MUSIC:
-            return AudioOutputFlags::INCALL_MUSIC;
-        case AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD:
-            return AudioOutputFlags::GAPLESS_OFFLOAD;
-        case AUDIO_OUTPUT_FLAG_ULTRASOUND:
-            return AudioOutputFlags::ULTRASOUND;
-        case AUDIO_OUTPUT_FLAG_SPATIALIZER:
-            return AudioOutputFlags::SPATIALIZER;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
-        int32_t aidl) {
-    using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
-
-    LegacyMask converted = VALUE_OR_RETURN(
-            (convertBitmask<LegacyMask, int32_t, audio_input_flags_t, AudioInputFlags>(
-                    aidl, aidl2legacy_AudioInputFlags_audio_input_flags_t,
-                    indexToEnum_index<AudioInputFlags>,
-                    enumToMask_bitmask<LegacyMask, audio_input_flags_t>)));
-    return static_cast<audio_input_flags_t>(converted);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
-        audio_input_flags_t legacy) {
-    using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
-
-    LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
-    return convertBitmask<int32_t, LegacyMask, AudioInputFlags, audio_input_flags_t>(
-            legacyMask, legacy2aidl_audio_input_flags_t_AudioInputFlags,
-            indexToEnum_bitmask<audio_input_flags_t>,
-            enumToMask_index<int32_t, AudioInputFlags>);
-}
-
-ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
-        int32_t aidl) {
-    return convertBitmask<audio_output_flags_t,
-            int32_t,
-            audio_output_flags_t,
-            AudioOutputFlags>(
-            aidl, aidl2legacy_AudioOutputFlags_audio_output_flags_t,
-            indexToEnum_index<AudioOutputFlags>,
-            enumToMask_bitmask<audio_output_flags_t, audio_output_flags_t>);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
-        audio_output_flags_t legacy) {
-    using LegacyMask = std::underlying_type_t<audio_output_flags_t>;
-
-    LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
-    return convertBitmask<int32_t, LegacyMask, AudioOutputFlags, audio_output_flags_t>(
-            legacyMask, legacy2aidl_audio_output_flags_t_AudioOutputFlags,
-            indexToEnum_bitmask<audio_output_flags_t>,
-            enumToMask_index<int32_t, AudioOutputFlags>);
-}
-
-ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
-        const AudioIoFlags& aidl, bool isInput) {
-    audio_io_flags legacy;
-    if (isInput) {
-        legacy.input = VALUE_OR_RETURN(
-                aidl2legacy_int32_t_audio_input_flags_t_mask(
-                        VALUE_OR_RETURN(UNION_GET(aidl, input))));
-    } else {
-        legacy.output = VALUE_OR_RETURN(
-                aidl2legacy_int32_t_audio_output_flags_t_mask(
-                        VALUE_OR_RETURN(UNION_GET(aidl, output))));
-    }
-    return legacy;
-}
-
-ConversionResult<AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
-        const audio_io_flags& legacy, bool isInput) {
-    AudioIoFlags aidl;
-    if (isInput) {
-        UNION_SET(aidl, input,
-                VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(legacy.input)));
-    } else {
-        UNION_SET(aidl, output,
-                VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(legacy.output)));
-    }
-    return aidl;
-}
-
-ConversionResult<audio_port_config_device_ext>
-aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
-        const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlDeviceExt) {
-    audio_port_config_device_ext legacy;
-    legacy.hw_module = VALUE_OR_RETURN(
-            aidl2legacy_int32_t_audio_module_handle_t(aidlDeviceExt.hwModule));
-    RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
-                    aidl.device, &legacy.type, legacy.address));
-    return legacy;
-}
-
-status_t legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
-        const audio_port_config_device_ext& legacy,
-        AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
-    aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
-    aidl->device = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
-    return OK;
-}
-
-ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
-        AudioStreamType aidl) {
-    switch (aidl) {
-        case AudioStreamType::INVALID:
-            break;  // return error
-        case AudioStreamType::SYS_RESERVED_DEFAULT:
-            return AUDIO_STREAM_DEFAULT;
-        case AudioStreamType::VOICE_CALL:
-            return AUDIO_STREAM_VOICE_CALL;
-        case AudioStreamType::SYSTEM:
-            return AUDIO_STREAM_SYSTEM;
-        case AudioStreamType::RING:
-            return AUDIO_STREAM_RING;
-        case AudioStreamType::MUSIC:
-            return AUDIO_STREAM_MUSIC;
-        case AudioStreamType::ALARM:
-            return AUDIO_STREAM_ALARM;
-        case AudioStreamType::NOTIFICATION:
-            return AUDIO_STREAM_NOTIFICATION;
-        case AudioStreamType::BLUETOOTH_SCO:
-            return AUDIO_STREAM_BLUETOOTH_SCO;
-        case AudioStreamType::ENFORCED_AUDIBLE:
-            return AUDIO_STREAM_ENFORCED_AUDIBLE;
-        case AudioStreamType::DTMF:
-            return AUDIO_STREAM_DTMF;
-        case AudioStreamType::TTS:
-            return AUDIO_STREAM_TTS;
-        case AudioStreamType::ACCESSIBILITY:
-            return AUDIO_STREAM_ACCESSIBILITY;
-        case AudioStreamType::ASSISTANT:
-            return AUDIO_STREAM_ASSISTANT;
-        case AudioStreamType::SYS_RESERVED_REROUTING:
-            return AUDIO_STREAM_REROUTING;
-        case AudioStreamType::SYS_RESERVED_PATCH:
-            return AUDIO_STREAM_PATCH;
-        case AudioStreamType::CALL_ASSISTANT:
-            return AUDIO_STREAM_CALL_ASSISTANT;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioStreamType> legacy2aidl_audio_stream_type_t_AudioStreamType(
-        audio_stream_type_t legacy) {
-    switch (legacy) {
-        case AUDIO_STREAM_DEFAULT:
-            return AudioStreamType::SYS_RESERVED_DEFAULT;
-        case AUDIO_STREAM_VOICE_CALL:
-            return AudioStreamType::VOICE_CALL;
-        case AUDIO_STREAM_SYSTEM:
-            return AudioStreamType::SYSTEM;
-        case AUDIO_STREAM_RING:
-            return AudioStreamType::RING;
-        case AUDIO_STREAM_MUSIC:
-            return AudioStreamType::MUSIC;
-        case AUDIO_STREAM_ALARM:
-            return AudioStreamType::ALARM;
-        case AUDIO_STREAM_NOTIFICATION:
-            return AudioStreamType::NOTIFICATION;
-        case AUDIO_STREAM_BLUETOOTH_SCO:
-            return AudioStreamType::BLUETOOTH_SCO;
-        case AUDIO_STREAM_ENFORCED_AUDIBLE:
-            return AudioStreamType::ENFORCED_AUDIBLE;
-        case AUDIO_STREAM_DTMF:
-            return AudioStreamType::DTMF;
-        case AUDIO_STREAM_TTS:
-            return AudioStreamType::TTS;
-        case AUDIO_STREAM_ACCESSIBILITY:
-            return AudioStreamType::ACCESSIBILITY;
-        case AUDIO_STREAM_ASSISTANT:
-            return AudioStreamType::ASSISTANT;
-        case AUDIO_STREAM_REROUTING:
-            return AudioStreamType::SYS_RESERVED_REROUTING;
-        case AUDIO_STREAM_PATCH:
-            return AudioStreamType::SYS_RESERVED_PATCH;
-        case AUDIO_STREAM_CALL_ASSISTANT:
-            return AudioStreamType::CALL_ASSISTANT;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
-        AudioSource aidl) {
-    switch (aidl) {
-        case AudioSource::SYS_RESERVED_INVALID:
-            return AUDIO_SOURCE_INVALID;
-        case AudioSource::DEFAULT:
-            return AUDIO_SOURCE_DEFAULT;
-        case AudioSource::MIC:
-            return AUDIO_SOURCE_MIC;
-        case AudioSource::VOICE_UPLINK:
-            return AUDIO_SOURCE_VOICE_UPLINK;
-        case AudioSource::VOICE_DOWNLINK:
-            return AUDIO_SOURCE_VOICE_DOWNLINK;
-        case AudioSource::VOICE_CALL:
-            return AUDIO_SOURCE_VOICE_CALL;
-        case AudioSource::CAMCORDER:
-            return AUDIO_SOURCE_CAMCORDER;
-        case AudioSource::VOICE_RECOGNITION:
-            return AUDIO_SOURCE_VOICE_RECOGNITION;
-        case AudioSource::VOICE_COMMUNICATION:
-            return AUDIO_SOURCE_VOICE_COMMUNICATION;
-        case AudioSource::REMOTE_SUBMIX:
-            return AUDIO_SOURCE_REMOTE_SUBMIX;
-        case AudioSource::UNPROCESSED:
-            return AUDIO_SOURCE_UNPROCESSED;
-        case AudioSource::VOICE_PERFORMANCE:
-            return AUDIO_SOURCE_VOICE_PERFORMANCE;
-        case AudioSource::ULTRASOUND:
-            return AUDIO_SOURCE_ULTRASOUND;
-        case AudioSource::ECHO_REFERENCE:
-            return AUDIO_SOURCE_ECHO_REFERENCE;
-        case AudioSource::FM_TUNER:
-            return AUDIO_SOURCE_FM_TUNER;
-        case AudioSource::HOTWORD:
-            return AUDIO_SOURCE_HOTWORD;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioSource> legacy2aidl_audio_source_t_AudioSource(
-        audio_source_t legacy) {
-    switch (legacy) {
-        case AUDIO_SOURCE_INVALID:
-            return AudioSource::SYS_RESERVED_INVALID;
-        case AUDIO_SOURCE_DEFAULT:
-            return AudioSource::DEFAULT;
-        case AUDIO_SOURCE_MIC:
-            return AudioSource::MIC;
-        case AUDIO_SOURCE_VOICE_UPLINK:
-            return AudioSource::VOICE_UPLINK;
-        case AUDIO_SOURCE_VOICE_DOWNLINK:
-            return AudioSource::VOICE_DOWNLINK;
-        case AUDIO_SOURCE_VOICE_CALL:
-            return AudioSource::VOICE_CALL;
-        case AUDIO_SOURCE_CAMCORDER:
-            return AudioSource::CAMCORDER;
-        case AUDIO_SOURCE_VOICE_RECOGNITION:
-            return AudioSource::VOICE_RECOGNITION;
-        case AUDIO_SOURCE_VOICE_COMMUNICATION:
-            return AudioSource::VOICE_COMMUNICATION;
-        case AUDIO_SOURCE_REMOTE_SUBMIX:
-            return AudioSource::REMOTE_SUBMIX;
-        case AUDIO_SOURCE_UNPROCESSED:
-            return AudioSource::UNPROCESSED;
-        case AUDIO_SOURCE_VOICE_PERFORMANCE:
-            return AudioSource::VOICE_PERFORMANCE;
-        case AUDIO_SOURCE_ULTRASOUND:
-            return AudioSource::ULTRASOUND;
-        case AUDIO_SOURCE_ECHO_REFERENCE:
-            return AudioSource::ECHO_REFERENCE;
-        case AUDIO_SOURCE_FM_TUNER:
-            return AudioSource::FM_TUNER;
-        case AUDIO_SOURCE_HOTWORD:
-            return AudioSource::HOTWORD;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl) {
-    return convertReinterpret<audio_session_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
 // This type is unnamed in the original definition, thus we name it here.
 using audio_port_config_mix_ext_usecase = decltype(audio_port_config_mix_ext::usecase);
 
@@ -1921,6 +326,27 @@
     return legacy2aidl_audio_session_t_int32_t(legacy.session);
 }
 
+ConversionResult<audio_port_config_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
+        const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlDeviceExt) {
+    audio_port_config_device_ext legacy;
+    legacy.hw_module = VALUE_OR_RETURN(
+            aidl2legacy_int32_t_audio_module_handle_t(aidlDeviceExt.hwModule));
+    RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+                    aidl.device, &legacy.type, legacy.address));
+    return legacy;
+}
+
+status_t legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
+        const audio_port_config_device_ext& legacy,
+        AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
+    aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
+    aidl->device = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
+    return OK;
+}
+
 // This type is unnamed in the original definition, thus we name it here.
 using audio_port_config_ext = decltype(audio_port_config::ext);
 
@@ -2165,148 +591,6 @@
     return aidl;
 }
 
-ConversionResult<audio_content_type_t>
-aidl2legacy_AudioContentType_audio_content_type_t(AudioContentType aidl) {
-    switch (aidl) {
-        case AudioContentType::UNKNOWN:
-            return AUDIO_CONTENT_TYPE_UNKNOWN;
-        case AudioContentType::SPEECH:
-            return AUDIO_CONTENT_TYPE_SPEECH;
-        case AudioContentType::MUSIC:
-            return AUDIO_CONTENT_TYPE_MUSIC;
-        case AudioContentType::MOVIE:
-            return AUDIO_CONTENT_TYPE_MOVIE;
-        case AudioContentType::SONIFICATION:
-            return AUDIO_CONTENT_TYPE_SONIFICATION;
-        case AudioContentType::ULTRASOUND:
-            return AUDIO_CONTENT_TYPE_ULTRASOUND;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioContentType>
-legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy) {
-    switch (legacy) {
-        case AUDIO_CONTENT_TYPE_UNKNOWN:
-            return AudioContentType::UNKNOWN;
-        case AUDIO_CONTENT_TYPE_SPEECH:
-            return AudioContentType::SPEECH;
-        case AUDIO_CONTENT_TYPE_MUSIC:
-            return AudioContentType::MUSIC;
-        case AUDIO_CONTENT_TYPE_MOVIE:
-            return AudioContentType::MOVIE;
-        case AUDIO_CONTENT_TYPE_SONIFICATION:
-            return AudioContentType::SONIFICATION;
-        case AUDIO_CONTENT_TYPE_ULTRASOUND:
-            return AudioContentType::ULTRASOUND;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_usage_t>
-aidl2legacy_AudioUsage_audio_usage_t(AudioUsage aidl) {
-    switch (aidl) {
-        case AudioUsage::INVALID:
-            break;  // return error
-        case AudioUsage::UNKNOWN:
-            return AUDIO_USAGE_UNKNOWN;
-        case AudioUsage::MEDIA:
-            return AUDIO_USAGE_MEDIA;
-        case AudioUsage::VOICE_COMMUNICATION:
-            return AUDIO_USAGE_VOICE_COMMUNICATION;
-        case AudioUsage::VOICE_COMMUNICATION_SIGNALLING:
-            return AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
-        case AudioUsage::ALARM:
-            return AUDIO_USAGE_ALARM;
-        case AudioUsage::NOTIFICATION:
-            return AUDIO_USAGE_NOTIFICATION;
-        case AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE:
-            return AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
-        case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST:
-            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
-        case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT:
-            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT;
-        case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED:
-            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED;
-        case AudioUsage::NOTIFICATION_EVENT:
-            return AUDIO_USAGE_NOTIFICATION_EVENT;
-        case AudioUsage::ASSISTANCE_ACCESSIBILITY:
-            return AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
-        case AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE:
-            return AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
-        case AudioUsage::ASSISTANCE_SONIFICATION:
-            return AUDIO_USAGE_ASSISTANCE_SONIFICATION;
-        case AudioUsage::GAME:
-            return AUDIO_USAGE_GAME;
-        case AudioUsage::VIRTUAL_SOURCE:
-            return AUDIO_USAGE_VIRTUAL_SOURCE;
-        case AudioUsage::ASSISTANT:
-            return AUDIO_USAGE_ASSISTANT;
-        case AudioUsage::CALL_ASSISTANT:
-            return AUDIO_USAGE_CALL_ASSISTANT;
-        case AudioUsage::EMERGENCY:
-            return AUDIO_USAGE_EMERGENCY;
-        case AudioUsage::SAFETY:
-            return AUDIO_USAGE_SAFETY;
-        case AudioUsage::VEHICLE_STATUS:
-            return AUDIO_USAGE_VEHICLE_STATUS;
-        case AudioUsage::ANNOUNCEMENT:
-            return AUDIO_USAGE_ANNOUNCEMENT;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioUsage>
-legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy) {
-    switch (legacy) {
-        case AUDIO_USAGE_UNKNOWN:
-            return AudioUsage::UNKNOWN;
-        case AUDIO_USAGE_MEDIA:
-            return AudioUsage::MEDIA;
-        case AUDIO_USAGE_VOICE_COMMUNICATION:
-            return AudioUsage::VOICE_COMMUNICATION;
-        case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
-            return AudioUsage::VOICE_COMMUNICATION_SIGNALLING;
-        case AUDIO_USAGE_ALARM:
-            return AudioUsage::ALARM;
-        case AUDIO_USAGE_NOTIFICATION:
-            return AudioUsage::NOTIFICATION;
-        case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
-            return AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE;
-        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
-            return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST;
-        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
-            return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT;
-        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
-            return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED;
-        case AUDIO_USAGE_NOTIFICATION_EVENT:
-            return AudioUsage::NOTIFICATION_EVENT;
-        case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
-            return AudioUsage::ASSISTANCE_ACCESSIBILITY;
-        case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
-            return AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE;
-        case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
-            return AudioUsage::ASSISTANCE_SONIFICATION;
-        case AUDIO_USAGE_GAME:
-            return AudioUsage::GAME;
-        case AUDIO_USAGE_VIRTUAL_SOURCE:
-            return AudioUsage::VIRTUAL_SOURCE;
-        case AUDIO_USAGE_ASSISTANT:
-            return AudioUsage::ASSISTANT;
-        case AUDIO_USAGE_CALL_ASSISTANT:
-            return AudioUsage::CALL_ASSISTANT;
-        case AUDIO_USAGE_EMERGENCY:
-            return AudioUsage::EMERGENCY;
-        case AUDIO_USAGE_SAFETY:
-            return AudioUsage::SAFETY;
-        case AUDIO_USAGE_VEHICLE_STATUS:
-            return AudioUsage::VEHICLE_STATUS;
-        case AUDIO_USAGE_ANNOUNCEMENT:
-            return AudioUsage::ANNOUNCEMENT;
-    }
-    return unexpected(BAD_VALUE);
-}
-
 ConversionResult<audio_flags_mask_t>
 aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl) {
     switch (aidl) {
@@ -2430,140 +714,6 @@
     return aidl;
 }
 
-ConversionResult<audio_encapsulation_mode_t>
-aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(AudioEncapsulationMode aidl) {
-    switch (aidl) {
-        case AudioEncapsulationMode::INVALID:
-            break;  // return error
-        case AudioEncapsulationMode::NONE:
-            return AUDIO_ENCAPSULATION_MODE_NONE;
-        case AudioEncapsulationMode::ELEMENTARY_STREAM:
-            return AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM;
-        case AudioEncapsulationMode::HANDLE:
-            return AUDIO_ENCAPSULATION_MODE_HANDLE;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioEncapsulationMode>
-legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy) {
-    switch (legacy) {
-        case AUDIO_ENCAPSULATION_MODE_NONE:
-            return AudioEncapsulationMode::NONE;
-        case AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM:
-            return AudioEncapsulationMode::ELEMENTARY_STREAM;
-        case AUDIO_ENCAPSULATION_MODE_HANDLE:
-            return AudioEncapsulationMode::HANDLE;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_offload_info_t>
-aidl2legacy_AudioOffloadInfo_audio_offload_info_t(const AudioOffloadInfo& aidl) {
-    audio_offload_info_t legacy = AUDIO_INFO_INITIALIZER;
-    audio_config_base_t base = VALUE_OR_RETURN(
-            aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, false /*isInput*/));
-    legacy.sample_rate = base.sample_rate;
-    legacy.channel_mask = base.channel_mask;
-    legacy.format = base.format;
-    legacy.stream_type = VALUE_OR_RETURN(
-            aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
-    legacy.bit_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitRatePerSecond));
-    legacy.duration_us = VALUE_OR_RETURN(convertIntegral<int64_t>(aidl.durationUs));
-    legacy.has_video = aidl.hasVideo;
-    legacy.is_streaming = aidl.isStreaming;
-    legacy.bit_width = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitWidth));
-    legacy.offload_buffer_size = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.offloadBufferSize));
-    legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
-    legacy.encapsulation_mode = VALUE_OR_RETURN(
-            aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(aidl.encapsulationMode));
-    legacy.content_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.contentId));
-    legacy.sync_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.syncId));
-    return legacy;
-}
-
-ConversionResult<AudioOffloadInfo>
-legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy) {
-    AudioOffloadInfo aidl;
-    // Version 0.1 fields.
-    if (legacy.size < offsetof(audio_offload_info_t, usage) + sizeof(audio_offload_info_t::usage)) {
-        return unexpected(BAD_VALUE);
-    }
-    const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
-        .channel_mask = legacy.channel_mask, .format = legacy.format };
-    aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(
-                    base, false /*isInput*/));
-    aidl.streamType = VALUE_OR_RETURN(
-            legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream_type));
-    aidl.bitRatePerSecond = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_rate));
-    aidl.durationUs = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.duration_us));
-    aidl.hasVideo = legacy.has_video;
-    aidl.isStreaming = legacy.is_streaming;
-    aidl.bitWidth = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_width));
-    aidl.offloadBufferSize = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.offload_buffer_size));
-    aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
-
-    // Version 0.2 fields.
-    if (legacy.version >= AUDIO_OFFLOAD_INFO_VERSION_0_2) {
-        if (legacy.size <
-            offsetof(audio_offload_info_t, sync_id) + sizeof(audio_offload_info_t::sync_id)) {
-            return unexpected(BAD_VALUE);
-        }
-        aidl.encapsulationMode = VALUE_OR_RETURN(
-                legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(
-                        legacy.encapsulation_mode));
-        aidl.contentId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.content_id));
-        aidl.syncId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.sync_id));
-    }
-    return aidl;
-}
-
-ConversionResult<audio_config_t>
-aidl2legacy_AudioConfig_audio_config_t(const AudioConfig& aidl, bool isInput) {
-    const audio_config_base_t legacyBase = VALUE_OR_RETURN(
-            aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, isInput));
-    audio_config_t legacy = AUDIO_CONFIG_INITIALIZER;
-    legacy.sample_rate = legacyBase.sample_rate;
-    legacy.channel_mask = legacyBase.channel_mask;
-    legacy.format = legacyBase.format;
-    legacy.offload_info = VALUE_OR_RETURN(
-            aidl2legacy_AudioOffloadInfo_audio_offload_info_t(aidl.offloadInfo));
-    legacy.frame_count = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.frameCount));
-    return legacy;
-}
-
-ConversionResult<AudioConfig>
-legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput) {
-    const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
-        .channel_mask = legacy.channel_mask, .format = legacy.format };
-    AudioConfig aidl;
-    aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(base, isInput));
-    aidl.offloadInfo = VALUE_OR_RETURN(
-            legacy2aidl_audio_offload_info_t_AudioOffloadInfo(legacy.offload_info));
-    aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.frame_count));
-    return aidl;
-}
-
-ConversionResult<audio_config_base_t>
-aidl2legacy_AudioConfigBase_audio_config_base_t(const AudioConfigBase& aidl, bool isInput) {
-    audio_config_base_t legacy;
-    legacy.sample_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
-    legacy.channel_mask = VALUE_OR_RETURN(
-            aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
-    legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
-    return legacy;
-}
-
-ConversionResult<AudioConfigBase>
-legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput) {
-    AudioConfigBase aidl;
-    aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
-    aidl.channelMask = VALUE_OR_RETURN(
-            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
-    aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
-    return aidl;
-}
-
 ConversionResult<sp<IMemory>>
 aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl) {
     sp<IMemory> legacy;
@@ -2582,8 +732,8 @@
     return aidl;
 }
 
-ConversionResult<sp<IMemory>>
-aidl2legacy_NullableSharedFileRegion_IMemory(const std::optional<media::SharedFileRegion>& aidl) {
+ConversionResult<sp<IMemory>> aidl2legacy_NullableSharedFileRegion_IMemory(
+        const std::optional<media::SharedFileRegion>& aidl) {
     sp<IMemory> legacy;
     if (!convertNullableSharedFileRegionToIMemory(aidl, &legacy)) {
         return unexpected(BAD_VALUE);
@@ -2618,31 +768,6 @@
     return aidl;
 }
 
-ConversionResult<audio_uuid_t>
-aidl2legacy_AudioUuid_audio_uuid_t(const AudioUuid& aidl) {
-    audio_uuid_t legacy;
-    legacy.timeLow = VALUE_OR_RETURN(convertReinterpret<uint32_t>(aidl.timeLow));
-    legacy.timeMid = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeMid));
-    legacy.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeHiAndVersion));
-    legacy.clockSeq = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.clockSeq));
-    if (aidl.node.size() != std::size(legacy.node)) {
-        return unexpected(BAD_VALUE);
-    }
-    std::copy(aidl.node.begin(), aidl.node.end(), legacy.node);
-    return legacy;
-}
-
-ConversionResult<AudioUuid>
-legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy) {
-    AudioUuid aidl;
-    aidl.timeLow = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.timeLow));
-    aidl.timeMid = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeMid));
-    aidl.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeHiAndVersion));
-    aidl.clockSeq = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.clockSeq));
-    std::copy(legacy.node, legacy.node + std::size(legacy.node), std::back_inserter(aidl.node));
-    return aidl;
-}
-
 ConversionResult<effect_descriptor_t>
 aidl2legacy_EffectDescriptor_effect_descriptor_t(const media::EffectDescriptor& aidl) {
     effect_descriptor_t legacy;
@@ -2673,76 +798,34 @@
     return aidl;
 }
 
-ConversionResult<audio_encapsulation_metadata_type_t>
-aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
-        AudioEncapsulationMetadataType aidl) {
-    switch (aidl) {
-        case AudioEncapsulationMetadataType::NONE:
-            return AUDIO_ENCAPSULATION_METADATA_TYPE_NONE;
-        case AudioEncapsulationMetadataType::FRAMEWORK_TUNER:
-            return AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER;
-        case AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR:
-            return AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR;
-    }
-    return unexpected(BAD_VALUE);
+ConversionResult<audio_port_mix_ext>
+aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
+        const AudioPortMixExt& aidl, const media::AudioPortMixExtSys& aidlSys) {
+    audio_port_mix_ext legacy{};
+    legacy.hw_module = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_module_handle_t(aidlSys.hwModule));
+    legacy.handle = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.handle));
+    return legacy;
 }
 
-ConversionResult<AudioEncapsulationMetadataType>
-legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
-        audio_encapsulation_metadata_type_t legacy) {
-    switch (legacy) {
-        case AUDIO_ENCAPSULATION_METADATA_TYPE_NONE:
-            return AudioEncapsulationMetadataType::NONE;
-        case AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER:
-            return AudioEncapsulationMetadataType::FRAMEWORK_TUNER;
-        case AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR:
-            return AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR;
-    }
-    return unexpected(BAD_VALUE);
+status_t
+legacy2aidl_audio_port_mix_ext_AudioPortMixExt(const audio_port_mix_ext& legacy,
+        AudioPortMixExt* aidl, media::AudioPortMixExtSys* aidlMixExt) {
+    aidlMixExt->hwModule = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
+    aidl->handle = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
+    return OK;
 }
 
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl) {
-    return convertBitmask<uint32_t,
-            int32_t,
-            audio_encapsulation_mode_t,
-            AudioEncapsulationMode>(
-            aidl, aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t,
-            indexToEnum_index<AudioEncapsulationMode>,
-            enumToMask_index<uint32_t, audio_encapsulation_mode_t>);
+ConversionResult<audio_port_session_ext>
+aidl2legacy_int32_t_audio_port_session_ext(int32_t aidl) {
+    audio_port_session_ext legacy;
+    legacy.session = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl));
+    return legacy;
 }
 
 ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy) {
-    return convertBitmask<int32_t,
-            uint32_t,
-            AudioEncapsulationMode,
-            audio_encapsulation_mode_t>(
-            legacy, legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode,
-            indexToEnum_index<audio_encapsulation_mode_t>,
-            enumToMask_index<int32_t, AudioEncapsulationMode>);
-}
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl) {
-    return convertBitmask<uint32_t,
-            int32_t,
-            audio_encapsulation_metadata_type_t,
-            AudioEncapsulationMetadataType>(
-            aidl, aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t,
-            indexToEnum_index<AudioEncapsulationMetadataType>,
-            enumToMask_index<uint32_t, audio_encapsulation_metadata_type_t>);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy) {
-    return convertBitmask<int32_t,
-            uint32_t,
-            AudioEncapsulationMetadataType,
-            audio_encapsulation_metadata_type_t>(
-            legacy, legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType,
-            indexToEnum_index<audio_encapsulation_metadata_type_t>,
-            enumToMask_index<int32_t, AudioEncapsulationMetadataType>);
+legacy2aidl_audio_port_session_ext_int32_t(const audio_port_session_ext& legacy) {
+    return legacy2aidl_audio_session_t_int32_t(legacy.session);
 }
 
 ConversionResult<audio_port_device_ext>
@@ -2775,36 +858,6 @@
     return OK;
 }
 
-ConversionResult<audio_port_mix_ext>
-aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
-        const AudioPortMixExt& aidl, const media::AudioPortMixExtSys& aidlSys) {
-    audio_port_mix_ext legacy{};
-    legacy.hw_module = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_module_handle_t(aidlSys.hwModule));
-    legacy.handle = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.handle));
-    return legacy;
-}
-
-status_t
-legacy2aidl_audio_port_mix_ext_AudioPortMixExt(const audio_port_mix_ext& legacy,
-        AudioPortMixExt* aidl, media::AudioPortMixExtSys* aidlMixExt) {
-    aidlMixExt->hwModule = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
-    aidl->handle = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
-    return OK;
-}
-
-ConversionResult<audio_port_session_ext>
-aidl2legacy_int32_t_audio_port_session_ext(int32_t aidl) {
-    audio_port_session_ext legacy;
-    legacy.session = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl));
-    return legacy;
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_port_session_ext_int32_t(const audio_port_session_ext& legacy) {
-    return legacy2aidl_audio_session_t_int32_t(legacy.session);
-}
-
 // This type is unnamed in the original definition, thus we name it here.
 using audio_port_v7_ext = decltype(audio_port_v7::ext);
 
@@ -2876,93 +929,6 @@
     LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
 }
 
-ConversionResult<audio_profile>
-aidl2legacy_AudioProfile_audio_profile(const AudioProfile& aidl, bool isInput) {
-    audio_profile legacy;
-    legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
-
-    if (aidl.sampleRates.size() > std::size(legacy.sample_rates)) {
-        return unexpected(BAD_VALUE);
-    }
-    RETURN_IF_ERROR(
-            convertRange(aidl.sampleRates.begin(), aidl.sampleRates.end(), legacy.sample_rates,
-                         convertIntegral<int32_t, unsigned int>));
-    legacy.num_sample_rates = aidl.sampleRates.size();
-
-    if (aidl.channelMasks.size() > std::size(legacy.channel_masks)) {
-        return unexpected(BAD_VALUE);
-    }
-    RETURN_IF_ERROR(
-            convertRange(aidl.channelMasks.begin(), aidl.channelMasks.end(), legacy.channel_masks,
-                    [isInput](const AudioChannelLayout& l) {
-                        return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
-                    }));
-    legacy.num_channel_masks = aidl.channelMasks.size();
-
-    legacy.encapsulation_type = VALUE_OR_RETURN(
-            aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(aidl.encapsulationType));
-    return legacy;
-}
-
-ConversionResult<AudioProfile>
-legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput) {
-    AudioProfile aidl;
-    aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
-
-    if (legacy.num_sample_rates > std::size(legacy.sample_rates)) {
-        return unexpected(BAD_VALUE);
-    }
-    RETURN_IF_ERROR(
-            convertRange(legacy.sample_rates, legacy.sample_rates + legacy.num_sample_rates,
-                         std::back_inserter(aidl.sampleRates),
-                         convertIntegral<unsigned int, int32_t>));
-
-    if (legacy.num_channel_masks > std::size(legacy.channel_masks)) {
-        return unexpected(BAD_VALUE);
-    }
-    RETURN_IF_ERROR(
-            convertRange(legacy.channel_masks, legacy.channel_masks + legacy.num_channel_masks,
-                         std::back_inserter(aidl.channelMasks),
-                    [isInput](audio_channel_mask_t m) {
-                        return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
-                    }));
-
-    aidl.encapsulationType = VALUE_OR_RETURN(
-            legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
-                    legacy.encapsulation_type));
-    return aidl;
-}
-
-ConversionResult<audio_gain>
-aidl2legacy_AudioGain_audio_gain(const AudioGain& aidl, bool isInput) {
-    audio_gain legacy;
-    legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
-    legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
-                    aidl.channelMask, isInput));
-    legacy.min_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.minValue));
-    legacy.max_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.maxValue));
-    legacy.default_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.defaultValue));
-    legacy.step_value = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.stepValue));
-    legacy.min_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.minRampMs));
-    legacy.max_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.maxRampMs));
-    return legacy;
-}
-
-ConversionResult<AudioGain>
-legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput) {
-    AudioGain aidl;
-    aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
-    aidl.channelMask = VALUE_OR_RETURN(
-            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
-    aidl.minValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_value));
-    aidl.maxValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_value));
-    aidl.defaultValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.default_value));
-    aidl.stepValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.step_value));
-    aidl.minRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_ramp_ms));
-    aidl.maxRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_ramp_ms));
-    return aidl;
-}
-
 ConversionResult<audio_port_v7>
 aidl2legacy_AudioPort_audio_port_v7(const media::AudioPort& aidl) {
     audio_port_v7 legacy;
@@ -3057,58 +1023,6 @@
     return aidl;
 }
 
-ConversionResult<audio_mode_t>
-aidl2legacy_AudioMode_audio_mode_t(AudioMode aidl) {
-    switch (aidl) {
-        case AudioMode::SYS_RESERVED_INVALID:
-            return AUDIO_MODE_INVALID;
-        case AudioMode::SYS_RESERVED_CURRENT:
-            return AUDIO_MODE_CURRENT;
-        case AudioMode::NORMAL:
-            return AUDIO_MODE_NORMAL;
-        case AudioMode::RINGTONE:
-            return AUDIO_MODE_RINGTONE;
-        case AudioMode::IN_CALL:
-            return AUDIO_MODE_IN_CALL;
-        case AudioMode::IN_COMMUNICATION:
-            return AUDIO_MODE_IN_COMMUNICATION;
-        case AudioMode::CALL_SCREEN:
-            return AUDIO_MODE_CALL_SCREEN;
-        case AudioMode::SYS_RESERVED_CALL_REDIRECT:
-            return AUDIO_MODE_CALL_REDIRECT;
-        case AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT:
-            return AUDIO_MODE_COMMUNICATION_REDIRECT;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioMode>
-legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy) {
-    switch (legacy) {
-        case AUDIO_MODE_INVALID:
-            return AudioMode::SYS_RESERVED_INVALID;
-        case AUDIO_MODE_CURRENT:
-            return AudioMode::SYS_RESERVED_CURRENT;
-        case AUDIO_MODE_NORMAL:
-            return AudioMode::NORMAL;
-        case AUDIO_MODE_RINGTONE:
-            return AudioMode::RINGTONE;
-        case AUDIO_MODE_IN_CALL:
-            return AudioMode::IN_CALL;
-        case AUDIO_MODE_IN_COMMUNICATION:
-            return AudioMode::IN_COMMUNICATION;
-        case AUDIO_MODE_CALL_SCREEN:
-            return AudioMode::CALL_SCREEN;
-        case AUDIO_MODE_CALL_REDIRECT:
-            return AudioMode::SYS_RESERVED_CALL_REDIRECT;
-        case AUDIO_MODE_COMMUNICATION_REDIRECT:
-            return AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT;
-        case AUDIO_MODE_CNT:
-            break;
-    }
-    return unexpected(BAD_VALUE);
-}
-
 ConversionResult<audio_unique_id_use_t>
 aidl2legacy_AudioUniqueIdUse_audio_unique_id_use_t(media::AudioUniqueIdUse aidl) {
     switch (aidl) {
@@ -3177,160 +1091,6 @@
     return convertReinterpret<int32_t>(legacy);
 }
 
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl) {
-    switch (aidl) {
-        case media::AudioDualMonoMode::OFF:
-            return AUDIO_DUAL_MONO_MODE_OFF;
-        case media::AudioDualMonoMode::LR:
-            return AUDIO_DUAL_MONO_MODE_LR;
-        case media::AudioDualMonoMode::LL:
-            return AUDIO_DUAL_MONO_MODE_LL;
-        case media::AudioDualMonoMode::RR:
-            return AUDIO_DUAL_MONO_MODE_RR;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
-    switch (legacy) {
-        case AUDIO_DUAL_MONO_MODE_OFF:
-            return media::AudioDualMonoMode::OFF;
-        case AUDIO_DUAL_MONO_MODE_LR:
-            return media::AudioDualMonoMode::LR;
-        case AUDIO_DUAL_MONO_MODE_LL:
-            return media::AudioDualMonoMode::LL;
-        case AUDIO_DUAL_MONO_MODE_RR:
-            return media::AudioDualMonoMode::RR;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl) {
-    return convertReinterpret<audio_timestretch_fallback_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl) {
-    return convertReinterpret<audio_timestretch_stretch_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl) {
-    audio_playback_rate_t legacy;
-    legacy.mSpeed = aidl.speed;
-    legacy.mPitch = aidl.pitch;
-    legacy.mFallbackMode = VALUE_OR_RETURN(
-            aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(aidl.fallbackMode));
-    legacy.mStretchMode = VALUE_OR_RETURN(
-            aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(aidl.stretchMode));
-    return legacy;
-}
-
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
-    media::AudioPlaybackRate aidl;
-    aidl.speed = legacy.mSpeed;
-    aidl.pitch = legacy.mPitch;
-    aidl.fallbackMode = VALUE_OR_RETURN(
-            legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(legacy.mFallbackMode));
-    aidl.stretchMode = VALUE_OR_RETURN(
-            legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(legacy.mStretchMode));
-    return aidl;
-}
-
-ConversionResult<audio_standard_t>
-aidl2legacy_AudioStandard_audio_standard_t(AudioStandard aidl) {
-    switch (aidl) {
-        case AudioStandard::NONE:
-            return AUDIO_STANDARD_NONE;
-        case AudioStandard::EDID:
-            return AUDIO_STANDARD_EDID;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioStandard>
-legacy2aidl_audio_standard_t_AudioStandard(audio_standard_t legacy) {
-    switch (legacy) {
-        case AUDIO_STANDARD_NONE:
-            return AudioStandard::NONE;
-        case AUDIO_STANDARD_EDID:
-            return AudioStandard::EDID;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_extra_audio_descriptor>
-aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
-        const ExtraAudioDescriptor& aidl) {
-    audio_extra_audio_descriptor legacy;
-    legacy.standard = VALUE_OR_RETURN(aidl2legacy_AudioStandard_audio_standard_t(aidl.standard));
-    if (aidl.audioDescriptor.size() > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
-        return unexpected(BAD_VALUE);
-    }
-    legacy.descriptor_length = aidl.audioDescriptor.size();
-    std::copy(aidl.audioDescriptor.begin(), aidl.audioDescriptor.end(),
-              std::begin(legacy.descriptor));
-    legacy.encapsulation_type =
-            VALUE_OR_RETURN(aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
-                    aidl.encapsulationType));
-    return legacy;
-}
-
-ConversionResult<ExtraAudioDescriptor>
-legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
-        const audio_extra_audio_descriptor& legacy) {
-    ExtraAudioDescriptor aidl;
-    aidl.standard = VALUE_OR_RETURN(legacy2aidl_audio_standard_t_AudioStandard(legacy.standard));
-    if (legacy.descriptor_length > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
-        return unexpected(BAD_VALUE);
-    }
-    aidl.audioDescriptor.resize(legacy.descriptor_length);
-    std::copy(legacy.descriptor, legacy.descriptor + legacy.descriptor_length,
-              aidl.audioDescriptor.begin());
-    aidl.encapsulationType =
-            VALUE_OR_RETURN(legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
-                    legacy.encapsulation_type));
-    return aidl;
-}
-
-ConversionResult<audio_encapsulation_type_t>
-aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
-        const AudioEncapsulationType& aidl) {
-    switch (aidl) {
-        case AudioEncapsulationType::NONE:
-            return AUDIO_ENCAPSULATION_TYPE_NONE;
-        case AudioEncapsulationType::IEC61937:
-            return AUDIO_ENCAPSULATION_TYPE_IEC61937;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioEncapsulationType>
-legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
-        const audio_encapsulation_type_t & legacy) {
-    switch (legacy) {
-        case AUDIO_ENCAPSULATION_TYPE_NONE:
-            return AudioEncapsulationType::NONE;
-        case AUDIO_ENCAPSULATION_TYPE_IEC61937:
-            return AudioEncapsulationType::IEC61937;
-    }
-    return unexpected(BAD_VALUE);
-}
-
 ConversionResult<TrackSecondaryOutputInfoPair>
 aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
         const media::TrackSecondaryOutputInfo& aidl) {
@@ -3403,25 +1163,4 @@
             indexToEnum_bitmask<audio_direct_mode_t>,
             enumToMask_index<int32_t, media::AudioDirectMode>);
 }
-
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl) {
-    switch (aidl) {
-        case media::LatencyMode::FREE:
-            return AUDIO_LATENCY_MODE_FREE;
-        case media::LatencyMode::LOW:
-            return AUDIO_LATENCY_MODE_LOW;
-    }
-    return unexpected(BAD_VALUE);
-}
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy) {
-    switch (legacy) {
-        case AUDIO_LATENCY_MODE_FREE:
-            return media::LatencyMode::FREE;
-        case AUDIO_LATENCY_MODE_LOW:
-            return media::LatencyMode::LOW;
-    }
-    return unexpected(BAD_VALUE);
-}
 }  // namespace android
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index e0a8571..d51fedb 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -193,88 +193,29 @@
     },
 }
 
-// This is intended for clients needing to include AidlConversionUtil.h, without dragging in a lot of extra
-// dependencies.
-cc_library_headers {
-    name: "libaudioclient_aidl_conversion_util",
-    host_supported: true,
-    vendor_available: true,
-    double_loadable: true,
-    min_sdk_version: "29",
-    export_include_dirs: [
-        "include",
-    ],
-    header_libs: [
-        "libbase_headers",
-        "liberror_headers",
-    ],
-    export_header_lib_headers: [
-        "libbase_headers",
-        "liberror_headers",
-    ],
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.btservices",
-        "com.android.media",
-        "com.android.media.swcodec",
-    ],
-    target: {
-        darwin: {
-            enabled: false,
-        },
-    },
-}
-
 cc_library {
     name: "libaudioclient_aidl_conversion",
     srcs: ["AidlConversion.cpp"],
-    export_include_dirs: ["include"],
-    host_supported: true,
-    vendor_available: true,
-    double_loadable: true,
-    min_sdk_version: "29",
-    header_libs: [
-        "libaudioclient_aidl_conversion_util",
-        "libaudio_system_headers",
-    ],
-    export_header_lib_headers: [
-        "libaudioclient_aidl_conversion_util",
-    ],
-    defaults: [
-        "latest_android_media_audio_common_types_cpp_export_shared",
-    ],
     shared_libs: [
         "audioclient-types-aidl-cpp",
-        "libbase",
-        "libbinder",
-        "liblog",
-        "libshmemcompat",
-        "libstagefright_foundation",
-        "libutils",
-        "shared-file-region-aidl-cpp",
-        "framework-permission-aidl-cpp",
+    ],
+    static_libs: [
+        "libaudio_aidl_conversion_common_cpp",
+    ],
+    export_include_dirs: ["include"],
+    header_libs: [
+        "libaudio_aidl_conversion_common_util_cpp",
+    ],
+    export_header_lib_headers: [
+        "libaudio_aidl_conversion_common_util_cpp",
     ],
     export_shared_lib_headers: [
         "audioclient-types-aidl-cpp",
-        "libbase",
-        "shared-file-region-aidl-cpp",
     ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wno-error=deprecated-declarations",
+    defaults: [
+        "audio_aidl_conversion_common_default",
+        "latest_android_media_audio_common_types_cpp_export_shared",
     ],
-    sanitize: {
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-    },
-    target: {
-        darwin: {
-            enabled: false,
-        },
-    },
 }
 
 // AIDL interface between libaudioclient and framework.jar
@@ -340,14 +281,12 @@
         "aidl/android/media/AudioAttributesInternal.aidl",
         "aidl/android/media/AudioClient.aidl",
         "aidl/android/media/AudioDirectMode.aidl",
-        "aidl/android/media/AudioDualMonoMode.aidl",
         "aidl/android/media/AudioFlag.aidl",
         "aidl/android/media/AudioGainSys.aidl",
         "aidl/android/media/AudioHalVersion.aidl",
         "aidl/android/media/AudioIoConfigEvent.aidl",
         "aidl/android/media/AudioIoDescriptor.aidl",
         "aidl/android/media/AudioPatch.aidl",
-        "aidl/android/media/AudioPlaybackRate.aidl",
         "aidl/android/media/AudioPort.aidl",
         "aidl/android/media/AudioPortSys.aidl",
         "aidl/android/media/AudioPortConfig.aidl",
@@ -362,7 +301,6 @@
         "aidl/android/media/AudioUniqueIdUse.aidl",
         "aidl/android/media/AudioVibratorInfo.aidl",
         "aidl/android/media/EffectDescriptor.aidl",
-        "aidl/android/media/LatencyMode.aidl",
         "aidl/android/media/TrackSecondaryOutputInfo.aidl",
     ],
     imports: [
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 141e1e3..2bbafa7 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -671,12 +671,12 @@
 }
 
 Status AudioSystem::AudioFlingerClient::onSupportedLatencyModesChanged(
-        int output, const std::vector<media::LatencyMode>& latencyModes) {
+        int output, const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) {
     audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_io_handle_t(output));
     std::vector<audio_latency_mode_t> modesLegacy = VALUE_OR_RETURN_BINDER_STATUS(
             convertContainer<std::vector<audio_latency_mode_t>>(
-                    latencyModes, aidl2legacy_LatencyMode_audio_latency_mode_t));
+                    latencyModes, aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
 
     std::vector<sp<SupportedLatencyModesCallback>> callbacks;
     {
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 96fc544..ff4b071 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1248,7 +1248,7 @@
 status_t AudioTrack::getDualMonoMode(audio_dual_mono_mode_t* mode) const
 {
     AutoMutex lock(mLock);
-    media::AudioDualMonoMode mediaMode;
+    media::audio::common::AudioDualMonoMode mediaMode;
     const status_t status = statusTFromBinderStatus(mAudioTrack->getDualMonoMode(&mediaMode));
     if (status == NO_ERROR) {
         *mode = VALUE_OR_RETURN_STATUS(
@@ -1363,7 +1363,7 @@
 {
     AutoMutex lock(mLock);
     if (isOffloadedOrDirect_l()) {
-        media::AudioPlaybackRate playbackRateTemp;
+        media::audio::common::AudioPlaybackRate playbackRateTemp;
         const status_t status = statusTFromBinderStatus(
                 mAudioTrack->getPlaybackRateParameters(&playbackRateTemp));
         if (status == NO_ERROR) { // update local version if changed.
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 6ad97d1..3dd1913 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -22,10 +22,10 @@
 
 #include <stdint.h>
 #include <sys/types.h>
-
+#include "IAudioFlinger.h"
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
-#include "IAudioFlinger.h"
+#include <system/thread_defs.h>
 
 namespace android {
 
@@ -813,8 +813,8 @@
 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));
-    media::LatencyMode modeAidl  = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_latency_mode_t_LatencyMode(mode));
+    media::audio::common::AudioLatencyMode modeAidl  = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode));
     return statusTFromBinderStatus(mDelegate->setRequestedLatencyMode(outputAidl, modeAidl));
 }
 
@@ -825,14 +825,14 @@
     }
 
     int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
-    std::vector<media::LatencyMode> modesAidl;
+    std::vector<media::audio::common::AudioLatencyMode> modesAidl;
 
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
             mDelegate->getSupportedLatencyModes(outputAidl, &modesAidl)));
 
     *modes = VALUE_OR_RETURN_STATUS(
             convertContainer<std::vector<audio_latency_mode_t>>(modesAidl,
-                     aidl2legacy_LatencyMode_audio_latency_mode_t));
+                     aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
 
     return NO_ERROR;
 }
@@ -840,7 +840,9 @@
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // AudioFlingerServerAdapter
 AudioFlingerServerAdapter::AudioFlingerServerAdapter(
-        const sp<AudioFlingerServerAdapter::Delegate>& delegate) : mDelegate(delegate) {}
+        const sp<AudioFlingerServerAdapter::Delegate>& delegate) : mDelegate(delegate) {
+    setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+}
 
 status_t AudioFlingerServerAdapter::onTransact(uint32_t code,
                                                const Parcel& data,
@@ -1332,17 +1334,17 @@
 }
 
 Status AudioFlingerServerAdapter::setRequestedLatencyMode(
-        int32_t output, media::LatencyMode modeAidl) {
+        int32_t output, media::audio::common::AudioLatencyMode modeAidl) {
     audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
             aidl2legacy_int32_t_audio_io_handle_t(output));
     audio_latency_mode_t modeLegacy = VALUE_OR_RETURN_BINDER(
-            aidl2legacy_LatencyMode_audio_latency_mode_t(modeAidl));
+            aidl2legacy_AudioLatencyMode_audio_latency_mode_t(modeAidl));
     return Status::fromStatusT(mDelegate->setRequestedLatencyMode(
             outputLegacy, modeLegacy));
 }
 
 Status AudioFlingerServerAdapter::getSupportedLatencyModes(
-        int output, std::vector<media::LatencyMode>* _aidl_return) {
+        int output, std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) {
     audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
             aidl2legacy_int32_t_audio_io_handle_t(output));
     std::vector<audio_latency_mode_t> modesLegacy;
@@ -1350,8 +1352,8 @@
     RETURN_BINDER_IF_ERROR(mDelegate->getSupportedLatencyModes(outputLegacy, &modesLegacy));
 
     *_aidl_return = VALUE_OR_RETURN_BINDER(
-            convertContainer<std::vector<media::LatencyMode>>(
-                    modesLegacy, legacy2aidl_audio_latency_mode_t_LatencyMode));
+            convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+                    modesLegacy, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
     return Status::ok();
 }
 
diff --git a/media/libaudioclient/TEST_MAPPING b/media/libaudioclient/TEST_MAPPING
index 51080ef..10f9d9b 100644
--- a/media/libaudioclient/TEST_MAPPING
+++ b/media/libaudioclient/TEST_MAPPING
@@ -32,5 +32,10 @@
     {
       "name": "audiosystem_tests"
     }
+  ],
+  "postsubmit": [
+    {
+       "name": "audioeffect_analysis"
+    }
   ]
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl b/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
deleted file mode 100644
index f6220c2..0000000
--- a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-// TODO(b/175167149): Reconcile AudioDualMonoMode with framework-media-sources
-
-@Backing(type="int")
-enum AudioDualMonoMode {
-    OFF = 0,
-    LR = 1,
-    LL = 2,
-    RR = 3,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl b/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
deleted file mode 100644
index e29d398..0000000
--- a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/**
- * The AudioPlaybackRate.
- *
- * See https://developer.android.com/reference/android/media/PlaybackParams.
- * TODO(b/175166815): Reconcile with framework-media-sources PlaybackParams.aidl.
- *       As this is used for native wire serialization, no need to define
- *       audio_timestretch_stretch_mode_t and audio_timestretch_fallback_mode_t enums
- *       until we attempt to unify with PlaybackParams.
- *
- * {@hide}
- */
-parcelable AudioPlaybackRate {
-    /** Speed of audio playback, >= 0.f, 1.f nominal (system limits are further restrictive) */
-    float speed;
-    /** Pitch of audio, >= 0.f, 1.f nominal (system limits are further restrictive) */
-    float pitch;
-    /** Interpreted as audio_timestretch_stretch_mode_t */
-    int stretchMode;
-    /** Interpreted as audio_timestretch_fallback_mode_t */
-    int fallbackMode;
-}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
index a2bb024..f055cc4 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
@@ -18,7 +18,7 @@
 
 import android.media.AudioIoConfigEvent;
 import android.media.AudioIoDescriptor;
-import android.media.LatencyMode;
+import android.media.audio.common.AudioLatencyMode;
 
 /**
  * A callback interface for AudioFlinger.
@@ -31,7 +31,8 @@
     /**
      * Called when the latency modes supported on a given output stream change.
      * output is the I/O handle of the output stream for which the change is signalled.
-     * latencyModes is the new list of supported latency modes (See LatencyMode.aidl).
+     * latencyModes is the new list of supported latency modes (See AudioLatencyMode.aidl).
      */
-    oneway void onSupportedLatencyModesChanged(int output, in LatencyMode[] latencyModes);
+    oneway void onSupportedLatencyModesChanged(
+            int output, in AudioLatencyMode[] latencyModes);
 }
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 9b8a843..e19198b 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -35,12 +35,12 @@
 import android.media.IAudioFlingerClient;
 import android.media.IAudioRecord;
 import android.media.IAudioTrack;
-import android.media.LatencyMode;
 import android.media.MicrophoneInfoData;
 import android.media.RenderPosition;
 import android.media.TrackSecondaryOutputInfo;
 import android.media.audio.common.AudioChannelLayout;
 import android.media.audio.common.AudioFormatDescription;
+import android.media.audio.common.AudioLatencyMode;
 import android.media.audio.common.AudioMMapPolicyInfo;
 import android.media.audio.common.AudioMMapPolicyType;
 import android.media.audio.common.AudioMode;
@@ -230,21 +230,21 @@
     void setDeviceConnectedState(in AudioPort devicePort, boolean connected);
 
     /**
-     * Requests a given latency mode (See LatencyMode.aidl) on an output stream.
+     * 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
      * if a specific latency mode is selected on the audio path below the HAL.
      * For instance spatial audio with head tracking.
      * output is the I/O handle of the output stream for which the request is made.
      * latencyMode is the requested latency mode.
      */
-     void setRequestedLatencyMode(int output, LatencyMode latencyMode);
+     void setRequestedLatencyMode(int output, AudioLatencyMode latencyMode);
 
     /**
      * Queries the list of latency modes (See LatencyMode.aidl) supported by an output stream.
      * output is the I/O handle of the output stream to which the query applies.
      * returns the list of supported latency modes.
      */
-    LatencyMode[] getSupportedLatencyModes(int output);
+    AudioLatencyMode[] getSupportedLatencyModes(int output);
 
     // When adding a new method, please review and update
     // IAudioFlinger.h AudioFlingerServerAdapter::Delegate::TransactionCode
diff --git a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
index ac58925..c3a2dbe 100644
--- a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
@@ -16,13 +16,13 @@
 
 package android.media;
 
-import android.media.AudioDualMonoMode;
-import android.media.AudioPlaybackRate;
 import android.media.AudioTimestampInternal;
 import android.media.SharedFileRegion;
 import android.media.VolumeShaperConfiguration;
 import android.media.VolumeShaperOperation;
 import android.media.VolumeShaperState;
+import android.media.audio.common.AudioDualMonoMode;
+import android.media.audio.common.AudioPlaybackRate;
 
 /**
  * Unless otherwise noted, methods returning int expect it to be interpreted as a status_t.
diff --git a/media/libaudioclient/aidl/android/media/LatencyMode.aidl b/media/libaudioclient/aidl/android/media/LatencyMode.aidl
deleted file mode 100644
index 0b2a72b..0000000
--- a/media/libaudioclient/aidl/android/media/LatencyMode.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 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.
- */
-
-package android.media;
-
-/**
- * The latency mode currently used by the spatializer mixer.
- * {@hide}
- */
-@Backing(type="byte")
-enum LatencyMode {
-    /** No specific constraint on the latency */
-    FREE = 0,
-    /** A relatively low latency compatible with head tracking operation (e.g less than 100ms) */
-    LOW = 1,
-}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 1e66164..b0f84a4 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -24,46 +24,20 @@
 #include <android/media/AudioAttributesInternal.h>
 #include <android/media/AudioClient.h>
 #include <android/media/AudioDirectMode.h>
-#include <android/media/AudioDualMonoMode.h>
 #include <android/media/AudioFlag.h>
 #include <android/media/AudioIoConfigEvent.h>
 #include <android/media/AudioIoDescriptor.h>
-#include <android/media/AudioPlaybackRate.h>
 #include <android/media/AudioPort.h>
 #include <android/media/AudioPortConfig.h>
 #include <android/media/AudioPortDeviceExtSys.h>
 #include <android/media/AudioTimestampInternal.h>
 #include <android/media/AudioUniqueIdUse.h>
 #include <android/media/EffectDescriptor.h>
-#include <android/media/LatencyMode.h>
 #include <android/media/TrackSecondaryOutputInfo.h>
-#include <android/media/audio/common/AudioChannelLayout.h>
-#include <android/media/audio/common/AudioConfig.h>
-#include <android/media/audio/common/AudioConfigBase.h>
-#include <android/media/audio/common/AudioContentType.h>
-#include <android/media/audio/common/AudioDeviceDescription.h>
-#include <android/media/audio/common/AudioEncapsulationMetadataType.h>
-#include <android/media/audio/common/AudioEncapsulationMode.h>
-#include <android/media/audio/common/AudioEncapsulationType.h>
-#include <android/media/audio/common/AudioFormatDescription.h>
-#include <android/media/audio/common/AudioGain.h>
-#include <android/media/audio/common/AudioGainConfig.h>
-#include <android/media/audio/common/AudioGainMode.h>
-#include <android/media/audio/common/AudioInputFlags.h>
-#include <android/media/audio/common/AudioMode.h>
-#include <android/media/audio/common/AudioOffloadInfo.h>
-#include <android/media/audio/common/AudioOutputFlags.h>
-#include <android/media/audio/common/AudioPortExt.h>
-#include <android/media/audio/common/AudioPortMixExt.h>
-#include <android/media/audio/common/AudioProfile.h>
-#include <android/media/audio/common/AudioSource.h>
-#include <android/media/audio/common/AudioStandard.h>
-#include <android/media/audio/common/AudioUsage.h>
-#include <android/media/audio/common/AudioUuid.h>
-#include <android/media/audio/common/ExtraAudioDescriptor.h>
 
 #include <android/media/SharedFileRegion.h>
 #include <binder/IMemory.h>
+#include <media/AidlConversionCppNdk.h>
 #include <media/AidlConversionUtil.h>
 #include <media/AudioClient.h>
 #include <media/AudioCommonTypes.h>
@@ -73,49 +47,6 @@
 
 namespace android {
 
-// maxSize is the size of the C-string buffer (including the 0-terminator), NOT the max length of
-// the string.
-status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize);
-ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize);
-
-ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy);
-
-ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy);
-
-ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy);
-
-ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy);
-
-ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy);
-
-ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy);
-
-ConversionResult<unsigned int> aidl2legacy_int32_t_config_mask(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_config_mask_int32_t(unsigned int legacy);
-
-ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy);
-
-ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy);
-
-ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl);
-ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy);
-
-ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl);
-ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy);
-
-ConversionResult<std::optional<String16>>
-aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl);
-ConversionResult<std::optional<std::string_view>>
-legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy);
-
 ConversionResult<audio_io_config_event_t> aidl2legacy_AudioIoConfigEvent_audio_io_config_event_t(
         media::AudioIoConfigEvent aidl);
 ConversionResult<media::AudioIoConfigEvent> legacy2aidl_audio_io_config_event_t_AudioIoConfigEvent(
@@ -131,75 +62,6 @@
 ConversionResult<media::AudioPortType> legacy2aidl_audio_port_type_t_AudioPortType(
         audio_port_type_t legacy);
 
-ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
-        const media::audio::common::AudioChannelLayout& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioChannelLayout>
-legacy2aidl_audio_channel_mask_t_AudioChannelLayout(audio_channel_mask_t legacy, bool isInput);
-
-ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
-        const media::audio::common::AudioDeviceDescription& aidl);
-ConversionResult<media::audio::common::AudioDeviceDescription>
-legacy2aidl_audio_devices_t_AudioDeviceDescription(audio_devices_t legacy);
-
-status_t aidl2legacy_AudioDevice_audio_device(
-        const media::audio::common::AudioDevice& aidl,
-        audio_devices_t* legacyType, char* legacyAddress);
-status_t aidl2legacy_AudioDevice_audio_device(
-        const media::audio::common::AudioDevice& aidl,
-        audio_devices_t* legacyType, String8* legacyAddress);
-status_t aidl2legacy_AudioDevice_audio_device(
-        const media::audio::common::AudioDevice& aidl,
-        audio_devices_t* legacyType, std::string* legacyAddress);
-ConversionResult<media::audio::common::AudioDevice>
-legacy2aidl_audio_device_AudioDevice(
-        audio_devices_t legacyType, const char* legacyAddress);
-ConversionResult<media::audio::common::AudioDevice>
-legacy2aidl_audio_device_AudioDevice(
-        audio_devices_t legacyType, const String8& legacyAddress);
-
-ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
-        const media::audio::common::AudioFormatDescription& aidl);
-ConversionResult<media::audio::common::AudioFormatDescription>
-legacy2aidl_audio_format_t_AudioFormatDescription(audio_format_t legacy);
-
-ConversionResult<audio_gain_mode_t>
-aidl2legacy_AudioGainMode_audio_gain_mode_t(media::audio::common::AudioGainMode aidl);
-ConversionResult<media::audio::common::AudioGainMode>
-legacy2aidl_audio_gain_mode_t_AudioGainMode(audio_gain_mode_t legacy);
-
-ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy);
-
-ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
-        const media::audio::common::AudioGainConfig& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioGainConfig>
-legacy2aidl_audio_gain_config_AudioGainConfig(const audio_gain_config& legacy, bool isInput);
-
-ConversionResult<audio_input_flags_t>
-aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
-ConversionResult<media::audio::common::AudioInputFlags>
-legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
-
-ConversionResult<audio_output_flags_t>
-aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
-ConversionResult<media::audio::common::AudioOutputFlags>
-legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
-
-ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
-        int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
-        audio_input_flags_t legacy);
-
-ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
-        int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
-        audio_output_flags_t legacy);
-
-ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
-        const media::audio::common::AudioIoFlags& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
-        const audio_io_flags& legacy, bool isInput);
-
 ConversionResult<audio_port_config_device_ext>
 aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
         const media::audio::common::AudioPortDeviceExt& aidl,
@@ -214,15 +76,6 @@
 ConversionResult<media::audio::common::AudioStreamType>
 legacy2aidl_audio_stream_type_t_AudioStreamType(audio_stream_type_t legacy);
 
-ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
-        media::audio::common::AudioSource aidl);
-ConversionResult<media::audio::common::AudioSource>
-        legacy2aidl_audio_source_t_AudioSource(
-        audio_source_t legacy);
-
-ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy);
-
 ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortMixExt(
         const media::audio::common::AudioPortMixExt& aidl, media::AudioPortRole role,
         const media::AudioPortMixExtSys& aidlMixExt);
@@ -255,17 +108,6 @@
 ConversionResult<media::AudioClient> legacy2aidl_AudioClient_AudioClient(
         const AudioClient& legacy);
 
-ConversionResult<audio_content_type_t>
-aidl2legacy_AudioContentType_audio_content_type_t(
-        media::audio::common::AudioContentType aidl);
-ConversionResult<media::audio::common::AudioContentType>
-legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy);
-
-ConversionResult<audio_usage_t>
-aidl2legacy_AudioUsage_audio_usage_t(media::audio::common::AudioUsage aidl);
-ConversionResult<media::audio::common::AudioUsage>
-legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy);
-
 ConversionResult<audio_flags_mask_t>
 aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl);
 ConversionResult<media::AudioFlag>
@@ -281,36 +123,13 @@
 ConversionResult<media::AudioAttributesInternal>
 legacy2aidl_audio_attributes_t_AudioAttributesInternal(const audio_attributes_t& legacy);
 
-ConversionResult<audio_encapsulation_mode_t>
-aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(
-        media::audio::common::AudioEncapsulationMode aidl);
-ConversionResult<media::audio::common::AudioEncapsulationMode>
-legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy);
-
-ConversionResult<audio_offload_info_t>
-aidl2legacy_AudioOffloadInfo_audio_offload_info_t(
-        const media::audio::common::AudioOffloadInfo& aidl);
-ConversionResult<media::audio::common::AudioOffloadInfo>
-legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy);
-
-ConversionResult<audio_config_t>
-aidl2legacy_AudioConfig_audio_config_t(const media::audio::common::AudioConfig& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioConfig>
-legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput);
-
-ConversionResult<audio_config_base_t>
-aidl2legacy_AudioConfigBase_audio_config_base_t(
-        const media::audio::common::AudioConfigBase& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioConfigBase>
-legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput);
-
 ConversionResult<sp<IMemory>>
 aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl);
 ConversionResult<media::SharedFileRegion>
 legacy2aidl_IMemory_SharedFileRegion(const sp<IMemory>& legacy);
 
-ConversionResult<sp<IMemory>>
-aidl2legacy_NullableSharedFileRegion_IMemory(const std::optional<media::SharedFileRegion>& aidl);
+ConversionResult<sp<::android::IMemory>> aidl2legacy_NullableSharedFileRegion_IMemory(
+        const std::optional<media::SharedFileRegion>& aidl);
 ConversionResult<std::optional<media::SharedFileRegion>>
 legacy2aidl_NullableIMemory_SharedFileRegion(const sp<IMemory>& legacy);
 
@@ -319,32 +138,10 @@
 ConversionResult<media::AudioTimestampInternal>
 legacy2aidl_AudioTimestamp_AudioTimestampInternal(const AudioTimestamp& legacy);
 
-ConversionResult<audio_uuid_t>
-aidl2legacy_AudioUuid_audio_uuid_t(const media::audio::common::AudioUuid& aidl);
-ConversionResult<media::audio::common::AudioUuid>
-legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy);
-
 ConversionResult<effect_descriptor_t>
 aidl2legacy_EffectDescriptor_effect_descriptor_t(const media::EffectDescriptor& aidl);
-ConversionResult<media::EffectDescriptor>
-legacy2aidl_effect_descriptor_t_EffectDescriptor(const effect_descriptor_t& legacy);
-
-ConversionResult<audio_encapsulation_metadata_type_t>
-aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
-        media::audio::common::AudioEncapsulationMetadataType aidl);
-ConversionResult<media::audio::common::AudioEncapsulationMetadataType>
-legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
-        audio_encapsulation_metadata_type_t legacy);
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy);
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy);
+ConversionResult<media::EffectDescriptor> legacy2aidl_effect_descriptor_t_EffectDescriptor(
+        const effect_descriptor_t& legacy);
 
 ConversionResult<audio_port_device_ext>
 aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
@@ -369,27 +166,11 @@
 ConversionResult<int32_t>
 legacy2aidl_audio_port_session_ext_int32_t(const audio_port_session_ext& legacy);
 
-ConversionResult<audio_profile>
-aidl2legacy_AudioProfile_audio_profile(
-        const media::audio::common::AudioProfile& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioProfile>
-legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput);
-
-ConversionResult<audio_gain>
-aidl2legacy_AudioGain_audio_gain(const media::audio::common::AudioGain& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioGain>
-legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput);
-
 ConversionResult<audio_port_v7>
 aidl2legacy_AudioPort_audio_port_v7(const media::AudioPort& aidl);
 ConversionResult<media::AudioPort>
 legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy);
 
-ConversionResult<audio_mode_t>
-aidl2legacy_AudioMode_audio_mode_t(media::audio::common::AudioMode aidl);
-ConversionResult<media::audio::common::AudioMode>
-legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy);
-
 ConversionResult<audio_unique_id_use_t>
 aidl2legacy_AudioUniqueIdUse_audio_unique_id_use_t(media::AudioUniqueIdUse aidl);
 ConversionResult<media::AudioUniqueIdUse>
@@ -400,45 +181,6 @@
 ConversionResult<int32_t>
 legacy2aidl_volume_group_t_int32_t(volume_group_t legacy);
 
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl);
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy);
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy);
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl);
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
-
-ConversionResult<audio_standard_t>
-aidl2legacy_AudioStandard_audio_standard_t(media::audio::common::AudioStandard aidl);
-ConversionResult<media::audio::common::AudioStandard>
-legacy2aidl_audio_standard_t_AudioStandard(audio_standard_t legacy);
-
-ConversionResult<audio_extra_audio_descriptor>
-aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
-        const media::audio::common::ExtraAudioDescriptor& aidl);
-ConversionResult<media::audio::common::ExtraAudioDescriptor>
-legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
-        const audio_extra_audio_descriptor& legacy);
-
-ConversionResult<audio_encapsulation_type_t>
-aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
-        const media::audio::common::AudioEncapsulationType& aidl);
-ConversionResult<media::audio::common::AudioEncapsulationType>
-legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
-        const audio_encapsulation_type_t & legacy);
-
 using TrackSecondaryOutputInfoPair = std::pair<audio_port_handle_t, std::vector<audio_io_handle_t>>;
 ConversionResult<TrackSecondaryOutputInfoPair>
 aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
@@ -455,9 +197,4 @@
 ConversionResult<audio_direct_mode_t> aidl2legacy_int32_t_audio_direct_mode_t_mask(int32_t aidl);
 ConversionResult<int32_t> legacy2aidl_audio_direct_mode_t_int32_t_mask(audio_direct_mode_t legacy);
 
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl);
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy);
-
 }  // namespace android
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 9411f46..beb9a77 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -705,7 +705,8 @@
                 const media::AudioIoDescriptor& ioDesc) override;
 
         binder::Status onSupportedLatencyModesChanged(
-                int output, const std::vector<media::LatencyMode>& latencyModes) override;
+                int output,
+                const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) override;
 
         status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
                                                audio_io_handle_t audioIo,
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index c891ae6..71f724d 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -685,9 +685,10 @@
     Status getAAudioMixerBurstCount(int32_t* _aidl_return) override;
     Status getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
     Status setDeviceConnectedState(const media::AudioPort& port, bool connected) override;
-    Status setRequestedLatencyMode(int output, media::LatencyMode mode) override;
+    Status setRequestedLatencyMode(
+            int output, media::audio::common::AudioLatencyMode mode) override;
     Status getSupportedLatencyModes(int output,
-            std::vector<media::LatencyMode>* _aidl_return) override;
+            std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) override;
 private:
     const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
 };
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index 1b09173..cbcef12 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -36,8 +36,9 @@
         "libutils",
     ],
     static_libs: [
-        "audioclient-types-aidl-cpp",
         "libaudioclient_aidl_conversion",
+        "libaudio_aidl_conversion_common_cpp",
+        "audioclient-types-aidl-cpp",
         "libstagefright_foundation",
     ],
 }
@@ -108,6 +109,7 @@
     shared_libs: [
         "capture_state_listener-aidl-cpp",
         "framework-permission-aidl-cpp",
+        "libaudioclient_aidl_conversion",
         "libbase",
         "libbinder",
         "libcgrouprc",
@@ -137,7 +139,6 @@
         "av-types-aidl-cpp",
         "effect-aidl-cpp",
         "libaudioclient",
-        "libaudioclient_aidl_conversion",
         "libaudiofoundation",
         "libaudiomanager",
         "libaudiopolicy",
@@ -176,6 +177,22 @@
 }
 
 cc_test {
+    name: "audioeffect_analysis",
+    defaults: ["libaudioclient_gtests_defaults"],
+    // flag needed for pfft/pffft.hpp
+    cflags: [
+        "-Wno-error=unused-parameter",
+    ],
+    srcs: [
+        "audioeffect_analyser.cpp",
+        "audio_test_utils.cpp",
+    ],
+    static_libs: [
+        "libpffft",
+    ],
+}
+
+cc_test {
     name: "audiorouting_tests",
     defaults: ["libaudioclient_gtests_defaults"],
     srcs: [
diff --git a/media/libaudioclient/tests/audio_test_utils.cpp b/media/libaudioclient/tests/audio_test_utils.cpp
index 850eb34..1e26ff6 100644
--- a/media/libaudioclient/tests/audio_test_utils.cpp
+++ b/media/libaudioclient/tests/audio_test_utils.cpp
@@ -17,11 +17,15 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "AudioTestUtils"
 
+#include <android-base/file.h>
 #include <system/audio_config.h>
 #include <utils/Log.h>
 
 #include "audio_test_utils.h"
 
+#define WAIT_PERIOD_MS 10  // from AudioTrack.cpp
+#define MAX_WAIT_TIME_MS 5000
+
 template <class T>
 constexpr void (*xmlDeleter)(T* t);
 template <>
@@ -37,12 +41,6 @@
     return std::unique_ptr<T, decltype(deleter)>{t, deleter};
 }
 
-// Generates a random string.
-void CreateRandomFile(int& fd) {
-    std::string filename = "/data/local/tmp/record-XXXXXX";
-    fd = mkstemp(filename.data());
-}
-
 void OnAudioDeviceUpdateNotifier::onAudioDeviceUpdate(audio_io_handle_t audioIo,
                                                       audio_port_handle_t deviceId) {
     std::unique_lock<std::mutex> lock{mMutex};
@@ -52,11 +50,14 @@
     mCondition.notify_all();
 }
 
-status_t OnAudioDeviceUpdateNotifier::waitForAudioDeviceCb() {
+status_t OnAudioDeviceUpdateNotifier::waitForAudioDeviceCb(audio_port_handle_t expDeviceId) {
     std::unique_lock<std::mutex> lock{mMutex};
-    if (mAudioIo == AUDIO_IO_HANDLE_NONE) {
+    if (mAudioIo == AUDIO_IO_HANDLE_NONE ||
+        (expDeviceId != AUDIO_PORT_HANDLE_NONE && expDeviceId != mDeviceId)) {
         mCondition.wait_for(lock, std::chrono::milliseconds(500));
-        if (mAudioIo == AUDIO_IO_HANDLE_NONE) return TIMED_OUT;
+        if (mAudioIo == AUDIO_IO_HANDLE_NONE ||
+            (expDeviceId != AUDIO_PORT_HANDLE_NONE && expDeviceId != mDeviceId))
+            return TIMED_OUT;
     }
     return OK;
 }
@@ -167,15 +168,16 @@
 }
 
 status_t AudioPlayback::fillBuffer() {
-    if (PLAY_STARTED != mState && PLAY_STOPPED != mState) return INVALID_OPERATION;
-    int retry = 25;
+    if (PLAY_STARTED != mState) return INVALID_OPERATION;
+    const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+    int counter = 0;
     uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mMemory->unsecurePointer()));
     size_t nonContig = 0;
     size_t bytesAvailable = mMemCapacity - mBytesUsedSoFar;
     while (bytesAvailable > 0) {
         AudioTrack::Buffer trackBuffer;
         trackBuffer.frameCount = mTrack->frameCount() * 2;
-        status_t status = mTrack->obtainBuffer(&trackBuffer, retry, &nonContig);
+        status_t status = mTrack->obtainBuffer(&trackBuffer, 1, &nonContig);
         if (OK == status) {
             size_t bytesToCopy = std::min(bytesAvailable, trackBuffer.size());
             if (bytesToCopy > 0) {
@@ -184,14 +186,11 @@
             mTrack->releaseBuffer(&trackBuffer);
             mBytesUsedSoFar += bytesToCopy;
             bytesAvailable = mMemCapacity - mBytesUsedSoFar;
-            if (bytesAvailable == 0) {
-                stop();
-            }
+            counter = 0;
         } else if (WOULD_BLOCK == status) {
-            if (mStopPlaying)
-                return OK;
-            else
-                return TIMED_OUT;
+            // if not received a buffer for MAX_WAIT_TIME_MS, something has gone wrong
+            if (counter == maxTries) return TIMED_OUT;
+            counter++;
         }
     }
     return OK;
@@ -199,14 +198,15 @@
 
 status_t AudioPlayback::waitForConsumption(bool testSeek) {
     if (PLAY_STARTED != mState) return INVALID_OPERATION;
-    // in static buffer mode, lets not play clips with duration > 30 sec
-    int retry = 300;
-    // Total number of frames in the input file.
+
+    const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+    int counter = 0;
     size_t totalFrameCount = mMemCapacity / mTrack->frameSize();
-    while (!mStopPlaying && retry > 0) {
-        // Get the total numbers of frames played.
+    while (!mStopPlaying && counter < maxTries) {
         uint32_t currPosition;
         mTrack->getPosition(&currPosition);
+        if (currPosition >= totalFrameCount) counter++;
+
         if (testSeek && (currPosition > totalFrameCount * 0.6)) {
             testSeek = false;
             if (!mTrack->hasStarted()) return BAD_VALUE;
@@ -227,10 +227,9 @@
             if (bufferPosition != setPosition) return BAD_VALUE;
             mTrack->start();
         }
-        std::this_thread::sleep_for(std::chrono::milliseconds(100));
-        retry--;
+        std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_PERIOD_MS));
     }
-    if (!mStopPlaying) return TIMED_OUT;
+    if (!mStopPlaying && counter == maxTries) return TIMED_OUT;
     return OK;
 }
 
@@ -246,7 +245,7 @@
 void AudioPlayback::stop() {
     std::unique_lock<std::mutex> lock{mMutex};
     mStopPlaying = true;
-    if (mState != PLAY_STOPPED) {
+    if (mState != PLAY_STOPPED && mState != PLAY_NO_INIT) {
         int32_t msec = 0;
         (void)mTrack->pendingDuration(&msec);
         mTrack->stopAndJoinCallbacks();
@@ -274,7 +273,7 @@
     }
 
     // no more frames to read
-    if (mNumFramesReceived > mNumFramesToRecord || mStopRecording) {
+    if (mNumFramesReceived >= mNumFramesToRecord || mStopRecording) {
         mStopRecording = true;
         return 0;
     }
@@ -369,14 +368,16 @@
 
 AudioCapture::AudioCapture(audio_source_t inputSource, uint32_t sampleRate, audio_format_t format,
                            audio_channel_mask_t channelMask, audio_input_flags_t flags,
-                           audio_session_t sessionId, AudioRecord::transfer_type transferType)
+                           audio_session_t sessionId, AudioRecord::transfer_type transferType,
+                           const audio_attributes_t* attributes)
     : mInputSource(inputSource),
       mSampleRate(sampleRate),
       mFormat(format),
       mChannelMask(channelMask),
       mFlags(flags),
       mSessionId(sessionId),
-      mTransferType(transferType) {
+      mTransferType(transferType),
+      mAttributes(attributes) {
     mFrameCount = 0;
     mNotificationFrames = 0;
     mNumFramesToRecord = 0;
@@ -389,9 +390,6 @@
     mReceivedCbMarkerCount = 0;
     mState = REC_NO_INIT;
     mStopRecording = false;
-#if RECORD_TO_FILE
-    CreateRandomFile(mOutFileFd);
-#endif
 }
 
 AudioCapture::~AudioCapture() {
@@ -431,19 +429,20 @@
         if (mSampleRate == 48000) {  // test all available constructors
             mRecord = new AudioRecord(mInputSource, mSampleRate, mFormat, mChannelMask,
                                       attributionSource, mFrameCount, nullptr /* callback */,
-                                      mNotificationFrames, mSessionId, mTransferType, mFlags);
+                                      mNotificationFrames, mSessionId, mTransferType, mFlags,
+                                      mAttributes);
         } else {
             mRecord = new AudioRecord(attributionSource);
             status = mRecord->set(mInputSource, mSampleRate, mFormat, mChannelMask, mFrameCount,
                                   nullptr /* callback */, 0 /* notificationFrames */,
                                   false /* canCallJava */, mSessionId, mTransferType, mFlags,
-                                  attributionSource.uid, attributionSource.pid);
+                                  attributionSource.uid, attributionSource.pid, mAttributes);
         }
         if (NO_ERROR != status) return status;
     } else if (mTransferType == AudioRecord::TRANSFER_CALLBACK) {
         mRecord = new AudioRecord(mInputSource, mSampleRate, mFormat, mChannelMask,
                                   attributionSource, mFrameCount, this, mNotificationFrames,
-                                  mSessionId, mTransferType, mFlags);
+                                  mSessionId, mTransferType, mFlags, mAttributes);
     } else {
         ALOGE("Test application is not handling transfer type %s",
               AudioRecord::convertTransferToText(mTransferType));
@@ -460,6 +459,26 @@
     return status;
 }
 
+status_t AudioCapture::setRecordDuration(float durationInSec) {
+    if (REC_READY != mState) {
+        return INVALID_OPERATION;
+    }
+    uint32_t sampleRate = mSampleRate == 0 ? mRecord->getSampleRate() : mSampleRate;
+    mNumFramesToRecord = (sampleRate * durationInSec);
+    return OK;
+}
+
+status_t AudioCapture::enableRecordDump() {
+    if (mOutFileFd != -1) {
+        return INVALID_OPERATION;
+    }
+    TemporaryFile tf("/data/local/tmp");
+    tf.DoNotRemove();
+    mOutFileFd = tf.release();
+    mFileName = std::string{tf.path};
+    return OK;
+}
+
 sp<AudioRecord> AudioCapture::getAudioRecordHandle() {
     return (REC_NO_INIT == mState) ? nullptr : mRecord;
 }
@@ -481,7 +500,7 @@
 status_t AudioCapture::stop() {
     status_t status = OK;
     mStopRecording = true;
-    if (mState != REC_STOPPED) {
+    if (mState != REC_STOPPED && mState != REC_NO_INIT) {
         if (mInputSource != AUDIO_SOURCE_DEFAULT) {
             bool state = false;
             status = AudioSystem::isSourceActive(mInputSource, &state);
@@ -495,81 +514,66 @@
 }
 
 status_t AudioCapture::obtainBuffer(RawBuffer& buffer) {
-    if (REC_STARTED != mState && REC_STOPPED != mState) return INVALID_OPERATION;
-    int retry = 25;
-    AudioRecord::Buffer recordBuffer;
-    recordBuffer.frameCount = mNotificationFrames;
+    if (REC_STARTED != mState) return INVALID_OPERATION;
+    const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+    int counter = 0;
     size_t nonContig = 0;
-    status_t status = mRecord->obtainBuffer(&recordBuffer, retry, &nonContig);
-    if (OK == status) {
-        const int64_t timestampUs =
-                ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
-                mRecord->getSampleRate();
-        RawBuffer buff{-1, timestampUs, static_cast<int32_t>(recordBuffer.size())};
-        memcpy(buff.mData.get(), recordBuffer.data(), recordBuffer.size());
-        buffer = std::move(buff);
-        mNumFramesReceived += recordBuffer.size() / mRecord->frameSize();
-        mRecord->releaseBuffer(&recordBuffer);
-        if (mNumFramesReceived > mNumFramesToRecord) {
-            stop();
+    while (mNumFramesReceived < mNumFramesToRecord) {
+        AudioRecord::Buffer recordBuffer;
+        recordBuffer.frameCount = mNotificationFrames;
+        status_t status = mRecord->obtainBuffer(&recordBuffer, 1, &nonContig);
+        if (OK == status) {
+            const int64_t timestampUs =
+                    ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
+                    mRecord->getSampleRate();
+            RawBuffer buff{-1, timestampUs, static_cast<int32_t>(recordBuffer.size())};
+            memcpy(buff.mData.get(), recordBuffer.data(), recordBuffer.size());
+            buffer = std::move(buff);
+            mNumFramesReceived += recordBuffer.size() / mRecord->frameSize();
+            mRecord->releaseBuffer(&recordBuffer);
+            counter = 0;
+        } else if (WOULD_BLOCK == status) {
+            // if not received a buffer for MAX_WAIT_TIME_MS, something has gone wrong
+            if (counter == maxTries) return TIMED_OUT;
+            counter++;
         }
-    } else if (status == WOULD_BLOCK) {
-        if (mStopRecording)
-            return WOULD_BLOCK;
-        else
-            return TIMED_OUT;
     }
     return OK;
 }
 
 status_t AudioCapture::obtainBufferCb(RawBuffer& buffer) {
     if (REC_STARTED != mState) return INVALID_OPERATION;
-    int retry = 10;
+    const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+    int counter = 0;
     std::unique_lock<std::mutex> lock{mMutex};
-    while (mBuffersReceived.empty() && !mStopRecording && retry > 0) {
-        mCondition.wait_for(lock, std::chrono::milliseconds(100));
-        retry--;
+    while (mBuffersReceived.empty() && !mStopRecording && counter < maxTries) {
+        mCondition.wait_for(lock, std::chrono::milliseconds(WAIT_PERIOD_MS));
+        counter++;
     }
     if (!mBuffersReceived.empty()) {
         auto it = mBuffersReceived.begin();
         buffer = std::move(*it);
         mBuffersReceived.erase(it);
     } else {
-        if (retry == 0) return TIMED_OUT;
-        if (mStopRecording)
-            return WOULD_BLOCK;
-        else
-            return UNKNOWN_ERROR;
+        if (!mStopRecording && counter == maxTries) return TIMED_OUT;
     }
     return OK;
 }
 
 status_t AudioCapture::audioProcess() {
     RawBuffer buffer;
-    while (true) {
-        status_t status;
+    status_t status = OK;
+    while (mNumFramesReceived < mNumFramesToRecord && status == OK) {
         if (mTransferType == AudioRecord::TRANSFER_CALLBACK)
             status = obtainBufferCb(buffer);
         else
             status = obtainBuffer(buffer);
-        switch (status) {
-            case OK:
-                if (mOutFileFd > 0) {
-                    const char* ptr =
-                            static_cast<const char*>(static_cast<void*>(buffer.mData.get()));
-                    write(mOutFileFd, ptr, buffer.mCapacity);
-                }
-                break;
-            case WOULD_BLOCK:
-                return OK;
-            case TIMED_OUT:          // "recorder application timed out from receiving buffers"
-            case NO_INIT:            // "recorder not initialized"
-            case INVALID_OPERATION:  // "recorder not started"
-            case UNKNOWN_ERROR:      // "Unknown error"
-            default:
-                return status;
+        if (OK == status && mOutFileFd > 0) {
+            const char* ptr = static_cast<const char*>(static_cast<void*>(buffer.mData.get()));
+            write(mOutFileFd, ptr, buffer.mCapacity);
         }
     }
+    return OK;
 }
 
 status_t listAudioPorts(std::vector<audio_port_v7>& portsVec) {
@@ -613,13 +617,15 @@
 }
 
 status_t getPortByAttributes(audio_port_role_t role, audio_port_type_t type,
-                             audio_devices_t deviceType, audio_port_v7& port) {
+                             audio_devices_t deviceType, const std::string& address,
+                             audio_port_v7& port) {
     std::vector<struct audio_port_v7> ports;
     status_t status = listAudioPorts(ports);
     if (status != OK) return status;
     for (auto i = 0; i < ports.size(); i++) {
         if (ports[i].role == role && ports[i].type == type &&
-            ports[i].ext.device.type == deviceType) {
+            ports[i].ext.device.type == deviceType &&
+            !strncmp(ports[i].ext.device.address, address.c_str(), AUDIO_DEVICE_MAX_ADDRESS_LEN)) {
             port = ports[i];
             return OK;
         }
diff --git a/media/libaudioclient/tests/audio_test_utils.h b/media/libaudioclient/tests/audio_test_utils.h
index f35b65d..90c30c2 100644
--- a/media/libaudioclient/tests/audio_test_utils.h
+++ b/media/libaudioclient/tests/audio_test_utils.h
@@ -34,8 +34,6 @@
 #include <media/AudioRecord.h>
 #include <media/AudioTrack.h>
 
-#define RECORD_TO_FILE 0
-
 using namespace android;
 
 struct MixPort {
@@ -53,11 +51,11 @@
 status_t parse_audio_policy_configuration_xml(std::vector<std::string>& attachedDevices,
                                               std::vector<MixPort>& mixPorts,
                                               std::vector<Route>& routes);
-void CreateRandomFile(int& fd);
 status_t listAudioPorts(std::vector<audio_port_v7>& portsVec);
 status_t listAudioPatches(std::vector<struct audio_patch>& patchesVec);
 status_t getPortByAttributes(audio_port_role_t role, audio_port_type_t type,
-                             audio_devices_t deviceType, audio_port_v7& port);
+                             audio_devices_t deviceType, const std::string& address,
+                             audio_port_v7& port);
 status_t getPatchForOutputMix(audio_io_handle_t audioIo, audio_patch& patch);
 status_t getPatchForInputMix(audio_io_handle_t audioIo, audio_patch& patch);
 bool patchContainsOutputDevice(audio_port_handle_t deviceId, audio_patch patch);
@@ -76,7 +74,7 @@
     std::condition_variable mCondition;
 
     void onAudioDeviceUpdate(audio_io_handle_t audioIo, audio_port_handle_t deviceId);
-    status_t waitForAudioDeviceCb();
+    status_t waitForAudioDeviceCb(audio_port_handle_t expDeviceId = AUDIO_PORT_HANDLE_NONE);
 };
 
 // Simple AudioPlayback class.
@@ -148,7 +146,8 @@
                  audio_channel_mask_t channelMask,
                  audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
                  audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
-                 AudioRecord::transfer_type transferType = AudioRecord::TRANSFER_CALLBACK);
+                 AudioRecord::transfer_type transferType = AudioRecord::TRANSFER_CALLBACK,
+                 const audio_attributes_t* attributes = nullptr);
     ~AudioCapture();
     size_t onMoreData(const AudioRecord::Buffer& buffer) override;
     void onOverrun() override;
@@ -156,6 +155,9 @@
     void onNewPos(uint32_t newPos) override;
     void onNewIAudioRecord() override;
     status_t create();
+    status_t setRecordDuration(float durationInSec);
+    status_t enableRecordDump();
+    std::string getRecordDumpFileName() const { return mFileName; }
     sp<AudioRecord> getAudioRecordHandle();
     status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
                    audio_session_t triggerSession = AUDIO_SESSION_NONE);
@@ -190,11 +192,13 @@
     const audio_input_flags_t mFlags;
     const audio_session_t mSessionId;
     const AudioRecord::transfer_type mTransferType;
+    const audio_attributes_t* mAttributes;
 
     size_t mMaxBytesPerCallback = 2048;
     sp<AudioRecord> mRecord;
     State mState;
     bool mStopRecording;
+    std::string mFileName;
     int mOutFileFd = -1;
 
     std::mutex mMutex;
diff --git a/media/libaudioclient/tests/audioeffect_analyser.cpp b/media/libaudioclient/tests/audioeffect_analyser.cpp
new file mode 100644
index 0000000..94accae
--- /dev/null
+++ b/media/libaudioclient/tests/audioeffect_analyser.cpp
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2022 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 "AudioEffectAnalyser"
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <gtest/gtest.h>
+#include <media/AudioEffect.h>
+#include <system/audio_effects/effect_bassboost.h>
+#include <system/audio_effects/effect_equalizer.h>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "audio_test_utils.h"
+#include "pffft.hpp"
+
+#define CHECK_OK(expr, msg) \
+    mStatus = (expr);       \
+    if (OK != mStatus) {    \
+        mMsg = (msg);       \
+        return;             \
+    }
+
+using namespace android;
+
+constexpr float kDefAmplitude = 0.60f;
+
+constexpr float kPlayBackDurationSec = 1.5;
+constexpr float kCaptureDurationSec = 1.0;
+constexpr float kPrimeDurationInSec = 0.5;
+
+// chosen to safely sample largest center freq of eq bands
+constexpr uint32_t kSamplingFrequency = 48000;
+
+// allows no fmt conversion before fft
+constexpr audio_format_t kFormat = AUDIO_FORMAT_PCM_FLOAT;
+
+// playback and capture are done with channel mask configured to mono.
+// effect analysis should not depend on mask, mono makes it easier.
+
+constexpr int kNPointFFT = 16384;
+constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
+
+const char* gPackageName = "AudioEffectAnalyser";
+
+static_assert(kPrimeDurationInSec + 2 * kNPointFFT / kSamplingFrequency < kCaptureDurationSec,
+              "capture at least, prime, pad, nPointFft size of samples");
+static_assert(kPrimeDurationInSec + 2 * kNPointFFT / kSamplingFrequency < kPlayBackDurationSec,
+              "playback needs to be active during capture");
+
+struct CaptureEnv {
+    // input args
+    uint32_t mSampleRate{kSamplingFrequency};
+    audio_format_t mFormat{kFormat};
+    audio_channel_mask_t mChannelMask{AUDIO_CHANNEL_IN_MONO};
+    float mCaptureDuration{kCaptureDurationSec};
+    // output val
+    status_t mStatus{OK};
+    std::string mMsg;
+    std::string mDumpFileName;
+
+    ~CaptureEnv();
+    void capture();
+};
+
+CaptureEnv::~CaptureEnv() {
+    if (!mDumpFileName.empty()) {
+        std::ifstream f(mDumpFileName);
+        if (f.good()) {
+            f.close();
+            remove(mDumpFileName.c_str());
+        }
+    }
+}
+
+void CaptureEnv::capture() {
+    audio_port_v7 port;
+    CHECK_OK(getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port),
+             "Could not find port")
+    const auto capture =
+            sp<AudioCapture>::make(AUDIO_SOURCE_REMOTE_SUBMIX, mSampleRate, mFormat, mChannelMask);
+    CHECK_OK(capture->create(), "record creation failed")
+    CHECK_OK(capture->setRecordDuration(mCaptureDuration), "set record duration failed")
+    CHECK_OK(capture->enableRecordDump(), "enable record dump failed")
+    auto cbCapture = sp<OnAudioDeviceUpdateNotifier>::make();
+    CHECK_OK(capture->getAudioRecordHandle()->addAudioDeviceCallback(cbCapture),
+             "addAudioDeviceCallback failed")
+    CHECK_OK(capture->start(), "start recording failed")
+    CHECK_OK(capture->audioProcess(), "recording process failed")
+    CHECK_OK(cbCapture->waitForAudioDeviceCb(), "audio device callback notification timed out");
+    if (port.id != capture->getAudioRecordHandle()->getRoutedDeviceId()) {
+        CHECK_OK(BAD_VALUE, "Capture NOT routed on expected port")
+    }
+    CHECK_OK(getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port),
+             "Could not find port")
+    CHECK_OK(capture->stop(), "record stop failed")
+    mDumpFileName = capture->getRecordDumpFileName();
+}
+
+struct PlaybackEnv {
+    // input args
+    uint32_t mSampleRate{kSamplingFrequency};
+    audio_format_t mFormat{kFormat};
+    audio_channel_mask_t mChannelMask{AUDIO_CHANNEL_OUT_MONO};
+    audio_session_t mSessionId{AUDIO_SESSION_NONE};
+    std::string mRes;
+    // output val
+    status_t mStatus{OK};
+    std::string mMsg;
+
+    void play();
+};
+
+void PlaybackEnv::play() {
+    const auto ap =
+            sp<AudioPlayback>::make(mSampleRate, mFormat, mChannelMask, AUDIO_OUTPUT_FLAG_NONE,
+                                    mSessionId, AudioTrack::TRANSFER_OBTAIN);
+    CHECK_OK(ap->loadResource(mRes.c_str()), "Unable to open Resource")
+    const auto cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+    CHECK_OK(ap->create(), "track creation failed")
+    ap->getAudioTrackHandle()->setVolume(1.0f);
+    CHECK_OK(ap->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback),
+             "addAudioDeviceCallback failed")
+    CHECK_OK(ap->start(), "audio track start failed")
+    CHECK_OK(cbPlayback->waitForAudioDeviceCb(), "audio device callback notification timed out")
+    CHECK_OK(ap->onProcess(), "playback process failed")
+    ap->stop();
+}
+
+void generateMultiTone(const std::vector<int>& toneFrequencies, float samplingFrequency,
+                       float duration, float amplitude, float* buffer, int numSamples) {
+    int totalFrameCount = (samplingFrequency * duration);
+    int limit = std::min(totalFrameCount, numSamples);
+
+    for (auto i = 0; i < limit; i++) {
+        buffer[i] = 0;
+        for (auto j = 0; j < toneFrequencies.size(); j++) {
+            buffer[i] += sin(2 * M_PI * toneFrequencies[j] * i / samplingFrequency);
+        }
+        buffer[i] *= (amplitude / toneFrequencies.size());
+    }
+}
+
+sp<AudioEffect> createEffect(const effect_uuid_t* type,
+                             audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX) {
+    std::string packageName{gPackageName};
+    AttributionSourceState attributionSource;
+    attributionSource.packageName = packageName;
+    attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
+    attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
+    attributionSource.token = sp<BBinder>::make();
+    sp<AudioEffect> effect = sp<AudioEffect>::make(attributionSource);
+    effect->set(type, nullptr, 0, nullptr, sessionId, AUDIO_IO_HANDLE_NONE, {}, false, false);
+    return effect;
+}
+
+void computeFilterGainsAtTones(float captureDuration, int nPointFft, std::vector<int>& binOffsets,
+                               float* inputMag, float* gaindB, const char* res,
+                               audio_session_t sessionId) {
+    int totalFrameCount = captureDuration * kSamplingFrequency;
+    auto output = pffft::AlignedVector<float>(totalFrameCount);
+    auto fftOutput = pffft::AlignedVector<float>(nPointFft);
+    PlaybackEnv argsP;
+    argsP.mRes = std::string{res};
+    argsP.mSessionId = sessionId;
+    CaptureEnv argsR;
+    argsR.mCaptureDuration = captureDuration;
+    std::thread playbackThread(&PlaybackEnv::play, &argsP);
+    std::thread captureThread(&CaptureEnv::capture, &argsR);
+    captureThread.join();
+    playbackThread.join();
+    ASSERT_EQ(OK, argsR.mStatus) << argsR.mMsg;
+    ASSERT_EQ(OK, argsP.mStatus) << argsP.mMsg;
+    ASSERT_FALSE(argsR.mDumpFileName.empty()) << "recorded not written to file";
+    std::ifstream fin(argsR.mDumpFileName, std::ios::in | std::ios::binary);
+    fin.read((char*)output.data(), totalFrameCount * sizeof(output[0]));
+    fin.close();
+    PFFFT_Setup* handle = pffft_new_setup(nPointFft, PFFFT_REAL);
+    // ignore first few samples. This is to not analyse until audio track is re-routed to remote
+    // submix source, also for the effect filter response to reach steady-state (priming / pruning
+    // samples).
+    int rerouteOffset = kPrimeDurationInSec * kSamplingFrequency;
+    pffft_transform_ordered(handle, output.data() + rerouteOffset, fftOutput.data(), nullptr,
+                            PFFFT_FORWARD);
+    pffft_destroy_setup(handle);
+    for (auto i = 0; i < binOffsets.size(); i++) {
+        auto k = binOffsets[i];
+        auto outputMag = sqrt((fftOutput[k * 2] * fftOutput[k * 2]) +
+                              (fftOutput[k * 2 + 1] * fftOutput[k * 2 + 1]));
+        gaindB[i] = 20 * log10(outputMag / inputMag[i]);
+    }
+}
+
+std::tuple<int, int> roundToFreqCenteredToFftBin(float binWidth, float freq) {
+    int bin_index = std::round(freq / binWidth);
+    int cfreq = std::round(bin_index * binWidth);
+    return std::make_tuple(bin_index, cfreq);
+}
+
+TEST(AudioEffectTest, CheckEqualizerEffect) {
+    audio_session_t sessionId =
+            (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+    sp<AudioEffect> equalizer = createEffect(SL_IID_EQUALIZER, sessionId);
+    ASSERT_EQ(OK, equalizer->initCheck());
+    ASSERT_EQ(NO_ERROR, equalizer->setEnabled(true));
+    if ((equalizer->descriptor().flags & EFFECT_FLAG_HW_ACC_MASK) != 0) {
+        GTEST_SKIP() << "effect processed output inaccessible, skipping test";
+    }
+#define MAX_PARAMS 64
+    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + MAX_PARAMS];
+    effect_param_t* eqParam = (effect_param_t*)(&buf32);
+
+    // get num of presets
+    eqParam->psize = sizeof(uint32_t);
+    eqParam->vsize = sizeof(uint16_t);
+    *(int32_t*)eqParam->data = EQ_PARAM_GET_NUM_OF_PRESETS;
+    EXPECT_EQ(0, equalizer->getParameter(eqParam));
+    EXPECT_EQ(0, eqParam->status);
+    int numPresets = *((uint16_t*)((int32_t*)eqParam->data + 1));
+
+    // get num of bands
+    eqParam->psize = sizeof(uint32_t);
+    eqParam->vsize = sizeof(uint16_t);
+    *(int32_t*)eqParam->data = EQ_PARAM_NUM_BANDS;
+    EXPECT_EQ(0, equalizer->getParameter(eqParam));
+    EXPECT_EQ(0, eqParam->status);
+    int numBands = *((uint16_t*)((int32_t*)eqParam->data + 1));
+
+    const int totalFrameCount = kSamplingFrequency * kPlayBackDurationSec;
+
+    // get band center frequencies
+    std::vector<int> centerFrequencies;
+    std::vector<int> binOffsets;
+    for (auto i = 0; i < numBands; i++) {
+        eqParam->psize = sizeof(uint32_t) * 2;
+        eqParam->vsize = sizeof(uint32_t);
+        *(int32_t*)eqParam->data = EQ_PARAM_CENTER_FREQ;
+        *((uint16_t*)((int32_t*)eqParam->data + 1)) = i;
+        EXPECT_EQ(0, equalizer->getParameter(eqParam));
+        EXPECT_EQ(0, eqParam->status);
+        float cfreq = *((int32_t*)eqParam->data + 2) / 1000;  // milli hz
+        // pick frequency close to bin center frequency
+        auto [bin_index, bin_freq] = roundToFreqCenteredToFftBin(kBinWidth, cfreq);
+        centerFrequencies.push_back(bin_freq);
+        binOffsets.push_back(bin_index);
+    }
+
+    // input for effect module
+    auto input = pffft::AlignedVector<float>(totalFrameCount);
+    generateMultiTone(centerFrequencies, kSamplingFrequency, kPlayBackDurationSec, kDefAmplitude,
+                      input.data(), totalFrameCount);
+    auto fftInput = pffft::AlignedVector<float>(kNPointFFT);
+    PFFFT_Setup* handle = pffft_new_setup(kNPointFFT, PFFFT_REAL);
+    pffft_transform_ordered(handle, input.data(), fftInput.data(), nullptr, PFFFT_FORWARD);
+    pffft_destroy_setup(handle);
+    float inputMag[numBands];
+    for (auto i = 0; i < numBands; i++) {
+        auto k = binOffsets[i];
+        inputMag[i] = sqrt((fftInput[k * 2] * fftInput[k * 2]) +
+                           (fftInput[k * 2 + 1] * fftInput[k * 2 + 1]));
+    }
+    TemporaryFile tf("/data/local/tmp");
+    close(tf.release());
+    std::ofstream fout(tf.path, std::ios::out | std::ios::binary);
+    fout.write((char*)input.data(), input.size() * sizeof(input[0]));
+    fout.close();
+
+    float expGaindB[numBands], actGaindB[numBands];
+
+    std::string msg = "";
+    int numPresetsOk = 0;
+    for (auto preset = 0; preset < numPresets; preset++) {
+        // set preset
+        eqParam->psize = sizeof(uint32_t);
+        eqParam->vsize = sizeof(uint32_t);
+        *(int32_t*)eqParam->data = EQ_PARAM_CUR_PRESET;
+        *((uint16_t*)((int32_t*)eqParam->data + 1)) = preset;
+        EXPECT_EQ(0, equalizer->setParameter(eqParam));
+        EXPECT_EQ(0, eqParam->status);
+        // get preset gains
+        eqParam->psize = sizeof(uint32_t);
+        eqParam->vsize = (numBands + 1) * sizeof(uint32_t);
+        *(int32_t*)eqParam->data = EQ_PARAM_PROPERTIES;
+        EXPECT_EQ(0, equalizer->getParameter(eqParam));
+        EXPECT_EQ(0, eqParam->status);
+        t_equalizer_settings* settings =
+                reinterpret_cast<t_equalizer_settings*>((int32_t*)eqParam->data + 1);
+        EXPECT_EQ(preset, settings->curPreset);
+        EXPECT_EQ(numBands, settings->numBands);
+        for (auto i = 0; i < numBands; i++) {
+            expGaindB[i] = ((int16_t)settings->bandLevels[i]) / 100.0f;  // gain in milli bels
+        }
+        memset(actGaindB, 0, sizeof(actGaindB));
+        ASSERT_NO_FATAL_FAILURE(computeFilterGainsAtTones(kCaptureDurationSec, kNPointFFT,
+                                                          binOffsets, inputMag, actGaindB, tf.path,
+                                                          sessionId));
+        bool isOk = true;
+        for (auto i = 0; i < numBands - 1; i++) {
+            auto diffA = expGaindB[i] - expGaindB[i + 1];
+            auto diffB = actGaindB[i] - actGaindB[i + 1];
+            if (diffA == 0 && fabs(diffA - diffB) > 1.0f) {
+                msg += (android::base::StringPrintf(
+                        "For eq preset : %d, between bands %d and %d, expected relative gain is : "
+                        "%f, got relative gain is : %f, error : %f \n",
+                        preset, i, i + 1, diffA, diffB, diffA - diffB));
+                isOk = false;
+            } else if (diffA * diffB < 0) {
+                msg += (android::base::StringPrintf(
+                        "For eq preset : %d, between bands %d and %d, expected relative gain and "
+                        "seen relative gain are of opposite signs \n. Expected relative gain is : "
+                        "%f, seen relative gain is : %f \n",
+                        preset, i, i + 1, diffA, diffB));
+                isOk = false;
+            }
+        }
+        if (isOk) numPresetsOk++;
+    }
+    EXPECT_EQ(numPresetsOk, numPresets) << msg;
+}
+
+TEST(AudioEffectTest, CheckBassBoostEffect) {
+    audio_session_t sessionId =
+            (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+    sp<AudioEffect> bassboost = createEffect(SL_IID_BASSBOOST, sessionId);
+    ASSERT_EQ(OK, bassboost->initCheck());
+    ASSERT_EQ(NO_ERROR, bassboost->setEnabled(true));
+    if ((bassboost->descriptor().flags & EFFECT_FLAG_HW_ACC_MASK) != 0) {
+        GTEST_SKIP() << "effect processed output inaccessible, skipping test";
+    }
+    int32_t buf32[sizeof(effect_param_t) / sizeof(int32_t) + MAX_PARAMS];
+    effect_param_t* bbParam = (effect_param_t*)(&buf32);
+
+    bbParam->psize = sizeof(int32_t);
+    bbParam->vsize = sizeof(int32_t);
+    *(int32_t*)bbParam->data = BASSBOOST_PARAM_STRENGTH_SUPPORTED;
+    EXPECT_EQ(0, bassboost->getParameter(bbParam));
+    EXPECT_EQ(0, bbParam->status);
+    bool strengthSupported = *((int32_t*)bbParam->data + 1);
+
+    const int totalFrameCount = kSamplingFrequency * kPlayBackDurationSec;
+
+    // selecting bass frequency, speech tone (for relative gain)
+    std::vector<int> testFrequencies{100, 1200};
+    std::vector<int> binOffsets;
+    for (auto i = 0; i < testFrequencies.size(); i++) {
+        // pick frequency close to bin center frequency
+        auto [bin_index, bin_freq] = roundToFreqCenteredToFftBin(kBinWidth, testFrequencies[i]);
+        testFrequencies[i] = bin_freq;
+        binOffsets.push_back(bin_index);
+    }
+
+    // input for effect module
+    auto input = pffft::AlignedVector<float>(totalFrameCount);
+    generateMultiTone(testFrequencies, kSamplingFrequency, kPlayBackDurationSec, kDefAmplitude,
+                      input.data(), totalFrameCount);
+    auto fftInput = pffft::AlignedVector<float>(kNPointFFT);
+    PFFFT_Setup* handle = pffft_new_setup(kNPointFFT, PFFFT_REAL);
+    pffft_transform_ordered(handle, input.data(), fftInput.data(), nullptr, PFFFT_FORWARD);
+    pffft_destroy_setup(handle);
+    float inputMag[testFrequencies.size()];
+    for (auto i = 0; i < testFrequencies.size(); i++) {
+        auto k = binOffsets[i];
+        inputMag[i] = sqrt((fftInput[k * 2] * fftInput[k * 2]) +
+                           (fftInput[k * 2 + 1] * fftInput[k * 2 + 1]));
+    }
+    TemporaryFile tf("/data/local/tmp");
+    close(tf.release());
+    std::ofstream fout(tf.path, std::ios::out | std::ios::binary);
+    fout.write((char*)input.data(), input.size() * sizeof(input[0]));
+    fout.close();
+
+    float gainWithOutFilter[testFrequencies.size()];
+    memset(gainWithOutFilter, 0, sizeof(gainWithOutFilter));
+    ASSERT_NO_FATAL_FAILURE(computeFilterGainsAtTones(kCaptureDurationSec, kNPointFFT, binOffsets,
+                                                      inputMag, gainWithOutFilter, tf.path,
+                                                      AUDIO_SESSION_OUTPUT_MIX));
+    float diffA = gainWithOutFilter[0] - gainWithOutFilter[1];
+    float prevGain = -100.f;
+    for (auto strength = 150; strength < 1000; strength += strengthSupported ? 150 : 1000) {
+        // configure filter strength
+        if (strengthSupported) {
+            bbParam->psize = sizeof(int32_t);
+            bbParam->vsize = sizeof(int16_t);
+            *(int32_t*)bbParam->data = BASSBOOST_PARAM_STRENGTH;
+            *((int16_t*)((int32_t*)bbParam->data + 1)) = strength;
+            EXPECT_EQ(0, bassboost->setParameter(bbParam));
+            EXPECT_EQ(0, bbParam->status);
+        }
+        float gainWithFilter[testFrequencies.size()];
+        memset(gainWithFilter, 0, sizeof(gainWithFilter));
+        ASSERT_NO_FATAL_FAILURE(computeFilterGainsAtTones(kCaptureDurationSec, kNPointFFT,
+                                                          binOffsets, inputMag, gainWithFilter,
+                                                          tf.path, sessionId));
+        float diffB = gainWithFilter[0] - gainWithFilter[1];
+        EXPECT_GT(diffB, diffA) << "bassboost effect not seen";
+        EXPECT_GE(diffB, prevGain) << "increase in boost strength causing fall in gain";
+        prevGain = diffB;
+    }
+}
diff --git a/media/libaudioclient/tests/audiorouting_tests.cpp b/media/libaudioclient/tests/audiorouting_tests.cpp
index 4bd81c8..2c5fcd7 100644
--- a/media/libaudioclient/tests/audiorouting_tests.cpp
+++ b/media/libaudioclient/tests/audiorouting_tests.cpp
@@ -46,10 +46,10 @@
         attributes.usage = AUDIO_USAGE_MEDIA;
         attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
         attributes.flags = flags[i];
-        sp<AudioPlayback> ap = sp<AudioPlayback>::make(
-                0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
-                AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE, AudioTrack::TRANSFER_OBTAIN,
-                &attributes);
+        sp<AudioPlayback> ap = sp<AudioPlayback>::make(0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
+                                                       AUDIO_CHANNEL_OUT_STEREO,
+                                                       AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE,
+                                                       AudioTrack::TRANSFER_OBTAIN, &attributes);
         ASSERT_NE(nullptr, ap);
         ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
                 << "Unable to open Resource";
@@ -77,46 +77,186 @@
     }
 }
 
-TEST(AudioTrackTest, TestRemoteSubmix) {
-    std::vector<std::string> attachedDevices;
-    std::vector<MixPort> mixPorts;
-    std::vector<Route> routes;
-    EXPECT_EQ(OK, parse_audio_policy_configuration_xml(attachedDevices, mixPorts, routes));
-    bool hasFlag = false;
-    for (int j = 0; j < attachedDevices.size() && !hasFlag; j++) {
-        if (attachedDevices[j].find("Remote Submix") != -1) hasFlag = true;
+TEST(AudioTrackTest, DefaultRoutingTest) {
+    audio_port_v7 port;
+    if (OK != getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+                                  AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port)) {
+        GTEST_SKIP() << "remote submix in device not connected";
     }
-    if (!hasFlag) GTEST_SKIP() << " Device does not have Remote Submix port.";
-    sp<AudioCapture> capture = new AudioCapture(AUDIO_SOURCE_REMOTE_SUBMIX, 48000,
-                                                AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO);
-    ASSERT_NE(nullptr, capture);
-    ASSERT_EQ(OK, capture->create()) << "record creation failed";
 
+    // create record instance
+    sp<AudioCapture> capture = sp<AudioCapture>::make(
+            AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO);
+    ASSERT_NE(nullptr, capture);
+    EXPECT_EQ(OK, capture->create()) << "record creation failed";
+    sp<OnAudioDeviceUpdateNotifier> cbCapture = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, capture->getAudioRecordHandle()->addAudioDeviceCallback(cbCapture));
+
+    // create playback instance
     sp<AudioPlayback> playback = sp<AudioPlayback>::make(
             48000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
             AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE);
     ASSERT_NE(nullptr, playback);
     ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
             << "Unable to open Resource";
-    ASSERT_EQ(OK, playback->create()) << "track creation failed";
+    EXPECT_EQ(OK, playback->create()) << "track creation failed";
+    sp<OnAudioDeviceUpdateNotifier> cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, playback->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback));
 
-    audio_port_v7 port;
-    status_t status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
-                                          AUDIO_DEVICE_IN_REMOTE_SUBMIX, port);
-    EXPECT_EQ(OK, status) << "Could not find port";
-
+    // capture should be routed to submix in port
     EXPECT_EQ(OK, capture->start()) << "start recording failed";
+    EXPECT_EQ(OK, cbCapture->waitForAudioDeviceCb());
     EXPECT_EQ(port.id, capture->getAudioRecordHandle()->getRoutedDeviceId())
             << "Capture NOT routed on expected port";
 
-    status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
-                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX, port);
+    // capture start should create submix out port
+    status_t status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+                                          AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port);
     EXPECT_EQ(OK, status) << "Could not find port";
 
+    // playback should be routed to submix out as long as capture is active
     EXPECT_EQ(OK, playback->start()) << "audio track start failed";
-    EXPECT_EQ(OK, playback->onProcess());
-    ASSERT_EQ(port.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
+    EXPECT_EQ(OK, cbPlayback->waitForAudioDeviceCb());
+    EXPECT_EQ(port.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
             << "Playback NOT routed on expected port";
+
     capture->stop();
     playback->stop();
 }
+
+class AudioRoutingTest : public ::testing::Test {
+  public:
+    void SetUp() override {
+        audio_port_v7 port;
+        if (OK != getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+                                      AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port)) {
+            GTEST_SKIP() << "remote submix in device not connected";
+        }
+        uint32_t mixType = MIX_TYPE_PLAYERS;
+        uint32_t mixFlag = MIX_ROUTE_FLAG_LOOP_BACK;
+        audio_devices_t deviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+        AudioMixMatchCriterion criterion(AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT,
+                                         RULE_MATCH_ATTRIBUTE_USAGE);
+        std::vector<AudioMixMatchCriterion> criteria{criterion};
+        audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+        config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+        config.format = AUDIO_FORMAT_PCM_16_BIT;
+        config.sample_rate = 48000;
+        AudioMix mix(criteria, mixType, config, mixFlag, String8{mAddress.c_str()}, 0);
+        mix.mDeviceType = deviceType;
+        mMixes.push(mix);
+        if (OK == AudioSystem::registerPolicyMixes(mMixes, true)) {
+            mPolicyMixRegistered = true;
+        }
+        ASSERT_TRUE(mPolicyMixRegistered) << "register policy mix failed";
+    }
+
+    void TearDown() override {
+        if (mPolicyMixRegistered) {
+            EXPECT_EQ(OK, AudioSystem::registerPolicyMixes(mMixes, false));
+        }
+    }
+
+    bool mPolicyMixRegistered{false};
+    std::string mAddress{"mix_1"};
+    Vector<AudioMix> mMixes;
+};
+
+TEST_F(AudioRoutingTest, ConcurrentDynamicRoutingTest) {
+    audio_port_v7 port, port_mix;
+    // expect legacy submix in port to be connected
+    status_t status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+                                          AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port);
+    EXPECT_EQ(OK, status) << "Could not find port";
+
+    // as policy mix is registered, expect submix in port with mAddress to be connected
+    status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_IN_REMOTE_SUBMIX, mAddress, port_mix);
+    EXPECT_EQ(OK, status) << "Could not find port";
+
+    // create playback instance
+    sp<AudioPlayback> playback = sp<AudioPlayback>::make(
+            48000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+            AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE, AudioTrack::TRANSFER_OBTAIN);
+    ASSERT_NE(nullptr, playback);
+    ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+            << "Unable to open Resource";
+    EXPECT_EQ(OK, playback->create()) << "track creation failed";
+    sp<OnAudioDeviceUpdateNotifier> cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, playback->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback));
+
+    // create capture instances on different ports
+    sp<AudioCapture> captureA = sp<AudioCapture>::make(
+            AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO);
+    ASSERT_NE(nullptr, captureA);
+    EXPECT_EQ(OK, captureA->create()) << "record creation failed";
+    sp<OnAudioDeviceUpdateNotifier> cbCaptureA = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, captureA->getAudioRecordHandle()->addAudioDeviceCallback(cbCaptureA));
+
+    audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
+    attr.source = AUDIO_SOURCE_REMOTE_SUBMIX;
+    sprintf(attr.tags, "addr=%s", mAddress.c_str());
+    sp<AudioCapture> captureB = sp<AudioCapture>::make(
+            AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
+            AUDIO_INPUT_FLAG_NONE, AUDIO_SESSION_ALLOCATE, AudioRecord::TRANSFER_CALLBACK, &attr);
+    ASSERT_NE(nullptr, captureB);
+    EXPECT_EQ(OK, captureB->create()) << "record creation failed";
+    sp<OnAudioDeviceUpdateNotifier> cbCaptureB = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, captureB->getAudioRecordHandle()->addAudioDeviceCallback(cbCaptureB));
+
+    // launch
+    EXPECT_EQ(OK, captureA->start()) << "start recording failed";
+    EXPECT_EQ(OK, cbCaptureA->waitForAudioDeviceCb());
+    EXPECT_EQ(port.id, captureA->getAudioRecordHandle()->getRoutedDeviceId())
+            << "Capture NOT routed on expected port";
+
+    EXPECT_EQ(OK, captureB->start()) << "start recording failed";
+    EXPECT_EQ(OK, cbCaptureB->waitForAudioDeviceCb());
+    EXPECT_EQ(port_mix.id, captureB->getAudioRecordHandle()->getRoutedDeviceId())
+            << "Capture NOT routed on expected port";
+
+    // as record started, expect submix out ports to be connected
+    status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port);
+    EXPECT_EQ(OK, status) << "unexpected submix out port found";
+
+    status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mAddress, port_mix);
+    EXPECT_EQ(OK, status) << "Could not find port";
+
+    // check if playback routed to desired port
+    EXPECT_EQ(OK, playback->start());
+    EXPECT_EQ(OK, cbPlayback->waitForAudioDeviceCb());
+    EXPECT_EQ(port_mix.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
+            << "Playback NOT routed on expected port";
+
+    captureB->stop();
+
+    // check if mAddress submix out is disconnected as capture session is stopped
+    status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mAddress, port_mix);
+    EXPECT_NE(OK, status) << "unexpected submix in port found";
+
+    // check if legacy submix out is connected
+    status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port);
+    EXPECT_EQ(OK, status) << "port not found";
+
+    // unregister policy
+    EXPECT_EQ(OK, AudioSystem::registerPolicyMixes(mMixes, false));
+    mPolicyMixRegistered = false;
+
+    // as policy mix is unregistered, expect submix in port with mAddress to be disconnected
+    status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_IN_REMOTE_SUBMIX, mAddress, port_mix);
+    EXPECT_NE(OK, status) << "unexpected submix in port found";
+
+    playback->onProcess();
+    // as captureA is active, it should re route to legacy submix
+    EXPECT_EQ(OK, cbPlayback->waitForAudioDeviceCb(port.id));
+    EXPECT_EQ(port.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
+            << "Playback NOT routed on expected port";
+
+    captureA->stop();
+    playback->stop();
+}
diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp
index a456a2a..c758fcd 100644
--- a/media/libaudiofoundation/Android.bp
+++ b/media/libaudiofoundation/Android.bp
@@ -18,12 +18,12 @@
 
     export_include_dirs: ["include"],
     header_libs: [
-        "libaudioclient_aidl_conversion_util",
+        "libaudio_aidl_conversion_common_util_cpp",
         "libaudio_system_headers",
         "libmedia_helper_headers",
     ],
     export_header_lib_headers: [
-        "libaudioclient_aidl_conversion_util",
+        "libaudio_aidl_conversion_common_util_cpp",
         "libaudio_system_headers",
         "libmedia_helper_headers",
     ],
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index b6e6c84..6c01e29 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -66,6 +66,9 @@
     for (const auto &channel : channelMasks) {
         if (audio_channel_mask_out_to_in(channel) != AUDIO_CHANNEL_INVALID) {
             inMaskSet.insert(audio_channel_mask_out_to_in(channel));
+        } else if (audio_channel_mask_get_representation(channel)
+                    == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+            inMaskSet.insert(channel);
         }
     }
     return inMaskSet;
@@ -76,6 +79,9 @@
     for (const auto &channel : channelMasks) {
         if (audio_channel_mask_in_to_out(channel) != AUDIO_CHANNEL_INVALID) {
             outMaskSet.insert(audio_channel_mask_in_to_out(channel));
+        } else if (audio_channel_mask_get_representation(channel)
+                    == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+            outMaskSet.insert(channel);
         }
     }
     return outMaskSet;
diff --git a/media/libaudiofoundation/tests/Android.bp b/media/libaudiofoundation/tests/Android.bp
index 0e733d3..2f4aee0 100644
--- a/media/libaudiofoundation/tests/Android.bp
+++ b/media/libaudiofoundation/tests/Android.bp
@@ -23,6 +23,7 @@
     static_libs: [
         "audioclient-types-aidl-cpp",
         "libaudioclient_aidl_conversion",
+        "libaudio_aidl_conversion_common_cpp",
         "libaudiofoundation",
         "libstagefright_foundation",
     ],
diff --git a/media/libaudiohal/impl/EffectHalHidl.cpp b/media/libaudiohal/impl/EffectHalHidl.cpp
index 8743c04..3956a6c 100644
--- a/media/libaudiohal/impl/EffectHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectHalHidl.cpp
@@ -17,11 +17,16 @@
 #define LOG_TAG "EffectHalHidl"
 //#define LOG_NDEBUG 0
 
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android-base/stringprintf.h>
 #include <common/all-versions/VersionUtils.h>
 #include <cutils/native_handle.h>
+#include <cutils/properties.h>
 #include <hwbinder/IPCThreadState.h>
 #include <media/EffectsFactoryApi.h>
+#include <mediautils/SchedulingPolicyService.h>
 #include <mediautils/TimeCheck.h>
+#include <system/audio_effects/effect_spatializer.h>
 #include <utils/Log.h>
 
 #include <util/EffectUtils.h>
@@ -50,6 +55,18 @@
     effect_descriptor_t halDescriptor{};
     if (EffectHalHidl::getDescriptor(&halDescriptor) == NO_ERROR) {
         mIsInput = (halDescriptor.flags & EFFECT_FLAG_TYPE_PRE_PROC) == EFFECT_FLAG_TYPE_PRE_PROC;
+        const bool isSpatializer =
+                memcmp(&halDescriptor.type, FX_IID_SPATIALIZER, sizeof(effect_uuid_t)) == 0;
+        if (isSpatializer) {
+            constexpr int32_t kRTPriorityMin = 1;
+            constexpr int32_t kRTPriorityMax = 3;
+            const int32_t priorityBoost = property_get_int32("audio.spatializer.priority", 1);
+            if (priorityBoost >= kRTPriorityMin && priorityBoost <= kRTPriorityMax) {
+                ALOGD("%s: audio.spatializer.priority %d on effect %lld",
+                         __func__, priorityBoost, (long long)effectId);
+                mHalThreadPriority = priorityBoost;
+            }
+        }
     }
 }
 
@@ -127,6 +144,8 @@
         ALOGE_IF(!mEfGroup, "Event flag creation for effects failed");
         return NO_INIT;
     }
+
+    (void)checkHalThreadPriority();
     mStatusMQ = std::move(tempStatusMQ);
     return OK;
 }
@@ -317,5 +336,67 @@
     return result;
 }
 
+status_t EffectHalHidl::getHalPid(pid_t *pid) const {
+    using ::android::hidl::base::V1_0::DebugInfo;
+    using ::android::hidl::manager::V1_0::IServiceManager;
+    DebugInfo debugInfo;
+    const auto ret = mEffect->getDebugInfo([&] (const auto &info) {
+        debugInfo = info;
+    });
+    if (!ret.isOk()) {
+        ALOGW("%s: cannot get effect debug info", __func__);
+        return INVALID_OPERATION;
+    }
+    if (debugInfo.pid != (int)IServiceManager::PidConstant::NO_PID) {
+        *pid = debugInfo.pid;
+        return NO_ERROR;
+    }
+    ALOGW("%s: effect debug info does not contain pid", __func__);
+    return NAME_NOT_FOUND;
+}
+
+status_t EffectHalHidl::getHalWorkerTid(pid_t *tid) {
+    int32_t reply = -1;
+    uint32_t replySize = sizeof(reply);
+    const status_t status =
+            command('gtid', 0 /* cmdSize */, nullptr /* pCmdData */, &replySize, &reply);
+    if (status == OK) {
+        *tid = (pid_t)reply;
+    } else {
+        ALOGW("%s: failed with status:%d", __func__, status);
+    }
+    return status;
+}
+
+bool EffectHalHidl::requestHalThreadPriority(pid_t threadPid, pid_t threadId) {
+    if (mHalThreadPriority == kRTPriorityDisabled) {
+        return true;
+    }
+    const int err = requestPriority(
+            threadPid, threadId,
+            mHalThreadPriority, false /*isForApp*/, true /*asynchronous*/);
+    ALOGW_IF(err, "%s: failed to set RT priority %d for pid %d tid %d; error %d",
+            __func__, mHalThreadPriority, threadPid, threadId, err);
+    // Audio will still work, but may be more susceptible to glitches.
+    return err == 0;
+}
+
+status_t EffectHalHidl::checkHalThreadPriority() {
+    if (mHalThreadPriority == kRTPriorityDisabled) return OK;
+    if (mHalThreadPriority < kRTPriorityMin
+            || mHalThreadPriority > kRTPriorityMax) return BAD_VALUE;
+
+    pid_t halPid, halWorkerTid;
+    const status_t status = getHalPid(&halPid) ?: getHalWorkerTid(&halWorkerTid);
+    const bool success = status == OK && requestHalThreadPriority(halPid, halWorkerTid);
+    ALOGD("%s: effectId %lld RT priority(%d) request %s%s",
+            __func__, (long long)mEffectId, mHalThreadPriority,
+            success ? "succeeded" : "failed",
+            status == OK
+                    ? base::StringPrintf(" for pid:%d tid:%d", halPid, halWorkerTid).c_str()
+                    : " (pid / tid cannot be read)");
+    return success ? OK : status != OK ? status : INVALID_OPERATION /* request failed */;
+}
+
 } // namespace effect
 } // namespace android
diff --git a/media/libaudiohal/impl/EffectHalHidl.h b/media/libaudiohal/impl/EffectHalHidl.h
index e139768..94dcd7e 100644
--- a/media/libaudiohal/impl/EffectHalHidl.h
+++ b/media/libaudiohal/impl/EffectHalHidl.h
@@ -78,6 +78,11 @@
     std::unique_ptr<StatusMQ> mStatusMQ;
     EventFlag* mEfGroup;
     bool mIsInput = false;
+    static constexpr int32_t kRTPriorityMin = 1;
+    static constexpr int32_t kRTPriorityMax = 3;
+    static constexpr int kRTPriorityDisabled = 0;
+    // Typical RealTime mHalThreadPriority ranges from 1 (low) to 3 (high).
+    int mHalThreadPriority = kRTPriorityDisabled;
 
     // Can not be constructed directly by clients.
     EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId);
@@ -93,6 +98,10 @@
             uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
             uint32_t *replySize, void *pReplyData);
     status_t setProcessBuffers();
+    status_t getHalPid(pid_t *pid) const;
+    status_t getHalWorkerTid(pid_t *tid);
+    bool requestHalThreadPriority(pid_t threadPid, pid_t threadId);
+    status_t checkHalThreadPriority();
 };
 
 } // namespace effect
diff --git a/media/libeffects/downmix/Android.bp b/media/libeffects/downmix/Android.bp
index abe622d..742626c 100644
--- a/media/libeffects/downmix/Android.bp
+++ b/media/libeffects/downmix/Android.bp
@@ -47,3 +47,29 @@
         "libhardware_headers",
     ],
 }
+
+cc_library_shared {
+    name: "libdownmixaidl",
+    srcs: [
+        "aidl/EffectDownmix.cpp",
+        "aidl/DownmixContext.cpp",
+        ":effectCommonFile",
+    ],
+    defaults: [
+        "aidlaudioservice_defaults",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    header_libs: [
+        "libaudioeffects",
+        "libhardware_headers"
+    ],
+    shared_libs: [
+        "libaudioutils",
+        "libcutils",
+        "liblog",
+    ],
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
+    ],
+}
diff --git a/media/libeffects/downmix/aidl/DownmixContext.cpp b/media/libeffects/downmix/aidl/DownmixContext.cpp
new file mode 100644
index 0000000..6869689
--- /dev/null
+++ b/media/libeffects/downmix/aidl/DownmixContext.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2022 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 "AHAL_DownmixContext"
+
+#include <android-base/logging.h>
+
+#include "DownmixContext.h"
+
+using aidl::android::hardware::audio::effect::IEffect;
+using ::android::hardware::audio::common::getChannelCount;
+
+namespace aidl::android::hardware::audio::effect {
+
+DownmixContext::DownmixContext(int statusDepth, const Parameter::Common& common)
+    : EffectContext(statusDepth, common) {
+    LOG(DEBUG) << __func__;
+    mState = DOWNMIX_STATE_UNINITIALIZED;
+    init_params(common);
+}
+
+DownmixContext::~DownmixContext() {
+    LOG(DEBUG) << __func__;
+    mState = DOWNMIX_STATE_UNINITIALIZED;
+}
+
+RetCode DownmixContext::enable() {
+    LOG(DEBUG) << __func__;
+    if (mState != DOWNMIX_STATE_INITIALIZED) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = DOWNMIX_STATE_ACTIVE;
+    return RetCode::SUCCESS;
+}
+
+RetCode DownmixContext::disable() {
+    LOG(DEBUG) << __func__;
+    if (mState != DOWNMIX_STATE_ACTIVE) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = DOWNMIX_STATE_INITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+void DownmixContext::reset() {
+    LOG(DEBUG) << __func__;
+    disable();
+    resetBuffer();
+}
+
+IEffect::Status DownmixContext::lvmProcess(float* in, float* out, int samples) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+    IEffect::Status status = {EX_ILLEGAL_ARGUMENT, 0, 0};
+
+    if (in == nullptr || out == nullptr || getInputFrameSize() != getOutputFrameSize() ||
+        getInputFrameSize() == 0) {
+        return status;
+    }
+
+    status = {EX_ILLEGAL_STATE, 0, 0};
+    if (mState == DOWNMIX_STATE_UNINITIALIZED) {
+        LOG(ERROR) << __func__ << "Trying to use an uninitialized downmixer";
+        return status;
+    } else if (mState == DOWNMIX_STATE_INITIALIZED) {
+        LOG(ERROR) << __func__ << "Trying to use a non-configured downmixer";
+        return status;
+    }
+
+    LOG(DEBUG) << __func__ << " start processing";
+    bool accumulate = false;
+    int frames = samples * sizeof(float) / getInputFrameSize();
+    if (mType == Downmix::Type::STRIP) {
+        int inputChannelCount = getChannelCount(mChMask);
+        while (frames) {
+            if (accumulate) {
+                out[0] = std::clamp(out[0] + in[0], -1.f, 1.f);
+                out[1] = std::clamp(out[1] + in[1], -1.f, 1.f);
+            } else {
+                out[0] = in[0];
+                out[1] = in[1];
+            }
+            in += inputChannelCount;
+            out += 2;
+            frames--;
+        }
+    } else {
+        int chMask = mChMask.get<AudioChannelLayout::layoutMask>();
+        if (!mChannelMix.process(in, out, frames, accumulate, (audio_channel_mask_t)chMask)) {
+            LOG(ERROR) << "Multichannel configuration " << mChMask.toString()
+                       << " is not supported";
+            return status;
+        }
+    }
+    LOG(DEBUG) << __func__ << " done processing";
+    return {STATUS_OK, samples, samples};
+}
+
+void DownmixContext::init_params(const Parameter::Common& common) {
+    // when configuring the effect, do not allow a blank or unsupported channel mask
+    AudioChannelLayout channelMask = common.input.base.channelMask;
+    if (isChannelMaskValid(channelMask)) {
+        LOG(ERROR) << "Downmix_Configure error: input channel mask " << channelMask.toString()
+                   << " not supported";
+    } else {
+        mType = Downmix::Type::FOLD;
+        mChMask = channelMask;
+        mState = DOWNMIX_STATE_INITIALIZED;
+    }
+}
+
+bool DownmixContext::isChannelMaskValid(AudioChannelLayout channelMask) {
+    if (channelMask.getTag() == AudioChannelLayout::layoutMask) return false;
+    int chMask = channelMask.get<AudioChannelLayout::layoutMask>();
+    // check against unsupported channels (up to FCC_26)
+    constexpr uint32_t MAXIMUM_CHANNEL_MASK = AudioChannelLayout::LAYOUT_22POINT2 |
+                                              AudioChannelLayout::CHANNEL_FRONT_WIDE_LEFT |
+                                              AudioChannelLayout::CHANNEL_FRONT_WIDE_RIGHT;
+    if (chMask & ~MAXIMUM_CHANNEL_MASK) {
+        LOG(ERROR) << "Unsupported channels in " << (chMask & ~MAXIMUM_CHANNEL_MASK);
+        return false;
+    }
+    return true;
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/downmix/aidl/DownmixContext.h b/media/libeffects/downmix/aidl/DownmixContext.h
new file mode 100644
index 0000000..8a244ac
--- /dev/null
+++ b/media/libeffects/downmix/aidl/DownmixContext.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2022 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 "effect-impl/EffectContext.h"
+
+#include <audio_utils/ChannelMix.h>
+
+namespace aidl::android::hardware::audio::effect {
+
+using media::audio::common::AudioChannelLayout;
+using media::audio::common::AudioDeviceDescription;
+
+enum DownmixState {
+    DOWNMIX_STATE_UNINITIALIZED,
+    DOWNMIX_STATE_INITIALIZED,
+    DOWNMIX_STATE_ACTIVE,
+};
+
+class DownmixContext final : public EffectContext {
+  public:
+    DownmixContext(int statusDepth, const Parameter::Common& common);
+    ~DownmixContext();
+    RetCode enable();
+    RetCode disable();
+    void reset();
+
+    RetCode setDmType(Downmix::Type type) {
+        mType = type;
+        return RetCode::SUCCESS;
+    }
+    Downmix::Type getDmType() const { return mType; }
+
+    RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override {
+        // FIXME change volume
+        mVolumeStereo = volumeStereo;
+        return RetCode::SUCCESS;
+    }
+    Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
+
+    RetCode setOutputDevice(const AudioDeviceDescription& device) override {
+        // FIXME change type if playing on headset vs speaker
+        mOutputDevice = device;
+        return RetCode::SUCCESS;
+    }
+    AudioDeviceDescription getOutputDevice() { return mOutputDevice; }
+
+    IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+  private:
+    DownmixState mState;
+    Downmix::Type mType;
+    AudioChannelLayout mChMask;
+    ::android::audio_utils::channels::ChannelMix mChannelMix;
+
+    // Common Params
+    AudioDeviceDescription mOutputDevice;
+    Parameter::VolumeStereo mVolumeStereo;
+
+    void init_params(const Parameter::Common& common);
+    bool isChannelMaskValid(AudioChannelLayout channelMask);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/downmix/aidl/EffectDownmix.cpp b/media/libeffects/downmix/aidl/EffectDownmix.cpp
new file mode 100644
index 0000000..17d0736
--- /dev/null
+++ b/media/libeffects/downmix/aidl/EffectDownmix.cpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2022 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 "AHAL_DownmixImpl"
+
+#include <android-base/logging.h>
+
+#include "EffectDownmix.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::DownmixImpl;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kDownmixImplUUID;
+using aidl::android::hardware::audio::effect::kDownmixTypeUUID;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (!in_impl_uuid || *in_impl_uuid != kDownmixImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<DownmixImpl>();
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kDownmixImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    *_aidl_return = DownmixImpl::kDescriptor;
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string DownmixImpl::kEffectName = "Multichannel Downmix To Stereo";
+const Descriptor DownmixImpl::kDescriptor = {
+        .common = {
+                .id = {.type = kDownmixTypeUUID, .uuid = kDownmixImplUUID, .proxy = std::nullopt},
+                .flags = {.type = Flags::Type::INSERT, .insert = Flags::Insert::FIRST},
+                .name = DownmixImpl::kEffectName,
+                .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus DownmixImpl::getDescriptor(Descriptor* _aidl_return) {
+    RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+    LOG(DEBUG) << __func__ << kDescriptor.toString();
+    *_aidl_return = kDescriptor;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DownmixImpl::setParameterCommon(const Parameter& param) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto tag = param.getTag();
+    switch (tag) {
+        case Parameter::common:
+            RETURN_IF(mContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setCommFailed");
+            break;
+        case Parameter::deviceDescription:
+            RETURN_IF(mContext->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
+            break;
+        case Parameter::mode:
+            RETURN_IF(mContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setModeFailed");
+            break;
+        case Parameter::source:
+            RETURN_IF(mContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setSourceFailed");
+            break;
+        case Parameter::volumeStereo:
+            RETURN_IF(mContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed");
+            break;
+        default: {
+            LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "commonParamNotSupported");
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DownmixImpl::commandImpl(CommandId command) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    switch (command) {
+        case CommandId::START:
+            mContext->enable();
+            break;
+        case CommandId::STOP:
+            mContext->disable();
+            break;
+        case CommandId::RESET:
+            mContext->reset();
+            break;
+        default:
+            LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "commandIdNotSupported");
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DownmixImpl::setParameterSpecific(const Parameter::Specific& specific) {
+    RETURN_IF(Parameter::Specific::downmix != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+              "EffectNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto& dmParam = specific.get<Parameter::Specific::downmix>();
+    auto tag = dmParam.getTag();
+
+    switch (tag) {
+        case Downmix::type: {
+            RETURN_IF(mContext->setDmType(dmParam.get<Downmix::type>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setTypeFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "DownmixTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus DownmixImpl::getParameterSpecific(const Parameter::Id& id,
+                                                     Parameter::Specific* specific) {
+    RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+    auto tag = id.getTag();
+    RETURN_IF(Parameter::Id::downmixTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    auto dmId = id.get<Parameter::Id::downmixTag>();
+    auto dmIdTag = dmId.getTag();
+    switch (dmIdTag) {
+        case Downmix::Id::commonTag:
+            return getParameterDownmix(dmId.get<Downmix::Id::commonTag>(), specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(dmIdTag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "DownmixTagNotSupported");
+    }
+}
+
+ndk::ScopedAStatus DownmixImpl::getParameterDownmix(const Downmix::Tag& tag,
+                                                    Parameter::Specific* specific) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    Downmix dmParam;
+    switch (tag) {
+        case Downmix::type: {
+            dmParam.set<Downmix::type>(mContext->getDmType());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "DownmixTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::downmix>(dmParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> DownmixImpl::createContext(const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+        return mContext;
+    }
+
+    mContext = std::make_shared<DownmixContext>(1 /* statusFmqDepth */, common);
+    return mContext;
+}
+
+RetCode DownmixImpl::releaseContext() {
+    if (mContext) {
+        mContext.reset();
+    }
+    return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status DownmixImpl::effectProcessImpl(float* in, float* out, int sampleToProcess) {
+    if (!mContext) {
+        LOG(ERROR) << __func__ << " nullContext";
+        return {EX_NULL_POINTER, 0, 0};
+    }
+    return mContext->lvmProcess(in, out, sampleToProcess);
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/downmix/aidl/EffectDownmix.h b/media/libeffects/downmix/aidl/EffectDownmix.h
new file mode 100644
index 0000000..d590133
--- /dev/null
+++ b/media/libeffects/downmix/aidl/EffectDownmix.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 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 <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <audio_effects/effect_downmix.h>
+
+#include "DownmixContext.h"
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class DownmixImpl final : public EffectImpl {
+  public:
+    static const std::string kEffectName;
+    static const Descriptor kDescriptor;
+    DownmixImpl() { LOG(DEBUG) << __func__; }
+    ~DownmixImpl() {
+        cleanUp();
+        LOG(DEBUG) << __func__;
+    }
+
+    ndk::ScopedAStatus commandImpl(CommandId command) override;
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+    ndk::ScopedAStatus setParameterCommon(const Parameter& param) override;
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+                                            Parameter::Specific* specific) override;
+    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    RetCode releaseContext() override;
+
+    std::shared_ptr<EffectContext> getContext() override { return mContext; }
+    std::string getEffectName() override { return kEffectName; }
+
+  private:
+    std::shared_ptr<DownmixContext> mContext;
+    ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific);
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/Android.bp b/media/libeffects/hapticgenerator/Android.bp
index ba511fe..07ba492 100644
--- a/media/libeffects/hapticgenerator/Android.bp
+++ b/media/libeffects/hapticgenerator/Android.bp
@@ -22,6 +22,23 @@
     default_applicable_licenses: ["frameworks_av_license"],
 }
 
+cc_defaults {
+    name : "hapticgeneratordefaults",
+    srcs: [
+        "Processors.cpp",
+    ],
+    shared_libs: [
+        "libaudioutils",
+        "libbase",
+        "liblog",
+        "libutils",
+        "libvibratorutils",
+    ],
+    header_libs: [
+        "libaudioeffects",
+    ],
+}
+
 cc_library_shared {
     name: "libhapticgenerator",
 
@@ -29,7 +46,10 @@
 
     srcs: [
         "EffectHapticGenerator.cpp",
-        "Processors.cpp",
+    ],
+
+    defaults: [
+        "hapticgeneratordefaults",
     ],
 
     cflags: [
@@ -43,17 +63,30 @@
         "-fvisibility=hidden",
     ],
 
-    shared_libs: [
-        "libaudioutils",
-        "libbase",
-        "liblog",
-        "libutils",
-        "libvibratorutils",
+    relative_install_path: "soundfx",
+}
+
+cc_library_shared {
+    name: "libhapticgeneratoraidl",
+
+    srcs: [
+        "aidl/EffectHapticGenerator.cpp",
+        "aidl/HapticGeneratorContext.cpp",
+        ":effectCommonFile",
     ],
 
-    relative_install_path: "soundfx",
+    defaults: [
+        "aidlaudioservice_defaults",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+        "hapticgeneratordefaults",
+    ],
 
-    header_libs: [
-        "libaudioeffects",
+    cflags: [
+        "-Wthread-safety",
+    ],
+
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
     ],
 }
diff --git a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp
new file mode 100644
index 0000000..7e22482
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2022 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 "AHAL_HapticGeneratorImpl"
+
+#include "EffectHapticGenerator.h"
+
+#include <android-base/logging.h>
+#include <audio_effects/effect_hapticgenerator.h>
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::HapticGeneratorImpl;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kHapticGeneratorImplUUID;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (!in_impl_uuid || *in_impl_uuid != kHapticGeneratorImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<HapticGeneratorImpl>();
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kHapticGeneratorImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    *_aidl_return = HapticGeneratorImpl::kDescriptor;
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string HapticGeneratorImpl::kEffectName = "Haptic Generator";
+const Descriptor HapticGeneratorImpl::kDescriptor = {
+        .common = {.id = {.type = kHapticGeneratorTypeUUID,
+                          .uuid = kHapticGeneratorImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT, .insert = Flags::Insert::FIRST},
+                   .name = HapticGeneratorImpl::kEffectName,
+                   .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus HapticGeneratorImpl::getDescriptor(Descriptor* _aidl_return) {
+    RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+    LOG(DEBUG) << __func__ << kDescriptor.toString();
+    *_aidl_return = kDescriptor;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::commandImpl(CommandId command) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    switch (command) {
+        case CommandId::START:
+            mContext->enable();
+            break;
+        case CommandId::STOP:
+            mContext->disable();
+            break;
+        case CommandId::RESET:
+            mContext->reset();
+            break;
+        default:
+            LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "commandIdNotSupported");
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::setParameterSpecific(const Parameter::Specific& specific) {
+    RETURN_IF(Parameter::Specific::hapticGenerator != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+              "EffectNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto& hgParam = specific.get<Parameter::Specific::hapticGenerator>();
+    auto tag = hgParam.getTag();
+
+    switch (tag) {
+        case HapticGenerator::hapticScales: {
+            RETURN_IF(mContext->setHgHapticScales(hgParam.get<HapticGenerator::hapticScales>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setHapticScaleFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case HapticGenerator::vibratorInfo: {
+            RETURN_IF(mContext->setHgVibratorInformation(
+                              hgParam.get<HapticGenerator::vibratorInfo>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setVibratorInfoFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::getParameterSpecific(const Parameter::Id& id,
+                                                             Parameter::Specific* specific) {
+    RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+    auto tag = id.getTag();
+    RETURN_IF(Parameter::Id::hapticGeneratorTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    auto hgId = id.get<Parameter::Id::hapticGeneratorTag>();
+    auto hgIdTag = hgId.getTag();
+    switch (hgIdTag) {
+        case HapticGenerator::Id::commonTag:
+            return getParameterHapticGenerator(hgId.get<HapticGenerator::Id::commonTag>(),
+                                               specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(hgIdTag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+    }
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::getParameterHapticGenerator(const HapticGenerator::Tag& tag,
+                                                                    Parameter::Specific* specific) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    HapticGenerator hgParam;
+    switch (tag) {
+        case HapticGenerator::hapticScales: {
+            hgParam.set<HapticGenerator::hapticScales>(mContext->getHgHapticScales());
+            break;
+        }
+        case HapticGenerator::vibratorInfo: {
+            hgParam.set<HapticGenerator::vibratorInfo>(mContext->getHgVibratorInformation());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::hapticGenerator>(hgParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> HapticGeneratorImpl::createContext(const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+        return mContext;
+    }
+
+    mContext = std::make_shared<HapticGeneratorContext>(1 /* statusFmqDepth */, common);
+    return mContext;
+}
+
+RetCode HapticGeneratorImpl::releaseContext() {
+    if (mContext) {
+        mContext->reset();
+    }
+    return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status HapticGeneratorImpl::effectProcessImpl(float* in, float* out, int samples) {
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!mContext, status, "nullContext");
+    return mContext->lvmProcess(in, out, samples);
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
new file mode 100644
index 0000000..02ca392
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 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 <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "HapticGeneratorContext.h"
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class HapticGeneratorImpl final : public EffectImpl {
+  public:
+    static const std::string kEffectName;
+    static const Descriptor kDescriptor;
+    HapticGeneratorImpl() { LOG(DEBUG) << __func__; }
+    ~HapticGeneratorImpl() {
+        cleanUp();
+        LOG(DEBUG) << __func__;
+    }
+
+    ndk::ScopedAStatus commandImpl(CommandId command) override;
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+                                            Parameter::Specific* specific) override;
+    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    RetCode releaseContext() override;
+
+    std::shared_ptr<EffectContext> getContext() override { return mContext; }
+    std::string getEffectName() override { return kEffectName; }
+
+  private:
+    std::shared_ptr<HapticGeneratorContext> mContext;
+    ndk::ScopedAStatus getParameterHapticGenerator(const HapticGenerator::Tag& tag,
+                                                   Parameter::Specific* specific);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
new file mode 100644
index 0000000..64f51c3
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2022 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 "AHAL_HapticGeneratorContext"
+
+#include <Utils.h>
+#include <android-base/parsedouble.h>
+#include <android-base/properties.h>
+
+#include "HapticGeneratorContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+HapticGeneratorContext::HapticGeneratorContext(int statusDepth, const Parameter::Common& common)
+    : EffectContext(statusDepth, common) {
+    LOG(DEBUG) << __func__;
+    mState = HAPTIC_GENERATOR_STATE_UNINITIALIZED;
+    mSampleRate = common.input.base.sampleRate;
+    mFrameCount = common.input.frameCount;
+    init_params(common.input.base.channelMask, common.output.base.channelMask);
+}
+
+HapticGeneratorContext::~HapticGeneratorContext() {
+    LOG(DEBUG) << __func__;
+    mState = HAPTIC_GENERATOR_STATE_UNINITIALIZED;
+}
+
+RetCode HapticGeneratorContext::enable() {
+    if (mState != HAPTIC_GENERATOR_STATE_INITIALIZED) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = HAPTIC_GENERATOR_STATE_ACTIVE;
+    return RetCode::SUCCESS;
+}
+
+RetCode HapticGeneratorContext::disable() {
+    if (mState != HAPTIC_GENERATOR_STATE_ACTIVE) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = HAPTIC_GENERATOR_STATE_INITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+void HapticGeneratorContext::reset() {
+    for (auto& filter : mProcessorsRecord.filters) {
+        filter->clear();
+    }
+    for (auto& slowEnv : mProcessorsRecord.slowEnvs) {
+        slowEnv->clear();
+    }
+    for (auto& distortion : mProcessorsRecord.distortions) {
+        distortion->clear();
+    }
+}
+
+RetCode HapticGeneratorContext::setHgHapticScales(
+        const std::vector<HapticGenerator::HapticScale> hapticScales) {
+    std::lock_guard lg(mMutex);
+    for (auto hapticScale : hapticScales) {
+        mParams.mHapticScales.insert_or_assign(hapticScale.id, hapticScale.scale);
+    }
+    mParams.mMaxVibratorScale = HapticGenerator::VibratorScale::MUTE;
+    for (const auto& [id, vibratorScale] : mParams.mHapticScales) {
+        mParams.mMaxVibratorScale = std::max(mParams.mMaxVibratorScale, vibratorScale);
+    }
+    return RetCode::SUCCESS;
+}
+
+HapticGenerator::VibratorInformation HapticGeneratorContext::getHgVibratorInformation() {
+    std::lock_guard lg(mMutex);
+    return mParams.mVibratorInfo;
+}
+
+std::vector<HapticGenerator::HapticScale> HapticGeneratorContext::getHgHapticScales() {
+    std::vector<HapticGenerator::HapticScale> result;
+    std::lock_guard lg(mMutex);
+    for (const auto& [id, vibratorScale] : mParams.mHapticScales) {
+        result.push_back({id, vibratorScale});
+    }
+    return result;
+}
+
+RetCode HapticGeneratorContext::setHgVibratorInformation(
+        const HapticGenerator::VibratorInformation& vibratorInfo) {
+    {
+        std::lock_guard lg(mMutex);
+        mParams.mVibratorInfo = vibratorInfo;
+
+        if (mProcessorsRecord.bpf != nullptr) {
+            mProcessorsRecord.bpf->setCoefficients(
+                    ::android::audio_effect::haptic_generator::bpfCoefs(
+                            mParams.mVibratorInfo.resonantFrequencyHz, DEFAULT_BPF_Q, mSampleRate));
+        }
+        if (mProcessorsRecord.bsf != nullptr) {
+            mProcessorsRecord.bsf->setCoefficients(
+                    ::android::audio_effect::haptic_generator::bsfCoefs(
+                            mParams.mVibratorInfo.resonantFrequencyHz,
+                            mParams.mVibratorInfo.qFactor, mParams.mVibratorInfo.qFactor / 2.0f,
+                            mSampleRate));
+        }
+    }
+    configure();
+    return RetCode::SUCCESS;
+}
+
+IEffect::Status HapticGeneratorContext::lvmProcess(float* in, float* out, int samples) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!in, status, "nullInput");
+    RETURN_VALUE_IF(!out, status, "nullOutput");
+    status = {EX_ILLEGAL_STATE, 0, 0};
+    RETURN_VALUE_IF(getInputFrameSize() != getOutputFrameSize(), status, "FrameSizeMismatch");
+    auto frameSize = getInputFrameSize();
+    RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
+
+    LOG(DEBUG) << __func__ << " start processing";
+    // The audio data must not be modified but just written to
+    // output buffer according the access mode.
+    bool accumulate = false;
+    if (in != out) {
+        for (int i = 0; i < samples; i++) {
+            if (accumulate) {
+                out[i] += in[i];
+            } else {
+                out[i] = in[i];
+            }
+        }
+    }
+
+    if (mState != HAPTIC_GENERATOR_STATE_ACTIVE) {
+        return status;
+    }
+
+    std::lock_guard lg(mMutex);
+    if (mParams.mMaxVibratorScale == HapticGenerator::VibratorScale::MUTE) {
+        // Haptic channels are muted, not need to generate haptic data.
+        return {STATUS_OK, samples, samples};
+    }
+
+    // Resize buffer if the haptic sample count is greater than buffer size.
+    size_t hapticSampleCount = mFrameCount * mParams.mHapticChannelCount;
+    if (hapticSampleCount > mInputBuffer.size()) {
+        // The inputBuffer and outputBuffer must have the same size, which must be at least
+        // the haptic sample count.
+        mInputBuffer.resize(hapticSampleCount);
+        mOutputBuffer.resize(hapticSampleCount);
+    }
+
+    // Construct input buffer according to haptic channel source
+    for (size_t i = 0; i < mFrameCount; ++i) {
+        for (size_t j = 0; j < mParams.mHapticChannelCount; ++j) {
+            mInputBuffer[i * mParams.mHapticChannelCount + j] =
+                    in[i * mParams.mAudioChannelCount + mParams.mHapticChannelSource[j]];
+        }
+    }
+
+    float* hapticOutBuffer =
+            runProcessingChain(mInputBuffer.data(), mOutputBuffer.data(), mFrameCount);
+    ::android::os::scaleHapticData(
+            hapticOutBuffer, hapticSampleCount,
+            static_cast<::android::os::HapticScale>(mParams.mMaxVibratorScale),
+            mParams.mVibratorInfo.qFactor);
+
+    // For haptic data, the haptic playback thread will copy the data from effect input
+    // buffer, which contains haptic data at the end of the buffer, directly to sink buffer.
+    // In that case, copy haptic data to input buffer instead of output buffer.
+    // Note: this may not work with rpc/binder calls
+    int offset = samples;
+    for (int i = 0; i < hapticSampleCount; ++i) {
+        in[samples + i] = hapticOutBuffer[i];
+    }
+    return {STATUS_OK, samples, static_cast<int32_t>(samples + hapticSampleCount)};
+}
+
+void HapticGeneratorContext::init_params(media::audio::common::AudioChannelLayout inputChMask,
+                                         media::audio::common::AudioChannelLayout outputChMask) {
+    std::lock_guard lg(mMutex);
+    mParams.mMaxVibratorScale = HapticGenerator::VibratorScale::MUTE;
+    mParams.mVibratorInfo.resonantFrequencyHz = DEFAULT_RESONANT_FREQUENCY;
+    mParams.mVibratorInfo.qFactor = DEFAULT_BSF_ZERO_Q;
+
+    mParams.mAudioChannelCount = ::android::hardware::audio::common::getChannelCount(
+            inputChMask, ~media::audio::common::AudioChannelLayout::LAYOUT_HAPTIC_AB);
+    mParams.mHapticChannelCount = ::android::hardware::audio::common::getChannelCount(
+            outputChMask, media::audio::common::AudioChannelLayout::LAYOUT_HAPTIC_AB);
+    LOG_ALWAYS_FATAL_IF(mParams.mHapticChannelCount > 2, "haptic channel count is too large");
+    for (size_t i = 0; i < mParams.mHapticChannelCount; ++i) {
+        // By default, use the first audio channel to generate haptic channels.
+        mParams.mHapticChannelSource[i] = 0;
+    }
+
+    mState = HAPTIC_GENERATOR_STATE_INITIALIZED;
+}
+
+float HapticGeneratorContext::getDistortionOutputGain() {
+    float distortionOutputGain = getFloatProperty(
+            "vendor.audio.hapticgenerator.distortion.output.gain", DEFAULT_DISTORTION_OUTPUT_GAIN);
+    LOG(DEBUG) << "Using distortion output gain as " << distortionOutputGain;
+    return distortionOutputGain;
+}
+
+float HapticGeneratorContext::getFloatProperty(const std::string& key, float defaultValue) {
+    float result;
+    std::string value = ::android::base::GetProperty(key, "");
+    if (!value.empty() && ::android::base::ParseFloat(value, &result)) {
+        return result;
+    }
+    return defaultValue;
+}
+
+void HapticGeneratorContext::addBiquadFilter(std::shared_ptr<HapticBiquadFilter> filter) {
+    // The process chain captures the shared pointer of the filter in lambda.
+    // The process record will keep a shared pointer to the filter so that it is possible to
+    // access the filter outside of the process chain.
+    mProcessorsRecord.filters.push_back(filter);
+    mProcessingChain.push_back([filter](float* out, const float* in, size_t frameCount) {
+        filter->process(out, in, frameCount);
+    });
+}
+
+/**
+ * Build haptic generator processing chain.
+ */
+void HapticGeneratorContext::buildProcessingChain() {
+    std::lock_guard lg(mMutex);
+    const size_t channelCount = mParams.mHapticChannelCount;
+    float highPassCornerFrequency = 50.0f;
+    auto hpf = ::android::audio_effect::haptic_generator::createHPF2(highPassCornerFrequency,
+                                                                     mSampleRate, channelCount);
+    addBiquadFilter(hpf);
+    float lowPassCornerFrequency = 9000.0f;
+    auto lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency,
+                                                                     mSampleRate, channelCount);
+    addBiquadFilter(lpf);
+
+    auto ramp = std::make_shared<::android::audio_effect::haptic_generator::Ramp>(
+            channelCount);  // ramp = half-wave rectifier.
+    // The process chain captures the shared pointer of the ramp in lambda. It will be the only
+    // reference to the ramp.
+    // The process record will keep a weak pointer to the ramp so that it is possible to access
+    // the ramp outside of the process chain.
+    mProcessorsRecord.ramps.push_back(ramp);
+    mProcessingChain.push_back([ramp](float* out, const float* in, size_t frameCount) {
+        ramp->process(out, in, frameCount);
+    });
+
+    highPassCornerFrequency = 60.0f;
+    hpf = ::android::audio_effect::haptic_generator::createHPF2(highPassCornerFrequency,
+                                                                mSampleRate, channelCount);
+    addBiquadFilter(hpf);
+    lowPassCornerFrequency = 700.0f;
+    lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency, mSampleRate,
+                                                                channelCount);
+    addBiquadFilter(lpf);
+
+    lowPassCornerFrequency = 400.0f;
+    lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency, mSampleRate,
+                                                                channelCount);
+    addBiquadFilter(lpf);
+    lowPassCornerFrequency = 500.0f;
+    lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency, mSampleRate,
+                                                                channelCount);
+    addBiquadFilter(lpf);
+
+    auto bpf = ::android::audio_effect::haptic_generator::createBPF(
+            mParams.mVibratorInfo.resonantFrequencyHz, DEFAULT_BPF_Q, mSampleRate, channelCount);
+    mProcessorsRecord.bpf = bpf;
+    addBiquadFilter(bpf);
+
+    float normalizationPower = DEFAULT_SLOW_ENV_NORMALIZATION_POWER;
+    // The process chain captures the shared pointer of the slow envelope in lambda. It will
+    // be the only reference to the slow envelope.
+    // The process record will keep a weak pointer to the slow envelope so that it is possible
+    // to access the slow envelope outside of the process chain.
+    // SlowEnvelope = partial normalizer, or AGC.
+    auto slowEnv = std::make_shared<::android::audio_effect::haptic_generator::SlowEnvelope>(
+            5.0f /*envCornerFrequency*/, mSampleRate, normalizationPower, 0.01f /*envOffset*/,
+            channelCount);
+    mProcessorsRecord.slowEnvs.push_back(slowEnv);
+    mProcessingChain.push_back([slowEnv](float* out, const float* in, size_t frameCount) {
+        slowEnv->process(out, in, frameCount);
+    });
+
+    auto bsf = ::android::audio_effect::haptic_generator::createBSF(
+            mParams.mVibratorInfo.resonantFrequencyHz, mParams.mVibratorInfo.qFactor,
+            mParams.mVibratorInfo.qFactor / 2.0f, mSampleRate, channelCount);
+    mProcessorsRecord.bsf = bsf;
+    addBiquadFilter(bsf);
+
+    // The process chain captures the shared pointer of the Distortion in lambda. It will
+    // be the only reference to the Distortion.
+    // The process record will keep a weak pointer to the Distortion so that it is possible
+    // to access the Distortion outside of the process chain.
+    auto distortion = std::make_shared<::android::audio_effect::haptic_generator::Distortion>(
+            DEFAULT_DISTORTION_CORNER_FREQUENCY, mSampleRate, DEFAULT_DISTORTION_INPUT_GAIN,
+            DEFAULT_DISTORTION_CUBE_THRESHOLD, getDistortionOutputGain(), channelCount);
+    mProcessorsRecord.distortions.push_back(distortion);
+    mProcessingChain.push_back([distortion](float* out, const float* in, size_t frameCount) {
+        distortion->process(out, in, frameCount);
+    });
+}
+
+void HapticGeneratorContext::configure() {
+    mProcessingChain.clear();
+    mProcessorsRecord.filters.clear();
+    mProcessorsRecord.ramps.clear();
+    mProcessorsRecord.slowEnvs.clear();
+    mProcessorsRecord.distortions.clear();
+
+    buildProcessingChain();
+}
+
+/**
+ * Run the processing chain to generate haptic data from audio data
+ *
+ * @param buf1 a buffer contains raw audio data
+ * @param buf2 a buffer that is large enough to keep all the data
+ * @param frameCount frame count of the data
+ *
+ * @return a pointer to the output buffer
+ */
+float* HapticGeneratorContext::runProcessingChain(float* buf1, float* buf2, size_t frameCount) {
+    float* in = buf1;
+    float* out = buf2;
+    for (const auto processingFunc : mProcessingChain) {
+        processingFunc(out, in, frameCount);
+        std::swap(in, out);
+    }
+    return in;
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
new file mode 100644
index 0000000..dc43feb
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 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 <android-base/thread_annotations.h>
+#include <vibrator/ExternalVibrationUtils.h>
+#include <map>
+
+#include "Processors.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+enum HapticGeneratorState {
+    HAPTIC_GENERATOR_STATE_UNINITIALIZED,
+    HAPTIC_GENERATOR_STATE_INITIALIZED,
+    HAPTIC_GENERATOR_STATE_ACTIVE,
+};
+
+struct HapticGeneratorParam {
+    // The audio channels used to generate haptic channels. The first channel will be used to
+    // generate HAPTIC_A, The second channel will be used to generate HAPTIC_B.
+    // The value will be offset of audio channel
+    int mHapticChannelSource[2];
+
+    int mHapticChannelCount;
+    int mAudioChannelCount;
+
+    HapticGenerator::HapticScale mHapticScale;
+    std::map<int, HapticGenerator::VibratorScale> mHapticScales;
+    // max intensity will be used to scale haptic data.
+    HapticGenerator::VibratorScale mMaxVibratorScale;
+
+    HapticGenerator::VibratorInformation mVibratorInfo;
+};
+
+// A structure to keep all shared pointers for all processors in HapticGenerator.
+struct HapticGeneratorProcessorsRecord {
+    std::vector<std::shared_ptr<HapticBiquadFilter>> filters;
+    std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::Ramp>> ramps;
+    std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::SlowEnvelope>> slowEnvs;
+    std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::Distortion>> distortions;
+
+    // Cache band-pass filter and band-stop filter for updating parameters
+    // according to vibrator info
+    std::shared_ptr<HapticBiquadFilter> bpf;
+    std::shared_ptr<HapticBiquadFilter> bsf;
+};
+
+class HapticGeneratorContext final : public EffectContext {
+  public:
+    HapticGeneratorContext(int statusDepth, const Parameter::Common& common);
+    ~HapticGeneratorContext();
+    RetCode enable();
+    RetCode disable();
+    void reset();
+
+    RetCode setHgHapticScales(const std::vector<HapticGenerator::HapticScale> hapticScales);
+    std::vector<HapticGenerator::HapticScale> getHgHapticScales();
+
+    RetCode setHgVibratorInformation(const HapticGenerator::VibratorInformation& vibratorInfo);
+    HapticGenerator::VibratorInformation getHgVibratorInformation();
+
+    IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+  private:
+    static constexpr float DEFAULT_RESONANT_FREQUENCY = 150.0f;
+    static constexpr float DEFAULT_BSF_ZERO_Q = 8.0f;
+    static constexpr float DEFAULT_BSF_POLE_Q = 4.0f;
+    static constexpr float DEFAULT_DISTORTION_OUTPUT_GAIN = 1.5f;
+    static constexpr float DEFAULT_BPF_Q = 1.0f;
+    static constexpr float DEFAULT_SLOW_ENV_NORMALIZATION_POWER = -0.8f;
+    static constexpr float DEFAULT_DISTORTION_CORNER_FREQUENCY = 300.0f;
+    static constexpr float DEFAULT_DISTORTION_INPUT_GAIN = 0.3f;
+    static constexpr float DEFAULT_DISTORTION_CUBE_THRESHOLD = 0.1f;
+
+    std::mutex mMutex;
+    HapticGeneratorState mState;
+    HapticGeneratorParam mParams GUARDED_BY(mMutex);
+    int mSampleRate;
+    int mFrameCount = 0;
+
+    // A cache for all shared pointers of the HapticGenerator
+    struct HapticGeneratorProcessorsRecord mProcessorsRecord;
+
+    // Using a vector of functions to record the processing chain for haptic-generating algorithm.
+    // The three parameters of the processing functions are pointer to output buffer, pointer to
+    // input buffer and frame count.
+    std::vector<std::function<void(float*, const float*, size_t)>> mProcessingChain;
+
+    // inputBuffer is where to keep input buffer for the generating algorithm. It will be
+    // constructed according to hapticChannelSource.
+    std::vector<float> mInputBuffer;
+
+    // outputBuffer is a buffer having the same length as inputBuffer. It can be used as
+    // intermediate buffer in the generating algorithm.
+    std::vector<float> mOutputBuffer;
+
+    void init_params(media::audio::common::AudioChannelLayout inputChMask,
+                     media::audio::common::AudioChannelLayout outputChMask);
+    void configure();
+
+    float getDistortionOutputGain();
+    float getFloatProperty(const std::string& key, float defaultValue);
+    void addBiquadFilter(std::shared_ptr<HapticBiquadFilter> filter);
+    void buildProcessingChain();
+    float* runProcessingChain(float* buf1, float* buf2, size_t frameCount);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/Android.bp b/media/libeffects/loudness/Android.bp
index bcd6947..fc0217b 100644
--- a/media/libeffects/loudness/Android.bp
+++ b/media/libeffects/loudness/Android.bp
@@ -44,3 +44,32 @@
 
     header_libs: ["libaudioeffects"],
 }
+
+cc_library_shared {
+    name: "libloudnessenhanceraidl",
+    srcs: [
+        "aidl/EffectLoudnessEnhancer.cpp",
+        "aidl/LoudnessEnhancerContext.cpp",
+        "dsp/core/dynamic_range_compression.cpp",
+        ":effectCommonFile",
+    ],
+    defaults: [
+        "aidlaudioservice_defaults",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    header_libs: [
+        "libaudioeffects",
+        "libhardware_headers",
+    ],
+    cflags: [
+        "-Wthread-safety",
+    ],
+    shared_libs: [
+        "libcutils",
+        "liblog",
+    ],
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
+    ],
+}
diff --git a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp
new file mode 100644
index 0000000..9d8bc80
--- /dev/null
+++ b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2022 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 "AHAL_LoudnessEnhancerImpl"
+
+#include <android-base/logging.h>
+
+#include "EffectLoudnessEnhancer.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kLoudnessEnhancerImplUUID;
+using aidl::android::hardware::audio::effect::LoudnessEnhancerImpl;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (!in_impl_uuid || *in_impl_uuid != kLoudnessEnhancerImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<LoudnessEnhancerImpl>();
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kLoudnessEnhancerImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    *_aidl_return = LoudnessEnhancerImpl::kDescriptor;
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string LoudnessEnhancerImpl::kEffectName = "Loudness Enhancer";
+const Descriptor LoudnessEnhancerImpl::kDescriptor = {
+        .common = {.id = {.type = kLoudnessEnhancerTypeUUID,
+                          .uuid = kLoudnessEnhancerImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT, .insert = Flags::Insert::FIRST},
+                   .name = LoudnessEnhancerImpl::kEffectName,
+                   .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::getDescriptor(Descriptor* _aidl_return) {
+    RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+    LOG(DEBUG) << __func__ << kDescriptor.toString();
+    *_aidl_return = kDescriptor;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::commandImpl(CommandId command) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    switch (command) {
+        case CommandId::START:
+            mContext->enable();
+            break;
+        case CommandId::STOP:
+            mContext->disable();
+            break;
+        case CommandId::RESET:
+            mContext->disable();
+            mContext->resetBuffer();
+            break;
+        default:
+            LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "commandIdNotSupported");
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::setParameterSpecific(const Parameter::Specific& specific) {
+    RETURN_IF(Parameter::Specific::loudnessEnhancer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+              "EffectNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto& leParam = specific.get<Parameter::Specific::loudnessEnhancer>();
+    auto tag = leParam.getTag();
+
+    switch (tag) {
+        case LoudnessEnhancer::gainMb: {
+            RETURN_IF(mContext->setLeGain(leParam.get<LoudnessEnhancer::gainMb>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setGainMbFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::getParameterSpecific(const Parameter::Id& id,
+                                                              Parameter::Specific* specific) {
+    RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+    auto tag = id.getTag();
+    RETURN_IF(Parameter::Id::loudnessEnhancerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    auto leId = id.get<Parameter::Id::loudnessEnhancerTag>();
+    auto leIdTag = leId.getTag();
+    switch (leIdTag) {
+        case LoudnessEnhancer::Id::commonTag:
+            return getParameterLoudnessEnhancer(leId.get<LoudnessEnhancer::Id::commonTag>(),
+                                                specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(leIdTag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+    }
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::getParameterLoudnessEnhancer(
+        const LoudnessEnhancer::Tag& tag, Parameter::Specific* specific) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    LoudnessEnhancer leParam;
+    switch (tag) {
+        case LoudnessEnhancer::gainMb: {
+            leParam.set<LoudnessEnhancer::gainMb>(mContext->getLeGain());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::loudnessEnhancer>(leParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> LoudnessEnhancerImpl::createContext(
+        const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+        return mContext;
+    }
+
+    mContext = std::make_shared<LoudnessEnhancerContext>(1 /* statusFmqDepth */, common);
+    return mContext;
+}
+
+RetCode LoudnessEnhancerImpl::releaseContext() {
+    if (mContext) {
+        mContext->disable();
+        mContext->resetBuffer();
+    }
+    return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status LoudnessEnhancerImpl::effectProcessImpl(float* in, float* out, int samples) {
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!mContext, status, "nullContext");
+    return mContext->lvmProcess(in, out, samples);
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
new file mode 100644
index 0000000..6402fd2
--- /dev/null
+++ b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 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 <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+#include "LoudnessEnhancerContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class LoudnessEnhancerImpl final : public EffectImpl {
+  public:
+    static const std::string kEffectName;
+    static const Descriptor kDescriptor;
+    LoudnessEnhancerImpl() { LOG(DEBUG) << __func__; }
+    ~LoudnessEnhancerImpl() {
+        cleanUp();
+        LOG(DEBUG) << __func__;
+    }
+
+    ndk::ScopedAStatus commandImpl(CommandId command) override;
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+                                            Parameter::Specific* specific) override;
+    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    RetCode releaseContext() override;
+
+    std::shared_ptr<EffectContext> getContext() override { return mContext; }
+    std::string getEffectName() override { return kEffectName; }
+
+  private:
+    std::shared_ptr<LoudnessEnhancerContext> mContext;
+    ndk::ScopedAStatus getParameterLoudnessEnhancer(const LoudnessEnhancer::Tag& tag,
+                                                    Parameter::Specific* specific);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp
new file mode 100644
index 0000000..033b222
--- /dev/null
+++ b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2022 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 "LoudnessEnhancerContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+LoudnessEnhancerContext::LoudnessEnhancerContext(int statusDepth, const Parameter::Common& common)
+    : EffectContext(statusDepth, common) {
+    LOG(DEBUG) << __func__;
+    mState = LOUDNESS_ENHANCER_STATE_UNINITIALIZED;
+    mSampleRate = common.input.base.sampleRate;
+    init_params();
+}
+
+LoudnessEnhancerContext::~LoudnessEnhancerContext() {
+    LOG(DEBUG) << __func__;
+    mState = LOUDNESS_ENHANCER_STATE_UNINITIALIZED;
+}
+
+RetCode LoudnessEnhancerContext::enable() {
+    if (mState != LOUDNESS_ENHANCER_STATE_INITIALIZED) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = LOUDNESS_ENHANCER_STATE_ACTIVE;
+    return RetCode::SUCCESS;
+}
+
+RetCode LoudnessEnhancerContext::disable() {
+    if (mState != LOUDNESS_ENHANCER_STATE_ACTIVE) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = LOUDNESS_ENHANCER_STATE_INITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+void LoudnessEnhancerContext::reset() {
+    float targetAmp = pow(10, mGain / 2000.0f);  // mB to linear amplification
+    {
+        std::lock_guard lg(mMutex);
+        if (mCompressor != nullptr) {
+            // Get samplingRate from input
+            mCompressor->Initialize(targetAmp, mSampleRate);
+        }
+    }
+}
+
+RetCode LoudnessEnhancerContext::setLeGain(int gainMb) {
+    mGain = gainMb;
+    reset();  // apply parameter update
+    return RetCode::SUCCESS;
+}
+
+IEffect::Status LoudnessEnhancerContext::lvmProcess(float* in, float* out, int samples) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!in, status, "nullInput");
+    RETURN_VALUE_IF(!out, status, "nullOutput");
+    status = {EX_ILLEGAL_STATE, 0, 0};
+    RETURN_VALUE_IF(getInputFrameSize() != getOutputFrameSize(), status, "FrameSizeMismatch");
+    auto frameSize = getInputFrameSize();
+    RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
+
+    LOG(DEBUG) << __func__ << " start processing";
+    {
+        std::lock_guard lg(mMutex);
+        // PcmType is always expected to be Float 32 bit.
+        constexpr float scale = 1 << 15;  // power of 2 is lossless conversion to int16_t range
+        constexpr float inverseScale = 1.f / scale;
+        const float inputAmp = pow(10, mGain / 2000.0f) * scale;
+        float leftSample, rightSample;
+        if (mCompressor != nullptr) {
+            for (int inIdx = 0; inIdx < samples; inIdx += 2) {
+                // makeup gain is applied on the input of the compressor
+                leftSample = inputAmp * in[inIdx];
+                rightSample = inputAmp * in[inIdx + 1];
+                mCompressor->Compress(&leftSample, &rightSample);
+                in[inIdx] = leftSample * inverseScale;
+                in[inIdx + 1] = rightSample * inverseScale;
+            }
+        } else {
+            for (int inIdx = 0; inIdx < samples; inIdx += 2) {
+                leftSample = inputAmp * in[inIdx];
+                rightSample = inputAmp * in[inIdx + 1];
+                in[inIdx] = leftSample * inverseScale;
+                in[inIdx + 1] = rightSample * inverseScale;
+            }
+        }
+        bool accumulate = false;
+        if (in != out) {
+            for (int i = 0; i < samples; i++) {
+                if (accumulate) {
+                    out[i] += in[i];
+                } else {
+                    out[i] = in[i];
+                }
+            }
+        }
+    }
+    return {STATUS_OK, samples, samples};
+}
+
+void LoudnessEnhancerContext::init_params() {
+    mGain = LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB;
+    float targetAmp = pow(10, mGain / 2000.0f);  // mB to linear amplification
+    LOG(DEBUG) << __func__ << "Target gain = " << mGain << "mB <=> factor = " << targetAmp;
+
+    {
+        std::lock_guard lg(mMutex);
+        mCompressor = std::make_unique<le_fx::AdaptiveDynamicRangeCompression>();
+        mCompressor->Initialize(targetAmp, mSampleRate);
+    }
+    mState = LOUDNESS_ENHANCER_STATE_INITIALIZED;
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h
new file mode 100644
index 0000000..b478b27
--- /dev/null
+++ b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 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 <android-base/thread_annotations.h>
+#include <audio_effects/effect_loudnessenhancer.h>
+
+#include "dsp/core/dynamic_range_compression.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+enum LoudnessEnhancerState {
+    LOUDNESS_ENHANCER_STATE_UNINITIALIZED,
+    LOUDNESS_ENHANCER_STATE_INITIALIZED,
+    LOUDNESS_ENHANCER_STATE_ACTIVE,
+};
+
+class LoudnessEnhancerContext final : public EffectContext {
+  public:
+    LoudnessEnhancerContext(int statusDepth, const Parameter::Common& common);
+    ~LoudnessEnhancerContext();
+
+    RetCode enable();
+    RetCode disable();
+    void reset();
+
+    RetCode setLeGain(int gainMb);
+    int getLeGain() const { return mGain; }
+
+    IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+  private:
+    std::mutex mMutex;
+    LoudnessEnhancerState mState;
+    int mSampleRate;
+    int mGain;
+    // In this implementation, there is no coupling between the compression on the left and right
+    // channels
+    std::unique_ptr<le_fx::AdaptiveDynamicRangeCompression> mCompressor GUARDED_BY(mMutex);
+
+    void init_params();
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
index fa26e60..3aee721 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -20,9 +20,13 @@
 
 #include "BundleContext.h"
 #include "BundleTypes.h"
+#include "math.h"
 
 namespace aidl::android::hardware::audio::effect {
 
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+
 RetCode BundleContext::init() {
     std::lock_guard lg(mMutex);
     // init with pre-defined preset NORMAL
@@ -67,38 +71,280 @@
 }
 
 RetCode BundleContext::enable() {
+    if (mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
+    // Bass boost or Virtualizer can be temporarily disabled if playing over device speaker due to
+    // their nature.
+    bool tempDisabled = false;
+    switch (mType) {
+        case lvm::BundleEffectType::EQUALIZER:
+            LOG(DEBUG) << __func__ << " enable bundle EQ";
+            if (mSamplesToExitCountEq <= 0) mNumberEffectsEnabled++;
+            mSamplesToExitCountEq = (mSamplesPerSecond * 0.1);
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
+            break;
+        case lvm::BundleEffectType::BASS_BOOST:
+            LOG(DEBUG) << __func__ << " enable bundle BB";
+            if (mSamplesToExitCountBb <= 0) mNumberEffectsEnabled++;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
+            mSamplesToExitCountBb = (mSamplesPerSecond * 0.1);
+            tempDisabled = mBassTempDisabled;
+            break;
+        case lvm::BundleEffectType::VIRTUALIZER:
+            LOG(DEBUG) << __func__ << " enable bundle VR";
+            if (mSamplesToExitCountVirt <= 0) mNumberEffectsEnabled++;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+            mSamplesToExitCountVirt = (mSamplesPerSecond * 0.1);
+            tempDisabled = mVirtualizerTempDisabled;
+            break;
+        case lvm::BundleEffectType::VOLUME:
+            LOG(DEBUG) << __func__ << " enable bundle VOL";
+            if ((mEffectInDrain & (1 << int(lvm::BundleEffectType::VOLUME))) == 0)
+                mNumberEffectsEnabled++;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
+            break;
+    }
+    mEnabled = true;
+    return (tempDisabled ? RetCode::SUCCESS : enableOperatingMode());
+}
+
+RetCode BundleContext::enableOperatingMode() {
     LVM_ControlParams_t params;
     {
         std::lock_guard lg(mMutex);
         RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params),
                         RetCode::ERROR_EFFECT_LIB_ERROR, "failGetControlParams");
-        if (mType == lvm::BundleEffectType::EQUALIZER) {
-            LOG(DEBUG) << __func__ << " enable bundle EQ";
-            params.EQNB_OperatingMode = LVM_EQNB_ON;
+        switch (mType) {
+            case lvm::BundleEffectType::EQUALIZER:
+                LOG(DEBUG) << __func__ << " enable bundle EQ";
+                params.EQNB_OperatingMode = LVM_EQNB_ON;
+                break;
+            case lvm::BundleEffectType::BASS_BOOST:
+                LOG(DEBUG) << __func__ << " enable bundle BB";
+                params.BE_OperatingMode = LVM_BE_ON;
+                break;
+            case lvm::BundleEffectType::VIRTUALIZER:
+                LOG(DEBUG) << __func__ << " enable bundle VR";
+                params.VirtualizerOperatingMode = LVM_MODE_ON;
+                break;
+            case lvm::BundleEffectType::VOLUME:
+                LOG(DEBUG) << __func__ << " enable bundle VOL";
+                break;
         }
         RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
                         RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
     }
-    mEnabled = true;
-    // LvmEffect_limitLevel(pContext);
-    return RetCode::SUCCESS;
+    return limitLevel();
 }
 
 RetCode BundleContext::disable() {
+    if (!mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
+    switch (mType) {
+        case lvm::BundleEffectType::EQUALIZER:
+            LOG(DEBUG) << __func__ << " disable bundle EQ";
+            mEffectInDrain |= 1 << int(lvm::BundleEffectType::EQUALIZER);
+            break;
+        case lvm::BundleEffectType::BASS_BOOST:
+            LOG(DEBUG) << __func__ << " disable bundle BB";
+            mEffectInDrain |= 1 << int(lvm::BundleEffectType::BASS_BOOST);
+            break;
+        case lvm::BundleEffectType::VIRTUALIZER:
+            LOG(DEBUG) << __func__ << " disable bundle VR";
+            mEffectInDrain |= 1 << int(lvm::BundleEffectType::VIRTUALIZER);
+            break;
+        case lvm::BundleEffectType::VOLUME:
+            LOG(DEBUG) << __func__ << " disable bundle VOL";
+            mEffectInDrain |= 1 << int(lvm::BundleEffectType::VOLUME);
+            break;
+    }
+    mEnabled = false;
+    return disableOperatingMode();
+}
+
+RetCode BundleContext::disableOperatingMode() {
     LVM_ControlParams_t params;
     {
         std::lock_guard lg(mMutex);
         RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params),
                         RetCode::ERROR_EFFECT_LIB_ERROR, "failGetControlParams");
-        if (mType == lvm::BundleEffectType::EQUALIZER) {
-            LOG(DEBUG) << __func__ << " disable bundle EQ";
-            params.EQNB_OperatingMode = LVM_EQNB_OFF;
+        switch (mType) {
+            case lvm::BundleEffectType::EQUALIZER:
+                LOG(DEBUG) << __func__ << " disable bundle EQ";
+                params.EQNB_OperatingMode = LVM_EQNB_OFF;
+                break;
+            case lvm::BundleEffectType::BASS_BOOST:
+                LOG(DEBUG) << __func__ << " disable bundle BB";
+                params.BE_OperatingMode = LVM_BE_OFF;
+                break;
+            case lvm::BundleEffectType::VIRTUALIZER:
+                LOG(DEBUG) << __func__ << " disable bundle VR";
+                params.VirtualizerOperatingMode = LVM_MODE_OFF;
+                break;
+            case lvm::BundleEffectType::VOLUME:
+                LOG(DEBUG) << __func__ << " disable bundle VOL";
+                break;
         }
         RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
                         RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
     }
     mEnabled = false;
-    // LvmEffect_limitLevel(pContext);
+    return limitLevel();
+}
+
+RetCode BundleContext::limitLevel() {
+    int gainCorrection = 0;
+    // Count the energy contribution per band for EQ and BassBoost only if they are active.
+    float energyContribution = 0;
+    float energyCross = 0;
+    float energyBassBoost = 0;
+    float crossCorrection = 0;
+    LVM_ControlParams_t params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        bool eqEnabled = params.EQNB_OperatingMode == LVM_EQNB_ON;
+        bool bbEnabled = params.BE_OperatingMode == LVM_BE_ON;
+        bool viEnabled = params.VirtualizerOperatingMode == LVM_MODE_ON;
+
+        if (eqEnabled) {
+            for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+                float bandFactor = mBandGaindB[i] / 15.0;
+                float bandCoefficient = lvm::kBandEnergyCoefficient[i];
+                float bandEnergy = bandFactor * bandCoefficient * bandCoefficient;
+                if (bandEnergy > 0) energyContribution += bandEnergy;
+            }
+
+            // cross EQ coefficients
+            float bandFactorSum = 0;
+            for (int i = 0; i < lvm::MAX_NUM_BANDS - 1; i++) {
+                float bandFactor1 = mBandGaindB[i] / 15.0;
+                float bandFactor2 = mBandGaindB[i + 1] / 15.0;
+
+                if (bandFactor1 > 0 && bandFactor2 > 0) {
+                    float crossEnergy =
+                            bandFactor1 * bandFactor2 * lvm::kBandEnergyCrossCoefficient[i];
+                    bandFactorSum += bandFactor1 * bandFactor2;
+
+                    if (crossEnergy > 0) energyCross += crossEnergy;
+                }
+            }
+            bandFactorSum -= 1.0;
+            if (bandFactorSum > 0) crossCorrection = bandFactorSum * 0.7;
+        }
+        // BassBoost contribution
+        if (bbEnabled) {
+            float boostFactor = mBassStrengthSaved / 1000.0;
+            float boostCoefficient = lvm::kBassBoostEnergyCoefficient;
+
+            energyContribution += boostFactor * boostCoefficient * boostCoefficient;
+
+            if (eqEnabled) {
+                for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+                    float bandFactor = mBandGaindB[i] / 15.0;
+                    float bandCrossCoefficient = lvm::kBassBoostEnergyCrossCoefficient[i];
+                    float bandEnergy = boostFactor * bandFactor * bandCrossCoefficient;
+                    if (bandEnergy > 0) energyBassBoost += bandEnergy;
+                }
+            }
+        }
+        // Virtualizer contribution
+        if (viEnabled) {
+            energyContribution += lvm::kVirtualizerContribution * lvm::kVirtualizerContribution;
+        }
+
+        double totalEnergyEstimation =
+                sqrt(energyContribution + energyCross + energyBassBoost) - crossCorrection;
+        LOG(INFO) << " TOTAL energy estimation: " << totalEnergyEstimation << " dB";
+
+        // roundoff
+        int maxLevelRound = (int)(totalEnergyEstimation + 0.99);
+        if (maxLevelRound + mVolume > 0) {
+            gainCorrection = maxLevelRound + mVolume;
+        }
+
+        params.VC_EffectLevel = mVolume - gainCorrection;
+        if (params.VC_EffectLevel < -96) {
+            params.VC_EffectLevel = -96;
+        }
+        LOG(INFO) << "\tVol: " << mVolume << ", GainCorrection: " << gainCorrection
+                  << ", Actual vol: " << params.VC_EffectLevel;
+
+        /* Activate the initial settings */
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+
+        if (mFirstVolume) {
+            RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetVolumeNoSmoothing(mInstance, &params),
+                            RetCode::ERROR_EFFECT_LIB_ERROR, " setVolumeNoSmoothingFailed");
+            LOG(INFO) << "\tLVM_VOLUME: Disabling Smoothing for first volume change to remove "
+                         "spikes/clicks";
+            mFirstVolume = false;
+        }
+    }
+
+    return RetCode::SUCCESS;
+}
+
+bool BundleContext::isDeviceSupportedBassBoost(
+        const aidl::android::media::audio::common::AudioDeviceDescription& device) {
+    return (device == AudioDeviceDescription{AudioDeviceType::OUT_SPEAKER, ""} ||
+            device == AudioDeviceDescription{AudioDeviceType::OUT_CARKIT,
+                                             AudioDeviceDescription::CONNECTION_BT_SCO} ||
+            device == AudioDeviceDescription{AudioDeviceType::OUT_SPEAKER,
+                                             AudioDeviceDescription::CONNECTION_BT_A2DP});
+}
+
+bool BundleContext::isDeviceSupportedVirtualizer(
+        const aidl::android::media::audio::common::AudioDeviceDescription& device) {
+    return (device == AudioDeviceDescription{AudioDeviceType::OUT_HEADSET,
+                                             AudioDeviceDescription::CONNECTION_ANALOG} ||
+            device == AudioDeviceDescription{AudioDeviceType::OUT_HEADPHONE,
+                                             AudioDeviceDescription::CONNECTION_ANALOG} ||
+            device == AudioDeviceDescription{AudioDeviceType::OUT_HEADPHONE,
+                                             AudioDeviceDescription::CONNECTION_BT_A2DP} ||
+            device == AudioDeviceDescription{AudioDeviceType::OUT_HEADSET,
+                                             AudioDeviceDescription::CONNECTION_USB});
+}
+
+RetCode BundleContext::setOutputDevice(
+        const aidl::android::media::audio::common::AudioDeviceDescription& device) {
+    mOutputDevice = device;
+    switch (mType) {
+        case lvm::BundleEffectType::BASS_BOOST:
+            if (isDeviceSupportedBassBoost(device)) {
+                // If a device doesn't support bass boost, the effect must be temporarily disabled.
+                // The effect must still report its original state as this can only be changed by
+                // the start/stop commands.
+                if (mEnabled) {
+                    disableOperatingMode();
+                }
+                mBassTempDisabled = true;
+            } else {
+                // If a device supports bass boost and the effect has been temporarily disabled
+                // previously then re-enable it
+                if (!mEnabled) {
+                    enableOperatingMode();
+                }
+                mBassTempDisabled = false;
+            }
+            break;
+        case lvm::BundleEffectType::VIRTUALIZER:
+            if (isDeviceSupportedVirtualizer(device)) {
+                if (mEnabled) {
+                    disableOperatingMode();
+                }
+                mVirtualizerTempDisabled = true;
+            } else {
+                if (!mEnabled) {
+                    enableOperatingMode();
+                }
+                mVirtualizerTempDisabled = false;
+            }
+            break;
+        default:
+            break;
+    }
     return RetCode::SUCCESS;
 }
 
@@ -153,8 +399,7 @@
     int rightdB = VolToDb(volume.right);
     int maxdB = std::max(leftdB, rightdB);
     int pandB = rightdB - leftdB;
-    // TODO: add volume effect implementation here:
-    // android::VolumeSetVolumeLevel(pContext, (int16_t)(maxdB * 100));
+    setVolumeLevel(maxdB * 100);
     LOG(DEBUG) << __func__ << " pandB: " << pandB << " maxdB " << maxdB;
 
     {
@@ -252,6 +497,82 @@
     return RetCode::SUCCESS;
 }
 
+RetCode BundleContext::setBassBoostStrength(int strength) {
+    if (strength < 0 || strength > lvm::kBassBoostCap.maxStrengthPm) {
+        LOG(ERROR) << __func__ << " invalid strength: " << strength;
+        return RetCode::ERROR_ILLEGAL_PARAMETER;
+    }
+
+    // Update Control Parameter
+    LVM_ControlParams_t params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        params.BE_EffectLevel = (LVM_INT16)((15 * strength) / 1000);
+        params.BE_CentreFreq = LVM_BE_CENTRE_90Hz;
+
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+    }
+    mBassStrengthSaved = strength;
+    LOG(INFO) << __func__ << " success with strength " << strength;
+    return limitLevel();
+}
+
+RetCode BundleContext::setVolumeLevel(int level) {
+    if (level < lvm::kVolumeCap.minLevelDb || level > lvm::kVolumeCap.maxLevelDb) {
+        return RetCode::ERROR_ILLEGAL_PARAMETER;
+    }
+
+    if (mMuteEnabled) {
+        mLevelSaved = level / 100;
+    } else {
+        mVolume = level / 100;
+    }
+    LOG(INFO) << __func__ << " success with level " << level;
+    return limitLevel();
+}
+
+int BundleContext::getVolumeLevel() const {
+    return (mMuteEnabled ? mLevelSaved * 100 : mVolume * 100);
+}
+
+RetCode BundleContext::setVolumeMute(bool mute) {
+    mMuteEnabled = mute;
+    if (mMuteEnabled) {
+        mLevelSaved = mVolume;
+        mVolume = -96;
+    } else {
+        mVolume = mLevelSaved;
+    }
+    return limitLevel();
+}
+
+RetCode BundleContext::setVirtualizerStrength(int strength) {
+    if (strength < 0 || strength > lvm::kVirtualizerCap.maxStrengthPm) {
+        return RetCode::ERROR_ILLEGAL_PARAMETER;
+    }
+
+    // Update Control Parameter
+    LVM_ControlParams_t params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        params.CS_EffectLevel = ((strength * 32767) / 1000);
+
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+    }
+
+    mVirtStrengthSaved = strength;
+    LOG(INFO) << __func__ << " success with strength " << strength;
+    return limitLevel();
+}
+
 void BundleContext::initControlParameter(LVM_ControlParams_t& params) const {
     /* General parameters */
     params.OperatingMode = LVM_MODE_ON;
@@ -339,21 +660,136 @@
 
 IEffect::Status BundleContext::lvmProcess(float* in, float* out, int samples) {
     IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!in, status, "nullInput");
+    RETURN_VALUE_IF(!out, status, "nullOutput");
+    status = {EX_ILLEGAL_STATE, 0, 0};
+    int64_t inputFrameCount = getCommon().input.frameCount;
+    int64_t outputFrameCount = getCommon().output.frameCount;
+    RETURN_VALUE_IF(inputFrameCount != outputFrameCount, status, "FrameCountMismatch");
+    int isDataAvailable = true;
 
     auto frameSize = getInputFrameSize();
-    RETURN_VALUE_IF(0== frameSize, status, "nullContext");
+    RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
 
     LOG(DEBUG) << __func__ << " start processing";
-    LVM_UINT16 frames = samples * sizeof(float) / frameSize;
-    LVM_ReturnStatus_en lvmStatus;
-    {
-        std::lock_guard lg(mMutex);
-        lvmStatus = LVM_Process(mInstance, in, out, frames, 0);
+    if ((mEffectProcessCalled & 1 << int(mType)) != 0) {
+        const int undrainedEffects = mEffectInDrain & ~mEffectProcessCalled;
+        if ((undrainedEffects & 1 << int(lvm::BundleEffectType::EQUALIZER)) != 0) {
+            LOG(DEBUG) << "Draining EQUALIZER";
+            mSamplesToExitCountEq = 0;
+            --mNumberEffectsEnabled;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
+        }
+        if ((undrainedEffects & 1 << int(lvm::BundleEffectType::BASS_BOOST)) != 0) {
+            LOG(DEBUG) << "Draining BASS_BOOST";
+            mSamplesToExitCountBb = 0;
+            --mNumberEffectsEnabled;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
+        }
+        if ((undrainedEffects & 1 << int(lvm::BundleEffectType::VIRTUALIZER)) != 0) {
+            LOG(DEBUG) << "Draining VIRTUALIZER";
+            mSamplesToExitCountVirt = 0;
+            --mNumberEffectsEnabled;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+        }
+        if ((undrainedEffects & 1 << int(lvm::BundleEffectType::VOLUME)) != 0) {
+            LOG(DEBUG) << "Draining VOLUME";
+            --mNumberEffectsEnabled;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
+        }
     }
-
-    if (lvmStatus != LVM_SUCCESS) {
-        LOG(ERROR) << __func__ << lvmStatus;
-        return {EX_UNSUPPORTED_OPERATION, 0, 0};
+    mEffectProcessCalled |= 1 << int(mType);
+    if (!mEnabled) {
+        switch (mType) {
+            case lvm::BundleEffectType::EQUALIZER:
+                if (mSamplesToExitCountEq > 0) {
+                    mSamplesToExitCountEq -= samples;
+                }
+                if (mSamplesToExitCountEq <= 0) {
+                    isDataAvailable = false;
+                    if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::EQUALIZER)) != 0) {
+                        mNumberEffectsEnabled--;
+                        mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
+                    }
+                    LOG(DEBUG) << "Effect_process() this is the last frame for EQUALIZER";
+                }
+                break;
+            case lvm::BundleEffectType::BASS_BOOST:
+                if (mSamplesToExitCountBb > 0) {
+                    mSamplesToExitCountBb -= samples;
+                }
+                if (mSamplesToExitCountBb <= 0) {
+                    isDataAvailable = false;
+                    if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::BASS_BOOST)) != 0) {
+                        mNumberEffectsEnabled--;
+                        mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
+                    }
+                    LOG(DEBUG) << "Effect_process() this is the last frame for BASS_BOOST";
+                }
+                break;
+            case lvm::BundleEffectType::VIRTUALIZER:
+                if (mSamplesToExitCountVirt > 0) {
+                    mSamplesToExitCountVirt -= samples;
+                }
+                if (mSamplesToExitCountVirt <= 0) {
+                    isDataAvailable = false;
+                    if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::VIRTUALIZER)) != 0) {
+                        mNumberEffectsEnabled--;
+                        mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+                    }
+                    LOG(DEBUG) << "Effect_process() this is the last frame for VIRTUALIZER";
+                }
+                break;
+            case lvm::BundleEffectType::VOLUME:
+                isDataAvailable = false;
+                if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::VOLUME)) != 0) {
+                    mNumberEffectsEnabled--;
+                    mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
+                }
+                LOG(DEBUG) << "Effect_process() LVM_VOLUME Effect is not enabled";
+                break;
+        }
+    }
+    if (isDataAvailable) {
+        mNumberEffectsCalled++;
+    }
+    bool accumulate = false;
+    if (mNumberEffectsCalled >= mNumberEffectsEnabled) {
+        // We expect the # effects called to be equal to # effects enabled in sequence (including
+        // draining effects).  Warn if this is not the case due to inconsistent calls.
+        ALOGW_IF(mNumberEffectsCalled > mNumberEffectsEnabled,
+                 "%s Number of effects called %d is greater than number of effects enabled %d",
+                 __func__, mNumberEffectsCalled, mNumberEffectsEnabled);
+        mEffectProcessCalled = 0;  // reset our consistency check.
+        if (!isDataAvailable) {
+            LOG(DEBUG) << "Effect_process() processing last frame";
+        }
+        mNumberEffectsCalled = 0;
+        LVM_UINT16 frames = samples * sizeof(float) / frameSize;
+        float* outTmp = (accumulate ? getWorkBuffer() : out);
+        /* Process the samples */
+        LVM_ReturnStatus_en lvmStatus;
+        {
+            std::lock_guard lg(mMutex);
+            lvmStatus = LVM_Process(mInstance, in, outTmp, frames, 0);
+            if (lvmStatus != LVM_SUCCESS) {
+                LOG(ERROR) << __func__ << lvmStatus;
+                return {EX_UNSUPPORTED_OPERATION, 0, 0};
+            }
+            if (accumulate) {
+                for (int i = 0; i < samples; i++) {
+                    out[i] += outTmp[i];
+                }
+            }
+        }
+    } else {
+        for (int i = 0; i < samples; i++) {
+            if (accumulate) {
+                out[i] += in[i];
+            } else {
+                out[i] = in[i];
+            }
+        }
     }
     LOG(DEBUG) << __func__ << " done processing";
     return {STATUS_OK, samples, samples};
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
index 7b38e66..be723f7 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -43,9 +43,11 @@
     lvm::BundleEffectType getBundleType() const { return mType; }
 
     RetCode enable();
+    RetCode enableOperatingMode();
     RetCode disable();
+    RetCode disableOperatingMode();
 
-    void setSampleRate (const int sampleRate) { mSampleRate = sampleRate; }
+    void setSampleRate(const int sampleRate) { mSampleRate = sampleRate; }
     int getSampleRate() const { return mSampleRate; }
 
     void setChannelMask(const aidl::android::media::audio::common::AudioChannelLayout& chMask) {
@@ -54,17 +56,37 @@
     aidl::android::media::audio::common::AudioChannelLayout getChannelMask() const {
         return mChMask;
     }
+    bool isDeviceSupportedBassBoost(
+            const aidl::android::media::audio::common::AudioDeviceDescription& device);
+    bool isDeviceSupportedVirtualizer(
+            const aidl::android::media::audio::common::AudioDeviceDescription& device);
+    RetCode setOutputDevice(
+            const aidl::android::media::audio::common::AudioDeviceDescription& device) override;
 
     RetCode setEqualizerPreset(const std::size_t presetIdx);
     int getEqualizerPreset() const { return mCurPresetIdx; }
     RetCode setEqualizerBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels);
     std::vector<Equalizer::BandLevel> getEqualizerBandLevels() const;
 
+    RetCode setBassBoostStrength(int strength);
+    int getBassBoostStrength() const { return mBassStrengthSaved; }
+
+    RetCode setVolumeLevel(int level);
+    int getVolumeLevel() const;
+
+    RetCode setVolumeMute(bool mute);
+    int getVolumeMute() const { return mMuteEnabled; }
+
+    RetCode setVirtualizerStrength(int strength);
+    int getVirtualizerStrength() const { return mVirtStrengthSaved; }
+
     RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
     Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
 
     IEffect::Status lvmProcess(float* in, float* out, int samples);
 
+    IEffect::Status processEffect(float* in, float* out, int sampleToProcess);
+
   private:
     std::mutex mMutex;
     const lvm::BundleEffectType mType;
@@ -90,7 +112,7 @@
     int mEffectProcessCalled = 0;
     int mNumberEffectsEnabled = 0;
     int mNumberEffectsCalled = 0;
-    bool mFirstVolume = false;
+    bool mFirstVolume = true;
     // Bass
     bool mBassTempDisabled = false;
     int mBassStrengthSaved = 0;
@@ -102,10 +124,12 @@
     bool mVirtualizerTempDisabled = false;
     // Volume
     int mLevelSaved = 0; /* for when mute is set, level must be saved */
+    int mVolume = 0;
     bool mMuteEnabled = false; /* Must store as mute = -96dB level */
 
     void initControlParameter(LVM_ControlParams_t& params) const;
     void initHeadroomParameter(LVM_HeadroomParams_t& params) const;
+    RetCode limitLevel();
     int16_t VolToDb(uint32_t vol) const;
     LVM_INT16 LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const;
     RetCode updateControlParameter(const std::vector<Equalizer::BandLevel>& bandLevels);
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
index 97f08a0..1996240 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -70,6 +70,8 @@
 static const Equalizer::Capability kEqCap = {.bandFrequencies = kEqBandFrequency,
                                              .presets = kEqPresets};
 
+static const std::string kEqualizerEffectName = "EqualizerBundle";
+
 static const Descriptor kEqualizerDesc = {
         .common = {.id = {.type = kEqualizerTypeUUID,
                           .uuid = kEqualizerBundleImplUUID,
@@ -77,14 +79,66 @@
                    .flags = {.type = Flags::Type::INSERT,
                              .insert = Flags::Insert::FIRST,
                              .volume = Flags::Volume::CTRL},
-                   .name = "EqualizerBundle",
+                   .name = kEqualizerEffectName,
                    .implementor = "NXP Software Ltd."},
         .capability = Capability::make<Capability::equalizer>(kEqCap)};
 
-// TODO: add descriptors for other bundle effect types here.
-static const Descriptor kVirtualizerDesc;
-static const Descriptor kBassBoostDesc;
-static const Descriptor kVolumeDesc;
+static const bool mStrengthSupported = true;
+
+static const BassBoost::Capability kBassBoostCap = {.maxStrengthPm = 1000,
+                                                    .strengthSupported = mStrengthSupported};
+
+static const std::string kBassBoostEffectName = "Dynamic Bass Boost";
+
+static const Descriptor kBassBoostDesc = {
+        .common = {.id = {.type = kBassBoostTypeUUID,
+                          .uuid = kBassBoostBundleImplUUID,
+                          .proxy = kBassBoostProxyUUID},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL,
+                             .deviceIndication = true},
+                   .cpuLoad = BASS_BOOST_CUP_LOAD_ARM9E,
+                   .memoryUsage = BUNDLE_MEM_USAGE,
+                   .name = kBassBoostEffectName,
+                   .implementor = "NXP Software Ltd."},
+        .capability = Capability::make<Capability::bassBoost>(kBassBoostCap)};
+
+static const Virtualizer::Capability kVirtualizerCap = {.maxStrengthPm = 1000,
+                                                        .strengthSupported = mStrengthSupported};
+
+static const std::string kVirtualizerEffectName = "Virtualizer";
+
+static const Descriptor kVirtualizerDesc = {
+        .common = {.id = {.type = kVirtualizerTypeUUID,
+                          .uuid = kVirtualizerBundleImplUUID,
+                          .proxy = kVirtualizerProxyUUID},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::LAST,
+                             .volume = Flags::Volume::CTRL,
+                             .deviceIndication = true},
+                   .cpuLoad = VIRTUALIZER_CUP_LOAD_ARM9E,
+                   .memoryUsage = BUNDLE_MEM_USAGE,
+                   .name = kVirtualizerEffectName,
+                   .implementor = "NXP Software Ltd."},
+        .capability = Capability::make<Capability::virtualizer>(kVirtualizerCap)};
+
+static const Volume::Capability kVolumeCap = {.minLevelDb = -9600, .maxLevelDb = 0};
+
+static const std::string kVolumeEffectName = "Volume";
+
+static const Descriptor kVolumeDesc = {
+        .common = {.id = {.type = kVolumeTypeUUID,
+                          .uuid = kVolumeBundleImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::LAST,
+                             .volume = Flags::Volume::CTRL},
+                   .cpuLoad = VOLUME_CUP_LOAD_ARM9E,
+                   .memoryUsage = BUNDLE_MEM_USAGE,
+                   .name = kVolumeEffectName,
+                   .implementor = "NXP Software Ltd."},
+        .capability = Capability::make<Capability::volume>(kVolumeCap)};
 
 /* The following tables have been computed using the actual levels measured by the output of
  * white noise or pink noise (IEC268-1) for the EQ and BassBoost Effects. These are estimates of
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
index b1bf04c..81b8aca 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -29,15 +29,24 @@
 #include <LVM.h>
 #include <limits.h>
 
+using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::EffectBundleAidl;
-using aidl::android::hardware::audio::effect::kEqualizerBundleImplUUID;
 using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kBassBoostBundleImplUUID;
+using aidl::android::hardware::audio::effect::kEqualizerBundleImplUUID;
+using aidl::android::hardware::audio::effect::kVirtualizerBundleImplUUID;
+using aidl::android::hardware::audio::effect::kVolumeBundleImplUUID;
 using aidl::android::hardware::audio::effect::State;
 using aidl::android::media::audio::common::AudioUuid;
 
+bool isUuidSupported(const AudioUuid* uuid) {
+    return (*uuid == kEqualizerBundleImplUUID || *uuid == kBassBoostBundleImplUUID ||
+            *uuid == kVirtualizerBundleImplUUID || *uuid == kVolumeBundleImplUUID);
+}
+
 extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
                                            std::shared_ptr<IEffect>* instanceSpp) {
-    if (uuid == nullptr || *uuid != kEqualizerBundleImplUUID) {
+    if (uuid == nullptr || !isUuidSupported(uuid)) {
         LOG(ERROR) << __func__ << "uuid not supported";
         return EX_ILLEGAL_ARGUMENT;
     }
@@ -51,19 +60,20 @@
     }
 }
 
-extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
-    if (!instanceSp) {
-        LOG(ERROR) << __func__ << "nullInstance";
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || !isUuidSupported(in_impl_uuid)) {
+        LOG(ERROR) << __func__ << "uuid not supported";
         return EX_ILLEGAL_ARGUMENT;
     }
-    State state;
-    ndk::ScopedAStatus status = instanceSp->getState(&state);
-    if (!status.isOk() || State::INIT != state) {
-        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
-                   << " in state: " << toString(state) << ", status: " << status.getDescription();
-        return EX_ILLEGAL_STATE;
+    if (*in_impl_uuid == kEqualizerBundleImplUUID) {
+        *_aidl_return = aidl::android::hardware::audio::effect::lvm::kEqualizerDesc;
+    } else if (*in_impl_uuid == kBassBoostBundleImplUUID) {
+        *_aidl_return = aidl::android::hardware::audio::effect::lvm:: kBassBoostDesc;
+    } else if (*in_impl_uuid == kVirtualizerBundleImplUUID) {
+        *_aidl_return = aidl::android::hardware::audio::effect::lvm::kVirtualizerDesc;
+    } else if (*in_impl_uuid == kVolumeBundleImplUUID) {
+        *_aidl_return = aidl::android::hardware::audio::effect::lvm::kVolumeDesc;
     }
-    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
     return EX_NONE;
 }
 
@@ -74,9 +84,21 @@
     if (uuid == kEqualizerBundleImplUUID) {
         mType = lvm::BundleEffectType::EQUALIZER;
         mDescriptor = &lvm::kEqualizerDesc;
+        mEffectName = &lvm::kEqualizerEffectName;
+    } else if (uuid == kBassBoostBundleImplUUID) {
+        mType = lvm::BundleEffectType::BASS_BOOST;
+        mDescriptor = &lvm::kBassBoostDesc;
+        mEffectName = &lvm::kBassBoostEffectName;
+    } else if (uuid == kVirtualizerBundleImplUUID) {
+        mType = lvm::BundleEffectType::VIRTUALIZER;
+        mDescriptor = &lvm::kVirtualizerDesc;
+        mEffectName = &lvm::kVirtualizerEffectName;
+    } else if (uuid == kVolumeBundleImplUUID) {
+        mType = lvm::BundleEffectType::VOLUME;
+        mDescriptor = &lvm::kVolumeDesc;
+        mEffectName = &lvm::kVolumeEffectName;
     } else {
-        // TODO: add other bundle effect types here.
-        LOG(ERROR) << __func__ << uuid.toString() << " not supported yet!";
+        LOG(ERROR) << __func__ << uuid.toString() << " not supported!";
     }
 }
 
@@ -130,52 +152,128 @@
 
 ndk::ScopedAStatus EffectBundleAidl::setParameterSpecific(const Parameter::Specific& specific) {
     LOG(DEBUG) << __func__ << " specific " << specific.toString();
-    auto tag = specific.getTag();
-    RETURN_IF(tag != Parameter::Specific::equalizer, EX_ILLEGAL_ARGUMENT,
-              "specificParamNotSupported");
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
+    auto tag = specific.getTag();
+    switch (tag) {
+        case Parameter::Specific::equalizer:
+            return setParameterEqualizer(specific);
+        case Parameter::Specific::bassBoost:
+            return setParameterBassBoost(specific);
+        case Parameter::Specific::virtualizer:
+            return setParameterVirtualizer(specific);
+        case Parameter::Specific::volume:
+            return setParameterVolume(specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "specificParamNotSupported");
+    }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterEqualizer(const Parameter::Specific& specific) {
     auto& eq = specific.get<Parameter::Specific::equalizer>();
     auto eqTag = eq.getTag();
     switch (eqTag) {
         case Equalizer::preset:
             RETURN_IF(mContext->setEqualizerPreset(eq.get<Equalizer::preset>()) != RetCode::SUCCESS,
                       EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
-            break;
+            return ndk::ScopedAStatus::ok();
         case Equalizer::bandLevels:
             RETURN_IF(mContext->setEqualizerBandLevels(eq.get<Equalizer::bandLevels>()) !=
                               RetCode::SUCCESS,
                       EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
-            break;
+            return ndk::ScopedAStatus::ok();
         default:
             LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
             return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
                                                                     "eqTagNotSupported");
     }
-    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterBassBoost(const Parameter::Specific& specific) {
+    auto& bb = specific.get<Parameter::Specific::bassBoost>();
+    auto bbTag = bb.getTag();
+    switch (bbTag) {
+        case BassBoost::strengthPm: {
+            RETURN_IF(mContext->setBassBoostStrength(bb.get<BassBoost::strengthPm>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setStrengthFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        default:
+            LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "bbTagNotSupported");
+    }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterVirtualizer(const Parameter::Specific& specific) {
+    auto& vr = specific.get<Parameter::Specific::virtualizer>();
+    auto vrTag = vr.getTag();
+    switch (vrTag) {
+        case Virtualizer::strengthPm: {
+            RETURN_IF(mContext->setVirtualizerStrength(vr.get<Virtualizer::strengthPm>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setStrengthFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        default:
+            LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "vrTagNotSupported");
+    }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterVolume(const Parameter::Specific& specific) {
+    auto& vol = specific.get<Parameter::Specific::volume>();
+    auto volTag = vol.getTag();
+    switch (volTag) {
+        case Volume::levelDb: {
+            RETURN_IF(mContext->setVolumeLevel(vol.get<Volume::levelDb>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setLevelFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case Volume::mute:
+            RETURN_IF(mContext->setVolumeMute(vol.get<Volume::mute>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setMuteFailed");
+            return ndk::ScopedAStatus::ok();
+        default:
+            LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "volTagNotSupported");
+    }
 }
 
 ndk::ScopedAStatus EffectBundleAidl::getParameterSpecific(const Parameter::Id& id,
                                                           Parameter::Specific* specific) {
     RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
     auto tag = id.getTag();
-    RETURN_IF(Parameter::Id::equalizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
-    auto eqId = id.get<Parameter::Id::equalizerTag>();
-    auto eqIdTag = eqId.getTag();
-    switch (eqIdTag) {
-        case Equalizer::Id::commonTag:
-            return getParameterEqualizer(eqId.get<Equalizer::Id::commonTag>(), specific);
+
+    switch (tag) {
+        case Parameter::Id::equalizerTag:
+            return getParameterEqualizer(id.get<Parameter::Id::equalizerTag>(), specific);
+        case Parameter::Id::bassBoostTag:
+            return getParameterBassBoost(id.get<Parameter::Id::bassBoostTag>(), specific);
+        case Parameter::Id::virtualizerTag:
+            return getParameterVirtualizer(id.get<Parameter::Id::virtualizerTag>(), specific);
+        case Parameter::Id::volumeTag:
+            return getParameterVolume(id.get<Parameter::Id::volumeTag>(), specific);
         default:
-            LOG(ERROR) << __func__ << " tag " << toString(eqIdTag) << " not supported";
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
             return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
-                                                                    "EqualizerTagNotSupported");
+                                                                    "wrongIdTag");
     }
 }
 
-ndk::ScopedAStatus EffectBundleAidl::getParameterEqualizer(const Equalizer::Tag& tag,
+ndk::ScopedAStatus EffectBundleAidl::getParameterEqualizer(const Equalizer::Id& id,
                                                            Parameter::Specific* specific) {
+    RETURN_IF(id.getTag() != Equalizer::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+              "EqualizerTagNotSupported");
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
     Equalizer eqParam;
+
+    auto tag = id.get<Equalizer::Id::commonTag>();
     switch (tag) {
         case Equalizer::bandLevels: {
             eqParam.set<Equalizer::bandLevels>(mContext->getEqualizerBandLevels());
@@ -196,6 +294,83 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus EffectBundleAidl::getParameterBassBoost(const BassBoost::Id& id,
+                                                           Parameter::Specific* specific) {
+    RETURN_IF(id.getTag() != BassBoost::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+              "BassBoostTagNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    BassBoost bbParam;
+
+    auto tag = id.get<BassBoost::Id::commonTag>();
+    switch (tag) {
+        case BassBoost::strengthPm: {
+            bbParam.set<BassBoost::strengthPm>(mContext->getBassBoostStrength());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "BassBoostTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::bassBoost>(bbParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterVolume(const Volume::Id& id,
+                                                        Parameter::Specific* specific) {
+    RETURN_IF(id.getTag() != Volume::Id::commonTag, EX_ILLEGAL_ARGUMENT, "VolumeTagNotSupported");
+
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    Volume volParam;
+
+    auto tag = id.get<Volume::Id::commonTag>();
+    switch (tag) {
+        case Volume::levelDb: {
+            volParam.set<Volume::levelDb>(mContext->getVolumeLevel());
+            break;
+        }
+        case Volume::mute: {
+            volParam.set<Volume::mute>(mContext->getVolumeMute());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "VolumeTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::volume>(volParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterVirtualizer(const Virtualizer::Id& id,
+                                                             Parameter::Specific* specific) {
+    RETURN_IF(id.getTag() != Virtualizer::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+              "VirtualizerTagNotSupported");
+
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    Virtualizer vrParam;
+
+    auto tag = id.get<Virtualizer::Id::commonTag>();
+    switch (tag) {
+        case Virtualizer::strengthPm: {
+            vrParam.set<Virtualizer::strengthPm>(mContext->getVirtualizerStrength());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "VirtualizerTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::virtualizer>(vrParam);
+    return ndk::ScopedAStatus::ok();
+}
+
 std::shared_ptr<EffectContext> EffectBundleAidl::createContext(const Parameter::Common& common) {
     if (mContext) {
         LOG(DEBUG) << __func__ << " context already exist";
@@ -243,6 +418,8 @@
 
 // Processing method running in EffectWorker thread.
 IEffect::Status EffectBundleAidl::effectProcessImpl(float* in, float* out, int sampleToProcess) {
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!mContext, status, "nullContext");
     return mContext->lvmProcess(in, out, sampleToProcess);
 }
 
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
index 9e2f656..0330e5a 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
@@ -50,16 +50,28 @@
 
     ndk::ScopedAStatus commandImpl(CommandId command) override;
 
-    std::string getEffectName() override { return "EqualizerBundle"; }
+    std::string getEffectName() override { return *mEffectName; }
 
   private:
     std::shared_ptr<BundleContext> mContext;
     const Descriptor* mDescriptor;
+    const std::string* mEffectName;
     lvm::BundleEffectType mType = lvm::BundleEffectType::EQUALIZER;
 
     IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
-    ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Tag& tag,
+
+    ndk::ScopedAStatus setParameterBassBoost(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterBassBoost(const BassBoost::Id& id,
                                              Parameter::Specific* specific);
+
+    ndk::ScopedAStatus setParameterEqualizer(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Id& id,
+                                             Parameter::Specific* specific);
+    ndk::ScopedAStatus setParameterVolume(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterVolume(const Volume::Id& id, Parameter::Specific* specific);
+    ndk::ScopedAStatus setParameterVirtualizer(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterVirtualizer(const Virtualizer::Id& id,
+                                               Parameter::Specific* specific);
 };
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 61a2bf5..59f1fc3 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -102,7 +102,8 @@
     uint32_t state;                // current state (enum preproc_session_state)
     int id;                        // audio session ID
     int io;                        // handle of input stream this session is on
-    webrtc::AudioProcessing* apm;  // handle on webRTC audio processing module (APM)
+    rtc::scoped_refptr<webrtc::AudioProcessing>
+            apm;  // handle on webRTC audio processing module (APM)
     // Audio Processing module builder
     webrtc::AudioProcessingBuilder ap_builder;
     // frameCount represents the size of the buffers used for processing, and must represent 10ms.
@@ -260,9 +261,6 @@
     ALOGV("Agc2Init");
     effect->session->config = effect->session->apm->GetConfig();
     effect->session->config.gain_controller2.fixed_digital.gain_db = 0.f;
-    effect->session->config.gain_controller2.adaptive_digital.level_estimator =
-            effect->session->config.gain_controller2.kRms;
-    effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db = 2.f;
     effect->session->apm->ApplyConfig(effect->session->config);
     return 0;
 }
@@ -332,24 +330,19 @@
             ALOGV("Agc2GetParameter() target level %f dB", *(float*)pValue);
             break;
         case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
-            *(uint32_t*)pValue = (uint32_t)(
-                    effect->session->config.gain_controller2.adaptive_digital.level_estimator);
-            ALOGV("Agc2GetParameter() level estimator %d",
-                  *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
+            // WebRTC only supports RMS level estimator now
+            *(uint32_t*)pValue = (uint32_t)(0);
+            ALOGV("Agc2GetParameter() level estimator RMS");
             break;
         case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
-            *(float*)pValue = (float)(effect->session->config.gain_controller2.adaptive_digital
-                                              .extra_saturation_margin_db);
+            *(float*)pValue = (float)(2.0);
             ALOGV("Agc2GetParameter() extra saturation margin %f dB", *(float*)pValue);
             break;
         case AGC2_PARAM_PROPERTIES:
             pProperties->fixedDigitalGain =
                     (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
-            pProperties->level_estimator = (uint32_t)(
-                    effect->session->config.gain_controller2.adaptive_digital.level_estimator);
-            pProperties->extraSaturationMargin =
-                    (float)(effect->session->config.gain_controller2.adaptive_digital
-                                    .extra_saturation_margin_db);
+            pProperties->level_estimator = 0;
+            pProperties->extraSaturationMargin = 2.0;
             break;
         default:
             ALOGW("Agc2GetParameter() unknown param %d", param);
@@ -438,16 +431,19 @@
             effect->session->config.gain_controller2.fixed_digital.gain_db = valueFloat;
             break;
         case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
-            ALOGV("Agc2SetParameter() level estimator %d",
-                  *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
-            effect->session->config.gain_controller2.adaptive_digital.level_estimator =
-                    (*(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
+            ALOGV("Agc2SetParameter() level estimator %d", *(uint32_t*)pValue);
+            if (*(uint32_t*)pValue != 0) {
+              // only RMS is supported
+              status = -EINVAL;
+            }
             break;
         case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
             valueFloat = (float)(*(int32_t*)pValue);
             ALOGV("Agc2SetParameter() extra saturation margin %f dB", valueFloat);
-            effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
-                    valueFloat;
+            if (valueFloat != 2.0) {
+              // extra_staturation_margin_db is no longer configurable in webrtc
+              status = -EINVAL;
+            }
             break;
         case AGC2_PARAM_PROPERTIES:
             ALOGV("Agc2SetParameter() properties gain %f, level %d margin %f",
@@ -455,11 +451,9 @@
                   pProperties->extraSaturationMargin);
             effect->session->config.gain_controller2.fixed_digital.gain_db =
                     pProperties->fixedDigitalGain;
-            effect->session->config.gain_controller2.adaptive_digital.level_estimator =
-                    (webrtc::AudioProcessing::Config::GainController2::LevelEstimator)
-                            pProperties->level_estimator;
-            effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
-                    pProperties->extraSaturationMargin;
+            if (pProperties->level_estimator != 0 || pProperties->extraSaturationMargin != 2.0) {
+              status = -EINVAL;
+            }
             break;
         default:
             ALOGW("Agc2SetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
@@ -879,8 +873,8 @@
 
 error:
     if (session->createdMsk == 0) {
-        delete session->apm;
-        session->apm = NULL;
+        // Scoped_refptr will handle reference counting here
+        session->apm = nullptr;
     }
     return status;
 }
@@ -889,8 +883,8 @@
     ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
     session->createdMsk &= ~(1 << fx->procId);
     if (session->createdMsk == 0) {
-        delete session->apm;
-        session->apm = NULL;
+        // Scoped_refptr will handle reference counting here
+        session->apm = nullptr;
         session->id = 0;
     }
 
diff --git a/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp b/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
index 07006a1..8fdb864 100644
--- a/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
+++ b/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
@@ -143,10 +143,6 @@
         const AGC2Params* agc2Params = &params->agc2Params;
         ASSERT_NO_FATAL_FAILURE(
                 effect.setParam(AGC2_PARAM_FIXED_DIGITAL_GAIN, agc2Params->fixedDigitalGain));
-        ASSERT_NO_FATAL_FAILURE(effect.setParam(AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR,
-                                                agc2Params->adaptDigiLevelEstimator));
-        ASSERT_NO_FATAL_FAILURE(effect.setParam(AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN,
-                                                agc2Params->extraSaturationMargin));
     } else if (isAECEffect(uuid)) {
         const AECParams* aecParams = &params->aecParams;
         ASSERT_NO_FATAL_FAILURE(effect.setParam(AEC_PARAM_ECHO_DELAY, aecParams->echoDelay));
diff --git a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
index 3bd93f8..03400d7 100644
--- a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
+++ b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
@@ -400,20 +400,6 @@
             ALOGE("Invalid AGC2 Fixed Digital Gain. Error %d\n", status);
             return EXIT_FAILURE;
         }
-        if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR,
-                                               (uint32_t)preProcCfgParams.agc2Level,
-                                               effectHandle[PREPROC_AGC2]);
-            status != 0) {
-            ALOGE("Invalid AGC2 Level Estimator. Error %d\n", status);
-            return EXIT_FAILURE;
-        }
-        if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN,
-                                               (float)preProcCfgParams.agc2SaturationMargin,
-                                               effectHandle[PREPROC_AGC2]);
-            status != 0) {
-            ALOGE("Invalid AGC2 Saturation Margin. Error %d\n", status);
-            return EXIT_FAILURE;
-        }
     }
     if (effectEn[PREPROC_NS]) {
         if (int status = preProcSetConfigParam(NS_PARAM_LEVEL, (uint32_t)preProcCfgParams.nsLevel,
diff --git a/media/libeffects/visualizer/Android.bp b/media/libeffects/visualizer/Android.bp
index 8dd6789..fb9d7b7 100644
--- a/media/libeffects/visualizer/Android.bp
+++ b/media/libeffects/visualizer/Android.bp
@@ -18,34 +18,59 @@
     ],
 }
 
-cc_library_shared {
-    name: "libvisualizer",
-
+cc_defaults {
+    name: "visualizer_defaults",
     vendor: true,
-
-    srcs: [
-        "EffectVisualizer.cpp",
-    ],
-
     cflags: [
-        "-O2",
-        "-fvisibility=hidden",
-
-        "-DBUILD_FLOAT",
+        "-DBUILD_FLOAT", // TODO: remove BUILD_FLOAT and SUPPORT_MC in lvm libs
         "-DSUPPORT_MC",
-
         "-Wall",
         "-Werror",
     ],
-
     shared_libs: [
         "liblog",
     ],
-
-    relative_install_path: "soundfx",
-
     header_libs: [
         "libaudioeffects",
         "libaudioutils_headers",
     ],
 }
+
+cc_library_shared {
+    name: "libvisualizer",
+    defaults: [
+        "visualizer_defaults",
+    ],
+    srcs: [
+        "EffectVisualizer.cpp",
+    ],
+    relative_install_path: "soundfx",
+    cflags: [
+        "-O2",
+        "-fvisibility=hidden",
+    ],
+}
+
+cc_library_shared {
+    name: "libvisualizeraidl",
+    srcs: [
+        "aidl/Visualizer.cpp",
+        "aidl/VisualizerContext.cpp",
+        ":effectCommonFile",
+    ],
+    defaults: [
+        "aidlaudioeffectservice_defaults",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+        "visualizer_defaults",
+    ],
+    cflags: [
+        "-Wthread-safety",
+    ],
+    shared_libs: [
+        "libcutils",
+    ],
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
+    ],
+}
diff --git a/media/libeffects/visualizer/aidl/Visualizer.cpp b/media/libeffects/visualizer/aidl/Visualizer.cpp
new file mode 100644
index 0000000..28a7287
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/Visualizer.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2022 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 "AHAL_VisualizerLibEffects"
+
+#include <android-base/logging.h>
+#include "Visualizer.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::VisualizerImpl;
+using aidl::android::hardware::audio::effect::kVisualizerImplUUID;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (!in_impl_uuid || *in_impl_uuid != kVisualizerImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<VisualizerImpl>();
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kVisualizerImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    *_aidl_return = VisualizerImpl::kDescriptor;
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string VisualizerImpl::kEffectName = "Visualizer";
+const Visualizer::Capability VisualizerImpl::kCapability = {
+        .maxLatencyMs = VisualizerContext::kMaxLatencyMs,
+        .captureSampleRange = {.min = 0, .max = VisualizerContext::kMaxCaptureBufSize}};
+const Descriptor VisualizerImpl::kDescriptor = {
+        .common = {.id = {.type = kVisualizerTypeUUID,
+                          .uuid = kVisualizerImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::LAST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = VisualizerImpl::kEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = Capability::make<Capability::visualizer>(VisualizerImpl::kCapability)};
+
+ndk::ScopedAStatus VisualizerImpl::getDescriptor(Descriptor* _aidl_return) {
+    RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+    LOG(DEBUG) << __func__ << kDescriptor.toString();
+    *_aidl_return = kDescriptor;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::commandImpl(CommandId command) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    switch (command) {
+        case CommandId::START:
+            mContext->enable();
+            break;
+        case CommandId::STOP:
+            mContext->disable();
+            break;
+        case CommandId::RESET:
+            mContext->disable();
+            mContext->resetBuffer();
+            break;
+        default:
+            LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "commandIdNotSupported");
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::setOnlyParameter(
+        const Visualizer::SetOnlyParameters& param) {
+    auto tag = param.getTag();
+    switch (tag) {
+        case Visualizer::SetOnlyParameters::latencyMs: {
+            RETURN_IF(mContext->setDownstreamLatency(
+                              param.get<Visualizer::SetOnlyParameters::latencyMs>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setLatencyFailed");
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "setOnlyParameterTagNotSupported");
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::setParameterSpecific(const Parameter::Specific& specific) {
+    RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+              "EffectNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto& param = specific.get<Parameter::Specific::visualizer>();
+    const auto tag = param.getTag();
+    switch (tag) {
+        case Visualizer::captureSamples: {
+            RETURN_IF(mContext->setCaptureSamples(param.get<Visualizer::captureSamples>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setCaptureSizeFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case Visualizer::scalingMode: {
+            RETURN_IF(mContext->setScalingMode(param.get<Visualizer::scalingMode>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setScalingModeFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case Visualizer::measurementMode: {
+            RETURN_IF(mContext->setMeasurementMode(param.get<Visualizer::measurementMode>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setMeasurementModeFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case Visualizer::setOnlyParameters: {
+            return setOnlyParameter(param.get<Visualizer::setOnlyParameters>());
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "VisualizerTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus VisualizerImpl::getOnlyParameter(const Visualizer::GetOnlyParameters::Tag tag,
+                                                    Parameter::Specific* specific) {
+    Visualizer visualizer;
+    Visualizer::GetOnlyParameters param;
+    switch (tag) {
+        case Visualizer::GetOnlyParameters::measurement: {
+            param.set<Visualizer::GetOnlyParameters::measurement>(mContext->getMeasure());
+            break;
+        }
+        case Visualizer::GetOnlyParameters::captureSampleBuffer: {
+            param.set<Visualizer::GetOnlyParameters::captureSampleBuffer>(mContext->capture());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "setOnlyParameterTagNotSupported");
+        }
+    }
+    visualizer.set<Visualizer::getOnlyParameters>(param);
+    specific->set<Parameter::Specific::visualizer>(visualizer);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::getParameterSpecific(const Parameter::Id& id,
+                                                        Parameter::Specific* specific) {
+    RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+    auto tag = id.getTag();
+    RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    auto specificId = id.get<Parameter::Id::visualizerTag>();
+    auto specificTag = specificId.getTag();
+    switch (specificTag) {
+        case Visualizer::Id::commonTag: {
+            return getParameterVisualizer(specificId.get<Visualizer::Id::commonTag>(), specific);
+        }
+        case Visualizer::Id::getOnlyParamTag: {
+            return getOnlyParameter(specificId.get<Visualizer::Id::getOnlyParamTag>(), specific);
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(specificTag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "VisualizerTagNotSupported");
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::getParameterVisualizer(const Visualizer::Tag& tag,
+                                                          Parameter::Specific* specific) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    Visualizer param;
+    switch (tag) {
+        case Visualizer::captureSamples: {
+            param.set<Visualizer::captureSamples>(mContext->getCaptureSamples());
+            break;
+        }
+        case Visualizer::scalingMode: {
+            param.set<Visualizer::scalingMode>(mContext->getScalingMode());
+            break;
+        }
+        case Visualizer::measurementMode: {
+            param.set<Visualizer::measurementMode>(mContext->getMeasurementMode());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "VisualizerTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::visualizer>(param);
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> VisualizerImpl::createContext(const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+        return mContext;
+    }
+
+    mContext = std::make_shared<VisualizerContext>(1 /* statusFmqDepth */, common);
+    mContext->initParams(common);
+    return mContext;
+}
+
+RetCode VisualizerImpl::releaseContext() {
+    if (mContext) {
+        mContext->disable();
+        mContext->resetBuffer();
+    }
+    return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status VisualizerImpl::effectProcessImpl(float* in, float* out, int samples) {
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!mContext, status, "nullContext");
+    return mContext->process(in, out, samples);
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/Visualizer.h b/media/libeffects/visualizer/aidl/Visualizer.h
new file mode 100644
index 0000000..5908d9a
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/Visualizer.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 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 <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+#include "VisualizerContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class VisualizerImpl final : public EffectImpl {
+  public:
+    static const std::string kEffectName;
+    static const Visualizer::Capability kCapability;
+    static const Descriptor kDescriptor;
+    VisualizerImpl() { LOG(DEBUG) << __func__; }
+    ~VisualizerImpl() {
+        cleanUp();
+        LOG(DEBUG) << __func__;
+    }
+
+    ndk::ScopedAStatus commandImpl(CommandId command) override;
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+                                            Parameter::Specific* specific) override;
+    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    RetCode releaseContext() override;
+
+    std::shared_ptr<EffectContext> getContext() override { return mContext; }
+    std::string getEffectName() override { return kEffectName; }
+
+  private:
+    std::shared_ptr<VisualizerContext> mContext;
+    ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag,
+                                                    Parameter::Specific* specific);
+    ndk::ScopedAStatus setOnlyParameter(const Visualizer::SetOnlyParameters& param);
+    ndk::ScopedAStatus getOnlyParameter(const Visualizer::GetOnlyParameters::Tag tag,
+                                        Parameter::Specific* specific);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.cpp b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
new file mode 100644
index 0000000..1965e0e
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2022 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 "VisualizerContext.h"
+
+#include <algorithm>
+#include <android/binder_status.h>
+#include <audio_utils/primitives.h>
+#include <math.h>
+#include <system/audio.h>
+#include <time.h>
+#include <Utils.h>
+
+#ifndef BUILD_FLOAT
+        #error AIDL Visualizer only support float 32bits, make sure add cflags -DBUILD_FLOAT,
+#endif
+
+using android::hardware::audio::common::getChannelCount;
+
+namespace aidl::android::hardware::audio::effect {
+
+VisualizerContext::VisualizerContext(int statusDepth, const Parameter::Common& common)
+    : EffectContext(statusDepth, common) {
+}
+
+VisualizerContext::~VisualizerContext() {
+    std::lock_guard lg(mMutex);
+    LOG(DEBUG) << __func__;
+    mState = State::UNINITIALIZED;
+}
+
+RetCode VisualizerContext::initParams(const Parameter::Common& common) {
+    std::lock_guard lg(mMutex);
+    LOG(DEBUG) << __func__;
+    if (common.input != common.output) {
+        LOG(ERROR) << __func__ << " mismatch input: " << common.input.toString()
+                   << " and output: " << common.output.toString();
+        return RetCode::ERROR_ILLEGAL_PARAMETER;
+    }
+
+    mState = State::INITIALIZED;
+    auto channelCount = getChannelCount(common.input.base.channelMask);
+#ifdef SUPPORT_MC
+    if (channelCount < 1 || channelCount > FCC_LIMIT) return RetCode::ERROR_ILLEGAL_PARAMETER;
+#else
+    if (channelCount != FCC_2) return RetCode::ERROR_ILLEGAL_PARAMETER;
+#endif
+    mChannelCount = channelCount;
+    mCommon = common;
+    return RetCode::SUCCESS;
+}
+
+RetCode VisualizerContext::enable() {
+    std::lock_guard lg(mMutex);
+    if (mState != State::INITIALIZED) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = State::ACTIVE;
+    return RetCode::SUCCESS;
+}
+
+RetCode VisualizerContext::disable() {
+    std::lock_guard lg(mMutex);
+    if (mState != State::ACTIVE) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = State::INITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+void VisualizerContext::reset() {
+    std::lock_guard lg(mMutex);
+    std::fill_n(mCaptureBuf.begin(), kMaxCaptureBufSize, 0x80);
+}
+
+RetCode VisualizerContext::setCaptureSamples(int samples) {
+    std::lock_guard lg(mMutex);
+    if (samples < 0 || (unsigned)samples > kMaxCaptureBufSize) {
+        LOG(ERROR) << __func__ << " captureSamples " << samples << " exceed valid range: 0 - "
+                   << kMaxCaptureBufSize;
+        return RetCode::ERROR_ILLEGAL_PARAMETER;
+    }
+    mCaptureSamples = samples;
+    return RetCode::SUCCESS;
+}
+int VisualizerContext::getCaptureSamples() {
+    std::lock_guard lg(mMutex);
+    return mCaptureSamples;
+}
+
+RetCode VisualizerContext::setMeasurementMode(Visualizer::MeasurementMode mode) {
+    std::lock_guard lg(mMutex);
+    mMeasurementMode = mode;
+    return RetCode::SUCCESS;
+}
+Visualizer::MeasurementMode VisualizerContext::getMeasurementMode() {
+    std::lock_guard lg(mMutex);
+    return mMeasurementMode;
+}
+
+RetCode VisualizerContext::setScalingMode(Visualizer::ScalingMode mode) {
+    std::lock_guard lg(mMutex);
+    mScalingMode = mode;
+    return RetCode::SUCCESS;
+}
+Visualizer::ScalingMode VisualizerContext::getScalingMode() {
+    std::lock_guard lg(mMutex);
+    return mScalingMode;
+}
+
+RetCode VisualizerContext::setDownstreamLatency(int latency) {
+    if (latency < 0 || (unsigned)latency > kMaxLatencyMs) {
+        LOG(ERROR) << __func__ << " latency " << latency << " exceed valid range: 0 - "
+                   << kMaxLatencyMs;
+        return RetCode::ERROR_ILLEGAL_PARAMETER;
+    }
+    std::lock_guard lg(mMutex);
+    mDownstreamLatency = latency;
+    return RetCode::SUCCESS;
+}
+
+uint32_t VisualizerContext::getDeltaTimeMsFromUpdatedTime_l() {
+    uint32_t deltaMs = 0;
+    if (mBufferUpdateTime.tv_sec != 0) {
+        struct timespec ts;
+        if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
+            time_t secs = ts.tv_sec - mBufferUpdateTime.tv_sec;
+            long nsec = ts.tv_nsec - mBufferUpdateTime.tv_nsec;
+            if (nsec < 0) {
+                --secs;
+                nsec += 1000000000;
+            }
+            deltaMs = secs * 1000 + nsec / 1000000;
+        }
+    }
+    return deltaMs;
+}
+
+Visualizer::GetOnlyParameters::Measurement VisualizerContext::getMeasure() {
+    uint16_t peakU16 = 0;
+    float sumRmsSquared = 0.0f;
+    uint8_t nbValidMeasurements = 0;
+
+    {
+        std::lock_guard lg(mMutex);
+        // reset measurements if last measurement was too long ago (which implies stored
+        // measurements aren't relevant anymore and shouldn't bias the new one)
+        const uint32_t delayMs = getDeltaTimeMsFromUpdatedTime_l();
+        if (delayMs > kDiscardMeasurementsTimeMs) {
+            LOG(INFO) << __func__ << " Discarding " << delayMs << " ms old measurements";
+            for (uint32_t i = 0; i < mMeasurementWindowSizeInBuffers; i++) {
+                mPastMeasurements[i].mIsValid = false;
+                mPastMeasurements[i].mPeakU16 = 0;
+                mPastMeasurements[i].mRmsSquared = 0;
+            }
+            mMeasurementBufferIdx = 0;
+        } else {
+            // only use actual measurements, otherwise the first RMS measure happening before
+            // MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS have been played will always be artificially
+            // low
+            for (uint32_t i = 0; i < mMeasurementWindowSizeInBuffers; i++) {
+                if (mPastMeasurements[i].mIsValid) {
+                    if (mPastMeasurements[i].mPeakU16 > peakU16) {
+                        peakU16 = mPastMeasurements[i].mPeakU16;
+                    }
+                    sumRmsSquared += mPastMeasurements[i].mRmsSquared;
+                    nbValidMeasurements++;
+                }
+            }
+        }
+    }
+
+    float rms = nbValidMeasurements == 0 ? 0.0f : sqrtf(sumRmsSquared / nbValidMeasurements);
+    Visualizer::GetOnlyParameters::Measurement measure;
+    // convert from I16 sample values to mB and write results
+    measure.rms = (rms < 0.000016f) ? -9600 : (int32_t)(2000 * log10(rms / 32767.0f));
+    measure.peak = (peakU16 == 0) ? -9600 : (int32_t)(2000 * log10(peakU16 / 32767.0f));
+    LOG(INFO) << __func__ << " peak " << peakU16 << " (" << measure.peak << "mB), rms " << rms
+              << " (" << measure.rms << "mB)";
+    return measure;
+}
+
+std::vector<uint8_t> VisualizerContext::capture() {
+    std::vector<uint8_t> result;
+    std::lock_guard lg(mMutex);
+    RETURN_VALUE_IF(mState != State::ACTIVE, result, "illegalState");
+    const uint32_t deltaMs = getDeltaTimeMsFromUpdatedTime_l();
+
+    // if audio framework has stopped playing audio although the effect is still active we must
+    // clear the capture buffer to return silence
+    if ((mLastCaptureIdx == mCaptureIdx) && (mBufferUpdateTime.tv_sec != 0) &&
+        (deltaMs > kMaxStallTimeMs)) {
+        LOG(INFO) << __func__ << " capture going to idle";
+        mBufferUpdateTime.tv_sec = 0;
+        return result;
+    }
+    int32_t latencyMs = mDownstreamLatency;
+    latencyMs -= deltaMs;
+    if (latencyMs < 0) {
+        latencyMs = 0;
+    }
+    uint32_t deltaSamples = mCaptureSamples + mCommon.input.base.sampleRate * latencyMs / 1000;
+
+    // large sample rate, latency, or capture size, could cause overflow.
+    // do not offset more than the size of buffer.
+    if (deltaSamples > kMaxCaptureBufSize) {
+        android_errorWriteLog(0x534e4554, "31781965");
+        deltaSamples = kMaxCaptureBufSize;
+    }
+
+    int32_t capturePoint;
+    //capturePoint = (int32_t)mCaptureIdx - deltaSamples;
+    __builtin_sub_overflow((int32_t) mCaptureIdx, deltaSamples, &capturePoint);
+    // a negative capturePoint means we wrap the buffer.
+    if (capturePoint < 0) {
+        uint32_t size = -capturePoint;
+        if (size > mCaptureSamples) {
+            size = mCaptureSamples;
+        }
+        result.insert(result.end(), &mCaptureBuf[kMaxCaptureBufSize + capturePoint],
+                        &mCaptureBuf[kMaxCaptureBufSize + capturePoint + size]);
+        mCaptureSamples -= size;
+        capturePoint = 0;
+    }
+    result.insert(result.end(), &mCaptureBuf[capturePoint],
+                    &mCaptureBuf[capturePoint + mCaptureSamples]);
+    mLastCaptureIdx = mCaptureIdx;
+    return result;
+}
+
+IEffect::Status VisualizerContext::process(float* in, float* out, int samples) {
+    IEffect::Status result = {STATUS_NOT_ENOUGH_DATA, 0, 0};
+    RETURN_VALUE_IF(in == nullptr || out == nullptr || samples == 0, result, "dataBufferError");
+
+    std::lock_guard lg(mMutex);
+    result.status = STATUS_INVALID_OPERATION;
+    RETURN_VALUE_IF(mState != State::ACTIVE, result, "stateNotActive");
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+    // perform measurements if needed
+    if (mMeasurementMode == Visualizer::MeasurementMode::PEAK_RMS) {
+        // find the peak and RMS squared for the new buffer
+        float rmsSqAcc = 0;
+        float maxSample = 0.f;
+        for (size_t inIdx = 0; inIdx < (unsigned)samples; ++inIdx) {
+            maxSample = fmax(maxSample, fabs(in[inIdx]));
+            rmsSqAcc += in[inIdx] * in[inIdx];
+        }
+        maxSample *= 1 << 15; // scale to int16_t, with exactly 1 << 15 representing positive num.
+        rmsSqAcc *= 1 << 30; // scale to int16_t * 2
+        mPastMeasurements[mMeasurementBufferIdx] = {
+                .mPeakU16 = (uint16_t)maxSample,
+                .mRmsSquared = rmsSqAcc / samples,
+                .mIsValid = true };
+        if (++mMeasurementBufferIdx >= mMeasurementWindowSizeInBuffers) {
+            mMeasurementBufferIdx = 0;
+        }
+    }
+
+    float fscale;  // multiplicative scale
+    if (mScalingMode == Visualizer::ScalingMode::NORMALIZED) {
+        // derive capture scaling factor from peak value in current buffer
+        // this gives more interesting captures for display.
+        float maxSample = 0.f;
+        for (size_t inIdx = 0; inIdx < (unsigned)samples; ) {
+            // we reconstruct the actual summed value to ensure proper normalization
+            // for multichannel outputs (channels > 2 may often be 0).
+            float smp = 0.f;
+            for (int i = 0; i < mChannelCount; ++i) {
+                smp += in[inIdx++];
+            }
+            maxSample = fmax(maxSample, fabs(smp));
+        }
+        if (maxSample > 0.f) {
+            fscale = 0.99f / maxSample;
+            int exp; // unused
+            const float significand = frexp(fscale, &exp);
+            if (significand == 0.5f) {
+                fscale *= 255.f / 256.f; // avoid returning unaltered PCM signal
+            }
+        } else {
+            // scale doesn't matter, the values are all 0.
+            fscale = 1.f;
+        }
+    } else {
+        assert(mScalingMode == Visualizer::ScalingMode::AS_PLAYED);
+        // Note: if channels are uncorrelated, 1/sqrt(N) could be used at the risk of clipping.
+        fscale = 1.f / mChannelCount;  // account for summing all the channels together.
+    }
+
+    uint32_t captIdx;
+    uint32_t inIdx;
+    for (inIdx = 0, captIdx = mCaptureIdx; inIdx < (unsigned)samples; captIdx++) {
+        // wrap
+        if (captIdx >= kMaxCaptureBufSize) {
+            captIdx = 0;
+        }
+
+        float smp = 0.f;
+        for (uint32_t i = 0; i < mChannelCount; ++i) {
+            smp += in[inIdx++];
+        }
+        mCaptureBuf[captIdx] = clamp8_from_float(smp * fscale);
+    }
+
+    // the following two should really be atomic, though it probably doesn't
+    // matter much for visualization purposes
+    mCaptureIdx = captIdx;
+    // update last buffer update time stamp
+    if (clock_gettime(CLOCK_MONOTONIC, &mBufferUpdateTime) < 0) {
+        mBufferUpdateTime.tv_sec = 0;
+    }
+
+    // TODO: handle access_mode
+    memcpy(out, in, samples * sizeof(float));
+    return {STATUS_OK, samples, samples};
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.h b/media/libeffects/visualizer/aidl/VisualizerContext.h
new file mode 100644
index 0000000..bfda0b9
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2022 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 <android-base/thread_annotations.h>
+#include <audio_effects/effect_dynamicsprocessing.h>
+
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class VisualizerContext final : public EffectContext {
+  public:
+    static const uint32_t kMaxCaptureBufSize = 65536;
+    static const uint32_t kMaxLatencyMs = 3000;  // 3 seconds of latency for audio pipeline
+
+    VisualizerContext(int statusDepth, const Parameter::Common& common);
+    ~VisualizerContext();
+
+    RetCode initParams(const Parameter::Common& common);
+
+    RetCode enable();
+    RetCode disable();
+    // keep all parameters and reset buffer.
+    void reset();
+
+    RetCode setCaptureSamples(int captureSize);
+    int getCaptureSamples();
+    RetCode setMeasurementMode(Visualizer::MeasurementMode mode);
+    Visualizer::MeasurementMode getMeasurementMode();
+    RetCode setScalingMode(Visualizer::ScalingMode mode);
+    Visualizer::ScalingMode getScalingMode();
+    RetCode setDownstreamLatency(int latency);
+
+    IEffect::Status process(float* in, float* out, int samples);
+    // Gets the current measurements, measured by process() and consumed by getParameter()
+    Visualizer::GetOnlyParameters::Measurement getMeasure();
+    // Gets the latest PCM capture, data captured by process() and consumed by getParameter()
+    std::vector<uint8_t> capture();
+
+    struct BufferStats {
+        bool mIsValid;
+        uint16_t mPeakU16; // the positive peak of the absolute value of the samples in a buffer
+        float mRmsSquared; // the average square of the samples in a buffer
+    };
+
+    enum State {
+        UNINITIALIZED,
+        INITIALIZED,
+        ACTIVE,
+    };
+
+  private:
+    // maximum time since last capture buffer update before resetting capture buffer. This means
+    // that the framework has stopped playing audio and we must start returning silence
+    static const uint32_t kMaxStallTimeMs = 1000;
+    // discard measurements older than this number of ms
+    static const uint32_t kDiscardMeasurementsTimeMs = 2000;
+    // maximum number of buffers for which we keep track of the measurements
+    // note: buffer index is stored in uint8_t
+    static const uint32_t kMeasurementWindowMaxSizeInBuffers = 25;
+
+    // serialize process() and parameter setting
+    std::mutex mMutex;
+    Parameter::Common mCommon GUARDED_BY(mMutex);
+    State mState GUARDED_BY(mMutex) = State::UNINITIALIZED;
+    uint32_t mCaptureIdx GUARDED_BY(mMutex) = 0;
+    uint32_t mLastCaptureIdx GUARDED_BY(mMutex) = 0;
+    Visualizer::ScalingMode mScalingMode GUARDED_BY(mMutex) = Visualizer::ScalingMode::NORMALIZED;
+    struct timespec mBufferUpdateTime GUARDED_BY(mMutex);
+    // capture buf with 8 bits PCM
+    std::array<uint8_t, kMaxCaptureBufSize> mCaptureBuf GUARDED_BY(mMutex);
+    uint32_t mDownstreamLatency GUARDED_BY(mMutex) = 0;
+    uint32_t mCaptureSamples GUARDED_BY(mMutex) = kMaxCaptureBufSize;
+
+    // to avoid recomputing it every time a buffer is processed
+    uint8_t mChannelCount GUARDED_BY(mMutex) = 0;
+    Visualizer::MeasurementMode mMeasurementMode GUARDED_BY(mMutex) =
+            Visualizer::MeasurementMode::NONE;
+    uint8_t mMeasurementWindowSizeInBuffers = kMeasurementWindowMaxSizeInBuffers;
+    uint8_t mMeasurementBufferIdx GUARDED_BY(mMutex) = 0;
+    std::array<BufferStats, kMeasurementWindowMaxSizeInBuffers> mPastMeasurements;
+    void init_params();
+
+    uint32_t getDeltaTimeMsFromUpdatedTime_l() REQUIRES(mMutex);
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libheadtracking/SensorPoseProvider.cpp b/media/libheadtracking/SensorPoseProvider.cpp
index bd8af04..31d469c 100644
--- a/media/libheadtracking/SensorPoseProvider.cpp
+++ b/media/libheadtracking/SensorPoseProvider.cpp
@@ -42,6 +42,7 @@
 
 // Identifier to use for our event queue on the loop.
 // The number 19 is arbitrary, only useful if using multiple objects on the same looper.
+// Note: Instead of a fixed number, the SensorEventQueue's fd could be used instead.
 constexpr int kIdent = 19;
 
 static inline Looper* ALooper_to_Looper(ALooper* alooper) {
@@ -60,7 +61,8 @@
     EventQueueGuard(const sp<SensorEventQueue>& queue, Looper* looper) : mQueue(queue) {
         mQueue->looper = Looper_to_ALooper(looper);
         mQueue->requestAdditionalInfo = false;
-        looper->addFd(mQueue->getFd(), kIdent, ALOOPER_EVENT_INPUT, nullptr, nullptr);
+        looper->addFd(mQueue->getFd(), kIdent, ALOOPER_EVENT_INPUT,
+                nullptr /* callback */, nullptr /* data */);
     }
 
     ~EventQueueGuard() {
@@ -75,7 +77,7 @@
     [[nodiscard]] SensorEventQueue* get() const { return mQueue.get(); }
 
   private:
-    sp<SensorEventQueue> mQueue;
+    const sp<SensorEventQueue> mQueue;
 };
 
 /**
@@ -95,10 +97,7 @@
         }
     }
 
-    SensorEnableGuard(const SensorEnableGuard&) = delete;
-    SensorEnableGuard& operator=(const SensorEnableGuard&) = delete;
-
-    // Enable moving.
+    // Enable move and delete default copy-ctor/copy-assignment.
     SensorEnableGuard(SensorEnableGuard&& other) : mQueue(other.mQueue), mSensor(other.mSensor) {
         other.mSensor = SensorPoseProvider::INVALID_HANDLE;
     }
@@ -122,6 +121,7 @@
     ~SensorPoseProviderImpl() override {
         // Disable all active sensors.
         mEnabledSensors.clear();
+        mQuit = true;
         mLooper->wake();
         mThread.join();
     }
@@ -130,7 +130,7 @@
         // Figure out the sensor's data format.
         DataFormat format = getSensorFormat(sensor);
         if (format == DataFormat::kUnknown) {
-            ALOGE("Unknown format for sensor %" PRId32, sensor);
+            ALOGE("%s: Unknown format for sensor %" PRId32, __func__, sensor);
             return false;
         }
 
@@ -144,17 +144,19 @@
 
         // Enable the sensor.
         if (mQueue->enableSensor(sensor, samplingPeriod.count(), 0, 0)) {
-            ALOGE("Failed to enable sensor");
+            ALOGE("%s: Failed to enable sensor %" PRId32, __func__, sensor);
             std::lock_guard lock(mMutex);
             mEnabledSensorsExtra.erase(sensor);
             return false;
         }
 
-        mEnabledSensors.emplace(sensor, SensorEnableGuard(mQueue.get(), sensor));
+        mEnabledSensors.emplace(sensor, SensorEnableGuard(mQueue, sensor));
+        ALOGD("%s: Sensor %" PRId32 " started", __func__, sensor);
         return true;
     }
 
     void stopSensor(int handle) override {
+        ALOGD("%s: Sensor %" PRId32 " stopped", __func__, handle);
         mEnabledSensors.erase(handle);
         std::lock_guard lock(mMutex);
         mEnabledSensorsExtra.erase(handle);
@@ -217,13 +219,14 @@
         std::optional<int32_t> discontinuityCount;
     };
 
+    bool mQuit = false;
     sp<Looper> mLooper;
     Listener* const mListener;
     SensorManager* const mSensorManager;
     std::timed_mutex mMutex;
+    sp<SensorEventQueue> mQueue;
     std::map<int32_t, SensorEnableGuard> mEnabledSensors;
     std::map<int32_t, SensorExtra> mEnabledSensorsExtra GUARDED_BY(mMutex);
-    sp<SensorEventQueue> mQueue;
 
     // We must do some of the initialization operations on the worker thread, because the API relies
     // on the thread-local looper. In addition, as a matter of convenience, we store some of the
@@ -244,7 +247,13 @@
     bool waitInitFinished() { return mInitPromise.get_future().get(); }
 
     void threadFunc() {
-        // Obtain looper.
+        // Name our std::thread to help identification.  As is, canCallJava == false.
+        androidSetThreadName("SensorPoseProvider-looper");
+
+        // Run at the highest non-realtime priority.
+        androidSetThreadPriority(gettid(), PRIORITY_URGENT_AUDIO);
+
+        // The looper is started on the created std::thread.
         mLooper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
 
         // Create event queue.
@@ -260,20 +269,28 @@
 
         initFinished(true);
 
-        while (true) {
-            int ret = mLooper->pollOnce(-1 /* no timeout */, nullptr, nullptr, nullptr);
+        while (!mQuit) {
+            const int ret = mLooper->pollOnce(-1 /* no timeout */, nullptr /* outFd */,
+                    nullptr /* outEvents */, nullptr /* outData */);
 
             switch (ret) {
                 case ALOOPER_POLL_WAKE:
-                    // Normal way to exit.
-                    return;
+                    // Continue to see if mQuit flag is set.
+                    // This can be spurious (due to bugreport being taken).
+                    continue;
 
                 case kIdent:
                     // Possible events on our queue.
                     break;
 
                 default:
-                    ALOGE("Unexpected status out of Looper::pollOnce: %d", ret);
+                    // Besides WAKE and kIdent, there should be no timeouts, callbacks,
+                    // ALOOPER_POLL_ERROR, or other events.
+                    // Exit now to avoid high frequency log spam on error,
+                    // e.g. if the fd becomes invalid (b/31093485).
+                    ALOGE("%s: Unexpected status out of Looper::pollOnce: %d", __func__, ret);
+                    mQuit = true;
+                    continue;
             }
 
             // Process an event.
@@ -285,7 +302,8 @@
             ssize_t size = mQueue->filterEvents(&event, actual);
 
             if (size < 0 || size > 1) {
-                ALOGE("Unexpected return value from SensorEventQueue::filterEvents: %zd", size);
+                ALOGE("%s: Unexpected return value from SensorEventQueue::filterEvents: %zd",
+                        __func__, size);
                 break;
             }
             if (size == 0) {
@@ -295,6 +313,7 @@
 
             handleEvent(event);
         }
+        ALOGD("%s: Exiting sensor event loop", __func__);
     }
 
     void handleEvent(const ASensorEvent& event) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
index 6788b56..5e29b3f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
@@ -191,8 +191,8 @@
         uint8_t key[kBlockSize],
         uint8_t iv[kBlockSize],
         CryptoPlugin::Mode mode,
-        size_t *clearbytes,
-        size_t *encryptedbytes)
+        uint32_t *clearbytes,
+        uint32_t *encryptedbytes)
 {
     // size needed to store all the crypto data
     size_t cryptosize;
@@ -236,7 +236,7 @@
     if (!meta.findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
         return NULL;
     }
-    size_t numSubSamples = cryptedsize / sizeof(size_t);
+    size_t numSubSamples = cryptedsize / sizeof(uint32_t);
 
     if (numSubSamples <= 0) {
         ALOGE("getSampleCryptoInfo INVALID numSubSamples: %zu", numSubSamples);
@@ -285,8 +285,8 @@
             (uint8_t*) key,
             (uint8_t*) iv,
             (CryptoPlugin::Mode)mode,
-            (size_t*) cleardata,
-            (size_t*) crypteddata);
+            (uint32_t*) cleardata,
+            (uint32_t*) crypteddata);
 }
 
 }   // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h
index 4360656..232638c 100644
--- a/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h
+++ b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h
@@ -106,8 +106,8 @@
                 uint8_t key[kBlockSize],
                 uint8_t iv[kBlockSize],
                 CryptoPlugin::Mode mode,
-                size_t *clearbytes,
-                size_t *encryptedbytes);
+                uint32_t *clearbytes,
+                uint32_t *encryptedbytes);
 
         static CryptoInfo *getSampleCryptoInfo(MetaDataBase &meta);
 
diff --git a/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp b/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
index c43e1f8..19c8577 100644
--- a/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
+++ b/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include <fstream>
+#include <memory>
 
 #include <media/stagefright/foundation/ABitReader.h>
 #include <HevcUtils.h>
@@ -88,10 +89,10 @@
         stringLine >> type >> chunkLength;
         ASSERT_GT(chunkLength, 0) << "Length of data chunk must be greater than 0";
 
-        char *data = (char *)malloc(chunkLength);
+        std::unique_ptr<char[]> data(new char[chunkLength]);
         ASSERT_NE(data, nullptr) << "Failed to allocate data buffer of size: " << chunkLength;
 
-        mMediaFileStream.read(data, chunkLength);
+        mMediaFileStream.read(data.get(), chunkLength);
         ASSERT_EQ(mMediaFileStream.gcount(), chunkLength)
                 << "Failed to read complete file, bytes read: " << mMediaFileStream.gcount();
 
@@ -105,7 +106,7 @@
         offset += 3;
         ASSERT_LE(offset, chunkLength) << "NAL unit offset must not exceed the chunk length";
 
-        uint8_t *nalUnit = (uint8_t *)(data + offset);
+        uint8_t *nalUnit = (uint8_t *)(data.get() + offset);
         size_t nalUnitLength = chunkLength - offset;
 
         // Add NAL units only if they're of type: VPS/SPS/PPS/SEI
@@ -118,20 +119,18 @@
             size_t sizeNalUnit = hevcParams.getSize(index);
             ASSERT_EQ(sizeNalUnit, nalUnitLength) << "Invalid size returned for NAL: " << type;
 
-            uint8_t *destination = (uint8_t *)malloc(nalUnitLength);
+            std::unique_ptr<uint8_t[]> destination(new uint8_t[nalUnitLength]);
             ASSERT_NE(destination, nullptr)
                     << "Failed to allocate buffer of size: " << nalUnitLength;
 
-            bool status = hevcParams.write(index, destination, nalUnitLength);
+            bool status = hevcParams.write(index, destination.get(), nalUnitLength);
             ASSERT_TRUE(status) << "Unable to write NAL Unit data";
 
-            free(destination);
             index++;
         } else {
             err = hevcParams.addNalUnit(nalUnit, nalUnitLength);
             ASSERT_NE(err, (status_t)OK) << "Invalid NAL Unit added, type: " << type;
         }
-        free(data);
     }
 
     size_t numNalUnits = hevcParams.getNumNalUnitsOfType(kVPSCode);
@@ -166,10 +165,10 @@
             << "Expected NAL type: 34(PPS), found: " << typeNalUnit;
 
     size_t hvccBoxSize = kHvccBoxMaxSize;
-    uint8_t *hvcc = (uint8_t *)malloc(kHvccBoxMaxSize);
+    std::unique_ptr<uint8_t[]> hvcc(new uint8_t[kHvccBoxMaxSize]);
     ASSERT_NE(hvcc, nullptr) << "Failed to allocate a hvcc buffer of size: " << kHvccBoxMaxSize;
 
-    err = hevcParams.makeHvcc(hvcc, &hvccBoxSize, kNALSizeLength);
+    err = hevcParams.makeHvcc(hvcc.get(), &hvccBoxSize, kNALSizeLength);
     ASSERT_EQ(err, (status_t)OK) << "Unable to create hvcc box";
 
     ASSERT_GT(hvccBoxSize, kHvccBoxMinSize)
@@ -179,8 +178,6 @@
     if (frameRate != mFrameRate)
         cout << "[   WARN   ] Expected frame rate: " << mFrameRate << " Found: " << frameRate
              << endl;
-
-    free(hvcc);
 }
 
 // Info File contains the type and length for each chunk/frame
diff --git a/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp b/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
index f934b54..b2044d3 100644
--- a/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
+++ b/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <fstream>
+#include <memory>
 
 #include <binder/Parcel.h>
 #include <media/stagefright/foundation/AString.h>
@@ -240,10 +241,10 @@
 
                     if (remaining < tempFontNameLength) break;
                     const uint8_t *tmpFont = tmpData;
-                    char *tmpFontName = strndup((const char *)tmpFont, tempFontNameLength);
+                    std::unique_ptr<char[]> tmpFontName(new char[tempFontNameLength]);
+                    strncpy(tmpFontName.get(), (const char *)tmpFont, tempFontNameLength);
                     ASSERT_NE(tmpFontName, nullptr) << "Font Name is null";
-                    ALOGI("FontName = %s", tmpFontName);
-                    free(tmpFontName);
+                    ALOGI("FontName = %s", tmpFontName.get());
                     tmpData += tempFontNameLength;
                     remaining -= tempFontNameLength;
                     fontRecordEntries.push_back({tempFontID, tempFontNameLength, tmpFont});
diff --git a/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp b/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
index 7221b92..2cc88ce 100644
--- a/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
+++ b/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
@@ -21,6 +21,7 @@
 #include <utils/Log.h>
 
 #include <audio_utils/sndfile.h>
+#include <memory>
 #include <stdio.h>
 
 #include "pvamrwbdecoder.h"
@@ -121,7 +122,7 @@
 
 TEST_F(AmrwbDecoderTest, MultiCreateAmrwbDecoderTest) {
     uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
-    void *decoderBuf = malloc(memRequirements);
+    std::unique_ptr<char[]> decoderBuf(new char[memRequirements]);
     ASSERT_NE(decoderBuf, nullptr)
             << "Failed to allocate decoder memory of size " << memRequirements;
 
@@ -129,25 +130,21 @@
     void *amrHandle = nullptr;
     int16_t *decoderCookie;
     for (int count = 0; count < kMaxCount; count++) {
-        pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+        pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
         ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
         ALOGV("Decoder created successfully");
     }
-    if (decoderBuf) {
-        free(decoderBuf);
-        decoderBuf = nullptr;
-    }
 }
 
 TEST_P(AmrwbDecoderTest, DecodeTest) {
     uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
-    void *decoderBuf = malloc(memRequirements);
+    std::unique_ptr<char[]> decoderBuf(new char[memRequirements]);
     ASSERT_NE(decoderBuf, nullptr)
             << "Failed to allocate decoder memory of size " << memRequirements;
 
     void *amrHandle = nullptr;
     int16_t *decoderCookie;
-    pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+    pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
     ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
 
     string inputFile = gEnv->getRes() + GetParam();
@@ -159,25 +156,21 @@
     SNDFILE *outFileHandle = openOutputFile(&sfInfo);
     ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
 
-    int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
+    int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf.get(), outFileHandle);
     ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
 
     sf_close(outFileHandle);
-    if (decoderBuf) {
-        free(decoderBuf);
-        decoderBuf = nullptr;
-    }
 }
 
 TEST_P(AmrwbDecoderTest, ResetDecoderTest) {
     uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
-    void *decoderBuf = malloc(memRequirements);
+    std::unique_ptr<char[]> decoderBuf(new char[memRequirements]);
     ASSERT_NE(decoderBuf, nullptr)
             << "Failed to allocate decoder memory of size " << memRequirements;
 
     void *amrHandle = nullptr;
     int16_t *decoderCookie;
-    pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+    pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
     ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
 
     string inputFile = gEnv->getRes() + GetParam();
@@ -190,20 +183,18 @@
     ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
 
     // Decode 150 frames first
-    int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle, kNumFrameReset);
+    int32_t decoderErr =
+            DecodeFrames(decoderCookie, decoderBuf.get(), outFileHandle, kNumFrameReset);
     ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
 
     // Reset Decoder
-    pvDecoder_AmrWb_Reset(decoderBuf, 1);
+    pvDecoder_AmrWb_Reset(decoderBuf.get(), 1);
 
     // Start decoding again
-    decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
+    decoderErr = DecodeFrames(decoderCookie, decoderBuf.get(), outFileHandle);
     ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
 
     sf_close(outFileHandle);
-    if (decoderBuf) {
-        free(decoderBuf);
-    }
 }
 
 INSTANTIATE_TEST_SUITE_P(AmrwbDecoderTestAll, AmrwbDecoderTest,
diff --git a/media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp b/media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp
index 91326a8..88e9eae 100644
--- a/media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp
+++ b/media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp
@@ -20,6 +20,7 @@
 #include <utils/Log.h>
 
 #include <audio_utils/sndfile.h>
+#include <memory>
 #include <stdio.h>
 
 #include "mp3reader.h"
@@ -99,27 +100,23 @@
 TEST_F(Mp3DecoderTest, MultiCreateMp3DecoderTest) {
     size_t memRequirements = pvmp3_decoderMemRequirements();
     ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
-    void *decoderBuf = malloc(memRequirements);
+    unique_ptr<char[]> decoderBuf(new char[memRequirements]);
     ASSERT_NE(decoderBuf, nullptr)
             << "Failed to allocate decoder memory of size " << memRequirements;
     for (int count = 0; count < kMaxCount; count++) {
-        pvmp3_InitDecoder(mConfig, decoderBuf);
+        pvmp3_InitDecoder(mConfig, (void*)decoderBuf.get());
         ALOGV("Decoder created successfully");
     }
-    if (decoderBuf) {
-        free(decoderBuf);
-        decoderBuf = nullptr;
-    }
 }
 
 TEST_P(Mp3DecoderTest, DecodeTest) {
     size_t memRequirements = pvmp3_decoderMemRequirements();
     ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
-    void *decoderBuf = malloc(memRequirements);
+    unique_ptr<char[]> decoderBuf(new char[memRequirements]);
     ASSERT_NE(decoderBuf, nullptr)
             << "Failed to allocate decoder memory of size " << memRequirements;
 
-    pvmp3_InitDecoder(mConfig, decoderBuf);
+    pvmp3_InitDecoder(mConfig, (void*)decoderBuf.get());
     ALOGV("Decoder created successfully");
     string inputFile = gEnv->getRes() + GetParam();
     bool status = mMp3Reader.init(inputFile.c_str());
@@ -130,27 +127,23 @@
     SNDFILE *outFileHandle = openOutputFile(&sfInfo);
     ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
 
-    ERROR_CODE decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo);
+    ERROR_CODE decoderErr = DecodeFrames((void*)decoderBuf.get(), outFileHandle, sfInfo);
     ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
     ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
     ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
 
     mMp3Reader.close();
     sf_close(outFileHandle);
-    if (decoderBuf) {
-        free(decoderBuf);
-        decoderBuf = nullptr;
-    }
 }
 
 TEST_P(Mp3DecoderTest, ResetDecoderTest) {
     size_t memRequirements = pvmp3_decoderMemRequirements();
     ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
-    void *decoderBuf = malloc(memRequirements);
+    unique_ptr<char[]> decoderBuf(new char[memRequirements]);
     ASSERT_NE(decoderBuf, nullptr)
             << "Failed to allocate decoder memory of size " << memRequirements;
 
-    pvmp3_InitDecoder(mConfig, decoderBuf);
+    pvmp3_InitDecoder(mConfig, (void*)decoderBuf.get());
     ALOGV("Decoder created successfully.");
     string inputFile = gEnv->getRes() + GetParam();
     bool status = mMp3Reader.init(inputFile.c_str());
@@ -162,24 +155,20 @@
     ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
 
     ERROR_CODE decoderErr;
-    decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo, kNumFrameReset);
+    decoderErr = DecodeFrames((void*)decoderBuf.get(), outFileHandle, sfInfo, kNumFrameReset);
     ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
     ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
     ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
 
-    pvmp3_resetDecoder(decoderBuf);
+    pvmp3_resetDecoder((void*)decoderBuf.get());
     // Decode the same file.
-    decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo);
+    decoderErr = DecodeFrames((void*)decoderBuf.get(), outFileHandle, sfInfo);
     ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
     ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
     ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
 
     mMp3Reader.close();
     sf_close(outFileHandle);
-    if (decoderBuf) {
-        free(decoderBuf);
-        decoderBuf = nullptr;
-    }
 }
 
 INSTANTIATE_TEST_SUITE_P(Mp3DecoderTestAll, Mp3DecoderTest,
diff --git a/media/module/esds/TEST_MAPPING b/media/module/esds/TEST_MAPPING
new file mode 100644
index 0000000..9368b6d
--- /dev/null
+++ b/media/module/esds/TEST_MAPPING
@@ -0,0 +1,9 @@
+// mappings for frameworks/av/media/module/esds
+{
+  // tests which require dynamic content
+  // invoke with: atest -- --enable-module-dynamic-download=true
+  // TODO(b/148094059): unit tests not allowed to download content
+  "dynamic-presubmit": [
+    { "name": "ESDSTest" }
+  ]
+}
diff --git a/media/module/esds/tests/ESDSTest.cpp b/media/module/esds/tests/ESDSTest.cpp
index ea9a888..33bdcac 100644
--- a/media/module/esds/tests/ESDSTest.cpp
+++ b/media/module/esds/tests/ESDSTest.cpp
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <fstream>
+#include <memory>
 
 #include <media/esds/ESDS.h>
 #include <binder/ProcessState.h>
@@ -121,18 +122,16 @@
 };
 
 TEST_P(ESDSUnitTest, InvalidDataTest) {
-    void *invalidData = calloc(mESDSSize, 1);
+    std::unique_ptr<char[]> invalidData(new char[mESDSSize]());
     ASSERT_NE(invalidData, nullptr) << "Unable to allocate memory";
-    ESDS esds(invalidData, mESDSSize);
-    free(invalidData);
+    ESDS esds((void*)invalidData.get(), mESDSSize);
     ASSERT_NE(esds.InitCheck(), OK) << "invalid ESDS data accepted";
 }
 
 TEST(ESDSSanityUnitTest, ConstructorSanityTest) {
-    void *invalidData = malloc(1);
+    std::unique_ptr<char[]> invalidData(new char[1]());
     ASSERT_NE(invalidData, nullptr) << "Unable to allocate memory";
-    ESDS esds_zero(invalidData, 0);
-    free(invalidData);
+    ESDS esds_zero((void*)invalidData.get(), 0);
     ASSERT_NE(esds_zero.InitCheck(), OK) << "invalid ESDS data accepted";
 
     ESDS esds_null(NULL, 0);
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index 2e889e3..3a5a869 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -394,6 +394,15 @@
             return MEDIA_MIMETYPE_AUDIO_MPEGH_MHA1;
         case FOURCC("mhm1"):
             return MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1;
+        case FOURCC("dtsc"):
+            return MEDIA_MIMETYPE_AUDIO_DTS;
+        case FOURCC("dtse"):
+        case FOURCC("dtsh"):
+            return MEDIA_MIMETYPE_AUDIO_DTS_HD;
+        case FOURCC("dtsl"):
+            return MEDIA_MIMETYPE_AUDIO_DTS_HD_MA;
+        case FOURCC("dtsx"):
+            return MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2;
         default:
             ALOGW("Unknown fourcc: %c%c%c%c",
                    (fourcc >> 24) & 0xff,
@@ -1804,6 +1813,11 @@
         case 0x6D730055: // "ms U" mp3 audio
         case FOURCC("mha1"):
         case FOURCC("mhm1"):
+        case FOURCC("dtsc"):
+        case FOURCC("dtse"):
+        case FOURCC("dtsh"):
+        case FOURCC("dtsl"):
+        case FOURCC("dtsx"):
         {
             if (mIsQT && depth >= 1 && mPath[depth - 1] == FOURCC("wave")) {
 
@@ -6723,7 +6737,7 @@
         const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
         offset = smpl->offset;
         size = smpl->size;
-        cts = mCurrentTime + smpl->compositionOffset;
+        cts = (int64_t)mCurrentTime + (int64_t)smpl->compositionOffset;
 
         if (mElstInitialEmptyEditTicks > 0) {
             cts += mElstInitialEmptyEditTicks;
diff --git a/media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp b/media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
index 77a8599..57ac822 100644
--- a/media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
+++ b/media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include <fstream>
+#include <memory>
 
 #include "media/stagefright/foundation/ABitReader.h"
 #include "media/stagefright/foundation/avc_utils.h"
@@ -151,10 +152,10 @@
     size_t fileSize = buf.st_size;
     ASSERT_NE(fileSize, 0) << "Invalid file size found";
 
-    const uint8_t *volBuffer = new uint8_t[fileSize];
+    std::unique_ptr<uint8_t[]> volBuffer(new uint8_t[fileSize]);
     ASSERT_NE(volBuffer, nullptr) << "Failed to allocate VOL buffer of size: " << fileSize;
 
-    inputFileStream.read((char *)(volBuffer), fileSize);
+    inputFileStream.read((char *)(volBuffer.get()), fileSize);
     ASSERT_EQ(inputFileStream.gcount(), fileSize)
             << "Failed to read complete file, bytes read: " << inputFileStream.gcount();
 
@@ -163,15 +164,13 @@
     int32_t volWidth = -1;
     int32_t volHeight = -1;
 
-    bool status = ExtractDimensionsFromVOLHeader(volBuffer, fileSize, &volWidth, &volHeight);
+    bool status = ExtractDimensionsFromVOLHeader(volBuffer.get(), fileSize, &volWidth, &volHeight);
     ASSERT_TRUE(status)
             << "Failed to get VOL dimensions from function: ExtractDimensionsFromVOLHeader()";
 
     ASSERT_EQ(volWidth, width) << "Expected width: " << width << "Found: " << volWidth;
 
     ASSERT_EQ(volHeight, height) << "Expected height: " << height << "Found: " << volHeight;
-
-    delete[] volBuffer;
 }
 
 TEST_P(AVCDimensionTest, DimensionTest) {
@@ -186,7 +185,8 @@
         stringLine >> type >> chunkLength;
         ASSERT_GT(chunkLength, 0) << "Length of the data chunk must be greater than zero";
 
-        const uint8_t *data = new uint8_t[chunkLength];
+        std::unique_ptr<uint8_t[]> dataArray(new uint8_t[chunkLength]);
+        const uint8_t *data = dataArray.get();
         ASSERT_NE(data, nullptr) << "Failed to create a data buffer of size: " << chunkLength;
 
         const uint8_t *nalStart;
@@ -197,9 +197,11 @@
                 << "Failed to read complete file, bytes read: " << mInputFileStream.gcount();
 
         size_t smallBufferSize = kSmallBufferSize;
-        const uint8_t *sanityData = new uint8_t[smallBufferSize];
+        uint8_t sanityDataBuffer[smallBufferSize];
+        const uint8_t *sanityData = sanityDataBuffer;
         memcpy((void *)sanityData, (void *)data, smallBufferSize);
 
+        // sanityData could be changed, but sanityDataPtr is not and can be cleaned up.
         status_t result = getNextNALUnit(&sanityData, &smallBufferSize, &nalStart, &nalSize, true);
         ASSERT_EQ(result, -EAGAIN) << "Invalid result found when wrong NAL unit passed";
 
@@ -221,7 +223,6 @@
             ASSERT_EQ(avcHeight, mFrameHeight)
                     << "Expected height: " << mFrameHeight << "Found: " << avcHeight;
         }
-        delete[] data;
     }
     if (mNalUnitsExpected < 0) {
         ASSERT_GT(numNalUnits, 0) << "Failed to find an NAL Unit";
@@ -251,7 +252,8 @@
         accessUnitLength += chunkLength;
 
         if (!type.compare("SPS")) {
-            const uint8_t *data = new uint8_t[chunkLength];
+            std::unique_ptr<uint8_t[]> dataArray(new uint8_t[chunkLength]);
+            const uint8_t *data = dataArray.get();
             ASSERT_NE(data, nullptr) << "Failed to create a data buffer of size: " << chunkLength;
 
             const uint8_t *nalStart;
@@ -271,14 +273,13 @@
                 profile = nalStart[1];
                 level = nalStart[3];
             }
-            delete[] data;
         }
     }
-    const uint8_t *accessUnitData = new uint8_t[accessUnitLength];
+    std::unique_ptr<uint8_t[]> accessUnitData(new uint8_t[accessUnitLength]);
     ASSERT_NE(accessUnitData, nullptr) << "Failed to create a buffer of size: " << accessUnitLength;
 
     mInputFileStream.seekg(0, ios::beg);
-    mInputFileStream.read((char *)accessUnitData, accessUnitLength);
+    mInputFileStream.read((char *)accessUnitData.get(), accessUnitLength);
     ASSERT_EQ(mInputFileStream.gcount(), accessUnitLength)
             << "Failed to read complete file, bytes read: " << mInputFileStream.gcount();
 
@@ -286,7 +287,7 @@
     ASSERT_NE(accessUnit, nullptr)
             << "Failed to create an android data buffer of size: " << accessUnitLength;
 
-    memcpy(accessUnit->data(), accessUnitData, accessUnitLength);
+    memcpy(accessUnit->data(), accessUnitData.get(), accessUnitLength);
     sp<ABuffer> csdDataBuffer = MakeAVCCodecSpecificData(accessUnit, &avcWidth, &avcHeight);
     ASSERT_NE(csdDataBuffer, nullptr) << "No data returned from MakeAVCCodecSpecificData()";
 
@@ -306,7 +307,6 @@
     ASSERT_EQ(*(csdData + 3), level)
             << "Expected AVC level: " << level << " found: " << *(csdData + 3);
     csdDataBuffer.clear();
-    delete[] accessUnitData;
     accessUnit.clear();
 }
 
@@ -321,32 +321,31 @@
         stringLine >> type >> chunkLength >> frameLayerID;
         ASSERT_GT(chunkLength, 0) << "Length of the data chunk must be greater than zero";
 
-        char *data = new char[chunkLength];
+        std::unique_ptr<char[]> data(new char[chunkLength]);
         ASSERT_NE(data, nullptr) << "Failed to allocation data buffer of size: " << chunkLength;
 
-        mInputFileStream.read(data, chunkLength);
+        mInputFileStream.read(data.get(), chunkLength);
         ASSERT_EQ(mInputFileStream.gcount(), chunkLength)
                 << "Failed to read complete file, bytes read: " << mInputFileStream.gcount();
 
         if (!type.compare("IDR")) {
-            bool isIDR = IsIDR((uint8_t *)data, chunkLength);
+            bool isIDR = IsIDR((uint8_t *)data.get(), chunkLength);
             ASSERT_TRUE(isIDR);
 
-            layerID = FindAVCLayerId((uint8_t *)data, chunkLength);
+            layerID = FindAVCLayerId((uint8_t *)data.get(), chunkLength);
             ASSERT_EQ(layerID, frameLayerID) << "Wrong layer ID found";
         } else if (!type.compare("P") || !type.compare("B")) {
             sp<ABuffer> accessUnit = new ABuffer(chunkLength);
             ASSERT_NE(accessUnit, nullptr) << "Unable to create access Unit";
 
-            memcpy(accessUnit->data(), data, chunkLength);
+            memcpy(accessUnit->data(), data.get(), chunkLength);
             bool isReferenceFrame = IsAVCReferenceFrame(accessUnit);
             ASSERT_TRUE(isReferenceFrame);
 
             accessUnit.clear();
-            layerID = FindAVCLayerId((uint8_t *)data, chunkLength);
+            layerID = FindAVCLayerId((uint8_t *)data.get(), chunkLength);
             ASSERT_EQ(layerID, frameLayerID) << "Wrong layer ID found";
         }
-        delete[] data;
     }
 }
 
diff --git a/media/module/foundation/tests/MetaDataBaseUnitTest.cpp b/media/module/foundation/tests/MetaDataBaseUnitTest.cpp
index 0aed4d2..b562e07 100644
--- a/media/module/foundation/tests/MetaDataBaseUnitTest.cpp
+++ b/media/module/foundation/tests/MetaDataBaseUnitTest.cpp
@@ -19,6 +19,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <fstream>
+#include <memory>
 
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaDataBase.h>
@@ -48,18 +49,16 @@
 class MetaDataBaseUnitTest : public ::testing::Test {};
 
 TEST_F(MetaDataBaseUnitTest, CreateMetaDataBaseTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     // Testing copy constructor
-    MetaDataBase *metaDataCopy = metaData;
+    MetaDataBase *metaDataCopy = metaData.get();
     ASSERT_NE(metaDataCopy, nullptr) << "Failed to create meta data copy";
-
-    delete metaData;
 }
 
 TEST_F(MetaDataBaseUnitTest, SetAndFindDataTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     // Setting the different key-value pair type for first time, overwrite
@@ -142,12 +141,10 @@
     int32_t angle;
     status = metaData->findInt32(kKeyRotation, &angle);
     ASSERT_FALSE(status) << "Value for an invalid key is returned when the key is not set";
-
-    delete (metaData);
 }
 
 TEST_F(MetaDataBaseUnitTest, OverWriteFunctionalityTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     // set/set/read to check first overwrite operation
@@ -186,12 +183,10 @@
     status = metaData->findInt32(kKeyHeight, &height);
     ASSERT_TRUE(status) << "kKeyHeight key does not exists in metadata";
     ASSERT_EQ(height, kHeight3) << "Value of height is not overwritten";
-
-    delete (metaData);
 }
 
 TEST_F(MetaDataBaseUnitTest, RemoveKeyTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     bool status = metaData->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
@@ -246,12 +241,10 @@
 
     metaData->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
     ASSERT_FALSE(status) << "Overwrite should be false since the metadata was cleared";
-
-    delete (metaData);
 }
 
 TEST_F(MetaDataBaseUnitTest, ConvertToStringTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     String8 info = metaData->toString();
@@ -281,8 +274,6 @@
     info = metaData->toString();
     ASSERT_EQ(info.length(), 0) << "MetaData length is non-zero after clearing it: "
                                 << info.length();
-
-    delete (metaData);
 }
 
 }  // namespace android
diff --git a/media/module/metadatautils/TEST_MAPPING b/media/module/metadatautils/TEST_MAPPING
new file mode 100644
index 0000000..21836a5
--- /dev/null
+++ b/media/module/metadatautils/TEST_MAPPING
@@ -0,0 +1,9 @@
+// mappings for frameworks/av/media/module/metadatautils
+{
+  // tests which require dynamic content
+  // invoke with: atest -- --enable-module-dynamic-download=true
+  // TODO(b/148094059): unit tests not allowed to download content
+  "dynamic-presubmit": [
+    { "name": "MetaDataUtilsTest" }
+  ]
+}
diff --git a/media/module/metadatautils/test/MetaDataUtilsTest.cpp b/media/module/metadatautils/test/MetaDataUtilsTest.cpp
index 08c9284..7c35249 100644
--- a/media/module/metadatautils/test/MetaDataUtilsTest.cpp
+++ b/media/module/metadatautils/test/MetaDataUtilsTest.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include <fstream>
+#include <memory>
 #include <string>
 
 #include <media/esds/ESDS.h>
@@ -228,7 +229,7 @@
     ASSERT_TRUE(status) << "Failed to get the mime type";
     ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_VIDEO_AVC);
 
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
 
     status = MakeAVCCodecSpecificData(*metaData, mInputBuffer, mInputBufferSize);
@@ -264,7 +265,6 @@
     int32_t result = memcmp(csdAMediaFormatBuffer, csdMetaDataBaseBuffer, csdAMediaFormatSize);
     ASSERT_EQ(result, 0) << "CSD from AMediaFormat and MetaDataBase do not match";
 
-    delete metaData;
     AMediaFormat_delete(csdData);
 }
 
@@ -275,7 +275,7 @@
     bool status = MakeAVCCodecSpecificData(csdData, mInputBuffer, mInputBufferSize);
     ASSERT_FALSE(status) << "MakeAVCCodecSpecificData with AMediaFormat succeeds with invalid data";
 
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
 
     status = MakeAVCCodecSpecificData(*metaData, mInputBuffer, mInputBufferSize);
@@ -307,7 +307,7 @@
     ASSERT_TRUE(status) << "Failed to get the mime type";
     ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_AUDIO_AAC);
 
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
 
     status = MakeAACCodecSpecificData(*metaData, mAacProfile, mAacSamplingFreqIndex,
@@ -356,11 +356,10 @@
     ASSERT_EQ(memcmpResult, 0) << "AMediaFormat and MetaDataBase CSDs do not match";
 
     AMediaFormat_delete(csdData);
-    delete metaData;
 }
 
 TEST_P(AacADTSTest, AacADTSValidationTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     bool status = MakeAACCodecSpecificData(*metaData, mInputBuffer, kAdtsCsdSize);
@@ -380,12 +379,10 @@
     status = metaData->findCString(kKeyMIMEType, &mimeType);
     ASSERT_TRUE(status) << "Failed to get mime type";
     ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_AUDIO_AAC);
-
-    delete metaData;
 }
 
 TEST_P(AacCSDValidateTest, AacInvalidInputTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     bool status = MakeAACCodecSpecificData(*metaData, mInputBuffer, kAdtsCsdSize);
@@ -412,14 +409,14 @@
         istringstream dataStringLine(dataLine);
         dataStringLine >> comment;
 
-        char *buffer = strndup(comment.c_str(), commentLength);
+        std::unique_ptr<char[]> buffer(new char[commentLength]);
         ASSERT_NE(buffer, nullptr) << "Failed to allocate buffer of size: " << commentLength;
+        strncpy(buffer.get(), comment.c_str(), commentLength);
 
         AMediaFormat *fileMeta = AMediaFormat_new();
         ASSERT_NE(fileMeta, nullptr) << "Failed to create AMedia format";
 
-        parseVorbisComment(fileMeta, buffer, commentLength);
-        free(buffer);
+        parseVorbisComment(fileMeta, buffer.get(), commentLength);
 
         if (!strncasecmp(tag.c_str(), "ANDROID_HAPTIC", sizeof(tag))) {
             int32_t numChannelExpected = stoi(value);
diff --git a/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
index 8577e62..b4e659c 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
@@ -33,7 +33,11 @@
 
 class MtpPropertyFuzzer : MtpPacketFuzzerUtils {
   public:
-    MtpPropertyFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
+    MtpPropertyFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+        mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+                                                    sizeof(struct usbdevfs_iso_packet_desc));
+    };
+    ~MtpPropertyFuzzer() { free(mUsbDevFsUrb); };
     void process();
 
   private:
@@ -41,7 +45,7 @@
 };
 
 void MtpPropertyFuzzer::process() {
-    MtpProperty* mtpProperty;
+    MtpProperty* mtpProperty = nullptr;
     if (mFdp.ConsumeBool()) {
         mtpProperty = new MtpProperty();
     } else {
@@ -75,6 +79,7 @@
                             fillFilePath(&mFdp);
                             int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
                             fillUsbRequest(fd, &mFdp);
+                            mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
                             mtpDataPacket.write(&mUsbRequest,
                                                 mFdp.PickValueInArray<UrbPacketDivisionMode>(
                                                         kUrbPacketDivisionModes),
diff --git a/media/utils/SchedulingPolicyService.cpp b/media/utils/SchedulingPolicyService.cpp
index ad38862..6e515ff 100644
--- a/media/utils/SchedulingPolicyService.cpp
+++ b/media/utils/SchedulingPolicyService.cpp
@@ -18,6 +18,7 @@
 //#define LOG_NDEBUG 0
 
 #include <binder/IServiceManager.h>
+#include <cutils/properties.h>
 #include <utils/Mutex.h>
 #include "ISchedulingPolicyService.h"
 #include "mediautils/SchedulingPolicyService.h"
@@ -86,4 +87,25 @@
     return ret;
 }
 
+int requestSpatializerPriority(pid_t pid, pid_t tid) {
+    if (pid == -1 || tid == -1) return BAD_VALUE;
+
+    // update priority to RT if specified.
+    constexpr int32_t kRTPriorityMin = 1;
+    constexpr int32_t kRTPriorityMax = 3;
+    const int32_t priorityBoost =
+            property_get_int32("audio.spatializer.priority", kRTPriorityMin);
+    if (priorityBoost >= kRTPriorityMin && priorityBoost <= kRTPriorityMax) {
+        const status_t status = requestPriority(
+                pid, tid, priorityBoost, false /* isForApp */, true /*asynchronous*/);
+        if (status != OK) {
+            ALOGW("%s: Cannot request spatializer priority boost %d, status:%d",
+                    __func__, priorityBoost, status);
+            return status < 0 ? status : UNKNOWN_ERROR;
+        }
+        return priorityBoost;
+    }
+    return 0;  // no boost requested
+}
+
 }   // namespace android
diff --git a/media/utils/include/mediautils/SchedulingPolicyService.h b/media/utils/include/mediautils/SchedulingPolicyService.h
index 546cec5..af1fcd2 100644
--- a/media/utils/include/mediautils/SchedulingPolicyService.h
+++ b/media/utils/include/mediautils/SchedulingPolicyService.h
@@ -23,7 +23,7 @@
 
 class IBinder;
 // Request elevated priority for thread tid, whose thread group leader must be pid.
-// The priority parameter is currently restricted to either 1 or 2.
+// The priority parameter is currently restricted from 1 to 3.
 // The asynchronous parameter should be 'true' to return immediately,
 // after the request is enqueued but not necessarily executed.
 // The default value 'false' means to return after request has been enqueued and executed.
@@ -37,6 +37,12 @@
 // 'client' is ignored in this case.
 int requestCpusetBoost(bool enable, const sp<IBinder> &client);
 
+// Audio: Request Spatializer RT priority for thread tid, whose thread group leader must be pid.
+// returns positive value if successful, the RT priority used
+//         zero, if no RT priority selected
+//         negative status code if RT priority unable to be set.
+int requestSpatializerPriority(pid_t pid, pid_t tid);
+
 }   // namespace android
 
 #endif  // _ANDROID_SCHEDULING_POLICY_SERVICE_H
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 8f82657..5b49e70 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2117,9 +2117,9 @@
 void AudioFlinger::onSupportedLatencyModesChanged(
         audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
     int32_t outputAidl = VALUE_OR_FATAL(legacy2aidl_audio_io_handle_t_int32_t(output));
-    std::vector<media::LatencyMode> modesAidl = VALUE_OR_FATAL(
-                convertContainer<std::vector<media::LatencyMode>>(modes,
-                        legacy2aidl_audio_latency_mode_t_LatencyMode));
+    std::vector<media::audio::common::AudioLatencyMode> modesAidl = VALUE_OR_FATAL(
+                convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+                        modes, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
 
     Mutex::Autolock _l(mClientLock);
     size_t size = mNotificationClients.size();
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index fc4c807..7b9b44a 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -678,14 +678,16 @@
         binder::Status getVolumeShaperState(
                 int32_t id,
                 std::optional<media::VolumeShaperState>* _aidl_return) override;
-        binder::Status getDualMonoMode(media::AudioDualMonoMode* _aidl_return) override;
-        binder::Status setDualMonoMode(media::AudioDualMonoMode mode) override;
+        binder::Status getDualMonoMode(
+                media::audio::common::AudioDualMonoMode* _aidl_return) override;
+        binder::Status setDualMonoMode(
+                media::audio::common::AudioDualMonoMode mode) override;
         binder::Status getAudioDescriptionMixLevel(float* _aidl_return) override;
         binder::Status setAudioDescriptionMixLevel(float leveldB) override;
         binder::Status getPlaybackRateParameters(
-                media::AudioPlaybackRate* _aidl_return) override;
+                media::audio::common::AudioPlaybackRate* _aidl_return) override;
         binder::Status setPlaybackRateParameters(
-                const media::AudioPlaybackRate& playbackRate) override;
+                const media::audio::common::AudioPlaybackRate& playbackRate) override;
 
     private:
         const sp<PlaybackThread::Track> mTrack;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index fc3c07f..98829d0 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1756,6 +1756,7 @@
     mNotifyFramesProcessed(notifyFramesProcessed)
 {
     ALOGV("constructor %p client %p", this, client.get());
+    setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
 
     if (client == 0) {
         return;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 67a8caf..a4c1832 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -269,6 +269,23 @@
     return ss.str();
 }
 
+static std::string toString(audio_latency_mode_t mode) {
+    // We convert to the AIDL type to print (eventually the legacy type will be removed).
+    const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+    return result.has_value() ? media::audio::common::toString(*result) : "UNKNOWN";
+}
+
+// Could be made a template, but other toString overloads for std::vector are confused.
+static std::string toString(const std::vector<audio_latency_mode_t>& elements) {
+    std::string s("{ ");
+    for (const auto& e : elements) {
+        s.append(toString(e));
+        s.append(" ");
+    }
+    s.append("}");
+    return s;
+}
+
 static pthread_once_t sFastTrackMultiplierOnce = PTHREAD_ONCE_INIT;
 
 static void sFastTrackMultiplierInit()
@@ -7321,6 +7338,17 @@
     if (status != INVALID_OPERATION) {
         updateHalSupportedLatencyModes_l();
     }
+
+    const pid_t tid = getTid();
+    if (tid == -1) {
+        // Unusual: PlaybackThread::onFirstRef() should set the threadLoop running.
+        ALOGW("%s: Cannot update Spatializer mixer thread priority, not running", __func__);
+    } else {
+        const int priorityBoost = requestSpatializerPriority(getpid(), tid);
+        if (priorityBoost > 0) {
+            stream()->setHalThreadPriority(priorityBoost);
+        }
+    }
 }
 
 status_t AudioFlinger::SpatializerThread::createAudioPatch_l(const struct audio_patch *patch,
@@ -7333,10 +7361,13 @@
 
 void AudioFlinger::SpatializerThread::updateHalSupportedLatencyModes_l() {
     std::vector<audio_latency_mode_t> latencyModes;
-    if (mOutput->stream->getRecommendedLatencyModes(&latencyModes) != NO_ERROR) {
+    const status_t status = mOutput->stream->getRecommendedLatencyModes(&latencyModes);
+    if (status != NO_ERROR) {
         latencyModes.clear();
     }
     if (latencyModes != mSupportedLatencyModes) {
+        ALOGD("%s: thread(%d) status %d supported latency modes: %s",
+            __func__, mId, status, toString(latencyModes).c_str());
         mSupportedLatencyModes.swap(latencyModes);
         sendHalLatencyModesChangedEvent_l();
     }
@@ -7376,6 +7407,8 @@
 
     if (latencyMode != mSetLatencyMode) {
         status_t status = mOutput->stream->setLatencyMode(latencyMode);
+        ALOGD("%s: thread(%d) setLatencyMode(%s) returned %d",
+                __func__, mId, toString(latencyMode).c_str(), status);
         if (status == NO_ERROR) {
             mSetLatencyMode = latencyMode;
         }
@@ -7457,6 +7490,8 @@
         std::vector<audio_latency_mode_t> modes) {
     Mutex::Autolock _l(mLock);
     if (modes != mSupportedLatencyModes) {
+        ALOGD("%s: thread(%d) supported latency modes: %s",
+            __func__, mId, toString(modes).c_str());
         mSupportedLatencyModes.swap(modes);
         sendHalLatencyModesChangedEvent_l();
     }
@@ -7533,10 +7568,11 @@
         ALOGV("%p kUseFastCapture = Always, initFastCapture = true", this);
         break;
     case FastCapture_Static:
-        initFastCapture = (mFrameCount * 1000) / mSampleRate < kMinNormalCaptureBufferSizeMs;
-        ALOGV("%p kUseFastCapture = Static, (%lld * 1000) / %u vs %u, initFastCapture = %d",
-                this, (long long)mFrameCount, mSampleRate, kMinNormalCaptureBufferSizeMs,
-                initFastCapture);
+        initFastCapture = !mIsMsdDevice // Disable fast capture for MSD BUS devices.
+                && (mFrameCount * 1000) / mSampleRate < kMinNormalCaptureBufferSizeMs;
+        ALOGV("%p kUseFastCapture = Static, (%lld * 1000) / %u vs %u, initFastCapture = %d "
+                "mIsMsdDevice = %d", this, (long long)mFrameCount, mSampleRate,
+                kMinNormalCaptureBufferSizeMs, initFastCapture, mIsMsdDevice);
         break;
     // case FastCapture_Dynamic:
     }
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index ca31bbc..02c4aaf 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -334,6 +334,7 @@
     : BnAudioTrack(),
       mTrack(track)
 {
+    setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
 }
 
 AudioFlinger::TrackHandle::~TrackHandle() {
@@ -438,7 +439,8 @@
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::getDualMonoMode(media::AudioDualMonoMode* _aidl_return)
+Status AudioFlinger::TrackHandle::getDualMonoMode(
+        media::audio::common::AudioDualMonoMode* _aidl_return)
 {
     audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
     const status_t status = mTrack->getDualMonoMode(&mode)
@@ -451,7 +453,7 @@
 }
 
 Status AudioFlinger::TrackHandle::setDualMonoMode(
-        media::AudioDualMonoMode mode)
+        media::audio::common::AudioDualMonoMode mode)
 {
     const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
@@ -475,7 +477,7 @@
 }
 
 Status AudioFlinger::TrackHandle::getPlaybackRateParameters(
-        media::AudioPlaybackRate* _aidl_return)
+        media::audio::common::AudioPlaybackRate* _aidl_return)
 {
     audio_playback_rate_t localPlaybackRate{};
     status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
@@ -488,7 +490,7 @@
 }
 
 Status AudioFlinger::TrackHandle::setPlaybackRateParameters(
-        const media::AudioPlaybackRate& playbackRate)
+        const media::audio::common::AudioPlaybackRate& playbackRate)
 {
     const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
@@ -2327,6 +2329,7 @@
     : BnAudioRecord(),
     mRecordTrack(recordTrack)
 {
+    setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
 }
 
 AudioFlinger::RecordHandle::~RecordHandle() {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index b8c39f4..3518037 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -68,16 +68,6 @@
 // media / notification / system volume.
 constexpr float IN_CALL_EARPIECE_HEADROOM_DB = 3.f;
 
-// Compressed formats for MSD module, ordered from most preferred to least preferred.
-static const std::vector<audio_format_t> msdCompressedFormatsOrder = {{
-        AUDIO_FORMAT_IEC60958, AUDIO_FORMAT_MAT_2_1, AUDIO_FORMAT_MAT_2_0, AUDIO_FORMAT_E_AC3,
-        AUDIO_FORMAT_AC3, AUDIO_FORMAT_PCM_16_BIT }};
-// Channel masks for MSD module, 3D > 2D > 1D ordering (most preferred to least preferred).
-static const std::vector<audio_channel_mask_t> msdSurroundChannelMasksOrder = {{
-        AUDIO_CHANNEL_OUT_3POINT1POINT2, AUDIO_CHANNEL_OUT_3POINT0POINT2,
-        AUDIO_CHANNEL_OUT_2POINT1POINT2, AUDIO_CHANNEL_OUT_2POINT0POINT2,
-        AUDIO_CHANNEL_OUT_5POINT1, AUDIO_CHANNEL_OUT_STEREO }};
-
 template <typename T>
 bool operator== (const SortedVector<T> &left, const SortedVector<T> &right)
 {
@@ -1644,10 +1634,28 @@
         const AudioProfileVector &sourceProfiles, const AudioProfileVector &sinkProfiles,
         audio_port_config *sourceConfig, audio_port_config *sinkConfig) const
 {
+    // Compressed formats for MSD module, ordered from most preferred to least preferred.
+    static const std::vector<audio_format_t> formatsOrder = {{
+            AUDIO_FORMAT_IEC60958, AUDIO_FORMAT_MAT_2_1, AUDIO_FORMAT_MAT_2_0, AUDIO_FORMAT_E_AC3,
+            AUDIO_FORMAT_AC3, AUDIO_FORMAT_PCM_16_BIT }};
+    static const std::vector<audio_channel_mask_t> channelMasksOrder = [](){
+        // Channel position masks for MSD module, 3D > 2D > 1D ordering (most preferred to least
+        // preferred).
+        std::vector<audio_channel_mask_t> masks = {{
+            AUDIO_CHANNEL_OUT_3POINT1POINT2, AUDIO_CHANNEL_OUT_3POINT0POINT2,
+            AUDIO_CHANNEL_OUT_2POINT1POINT2, AUDIO_CHANNEL_OUT_2POINT0POINT2,
+            AUDIO_CHANNEL_OUT_5POINT1, AUDIO_CHANNEL_OUT_STEREO }};
+        // insert index masks (higher counts most preferred) as preferred over position masks
+        for (int i = 1; i <= AUDIO_CHANNEL_COUNT_MAX; i++) {
+            masks.insert(
+                    masks.begin(), audio_channel_mask_for_index_assignment_from_count(i));
+        }
+        return masks;
+    }();
+
     struct audio_config_base bestSinkConfig;
-    status_t result = findBestMatchingOutputConfig(sourceProfiles, sinkProfiles,
-            msdCompressedFormatsOrder, msdSurroundChannelMasksOrder,
-            true /*preferHigherSamplingRates*/, bestSinkConfig);
+    status_t result = findBestMatchingOutputConfig(sourceProfiles, sinkProfiles, formatsOrder,
+            channelMasksOrder, true /*preferHigherSamplingRates*/, bestSinkConfig);
     if (result != NO_ERROR) {
         ALOGD("%s() no matching config found for sink, hwAvSync: %d",
                 __func__, hwAvSync);
@@ -1669,7 +1677,10 @@
     }
     sourceConfig->sample_rate = bestSinkConfig.sample_rate;
     // Specify exact channel mask to prevent guessing by bit count in PatchPanel.
-    sourceConfig->channel_mask = audio_channel_mask_out_to_in(bestSinkConfig.channel_mask);
+    sourceConfig->channel_mask =
+            audio_channel_mask_get_representation(bestSinkConfig.channel_mask)
+            == AUDIO_CHANNEL_REPRESENTATION_INDEX ?
+            bestSinkConfig.channel_mask : audio_channel_mask_out_to_in(bestSinkConfig.channel_mask);
     sourceConfig->format = bestSinkConfig.format;
     // Copy input stream directly without any processing (e.g. resampling).
     sourceConfig->flags.input = static_cast<audio_input_flags_t>(
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 92e1b6b..281785e 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -202,6 +202,7 @@
       mCaptureStateNotifier(false),
       mCreateAudioPolicyManager(createAudioPolicyManager),
       mDestroyAudioPolicyManager(destroyAudioPolicyManager) {
+      setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
 }
 
 void AudioPolicyService::loadAudioPolicyManager()
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 38ad494..2fe7b9e 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -34,6 +34,7 @@
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/MediaMetricsItem.h>
 #include <media/ShmemCompat.h>
+#include <mediautils/SchedulingPolicyService.h>
 #include <mediautils/ServiceUtilities.h>
 #include <utils/Thread.h>
 
@@ -111,6 +112,14 @@
     };
 
     void onMessageReceived(const sp<AMessage> &msg) override {
+        // No ALooper method to get the tid so update
+        // Spatializer priority on the first message received.
+        std::call_once(mPrioritySetFlag, [](){
+            const pid_t pid = getpid();
+            const pid_t tid = gettid();
+            (void)requestSpatializerPriority(pid, tid);
+        });
+
         sp<Spatializer> spatializer = mSpatializer.promote();
         if (spatializer == nullptr) {
             ALOGW("%s: Cannot promote spatializer", __func__);
@@ -163,6 +172,7 @@
     }
 private:
     wp<Spatializer> mSpatializer;
+    std::once_flag mPrioritySetFlag;
 };
 
 const std::vector<const char *> Spatializer::sHeadPoseKeys = {
@@ -255,6 +265,7 @@
     : mEngineDescriptor(engineDescriptor),
       mPolicyCallback(callback) {
     ALOGV("%s", __func__);
+    setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
 }
 
 void Spatializer::onFirstRef() {
@@ -263,7 +274,7 @@
     mLooper->start(
             /*runOnCallingThread*/false,
             /*canCallJava*/       false,
-            PRIORITY_AUDIO);
+            PRIORITY_URGENT_AUDIO);
 
     mHandler = new EngineCallbackHandler(this);
     mLooper->registerHandler(mHandler);
@@ -963,7 +974,10 @@
         }
     }
     if (mOutput != AUDIO_IO_HANDLE_NONE && supportsSetLatencyMode) {
-        AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
+        const status_t status =
+                AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
+        ALOGD("%s: setRequestedLatencyMode for output thread(%d) to %s returned %d",
+                __func__, mOutput, toString(requestedLatencyMode).c_str(), status);
     }
 }
 
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index bcbd92b..0f6bafe 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -23,6 +23,7 @@
 #include <android/media/SpatializationLevel.h>
 #include <android/media/SpatializationMode.h>
 #include <android/media/SpatializerHeadTrackingMode.h>
+#include <android/media/audio/common/AudioLatencyMode.h>
 #include <audio_utils/SimpleLog.h>
 #include <math.h>
 #include <media/AudioEffect.h>
@@ -165,14 +166,11 @@
     std::string toString(unsigned level) const NO_THREAD_SAFETY_ANALYSIS;
 
     static std::string toString(audio_latency_mode_t mode) {
-        switch (mode) {
-            case AUDIO_LATENCY_MODE_FREE:
-                return "LATENCY_MODE_FREE";
-            case AUDIO_LATENCY_MODE_LOW:
-                return "LATENCY_MODE_LOW";
-        }
-        return "EnumNotImplemented";
-    };
+        // We convert to the AIDL type to print (eventually the legacy type will be removed).
+        const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+        return result.has_value() ?
+                media::audio::common::toString(*result) : "unknown_latency_mode";
+    }
 
     /**
      * Format head to stage vector to a string, [0.00, 0.00, 0.00, -1.29, -0.50, 15.27].
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index d51c57c..c341b32 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -446,7 +446,7 @@
     sp<AudioProfile> ac3OutputProfile = new AudioProfile(
             AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, k48000SamplingRate);
     sp<AudioProfile> iec958OutputProfile = new AudioProfile(
-            AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_OUT_STEREO, k48000SamplingRate);
+            AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_INDEX_MASK_24, k48000SamplingRate);
     mMsdOutputDevice->addAudioProfile(pcmOutputProfile);
     mMsdOutputDevice->addAudioProfile(ac3OutputProfile);
     mMsdOutputDevice->addAudioProfile(iec958OutputProfile);
@@ -519,7 +519,7 @@
     // Add HDMI input device with IEC60958 profile for HDMI in -> MSD patching.
     mHdmiInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_HDMI);
     sp<AudioProfile> iec958InputProfile = new AudioProfile(
-            AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate);
+            AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_INDEX_MASK_24, k48000SamplingRate);
     mHdmiInputDevice->addAudioProfile(iec958InputProfile);
     config.addDevice(mHdmiInputDevice);
     sp<InputProfile> hdmiInputProfile = new InputProfile("hdmi input");
@@ -677,8 +677,8 @@
     ASSERT_EQ(AUDIO_PORT_ROLE_SINK, patch->mPatch.sinks[0].role);
     ASSERT_EQ(AUDIO_FORMAT_IEC60958, patch->mPatch.sources[0].format);
     ASSERT_EQ(AUDIO_FORMAT_IEC60958, patch->mPatch.sinks[0].format);
-    ASSERT_EQ(AUDIO_CHANNEL_IN_STEREO, patch->mPatch.sources[0].channel_mask);
-    ASSERT_EQ(AUDIO_CHANNEL_OUT_STEREO, patch->mPatch.sinks[0].channel_mask);
+    ASSERT_EQ(AUDIO_CHANNEL_INDEX_MASK_24, patch->mPatch.sources[0].channel_mask);
+    ASSERT_EQ(AUDIO_CHANNEL_INDEX_MASK_24, patch->mPatch.sinks[0].channel_mask);
     ASSERT_EQ(k48000SamplingRate, patch->mPatch.sources[0].sample_rate);
     ASSERT_EQ(k48000SamplingRate, patch->mPatch.sinks[0].sample_rate);
     ASSERT_EQ(1, patchCount.deltaFromSnapshot());
@@ -754,7 +754,7 @@
     audio_config_base_t msdDirectConfig2 = AUDIO_CONFIG_BASE_INITIALIZER;
     msdDirectConfig2.format = AUDIO_FORMAT_IEC60958;
     msdDirectConfig2.sample_rate = 48000;
-    msdDirectConfig2.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+    msdDirectConfig2.channel_mask = AUDIO_CHANNEL_INDEX_MASK_24;
 
     audio_config_base_t msdNonDirectConfig = AUDIO_CONFIG_BASE_INITIALIZER;
     msdNonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT;
@@ -821,7 +821,7 @@
     audio_config_t msdDirectConfig2 = AUDIO_CONFIG_INITIALIZER;
     msdDirectConfig2.format = AUDIO_FORMAT_IEC60958;
     msdDirectConfig2.sample_rate = 48000;
-    msdDirectConfig2.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+    msdDirectConfig2.channel_mask = AUDIO_CHANNEL_INDEX_MASK_24;
 
     audio_config_t msdNonDirectConfig = AUDIO_CONFIG_INITIALIZER;
     msdNonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 15df981..2a8a103 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -944,8 +944,8 @@
     std::vector<int> surfaceIds;
     bool isDepthCompositeStream =
             camera3::DepthCompositeStream::isDepthCompositeStream(surfaces[0]);
-    bool isHeicCompisiteStream = camera3::HeicCompositeStream::isHeicCompositeStream(surfaces[0]);
-    if (isDepthCompositeStream || isHeicCompisiteStream) {
+    bool isHeicCompositeStream = camera3::HeicCompositeStream::isHeicCompositeStream(surfaces[0]);
+    if (isDepthCompositeStream || isHeicCompositeStream) {
         sp<CompositeStream> compositeStream;
         if (isDepthCompositeStream) {
             compositeStream = new camera3::DepthCompositeStream(mDevice, getRemoteCallback());
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 84b5aa4..396104c 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -1526,7 +1526,8 @@
                 vsyncTime.deadlineTimestamp >= currentTime &&
                 ((!cameraDisplayInSync && vsyncTime.expectedPresentationTime > minPresentT) ||
                  (cameraDisplayInSync && vsyncTime.expectedPresentationTime >
-                mLastPresentTime + minInterval + biasForShortDelay * kTimelineThresholdNs))) {
+                mLastPresentTime + minInterval +
+                    static_cast<nsecs_t>(biasForShortDelay * kTimelineThresholdNs)))) {
             expectedPresentT = vsyncTime.expectedPresentationTime;
             minDiff = std::abs(vsyncTime.expectedPresentationTime - idealPresentT);
         }