Deprecate AImageReader_getWindowNativeHandle am: 5f86662a67

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/24642003

Change-Id: If70190077324a03a302ec8f012fd83515095e1ed
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index 35b8e21..6b040ab 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -245,7 +245,7 @@
     ALOGV("getParameters");
     String8 params;
     sp <::android::hardware::ICamera> c = mCamera;
-    if (c != 0) params = mCamera->getParameters();
+    if (c != 0) params = c->getParameters();
     return params;
 }
 
@@ -269,7 +269,7 @@
     ALOGV("setPreviewCallbackFlags");
     sp <::android::hardware::ICamera> c = mCamera;
     if (c == 0) return;
-    mCamera->setPreviewCallbackFlag(flag);
+    c->setPreviewCallbackFlag(flag);
 }
 
 status_t Camera::setPreviewCallbackTarget(
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index 365ac5c..61c7551 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -400,7 +400,6 @@
 
     camera_metadata_ro_entry rawEntry = static_cast<const CameraMetadata*>(mData.get())->find(tag);
     if (rawEntry.count == 0) {
-        ALOGE("%s: cannot find metadata tag %d", __FUNCTION__, tag);
         return ACAMERA_ERROR_METADATA_NOT_FOUND;
     }
     entry->tag = tag;
diff --git a/drm/mediadrm/plugins/clearkey/aidl/Android.bp b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
index eaf5051..0b0d46a 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
@@ -8,21 +8,7 @@
 }
 
 cc_defaults {
-    name: "aidl_clearkey_service_defaults",
-    vendor: true,
-
-    srcs: [
-        "CreatePluginFactories.cpp",
-        "CryptoPlugin.cpp",
-        "DrmFactory.cpp",
-        "DrmPlugin.cpp",
-    ],
-
-    relative_install_path: "hw",
-
-    cflags: ["-Wall", "-Werror", "-Wthread-safety"],
-
-    include_dirs: ["frameworks/av/include"],
+    name: "aidl_clearkey_service_defaults-use-shared-deps",
 
     shared_libs: [
         "libbase",
@@ -39,6 +25,46 @@
         "libclearkeybase",
         "libjsoncpp",
     ],
+}
+
+cc_defaults {
+    name: "aidl_clearkey_service_defaults-use-static-deps",
+
+    stl: "c++_static",
+
+    shared_libs: [
+        "libbinder_ndk",
+        "libcrypto",
+        "liblog",
+    ],
+
+    static_libs: [
+        "android.hardware.common-V2-ndk",
+        "android.hardware.drm-V1-ndk",
+        "libbase",
+        "libclearkeybase",
+        "libjsoncpp",
+        "libprotobuf-cpp-lite",
+        "libutils",
+    ],
+}
+
+cc_defaults {
+    name: "aidl_clearkey_service_defaults",
+    vendor: true,
+
+    srcs: [
+        "CreatePluginFactories.cpp",
+        "CryptoPlugin.cpp",
+        "DrmFactory.cpp",
+        "DrmPlugin.cpp",
+    ],
+
+    relative_install_path: "hw",
+
+    cflags: ["-Wall", "-Werror", "-Wthread-safety"],
+
+    include_dirs: ["frameworks/av/include"],
 
     local_include_dirs: ["include"],
 
@@ -49,7 +75,10 @@
 
 cc_binary {
     name: "android.hardware.drm-service.clearkey",
-    defaults: ["aidl_clearkey_service_defaults"],
+    defaults: [
+        "aidl_clearkey_service_defaults",
+        "aidl_clearkey_service_defaults-use-shared-deps",
+    ],
     srcs: ["Service.cpp"],
     init_rc: ["android.hardware.drm-service.clearkey.rc"],
     vintf_fragments: ["android.hardware.drm-service.clearkey.xml"],
@@ -57,17 +86,31 @@
 
 cc_binary {
     name: "android.hardware.drm-service-lazy.clearkey",
-    defaults: ["aidl_clearkey_service_defaults"],
+    defaults: [
+        "aidl_clearkey_service_defaults",
+        "aidl_clearkey_service_defaults-use-shared-deps",
+    ],
     overrides: ["android.hardware.drm-service.clearkey"],
     srcs: ["ServiceLazy.cpp"],
     init_rc: ["android.hardware.drm-service-lazy.clearkey.rc"],
     vintf_fragments: ["android.hardware.drm-service.clearkey.xml"],
 }
 
+cc_binary {
+    name: "android.hardware.drm-service.clearkey.apex",
+    stem: "android.hardware.drm-service.clearkey",
+    defaults: [
+        "aidl_clearkey_service_defaults",
+        "aidl_clearkey_service_defaults-use-static-deps",
+    ],
+    srcs: ["Service.cpp"],
+    installable: false, // installed in APEX
+}
+
 phony {
     name: "android.hardware.drm@latest-service.clearkey",
     required: [
-        "android.hardware.drm-service.clearkey",
+        "com.android.hardware.drm.clearkey",
     ],
 }
 
@@ -123,3 +166,34 @@
         ],
     },
 }
+
+apex {
+    name: "com.android.hardware.drm.clearkey",
+    manifest: "manifest.json",
+    file_contexts: "file_contexts",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
+    vendor: true,
+    updatable: false,
+
+    binaries: [
+        "android.hardware.drm-service.clearkey.apex",
+    ],
+    prebuilts: [
+        "android.hardware.drm-service.clearkey.apex.rc",
+        "android.hardware.drm-service.clearkey.xml"
+    ],
+}
+
+prebuilt_etc {
+    name: "android.hardware.drm-service.clearkey.apex.rc",
+    src: "android.hardware.drm-service.clearkey.apex.rc",
+    installable: false,
+}
+
+prebuilt_etc {
+    name: "android.hardware.drm-service.clearkey.xml",
+    src: "android.hardware.drm-service.clearkey.xml",
+    sub_dir: "vintf",
+    installable: false,
+}
diff --git a/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.apex.rc b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.apex.rc
new file mode 100644
index 0000000..f4645b3
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.apex.rc
@@ -0,0 +1,7 @@
+service vendor.drm-clearkey-service /apex/com.android.hardware.drm.clearkey/bin/hw/android.hardware.drm-service.clearkey
+    class hal
+    user media
+    group mediadrm drmrpc
+    ioprio rt 4
+    task_profiles ProcessCapacityHigh
+    interface aidl android.hardware.drm.IDrmFactory/clearkey
diff --git a/drm/mediadrm/plugins/clearkey/aidl/file_contexts b/drm/mediadrm/plugins/clearkey/aidl/file_contexts
new file mode 100644
index 0000000..e9e6ca2
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/file_contexts
@@ -0,0 +1,3 @@
+(/.*)?                                                      u:object_r:vendor_file:s0
+/etc(/.*)?                                                  u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.drm-service(-lazy)?\.clearkey    u:object_r:hal_drm_clearkey_aidl_exec:s0
diff --git a/drm/mediadrm/plugins/clearkey/aidl/manifest.json b/drm/mediadrm/plugins/clearkey/aidl/manifest.json
new file mode 100644
index 0000000..369dc21
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/manifest.json
@@ -0,0 +1,4 @@
+{
+  "name": "com.android.hardware.drm.clearkey",
+  "version": 1
+}
diff --git a/media/codec2/hal/aidl/Android.bp b/media/codec2/hal/aidl/Android.bp
index b19f78c..b968c39 100644
--- a/media/codec2/hal/aidl/Android.bp
+++ b/media/codec2/hal/aidl/Android.bp
@@ -50,100 +50,95 @@
 }
 
 // DO NOT DEPEND ON THIS DIRECTLY
-// use libcodec2-hidl-defaults instead
-//cc_library {
-//    name: "libcodec2_hidl@1.0",
-//    vendor_available: true,
-//    min_sdk_version: "29",
-//    apex_available: [
-//        "//apex_available:platform",
-//        "com.android.media.swcodec",
-//    ],
-//
-//    defaults: ["hidl_defaults"],
-//
-//    srcs: [
-//        "Component.cpp",
-//        "ComponentInterface.cpp",
-//        "ComponentStore.cpp",
-//        "Configurable.cpp",
-//        "InputBufferManager.cpp",
-//        "InputSurface.cpp",
-//        "InputSurfaceConnection.cpp",
-//        "types.cpp",
-//    ],
-//
-//    header_libs: [
-//        "libbinder_headers",
-//        "libcodec2_hal_common",
-//        "libcodec2_internal", // private
-//        "libsystem_headers",
-//    ],
-//
-//    shared_libs: [
-//        "android.hardware.graphics.bufferqueue@1.0",
-//        "android.hardware.graphics.bufferqueue@2.0",
-//        "android.hardware.graphics.common@1.0",
-//        "android.hardware.media@1.0",
-//        "android.hardware.media.bufferpool@2.0",
-//        "android.hardware.media.c2@1.0",
-//        "android.hardware.media.omx@1.0",
-//        "libbase",
-//        "libcodec2",
-//        "libcodec2_vndk",
-//        "libcodec2_hidl_plugin_stub",
-//        "libcutils",
-//        "libhidlbase",
-//        "liblog",
-//        "libstagefright_bufferpool@2.0.1",
-//        "libstagefright_bufferqueue_helper_novndk",
-//        "libui",
-//        "libutils",
-//    ],
-//
-//    target: {
-//        vendor: {
-//            exclude_shared_libs: [
-//                "libstagefright_bufferqueue_helper_novndk",
-//                "libcodec2_hidl_plugin_stub",
-//            ],
-//            shared_libs: [
-//                "libstagefright_bufferqueue_helper",
-//                "libcodec2_hidl_plugin",
-//            ],
-//        },
-//        apex: {
-//            exclude_shared_libs: [
-//                "libcodec2_hidl_plugin",
-//                "libcodec2_hidl_plugin_stub",
-//            ],
-//        },
-//    },
-//
-//    export_include_dirs: [
-//        "include",
-//    ],
-//
-//    export_shared_lib_headers: [
-//        "android.hardware.media.c2@1.0",
-//        "libcodec2",
-//        "libcodec2_vndk",
-//        "libhidlbase",
-//        "libstagefright_bufferpool@2.0.1",
-//        "libui",
-//    ],
-//}
-//
-//// public dependency for Codec 2.0 HAL service implementations
-//cc_defaults {
-//    name: "libcodec2-hidl-defaults@1.0",
-//    defaults: ["libcodec2-impl-defaults"],
-//
-//    shared_libs: [
-//        "android.hardware.media.c2@1.0",
-//        "libcodec2_hidl@1.0",
-//    ],
-//}
+// use libcodec2-aidl-defaults instead
+cc_library {
+    name: "libcodec2_aidl",
+    vendor_available: true,
+    min_sdk_version: "34",
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media.swcodec",
+        "test_com.android.media.swcodec",
+    ],
+
+    srcs: [
+        "BufferTypes.cpp",
+        "Component.cpp",
+        "ComponentInterface.cpp",
+        "ComponentStore.cpp",
+        "Configurable.cpp",
+        "InputBufferManager.cpp",
+        "ParamTypes.cpp",
+    ],
+
+    header_libs: [
+        "libcodec2_internal", // private
+    ],
+
+    shared_libs: [
+        "android.hardware.common-V2-ndk",
+        "android.hardware.media.bufferpool2-V1-ndk",
+        "android.hardware.media.c2-V1-ndk",
+        "libbase",
+        "libbinder_ndk",
+        "libcodec2",
+        "libcodec2_hal_common",
+        "libcodec2_hidl_plugin_stub",
+        "libcodec2_vndk",
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libnativewindow",
+        "libstagefright_aidl_bufferpool2",
+        "libstagefright_bufferpool@2.0.1",
+        "libui",
+        "libutils",
+    ],
+
+    static_libs: [
+        "libaidlcommonsupport",
+    ],
+
+    target: {
+        vendor: {
+            exclude_shared_libs: [
+                "libcodec2_hidl_plugin_stub",
+            ],
+            shared_libs: [
+                "libcodec2_hidl_plugin",
+            ],
+        },
+        apex: {
+            exclude_shared_libs: [
+                "libcodec2_hidl_plugin_stub",
+                "libcodec2_hidl_plugin",
+            ],
+        },
+    },
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    export_shared_lib_headers: [
+        "android.hardware.media.c2-V1-ndk",
+        "libcodec2",
+        "libstagefright_bufferpool@2.0.1",
+        "libui",
+    ],
+}
+
+// public dependency for Codec 2.0 HAL service implementations
+cc_defaults {
+    name: "libcodec2-aidl-defaults",
+    min_sdk_version: "34",
+    defaults: ["libcodec2-impl-defaults"],
+
+    shared_libs: [
+        "android.hardware.media.c2-V1-ndk",
+        "libcodec2_aidl",
+    ],
+}
 
 // public dependency for Codec 2.0 HAL client
 cc_defaults {
@@ -156,3 +151,28 @@
         "libcodec2_aidl_client",
     ],
 }
+
+cc_fuzz {
+    name: "libcodec2-aidl-fuzzer",
+    vendor: true,
+    srcs: [
+        "fuzzer.cpp",
+    ],
+    defaults: [
+        "libcodec2-aidl-defaults",
+        "service_fuzzer_defaults",
+    ],
+    shared_libs: [
+        "libcodec2_vndk",
+
+        "libcodec2_soft_avcdec",
+        "libcodec2_soft_avcenc",
+        "libcodec2_soft_aacdec",
+        "libcodec2_soft_aacenc",
+    ],
+    fuzz_config: {
+        cc: [
+            "wonsik@google.com",
+        ],
+    },
+}
diff --git a/media/codec2/hal/aidl/Component.cpp b/media/codec2/hal/aidl/Component.cpp
new file mode 100644
index 0000000..fa18c3e
--- /dev/null
+++ b/media/codec2/hal/aidl/Component.cpp
@@ -0,0 +1,449 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-Component-Aidl"
+#include <android-base/logging.h>
+
+#include <codec2/aidl/Component.h>
+#include <codec2/aidl/ComponentStore.h>
+#include <codec2/aidl/InputBufferManager.h>
+
+#ifndef __ANDROID_APEX__
+#include <FilterWrapper.h>
+#endif
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_interface_utils.h>
+#include <utils/Timers.h>
+
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+
+#include <chrono>
+#include <thread>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+using ::aidl::android::hardware::common::NativeHandle;
+using ::aidl::android::hardware::media::bufferpool2::IClientManager;
+using ::ndk::ScopedAStatus;
+
+// ComponentListener wrapper
+struct Component::Listener : public C2Component::Listener {
+
+    Listener(const std::shared_ptr<Component>& component) :
+        mComponent(component),
+        mListener(component->mListener) {
+    }
+
+    virtual void onError_nb(
+            std::weak_ptr<C2Component> /* c2component */,
+            uint32_t errorCode) override {
+        std::shared_ptr<IComponentListener> listener = mListener.lock();
+        if (listener) {
+            ScopedAStatus transStatus = listener->onError(Status{Status::OK}, errorCode);
+            if (!transStatus.isOk()) {
+                LOG(ERROR) << "Component::Listener::onError_nb -- "
+                           << "transaction failed.";
+            }
+        }
+    }
+
+    virtual void onTripped_nb(
+            std::weak_ptr<C2Component> /* c2component */,
+            std::vector<std::shared_ptr<C2SettingResult>> c2settingResult
+            ) override {
+      std::shared_ptr<IComponentListener> listener = mListener.lock();
+        if (listener) {
+            std::vector<SettingResult> settingResults(c2settingResult.size());
+            size_t ix = 0;
+            for (const std::shared_ptr<C2SettingResult> &c2result :
+                    c2settingResult) {
+                if (c2result) {
+                    if (!ToAidl(&settingResults[ix++], *c2result)) {
+                        break;
+                    }
+                }
+            }
+            settingResults.resize(ix);
+            ScopedAStatus transStatus = listener->onTripped(settingResults);
+            if (!transStatus.isOk()) {
+                LOG(ERROR) << "Component::Listener::onTripped_nb -- "
+                           << "transaction failed.";
+            }
+        }
+    }
+
+    virtual void onWorkDone_nb(
+            std::weak_ptr<C2Component> /* c2component */,
+            std::list<std::unique_ptr<C2Work>> c2workItems) override {
+        for (const std::unique_ptr<C2Work>& work : c2workItems) {
+            if (work) {
+                if (work->worklets.empty()
+                        || !work->worklets.back()
+                        || (work->worklets.back()->output.flags &
+                            C2FrameData::FLAG_INCOMPLETE) == 0) {
+                    InputBufferManager::
+                            unregisterFrameData(mListener, work->input);
+                }
+            }
+        }
+
+        std::shared_ptr<IComponentListener> listener = mListener.lock();
+        if (listener) {
+            WorkBundle workBundle;
+
+            std::shared_ptr<Component> strongComponent = mComponent.lock();
+            // TODO
+            // beginTransferBufferQueueBlocks(c2workItems, true);
+            if (!ToAidl(&workBundle, c2workItems, strongComponent ?
+                    &strongComponent->mBufferPoolSender : nullptr)) {
+                LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
+                           << "received corrupted work items.";
+                // TODO
+                // endTransferBufferQueueBlocks(c2workItems, false, true);
+                return;
+            }
+            ScopedAStatus transStatus = listener->onWorkDone(workBundle);
+            if (!transStatus.isOk()) {
+                LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
+                           << "transaction failed.";
+                // TODO
+                // endTransferBufferQueueBlocks(c2workItems, false, true);
+                return;
+            }
+            // TODO
+            // endTransferBufferQueueBlocks(c2workItems, true, true);
+        }
+    }
+
+protected:
+    std::weak_ptr<Component> mComponent;
+    std::weak_ptr<IComponentListener> mListener;
+};
+
+// Component::DeathContext
+struct Component::DeathContext {
+    std::weak_ptr<Component> mWeakComp;
+};
+
+// Component
+Component::Component(
+        const std::shared_ptr<C2Component>& component,
+        const std::shared_ptr<IComponentListener>& listener,
+        const std::shared_ptr<ComponentStore>& store,
+        const std::shared_ptr<IClientManager>& clientPoolManager)
+      : mComponent{component},
+        mInterface{SharedRefBase::make<ComponentInterface>(
+                component->intf(), store->getParameterCache())},
+        mListener{listener},
+        mStore{store},
+        mBufferPoolSender{clientPoolManager},
+        mDeathContext(nullptr) {
+    // Retrieve supported parameters from store
+    // TODO: We could cache this per component/interface type
+    mInit = mInterface->status();
+}
+
+c2_status_t Component::status() const {
+    return mInit;
+}
+
+// Methods from ::android::hardware::media::c2::V1_1::IComponent
+ScopedAStatus Component::queue(const WorkBundle& workBundle) {
+    std::list<std::unique_ptr<C2Work>> c2works;
+
+    if (!FromAidl(&c2works, workBundle)) {
+        return ScopedAStatus::fromServiceSpecificError(Status::CORRUPTED);
+    }
+
+    // Register input buffers.
+    for (const std::unique_ptr<C2Work>& work : c2works) {
+        if (work) {
+            InputBufferManager::
+                    registerFrameData(mListener, work->input);
+        }
+    }
+
+    c2_status_t err = mComponent->queue_nb(&c2works);
+    if (err == C2_OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(err);
+}
+
+ScopedAStatus Component::flush(WorkBundle *flushedWorkBundle) {
+    std::list<std::unique_ptr<C2Work>> c2flushedWorks;
+    c2_status_t c2res = mComponent->flush_sm(
+            C2Component::FLUSH_COMPONENT,
+            &c2flushedWorks);
+
+    // Unregister input buffers.
+    for (const std::unique_ptr<C2Work>& work : c2flushedWorks) {
+        if (work) {
+            if (work->worklets.empty()
+                    || !work->worklets.back()
+                    || (work->worklets.back()->output.flags &
+                        C2FrameData::FLAG_INCOMPLETE) == 0) {
+                InputBufferManager::
+                        unregisterFrameData(mListener, work->input);
+            }
+        }
+    }
+
+    // TODO
+    // beginTransferBufferQueueBlocks(c2flushedWorks, true);
+    if (c2res == C2_OK) {
+        if (!ToAidl(flushedWorkBundle, c2flushedWorks, &mBufferPoolSender)) {
+            c2res = C2_CORRUPTED;
+        }
+    }
+    // TODO
+    // endTransferBufferQueueBlocks(c2flushedWorks, true, true);
+    if (c2res == C2_OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(c2res);
+}
+
+ScopedAStatus Component::drain(bool withEos) {
+    c2_status_t res = mComponent->drain_nb(withEos ?
+            C2Component::DRAIN_COMPONENT_WITH_EOS :
+            C2Component::DRAIN_COMPONENT_NO_EOS);
+    if (res == C2_OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(res);
+}
+
+namespace /* unnamed */ {
+
+struct BlockPoolIntf : public ConfigurableC2Intf {
+    BlockPoolIntf(const std::shared_ptr<C2BlockPool>& pool)
+          : ConfigurableC2Intf{
+                "C2BlockPool:" +
+                    (pool ? std::to_string(pool->getLocalId()) : "null"),
+                0},
+            mPool{pool} {
+    }
+
+    virtual c2_status_t config(
+            const std::vector<C2Param*>& params,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures
+            ) override {
+        (void)params;
+        (void)mayBlock;
+        (void)failures;
+        return C2_OK;
+    }
+
+    virtual c2_status_t query(
+            const std::vector<C2Param::Index>& indices,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2Param>>* const params
+            ) const override {
+        (void)indices;
+        (void)mayBlock;
+        (void)params;
+        return C2_OK;
+    }
+
+    virtual c2_status_t querySupportedParams(
+            std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
+            ) const override {
+        (void)params;
+        return C2_OK;
+    }
+
+    virtual c2_status_t querySupportedValues(
+            std::vector<C2FieldSupportedValuesQuery>& fields,
+            c2_blocking_t mayBlock) const override {
+        (void)fields;
+        (void)mayBlock;
+        return C2_OK;
+    }
+
+protected:
+    std::shared_ptr<C2BlockPool> mPool;
+};
+
+} // unnamed namespace
+
+ScopedAStatus Component::createBlockPool(
+        const IComponent::BlockPoolAllocator &allocator,
+        IComponent::BlockPool *blockPool) {
+    std::shared_ptr<C2BlockPool> c2BlockPool;
+    static constexpr IComponent::BlockPoolAllocator::Tag ALLOCATOR_ID =
+        IComponent::BlockPoolAllocator::allocatorId;
+    static constexpr IComponent::BlockPoolAllocator::Tag IGBA =
+        IComponent::BlockPoolAllocator::igba;
+    c2_status_t status = C2_OK;
+    switch (allocator.getTag()) {
+        case ALLOCATOR_ID:
+#ifdef __ANDROID_APEX__
+            status = CreateCodec2BlockPool(
+                    static_cast<::android::C2PlatformAllocatorStore::id_t>(
+                            allocator.get<ALLOCATOR_ID>()),
+                    mComponent,
+                    &c2BlockPool);
+#else
+            status = ComponentStore::GetFilterWrapper()->createBlockPool(
+                    static_cast<::android::C2PlatformAllocatorStore::id_t>(
+                            allocator.get<ALLOCATOR_ID>()),
+                    mComponent,
+                    &c2BlockPool);
+#endif
+            if (status != C2_OK) {
+                blockPool = nullptr;
+            }
+            break;
+        case IGBA:
+            // FIXME
+            break;
+        default:
+            break;
+    }
+    if (blockPool) {
+        mBlockPoolsMutex.lock();
+        mBlockPools.emplace(c2BlockPool->getLocalId(), c2BlockPool);
+        mBlockPoolsMutex.unlock();
+    } else if (status == C2_OK) {
+        status = C2_CORRUPTED;
+    }
+
+    blockPool->blockPoolId = c2BlockPool ? c2BlockPool->getLocalId() : 0;
+    blockPool->configurable = SharedRefBase::make<CachedConfigurable>(
+            std::make_unique<BlockPoolIntf>(c2BlockPool));
+    if (status == C2_OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(status);
+}
+
+ScopedAStatus Component::destroyBlockPool(int64_t blockPoolId) {
+    std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+    if (mBlockPools.erase(blockPoolId) == 1) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(Status::CORRUPTED);
+}
+
+ScopedAStatus Component::start() {
+    c2_status_t status = mComponent->start();
+    if (status == C2_OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(status);
+}
+
+ScopedAStatus Component::stop() {
+    InputBufferManager::unregisterFrameData(mListener);
+    c2_status_t status = mComponent->stop();
+    if (status == C2_OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(status);
+}
+
+ScopedAStatus Component::reset() {
+    c2_status_t status = mComponent->reset();
+    {
+        std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+        mBlockPools.clear();
+    }
+    InputBufferManager::unregisterFrameData(mListener);
+    if (status == C2_OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(status);
+}
+
+ScopedAStatus Component::release() {
+    c2_status_t status = mComponent->release();
+    {
+        std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+        mBlockPools.clear();
+    }
+    InputBufferManager::unregisterFrameData(mListener);
+    if (status == C2_OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(status);
+}
+
+ScopedAStatus Component::getInterface(
+        std::shared_ptr<IComponentInterface> *intf) {
+    *intf = mInterface;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Component::configureVideoTunnel(
+        int32_t avSyncHwId, NativeHandle *handle) {
+    (void)avSyncHwId;
+    (void)handle;
+    return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
+}
+
+void Component::initListener(const std::shared_ptr<Component>& self) {
+    std::shared_ptr<C2Component::Listener> c2listener =
+            std::make_shared<Listener>(self);
+    c2_status_t res = mComponent->setListener_vb(c2listener, C2_DONT_BLOCK);
+    if (res != C2_OK) {
+        mInit = res;
+    }
+
+    mDeathRecipient = ::ndk::ScopedAIBinder_DeathRecipient(
+            AIBinder_DeathRecipient_new(OnBinderDied));
+    mDeathContext = new DeathContext{weak_from_this()};
+    AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), OnBinderUnlinked);
+    AIBinder_linkToDeath(mListener->asBinder().get(), mDeathRecipient.get(), mDeathContext);
+}
+
+// static
+void Component::OnBinderDied(void *cookie) {
+    DeathContext *context = (DeathContext *)cookie;
+    std::shared_ptr<Component> comp = context->mWeakComp.lock();
+    if (comp) {
+        comp->release();
+    }
+}
+
+// static
+void Component::OnBinderUnlinked(void *cookie) {
+    delete (DeathContext *)cookie;
+}
+
+Component::~Component() {
+    InputBufferManager::unregisterFrameData(mListener);
+    mStore->reportComponentDeath(this);
+    if (mDeathRecipient.get()) {
+        AIBinder_unlinkToDeath(mListener->asBinder().get(), mDeathRecipient.get(), mDeathContext);
+    }
+}
+
+} // namespace utils
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/media/codec2/hal/aidl/ComponentInterface.cpp b/media/codec2/hal/aidl/ComponentInterface.cpp
new file mode 100644
index 0000000..2d812c9
--- /dev/null
+++ b/media/codec2/hal/aidl/ComponentInterface.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-ComponentInterface"
+#include <android-base/logging.h>
+
+#include <android/binder_auto_utils.h>
+#include <codec2/aidl/ComponentInterface.h>
+#include <codec2/aidl/Configurable.h>
+
+#include <utils/Timers.h>
+
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+
+#include <chrono>
+#include <thread>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+using ::ndk::ScopedAStatus;
+
+namespace /* unnamed */ {
+
+// Implementation of ConfigurableC2Intf based on C2ComponentInterface
+struct CompIntf : public ConfigurableC2Intf {
+    CompIntf(const std::shared_ptr<C2ComponentInterface>& intf) :
+        ConfigurableC2Intf{intf->getName(), intf->getId()},
+        mIntf{intf} {
+    }
+
+    virtual c2_status_t config(
+            const std::vector<C2Param*>& params,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures
+            ) override {
+        return mIntf->config_vb(params, mayBlock, failures);
+    }
+
+    virtual c2_status_t query(
+            const std::vector<C2Param::Index>& indices,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2Param>>* const params
+            ) const override {
+        return mIntf->query_vb({}, indices, mayBlock, params);
+    }
+
+    virtual c2_status_t querySupportedParams(
+            std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
+            ) const override {
+        return mIntf->querySupportedParams_nb(params);
+    }
+
+    virtual c2_status_t querySupportedValues(
+            std::vector<C2FieldSupportedValuesQuery>& fields,
+            c2_blocking_t mayBlock) const override {
+        return mIntf->querySupportedValues_vb(fields, mayBlock);
+    }
+
+protected:
+    std::shared_ptr<C2ComponentInterface> mIntf;
+};
+
+} // unnamed namespace
+
+// ComponentInterface
+ComponentInterface::ComponentInterface(
+        const std::shared_ptr<C2ComponentInterface>& intf,
+        const std::shared_ptr<ParameterCache>& cache)
+      : mInterface{intf},
+        mConfigurable{SharedRefBase::make<CachedConfigurable>(
+                std::make_unique<CompIntf>(intf))} {
+    mInit = mConfigurable->init(cache);
+}
+
+c2_status_t ComponentInterface::status() const {
+    return mInit;
+}
+
+ScopedAStatus ComponentInterface::getConfigurable(
+        std::shared_ptr<IConfigurable> *configurable) {
+    *configurable = mConfigurable;
+    return ScopedAStatus::ok();
+}
+
+}  // namespace utils
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp
new file mode 100644
index 0000000..19734c0
--- /dev/null
+++ b/media/codec2/hal/aidl/ComponentStore.cpp
@@ -0,0 +1,478 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-ComponentStore-Aidl"
+#include <android-base/logging.h>
+
+#include <bufferpool2/ClientManager.h>
+#include <codec2/aidl/Component.h>
+#include <codec2/aidl/ComponentInterface.h>
+#include <codec2/aidl/ComponentStore.h>
+#include <codec2/aidl/ParamTypes.h>
+
+#include <android-base/file.h>
+#include <utils/Errors.h>
+
+#include <C2PlatformSupport.h>
+#include <util/C2InterfaceHelper.h>
+
+#include <chrono>
+#include <ctime>
+#include <iomanip>
+#include <ostream>
+#include <sstream>
+
+#ifndef __ANDROID_APEX__
+#include <codec2/hidl/plugin/FilterPlugin.h>
+#include <dlfcn.h>
+#include <C2Config.h>
+#include <DefaultFilterPlugin.h>
+#include <FilterWrapper.h>
+#endif
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+using ::android::DefaultFilterPlugin;
+using ::android::FilterWrapper;
+using ::ndk::ScopedAStatus;
+
+namespace /* unnamed */ {
+
+struct StoreIntf : public ConfigurableC2Intf {
+    StoreIntf(const std::shared_ptr<C2ComponentStore>& store)
+          : ConfigurableC2Intf{store ? store->getName() : "", 0},
+            mStore{store} {
+    }
+
+    virtual c2_status_t config(
+            const std::vector<C2Param*> &params,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2SettingResult>> *const failures
+            ) override {
+        // Assume all params are blocking
+        // TODO: Filter for supported params
+        if (mayBlock == C2_DONT_BLOCK && params.size() != 0) {
+            return C2_BLOCKING;
+        }
+        return mStore->config_sm(params, failures);
+    }
+
+    virtual c2_status_t query(
+            const std::vector<C2Param::Index> &indices,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2Param>> *const params) const override {
+        // Assume all params are blocking
+        // TODO: Filter for supported params
+        if (mayBlock == C2_DONT_BLOCK && indices.size() != 0) {
+            return C2_BLOCKING;
+        }
+        return mStore->query_sm({}, indices, params);
+    }
+
+    virtual c2_status_t querySupportedParams(
+            std::vector<std::shared_ptr<C2ParamDescriptor>> *const params
+            ) const override {
+        return mStore->querySupportedParams_nb(params);
+    }
+
+    virtual c2_status_t querySupportedValues(
+            std::vector<C2FieldSupportedValuesQuery> &fields,
+            c2_blocking_t mayBlock) const override {
+        // Assume all params are blocking
+        // TODO: Filter for supported params
+        if (mayBlock == C2_DONT_BLOCK && fields.size() != 0) {
+            return C2_BLOCKING;
+        }
+        return mStore->querySupportedValues_sm(fields);
+    }
+
+protected:
+    std::shared_ptr<C2ComponentStore> mStore;
+};
+
+} // unnamed namespace
+
+struct ComponentStore::StoreParameterCache : public ParameterCache {
+    std::mutex mStoreMutex;
+    ComponentStore* mStore;
+
+    StoreParameterCache(ComponentStore* store): mStore{store} {
+    }
+
+    virtual c2_status_t validate(
+            const std::vector<std::shared_ptr<C2ParamDescriptor>>& params
+            ) override {
+        std::scoped_lock _lock(mStoreMutex);
+        return mStore ? mStore->validateSupportedParams(params) : C2_NO_INIT;
+    }
+
+    void onStoreDestroyed() {
+        std::scoped_lock _lock(mStoreMutex);
+        mStore = nullptr;
+    }
+};
+
+ComponentStore::ComponentStore(const std::shared_ptr<C2ComponentStore>& store)
+      : mConfigurable{SharedRefBase::make<CachedConfigurable>(std::make_unique<StoreIntf>(store))},
+        mParameterCache{std::make_shared<StoreParameterCache>(this)},
+        mStore{store} {
+
+    std::shared_ptr<C2ComponentStore> platformStore =
+        ::android::GetCodec2PlatformComponentStore();
+    ::android::SetPreferredCodec2ComponentStore(store);
+
+    // Retrieve struct descriptors
+    mParamReflector = mStore->getParamReflector();
+
+    // Retrieve supported parameters from store
+    using namespace std::placeholders;
+    mInit = mConfigurable->init(mParameterCache);
+}
+
+ComponentStore::~ComponentStore() {
+    mParameterCache->onStoreDestroyed();
+}
+
+c2_status_t ComponentStore::status() const {
+    return mInit;
+}
+
+c2_status_t ComponentStore::validateSupportedParams(
+        const std::vector<std::shared_ptr<C2ParamDescriptor>>& params) {
+    c2_status_t res = C2_OK;
+
+    for (const std::shared_ptr<C2ParamDescriptor> &desc : params) {
+        if (!desc) {
+            // All descriptors should be valid
+            res = res ? res : C2_BAD_VALUE;
+            continue;
+        }
+        C2Param::CoreIndex coreIndex = desc->index().coreIndex();
+        std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
+        auto it = mStructDescriptors.find(coreIndex);
+        if (it == mStructDescriptors.end()) {
+            std::shared_ptr<C2StructDescriptor> structDesc =
+                    mParamReflector->describe(coreIndex);
+            if (!structDesc) {
+                // All supported params must be described
+                res = C2_BAD_INDEX;
+            }
+            mStructDescriptors.insert({ coreIndex, structDesc });
+        }
+    }
+    return res;
+}
+
+std::shared_ptr<ParameterCache> ComponentStore::getParameterCache() const {
+    return mParameterCache;
+}
+
+#ifndef __ANDROID_APEX__
+// static
+std::shared_ptr<FilterWrapper> ComponentStore::GetFilterWrapper() {
+    constexpr const char kPluginPath[] = "libc2filterplugin.so";
+    static std::shared_ptr<FilterWrapper> wrapper = FilterWrapper::Create(
+            std::make_unique<DefaultFilterPlugin>(kPluginPath));
+    return wrapper;
+}
+#endif
+
+// Methods from ::aidl::android::hardware::media::c2::IComponentStore
+ScopedAStatus ComponentStore::createComponent(
+        const std::string& name,
+        const std::shared_ptr<IComponentListener>& listener,
+        const std::shared_ptr<IClientManager>& pool,
+        std::shared_ptr<IComponent> *component) {
+
+    std::shared_ptr<C2Component> c2component;
+    c2_status_t status =
+            mStore->createComponent(name, &c2component);
+
+    if (status == C2_OK) {
+#ifndef __ANDROID_APEX__
+        c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
+#endif
+        onInterfaceLoaded(c2component->intf());
+        std::shared_ptr<Component> comp =
+            SharedRefBase::make<Component>(c2component, listener, shared_from_this(), pool);
+        *component = comp;
+        if (!component) {
+            status = C2_CORRUPTED;
+        } else {
+            reportComponentBirth(comp.get());
+            if (comp->status() != C2_OK) {
+                status = comp->status();
+            } else {
+                comp->initListener(comp);
+                if (comp->status() != C2_OK) {
+                    status = comp->status();
+                }
+            }
+        }
+    }
+    if (status == C2_OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(status);
+}
+
+ScopedAStatus ComponentStore::createInterface(
+        const std::string& name,
+        std::shared_ptr<IComponentInterface> *intf) {
+    std::shared_ptr<C2ComponentInterface> c2interface;
+    c2_status_t res = mStore->createInterface(name, &c2interface);
+    if (res == C2_OK) {
+#ifndef __ANDROID_APEX__
+        c2interface = GetFilterWrapper()->maybeWrapInterface(c2interface);
+#endif
+        onInterfaceLoaded(c2interface);
+        *intf = SharedRefBase::make<ComponentInterface>(c2interface, mParameterCache);
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(res);
+}
+
+ScopedAStatus ComponentStore::listComponents(
+        std::vector<IComponentStore::ComponentTraits> *traits) {
+    std::vector<std::shared_ptr<const C2Component::Traits>> c2traits =
+            mStore->listComponents();
+    traits->resize(c2traits.size());
+    size_t ix = 0;
+    for (const std::shared_ptr<const C2Component::Traits> &c2trait : c2traits) {
+        if (c2trait) {
+            if (ToAidl(&traits->at(ix), *c2trait)) {
+                ++ix;
+            } else {
+                break;
+            }
+        }
+    }
+    traits->resize(ix);
+    return ScopedAStatus::ok();
+}
+
+void ComponentStore::onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf) {
+    // invalidate unsupported struct descriptors if a new interface is loaded as it may have
+    // exposed new descriptors
+    std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
+    if (!mLoadedInterfaces.count(intf->getName())) {
+        mUnsupportedStructDescriptors.clear();
+        mLoadedInterfaces.emplace(intf->getName());
+    }
+}
+
+ScopedAStatus ComponentStore::getStructDescriptors(
+        const std::vector<int32_t>& indices,
+        std::vector<StructDescriptor> *descriptors) {
+    descriptors->resize(indices.size());
+    size_t dstIx = 0;
+    int32_t res = Status::OK;
+    for (size_t srcIx = 0; srcIx < indices.size(); ++srcIx) {
+        std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
+        const C2Param::CoreIndex coreIndex =
+            C2Param::CoreIndex(uint32_t(indices[srcIx])).coreIndex();
+        const auto item = mStructDescriptors.find(coreIndex);
+        if (item == mStructDescriptors.end()) {
+            // not in the cache, and not known to be unsupported, query local reflector
+            if (!mUnsupportedStructDescriptors.count(coreIndex)) {
+                std::shared_ptr<C2StructDescriptor> structDesc =
+                    mParamReflector->describe(coreIndex);
+                if (!structDesc) {
+                    mUnsupportedStructDescriptors.emplace(coreIndex);
+                } else {
+                    mStructDescriptors.insert({ coreIndex, structDesc });
+                    if (ToAidl(&descriptors->at(dstIx), *structDesc)) {
+                        ++dstIx;
+                        continue;
+                    }
+                    res = Status::CORRUPTED;
+                    break;
+                }
+            }
+            res = Status::NOT_FOUND;
+        } else if (item->second) {
+            if (ToAidl(&descriptors->at(dstIx), *item->second)) {
+                ++dstIx;
+                continue;
+            }
+            res = Status::CORRUPTED;
+            break;
+        } else {
+            res = Status::NO_MEMORY;
+            break;
+        }
+    }
+    descriptors->resize(dstIx);
+    if (res == Status::OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(res);
+}
+
+ScopedAStatus ComponentStore::getPoolClientManager(
+        std::shared_ptr<IClientManager> *manager) {
+    using ::aidl::android::hardware::media::bufferpool2::implementation::ClientManager;
+    *manager = ClientManager::getInstance();
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus ComponentStore::copyBuffer(const Buffer& src, const Buffer& dst) {
+    // TODO implement
+    (void)src;
+    (void)dst;
+    return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
+}
+
+ScopedAStatus ComponentStore::getConfigurable(
+        std::shared_ptr<IConfigurable> *configurable) {
+    *configurable = mConfigurable;
+    return ScopedAStatus::ok();
+}
+
+// Called from createComponent() after a successful creation of `component`.
+void ComponentStore::reportComponentBirth(Component* component) {
+    ComponentStatus componentStatus;
+    componentStatus.c2Component = component->mComponent;
+    componentStatus.birthTime = std::chrono::system_clock::now();
+
+    std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+    mComponentRoster.emplace(component, componentStatus);
+}
+
+// Called from within the destructor of `component`. No virtual function calls
+// are made on `component` here.
+void ComponentStore::reportComponentDeath(Component* component) {
+    std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+    mComponentRoster.erase(component);
+}
+
+// Dumps component traits.
+std::ostream& ComponentStore::dump(
+        std::ostream& out,
+        const std::shared_ptr<const C2Component::Traits>& comp) {
+
+    constexpr const char indent[] = "    ";
+
+    out << indent << "name: " << comp->name << std::endl;
+    out << indent << "domain: " << comp->domain << std::endl;
+    out << indent << "kind: " << comp->kind << std::endl;
+    out << indent << "rank: " << comp->rank << std::endl;
+    out << indent << "mediaType: " << comp->mediaType << std::endl;
+    out << indent << "aliases:";
+    for (const auto& alias : comp->aliases) {
+        out << ' ' << alias;
+    }
+    out << std::endl;
+
+    return out;
+}
+
+// Dumps component status.
+std::ostream& ComponentStore::dump(
+        std::ostream& out,
+        ComponentStatus& compStatus) {
+
+    constexpr const char indent[] = "    ";
+
+    // Print birth time.
+    std::chrono::milliseconds ms =
+            std::chrono::duration_cast<std::chrono::milliseconds>(
+                compStatus.birthTime.time_since_epoch());
+    std::time_t birthTime = std::chrono::system_clock::to_time_t(
+            compStatus.birthTime);
+    std::tm tm = *std::localtime(&birthTime);
+    out << indent << "Creation time: "
+        << std::put_time(&tm, "%Y-%m-%d %H:%M:%S")
+        << '.' << std::setfill('0') << std::setw(3) << ms.count() % 1000
+        << std::endl;
+
+    // Print name and id.
+    std::shared_ptr<C2ComponentInterface> intf = compStatus.c2Component->intf();
+    if (!intf) {
+        out << indent << "Unknown component -- null interface" << std::endl;
+        return out;
+    }
+    out << indent << "Name: " << intf->getName() << std::endl;
+    out << indent << "Id: " << intf->getId() << std::endl;
+
+    return out;
+}
+
+// Dumps information when lshal is called.
+binder_status_t ComponentStore::dump(
+        int fd, [[maybe_unused]] const char** args, [[maybe_unused]] uint32_t numArgs) {
+    LOG(INFO) << "debug -- dumping...";
+    std::ostringstream out;
+
+    { // Populate "out".
+
+        constexpr const char indent[] = "  ";
+
+        // Show name.
+        out << "Beginning of dump -- C2ComponentStore: "
+                << mStore->getName() << std::endl << std::endl;
+
+        // Retrieve the list of supported components.
+        std::vector<std::shared_ptr<const C2Component::Traits>> traitsList =
+                mStore->listComponents();
+
+        // Dump the traits of supported components.
+        out << indent << "Supported components:" << std::endl << std::endl;
+        if (traitsList.size() == 0) {
+            out << indent << indent << "NONE" << std::endl << std::endl;
+        } else {
+            for (const auto& traits : traitsList) {
+                dump(out, traits) << std::endl;
+            }
+        }
+
+        // Dump active components.
+        {
+            out << indent << "Active components:" << std::endl << std::endl;
+            std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+            if (mComponentRoster.size() == 0) {
+                out << indent << indent << "NONE" << std::endl << std::endl;
+            } else {
+                for (auto& pair : mComponentRoster) {
+                    dump(out, pair.second) << std::endl;
+                }
+            }
+        }
+
+        out << "End of dump -- C2ComponentStore: "
+                << mStore->getName() << std::endl;
+    }
+
+    if (!::android::base::WriteStringToFd(out.str(), fd)) {
+        PLOG(WARNING) << "debug -- dumping failed -- write()";
+    } else {
+        LOG(INFO) << "debug -- dumping succeeded";
+    }
+    return STATUS_OK;
+}
+
+} // namespace utils
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/media/codec2/hal/aidl/Configurable.cpp b/media/codec2/hal/aidl/Configurable.cpp
new file mode 100644
index 0000000..0326263
--- /dev/null
+++ b/media/codec2/hal/aidl/Configurable.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-Configurable-Aidl"
+#include <android-base/logging.h>
+
+#include <android/binder_auto_utils.h>
+#include <codec2/aidl/Configurable.h>
+#include <codec2/aidl/ParamTypes.h>
+
+#include <C2ParamInternal.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+using ::ndk::ScopedAStatus;
+
+CachedConfigurable::CachedConfigurable(
+        std::unique_ptr<ConfigurableC2Intf>&& intf)
+      : mIntf{std::move(intf)} {
+}
+
+c2_status_t CachedConfigurable::init(
+        const std::shared_ptr<ParameterCache>& cache) {
+    // Retrieve supported parameters from store
+    c2_status_t init = mIntf->querySupportedParams(&mSupportedParams);
+    c2_status_t validate = cache->validate(mSupportedParams);
+    return init == C2_OK ? C2_OK : validate;
+}
+
+// Methods from ::android::hardware::media::c2::V1_0::IConfigurable follow.
+
+ScopedAStatus CachedConfigurable::getId(int32_t* id) {
+    *id = mIntf->getId();
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus CachedConfigurable::getName(std::string* name) {
+    *name = mIntf->getName();
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus CachedConfigurable::query(
+        const std::vector<int32_t>& indices,
+        bool mayBlock,
+        Params* params) {
+    typedef C2Param::Index Index;
+    std::vector<Index> c2heapParamIndices(
+            (Index*)indices.data(),
+            (Index*)indices.data() + indices.size());
+    std::vector<std::unique_ptr<C2Param>> c2heapParams;
+    c2_status_t c2res = mIntf->query(
+            c2heapParamIndices,
+            mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
+            &c2heapParams);
+
+    if (!CreateParamsBlob(params, c2heapParams)) {
+        LOG(WARNING) << "query -- invalid output params.";
+    }
+    if (c2res == C2_OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(c2res);
+}
+
+ScopedAStatus CachedConfigurable::config(
+        const Params& params,
+        bool mayBlock,
+        ConfigResult* result) {
+    // inParams is not writable, so create a copy as config modifies the parameters
+    std::vector<C2Param*> c2params;
+    if (!ParseParamsBlob(&c2params, params)) {
+        LOG(WARNING) << "config -- invalid input params.";
+        return ScopedAStatus::fromServiceSpecificError(C2_CORRUPTED);
+    }
+    // TODO: check if blob was invalid
+    std::vector<std::unique_ptr<C2SettingResult>> c2failures;
+    c2_status_t c2res = mIntf->config(
+            c2params,
+            mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
+            &c2failures);
+    result->failures.resize(c2failures.size());
+    {
+        size_t ix = 0;
+        for (const std::unique_ptr<C2SettingResult>& c2result : c2failures) {
+            if (c2result) {
+                if (ToAidl(&result->failures[ix], *c2result)) {
+                    ++ix;
+                } else {
+                    LOG(DEBUG) << "config -- invalid setting results.";
+                    break;
+                }
+            }
+        }
+        result->failures.resize(ix);
+    }
+    if (!CreateParamsBlob(&result->params, c2params)) {
+        LOG(DEBUG) << "config -- invalid output params.";
+    }
+    if (c2res == C2_OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(c2res);
+}
+
+ScopedAStatus CachedConfigurable::querySupportedParams(
+        int32_t start,
+        int32_t count,
+        std::vector<ParamDescriptor>* paramDesc) {
+    C2LinearRange request = C2LinearCapacity(mSupportedParams.size()).range(
+            start, count);
+    paramDesc->resize(request.size());
+    int32_t res = Status::OK;
+    size_t dstIx = 0;
+    for (size_t srcIx = request.offset(); srcIx < request.endOffset(); ++srcIx) {
+        if (mSupportedParams[srcIx]) {
+            if (ToAidl(&(*paramDesc)[dstIx], *mSupportedParams[srcIx])) {
+                ++dstIx;
+            } else {
+                res = Status::CORRUPTED;
+                LOG(WARNING) << "querySupportedParams -- invalid output params.";
+                break;
+            }
+        } else {
+            res = Status::BAD_INDEX;
+        }
+    }
+    paramDesc->resize(dstIx);
+    if (res == Status::OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(res);
+}
+
+ScopedAStatus CachedConfigurable::querySupportedValues(
+        const std::vector<FieldSupportedValuesQuery>& fields,
+        bool mayBlock,
+        std::vector<FieldSupportedValuesQueryResult>* result) {
+    std::vector<C2FieldSupportedValuesQuery> c2fields;
+    {
+        // C2FieldSupportedValuesQuery objects are restricted in that some
+        // members are const.
+        // C2ParamField - required for its constructor - has no constructors
+        // from fields. Use C2ParamInspector.
+        for (const FieldSupportedValuesQuery &query : fields) {
+            c2fields.emplace_back(_C2ParamInspector::CreateParamField(
+                    (uint32_t)query.field.index,
+                    query.field.fieldId.offset,
+                    query.field.fieldId.sizeBytes),
+                    query.type == FieldSupportedValuesQuery::Type::POSSIBLE ?
+                    C2FieldSupportedValuesQuery::POSSIBLE :
+                    C2FieldSupportedValuesQuery::CURRENT);
+        }
+    }
+    c2_status_t c2res = mIntf->querySupportedValues(
+            c2fields,
+            mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK);
+    result->resize(fields.size());
+    size_t dstIx = 0;
+    for (const C2FieldSupportedValuesQuery &res : c2fields) {
+        if (ToAidl(&(*result)[dstIx], res)) {
+            ++dstIx;
+        } else {
+            result->resize(dstIx);
+            c2res = C2_CORRUPTED;
+            LOG(WARNING) << "querySupportedValues -- invalid output params.";
+            break;
+        }
+    }
+    if (c2res == C2_OK) {
+        return ScopedAStatus::ok();
+    }
+    return ScopedAStatus::fromServiceSpecificError(c2res);
+}
+
+}  // namespace utils
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
diff --git a/media/codec2/hal/aidl/InputBufferManager.cpp b/media/codec2/hal/aidl/InputBufferManager.cpp
new file mode 100644
index 0000000..5c58155
--- /dev/null
+++ b/media/codec2/hal/aidl/InputBufferManager.cpp
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-InputBufferManager-Aidl"
+#include <android-base/logging.h>
+
+#include <codec2/aidl/InputBufferManager.h>
+
+#include <aidl/android/hardware/media/c2/IComponentListener.h>
+#include <android-base/logging.h>
+
+#include <C2Buffer.h>
+#include <C2Work.h>
+
+#include <chrono>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+using namespace ::android;
+
+void InputBufferManager::registerFrameData(
+        const std::shared_ptr<IComponentListener>& listener,
+        const C2FrameData& input) {
+    getInstance()._registerFrameData(listener, input);
+}
+
+void InputBufferManager::unregisterFrameData(
+        const std::weak_ptr<IComponentListener>& listener,
+        const C2FrameData& input) {
+    getInstance()._unregisterFrameData(listener, input);
+}
+
+void InputBufferManager::unregisterFrameData(
+        const std::weak_ptr<IComponentListener>& listener) {
+    getInstance()._unregisterFrameData(listener);
+}
+
+void InputBufferManager::setNotificationInterval(
+        nsecs_t notificationIntervalNs) {
+    getInstance()._setNotificationInterval(notificationIntervalNs);
+}
+
+void InputBufferManager::_registerFrameData(
+        const std::shared_ptr<IComponentListener>& listener,
+        const C2FrameData& input) {
+    uint64_t frameIndex = input.ordinal.frameIndex.peeku();
+    LOG(VERBOSE) << "InputBufferManager::_registerFrameData -- called with "
+                 << "listener @ 0x" << std::hex << listener.get()
+                 << ", frameIndex = " << std::dec << frameIndex
+                 << ".";
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    std::set<TrackedBuffer*> &bufferIds =
+            mTrackedBuffersMap[listener][frameIndex];
+
+    for (size_t i = 0; i < input.buffers.size(); ++i) {
+        if (!input.buffers[i]) {
+            LOG(VERBOSE) << "InputBufferManager::_registerFrameData -- "
+                         << "Input buffer at index " << i << " is null.";
+            continue;
+        }
+        TrackedBuffer *bufferId =
+            new TrackedBuffer(listener, frameIndex, i, input.buffers[i]);
+        mTrackedBufferCache.emplace(bufferId);
+        bufferIds.emplace(bufferId);
+
+        c2_status_t status = input.buffers[i]->registerOnDestroyNotify(
+                onBufferDestroyed,
+                reinterpret_cast<void*>(bufferId));
+        if (status != C2_OK) {
+            LOG(DEBUG) << "InputBufferManager::_registerFrameData -- "
+                       << "registerOnDestroyNotify() failed "
+                       << "(listener @ 0x" << std::hex << listener.get()
+                       << ", frameIndex = " << std::dec << frameIndex
+                       << ", bufferIndex = " << i
+                       << ") => status = " << status
+                       << ".";
+        }
+    }
+
+    mDeathNotifications.emplace(
+            listener,
+            DeathNotifications(
+                mNotificationIntervalNs.load(std::memory_order_relaxed)));
+}
+
+// Remove a pair (listener, frameIndex) from mTrackedBuffersMap and
+// mDeathNotifications. This implies all bufferIndices are removed.
+//
+// This is called from onWorkDone() and flush().
+void InputBufferManager::_unregisterFrameData(
+        const std::weak_ptr<IComponentListener>& listener,
+        const C2FrameData& input) {
+    uint64_t frameIndex = input.ordinal.frameIndex.peeku();
+    LOG(VERBOSE) << "InputBufferManager::_unregisterFrameData -- called with "
+                 << "frameIndex = " << frameIndex << ".";
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    auto findListener = mTrackedBuffersMap.find(listener);
+    if (findListener != mTrackedBuffersMap.end()) {
+        std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds
+                = findListener->second;
+        auto findFrameIndex = frameIndex2BufferIds.find(frameIndex);
+        if (findFrameIndex != frameIndex2BufferIds.end()) {
+            std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second;
+            for (TrackedBuffer* bufferId : bufferIds) {
+                std::shared_ptr<C2Buffer> buffer = bufferId->buffer.lock();
+                if (buffer) {
+                    c2_status_t status = buffer->unregisterOnDestroyNotify(
+                            onBufferDestroyed,
+                            reinterpret_cast<void*>(bufferId));
+                    if (status != C2_OK) {
+                        LOG(DEBUG) << "InputBufferManager::_unregisterFrameData "
+                                   << "-- unregisterOnDestroyNotify() failed "
+                                   << "(frameIndex = " << bufferId->frameIndex
+                                   << ", bufferIndex = " << bufferId->bufferIndex
+                                   << ") => status = " << status
+                                   << ".";
+                    }
+                }
+                mTrackedBufferCache.erase(bufferId);
+                delete bufferId;
+            }
+
+            frameIndex2BufferIds.erase(findFrameIndex);
+            if (frameIndex2BufferIds.empty()) {
+                mTrackedBuffersMap.erase(findListener);
+            }
+        }
+    }
+
+    auto findListenerD = mDeathNotifications.find(listener);
+    if (findListenerD != mDeathNotifications.end()) {
+        DeathNotifications &deathNotifications = findListenerD->second;
+        auto findFrameIndex = deathNotifications.indices.find(frameIndex);
+        if (findFrameIndex != deathNotifications.indices.end()) {
+            std::vector<size_t> &bufferIndices = findFrameIndex->second;
+            deathNotifications.count -= bufferIndices.size();
+            deathNotifications.indices.erase(findFrameIndex);
+        }
+    }
+}
+
+// Remove listener from mTrackedBuffersMap and mDeathNotifications. This implies
+// all frameIndices and bufferIndices are removed.
+//
+// This is called when the component cleans up all input buffers, i.e., when
+// reset(), release(), stop() or ~Component() is called.
+void InputBufferManager::_unregisterFrameData(
+        const std::weak_ptr<IComponentListener>& listener) {
+    LOG(VERBOSE) << "InputBufferManager::_unregisterFrameData.";
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    auto findListener = mTrackedBuffersMap.find(listener);
+    if (findListener != mTrackedBuffersMap.end()) {
+        std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds =
+                findListener->second;
+        for (auto findFrameIndex = frameIndex2BufferIds.begin();
+                findFrameIndex != frameIndex2BufferIds.end();
+                ++findFrameIndex) {
+            std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second;
+            for (TrackedBuffer* bufferId : bufferIds) {
+                std::shared_ptr<C2Buffer> buffer = bufferId->buffer.lock();
+                if (buffer) {
+                    c2_status_t status = buffer->unregisterOnDestroyNotify(
+                            onBufferDestroyed,
+                            reinterpret_cast<void*>(bufferId));
+                    if (status != C2_OK) {
+                        LOG(DEBUG) << "InputBufferManager::_unregisterFrameData "
+                                   << "-- unregisterOnDestroyNotify() failed "
+                                   << "(frameIndex = " << bufferId->frameIndex
+                                   << ", bufferIndex = " << bufferId->bufferIndex
+                                   << ") => status = " << status
+                                   << ".";
+                    }
+                    mTrackedBufferCache.erase(bufferId);
+                    delete bufferId;
+                }
+            }
+        }
+        mTrackedBuffersMap.erase(findListener);
+    }
+
+    mDeathNotifications.erase(listener);
+}
+
+// Set mNotificationIntervalNs.
+void InputBufferManager::_setNotificationInterval(
+        nsecs_t notificationIntervalNs) {
+    mNotificationIntervalNs.store(
+            notificationIntervalNs,
+            std::memory_order_relaxed);
+}
+
+// Move a buffer from mTrackedBuffersMap to mDeathNotifications.
+// This is called when a registered C2Buffer object is destroyed.
+void InputBufferManager::onBufferDestroyed(const C2Buffer* buf, void* arg) {
+    getInstance()._onBufferDestroyed(buf, arg);
+}
+
+void InputBufferManager::_onBufferDestroyed(const C2Buffer* buf, void* arg) {
+    if (!buf || !arg) {
+        LOG(WARNING) << "InputBufferManager::_onBufferDestroyed -- called with "
+                     << "null argument (s): "
+                     << "buf @ 0x" << std::hex << buf
+                     << ", arg @ 0x" << std::hex << arg
+                     << std::dec << ".";
+        return;
+    }
+
+    std::lock_guard<std::mutex> lock(mMutex);
+    TrackedBuffer *bufferId = reinterpret_cast<TrackedBuffer*>(arg);
+
+    if (mTrackedBufferCache.find(bufferId) == mTrackedBufferCache.end()) {
+        LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- called with "
+                     << "unregistered buffer: "
+                     << "buf @ 0x" << std::hex << buf
+                     << ", arg @ 0x" << std::hex << arg
+                     << std::dec << ".";
+        return;
+    }
+
+    LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- called with "
+                 << "buf @ 0x" << std::hex << buf
+                 << ", arg @ 0x" << std::hex << arg
+                 << std::dec << " -- "
+                 << ", frameIndex = " << bufferId->frameIndex
+                 << ", bufferIndex = " << bufferId->bufferIndex
+                 << ".";
+    auto findListener = mTrackedBuffersMap.find(bufferId->listener);
+    if (findListener == mTrackedBuffersMap.end()) {
+        LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- "
+                     << "received invalid listener: "
+                     << " (frameIndex = " << bufferId->frameIndex
+                     << ", bufferIndex = " << bufferId->bufferIndex
+                     << ").";
+        return;
+    }
+
+    std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds
+            = findListener->second;
+    auto findFrameIndex = frameIndex2BufferIds.find(bufferId->frameIndex);
+    if (findFrameIndex == frameIndex2BufferIds.end()) {
+        LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- "
+                   << "received invalid frame index: "
+                   << "frameIndex = " << bufferId->frameIndex
+                   << ", bufferIndex = " << bufferId->bufferIndex
+                   << ").";
+        return;
+    }
+
+    std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second;
+    auto findBufferId = bufferIds.find(bufferId);
+    if (findBufferId == bufferIds.end()) {
+        LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- "
+                   << "received invalid buffer index: "
+                   << "bufferIndex = " << bufferId->bufferIndex
+                   << " (frameIndex = " << bufferId->frameIndex
+                   << ").";
+        return;
+    }
+
+    bufferIds.erase(findBufferId);
+    if (bufferIds.empty()) {
+        frameIndex2BufferIds.erase(findFrameIndex);
+        if (frameIndex2BufferIds.empty()) {
+            mTrackedBuffersMap.erase(findListener);
+        }
+    }
+
+    DeathNotifications &deathNotifications = mDeathNotifications[bufferId->listener];
+    deathNotifications.indices[bufferId->frameIndex].emplace_back(bufferId->bufferIndex);
+    ++deathNotifications.count;
+    mOnBufferDestroyed.notify_one();
+
+    mTrackedBufferCache.erase(bufferId);
+    delete bufferId;
+}
+
+// Notify the clients about buffer destructions.
+// Return false if all destructions have been notified.
+// Return true and set timeToRetry to the time point to wait for before
+// retrying if some destructions have not been notified.
+bool InputBufferManager::processNotifications(nsecs_t* timeToRetryNs) {
+
+    struct Notification {
+        std::shared_ptr<IComponentListener> listener;
+        std::vector<IComponentListener::InputBuffer> inputBuffers;
+        Notification(const std::shared_ptr<IComponentListener>& l, size_t s)
+              : listener(l), inputBuffers(s) {}
+    };
+    std::list<Notification> notifications;
+    nsecs_t notificationIntervalNs =
+            mNotificationIntervalNs.load(std::memory_order_relaxed);
+
+    bool retry = false;
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        *timeToRetryNs = notificationIntervalNs;
+        nsecs_t timeNowNs = systemTime();
+        for (auto it = mDeathNotifications.begin();
+                it != mDeathNotifications.end(); ) {
+            std::shared_ptr<IComponentListener> listener = it->first.lock();
+            if (!listener) {
+                ++it;
+                continue;
+            }
+            DeathNotifications &deathNotifications = it->second;
+
+            nsecs_t timeSinceLastNotifiedNs =
+                    timeNowNs - deathNotifications.lastSentNs;
+            // If not enough time has passed since the last callback, leave the
+            // notifications for this listener untouched for now and retry
+            // later.
+            if (timeSinceLastNotifiedNs < notificationIntervalNs) {
+                retry = true;
+                *timeToRetryNs = std::min(*timeToRetryNs,
+                        notificationIntervalNs - timeSinceLastNotifiedNs);
+                LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+                             << "Notifications for listener @ "
+                                 << std::hex << listener.get()
+                             << " will be postponed.";
+                ++it;
+                continue;
+            }
+
+            // If enough time has passed since the last notification to this
+            // listener but there are currently no pending notifications, the
+            // listener can be removed from mDeathNotifications---there is no
+            // need to keep track of the last notification time anymore.
+            if (deathNotifications.count == 0) {
+                it = mDeathNotifications.erase(it);
+                continue;
+            }
+
+            // Create the argument for the callback.
+            notifications.emplace_back(listener, deathNotifications.count);
+            std::vector<IComponentListener::InputBuffer> &inputBuffers =
+                    notifications.back().inputBuffers;
+            size_t i = 0;
+            for (std::pair<const uint64_t, std::vector<size_t>>& p :
+                    deathNotifications.indices) {
+                uint64_t frameIndex = p.first;
+                const std::vector<size_t> &bufferIndices = p.second;
+                for (const size_t& bufferIndex : bufferIndices) {
+                    IComponentListener::InputBuffer &inputBuffer
+                            = inputBuffers[i++];
+                    inputBuffer.arrayIndex = bufferIndex;
+                    inputBuffer.frameIndex = frameIndex;
+                }
+            }
+
+            // Clear deathNotifications for this listener and set retry to true
+            // so processNotifications will be called again. This will
+            // guarantee that a listener with no pending notifications will
+            // eventually be removed from mDeathNotifications after
+            // mNotificationIntervalNs nanoseconds has passed.
+            retry = true;
+            deathNotifications.indices.clear();
+            deathNotifications.count = 0;
+            deathNotifications.lastSentNs = timeNowNs;
+            ++it;
+        }
+    }
+
+    // Call onInputBuffersReleased() outside the lock to avoid deadlock.
+    for (const Notification& notification : notifications) {
+        if (!notification.listener->onInputBuffersReleased(
+                notification.inputBuffers).isOk()) {
+            // This may trigger if the client has died.
+            LOG(DEBUG) << "InputBufferManager::processNotifications -- "
+                       << "failed to send death notifications to "
+                       << "listener @ 0x" << std::hex
+                                          << notification.listener.get()
+                       << std::dec << ".";
+        } else {
+#if LOG_NDEBUG == 0
+            std::stringstream inputBufferLog;
+            for (const IComponentListener::InputBuffer& inputBuffer :
+                    notification.inputBuffers) {
+                inputBufferLog << " (" << inputBuffer.frameIndex
+                               << ", " << inputBuffer.arrayIndex
+                               << ")";
+            }
+            LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+                         << "death notifications sent to "
+                         << "listener @ 0x" << std::hex
+                                            << notification.listener.get()
+                                            << std::dec
+                         << " with these (frameIndex, bufferIndex) pairs:"
+                         << inputBufferLog.str();
+#endif
+        }
+    }
+#if LOG_NDEBUG == 0
+    if (retry) {
+        LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+                     << "will retry again in " << *timeToRetryNs << "ns.";
+    } else {
+        LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+                     << "no pending death notifications.";
+    }
+#endif
+    return retry;
+}
+
+void InputBufferManager::main() {
+    LOG(VERBOSE) << "InputBufferManager main -- started.";
+    nsecs_t timeToRetryNs;
+    while (true) {
+        std::unique_lock<std::mutex> lock(mMutex);
+        while (mDeathNotifications.empty()) {
+            mOnBufferDestroyed.wait(lock);
+        }
+        lock.unlock();
+        while (processNotifications(&timeToRetryNs)) {
+            std::this_thread::sleep_for(
+                    std::chrono::nanoseconds(timeToRetryNs));
+        }
+    }
+}
+
+InputBufferManager::InputBufferManager()
+      : mMainThread{&InputBufferManager::main, this} {
+}
+
+InputBufferManager& InputBufferManager::getInstance() {
+    static InputBufferManager instance{};
+    return instance;
+}
+
+}  // namespace utils
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
diff --git a/media/codec2/hal/aidl/ParamTypes.cpp b/media/codec2/hal/aidl/ParamTypes.cpp
index 0a430f9..7026f4c 100644
--- a/media/codec2/hal/aidl/ParamTypes.cpp
+++ b/media/codec2/hal/aidl/ParamTypes.cpp
@@ -157,14 +157,13 @@
 namespace c2 {
 namespace utils {
 
+// TODO: read it from aconfig flags
+bool IsEnabled() { return false; }
+
 const char* asString(Status status, const char* def) {
     return asString(static_cast<c2_status_t>(status.status), def);
 }
 
-namespace /* unnamed */ {
-
-} // unnamed namespace
-
 // C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
 bool ToAidl(
         FieldSupportedValuesQuery* d,
diff --git a/media/codec2/hal/aidl/fuzzer.cpp b/media/codec2/hal/aidl/fuzzer.cpp
new file mode 100644
index 0000000..c1a2762
--- /dev/null
+++ b/media/codec2/hal/aidl/fuzzer.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include <C2PlatformSupport.h>
+
+#include <android/binder_interface_utils.h>
+#include <codec2/aidl/ComponentStore.h>
+
+using aidl::android::hardware::media::c2::utils::ComponentStore;
+using android::fuzzService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    std::shared_ptr<C2ComponentStore> store = ::android::GetCodec2PlatformComponentStore();
+    std::shared_ptr<ComponentStore> binder = SharedRefBase::make<ComponentStore>(store);
+
+    fuzzService(binder->asBinder().get(), FuzzedDataProvider(data, size));
+
+    return 0;
+}
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/Component.h b/media/codec2/hal/aidl/include/codec2/aidl/Component.h
new file mode 100644
index 0000000..d5ea92b
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/Component.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_AIDL_UTILS_COMPONENT_H
+#define CODEC2_AIDL_UTILS_COMPONENT_H
+
+#include <codec2/aidl/ComponentInterface.h>
+#include <codec2/aidl/Configurable.h>
+#include <codec2/aidl/BufferTypes.h>
+#include <codec2/aidl/ParamTypes.h>
+
+#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
+#include <aidl/android/hardware/media/c2/BnComponent.h>
+#include <aidl/android/hardware/media/c2/IComponentInterface.h>
+#include <aidl/android/hardware/media/c2/IComponentListener.h>
+#include <aidl/android/hardware/media/c2/IComponentStore.h>
+
+#include <C2Component.h>
+#include <C2Buffer.h>
+#include <C2.h>
+
+#include <map>
+#include <memory>
+#include <mutex>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+
+struct ComponentStore;
+
+struct Component : public BnComponent,
+                   public std::enable_shared_from_this<Component> {
+    Component(
+            const std::shared_ptr<C2Component>&,
+            const std::shared_ptr<IComponentListener>& listener,
+            const std::shared_ptr<ComponentStore>& store,
+            const std::shared_ptr<bufferpool2::IClientManager>& clientPoolManager);
+    c2_status_t status() const;
+
+    // Methods from IComponent follow.
+    ::ndk::ScopedAStatus queue(const WorkBundle& workBundle) override;
+    ::ndk::ScopedAStatus flush(WorkBundle *workBundle) override;
+    ::ndk::ScopedAStatus drain(bool withEos) override;
+    ::ndk::ScopedAStatus createBlockPool(
+            const IComponent::BlockPoolAllocator &allocator,
+            IComponent::BlockPool *blockPool) override;
+    ::ndk::ScopedAStatus destroyBlockPool(int64_t blockPoolId) override;
+    ::ndk::ScopedAStatus start() override;
+    ::ndk::ScopedAStatus stop() override;
+    ::ndk::ScopedAStatus reset() override;
+    ::ndk::ScopedAStatus release() override;
+    ::ndk::ScopedAStatus getInterface(
+            std::shared_ptr<IComponentInterface> *intf) override;
+    ::ndk::ScopedAStatus configureVideoTunnel(
+            int32_t avSyncHwId,
+            common::NativeHandle* handle) override;
+
+protected:
+    c2_status_t mInit;
+    std::shared_ptr<C2Component> mComponent;
+    std::shared_ptr<ComponentInterface> mInterface;
+    std::shared_ptr<IComponentListener> mListener;
+    std::shared_ptr<ComponentStore> mStore;
+    DefaultBufferPoolSender mBufferPoolSender;
+
+    std::mutex mBlockPoolsMutex;
+    // This map keeps C2BlockPool objects that are created by createBlockPool()
+    // alive. These C2BlockPool objects can be deleted by calling
+    // destroyBlockPool(), reset() or release(), or by destroying the component.
+    std::map<uint64_t, std::shared_ptr<C2BlockPool>> mBlockPools;
+
+    void initListener(const std::shared_ptr<Component>& self);
+
+    virtual ~Component() override;
+
+    friend struct ComponentStore;
+
+    struct Listener;
+
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+    static void OnBinderDied(void *cookie);
+    static void OnBinderUnlinked(void *cookie);
+    struct DeathContext;
+    DeathContext *mDeathContext;
+};
+
+}  // namespace utils
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
+#endif  // CODEC2_AIDL_UTILS_COMPONENT_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h
new file mode 100644
index 0000000..7723bee
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_AIDL_UTILS_COMPONENT_INTERFACE_H
+#define CODEC2_AIDL_UTILS_COMPONENT_INTERFACE_H
+
+#include <codec2/aidl/Configurable.h>
+#include <codec2/aidl/ParamTypes.h>
+
+#include <aidl/android/hardware/media/c2/BnComponentInterface.h>
+
+#include <C2Component.h>
+#include <C2Buffer.h>
+#include <C2.h>
+
+#include <memory>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+struct ComponentStore;
+
+struct ComponentInterface : public BnComponentInterface {
+    ComponentInterface(
+            const std::shared_ptr<C2ComponentInterface>& interface,
+            const std::shared_ptr<ParameterCache>& cache);
+    c2_status_t status() const;
+    ::ndk::ScopedAStatus getConfigurable(
+            std::shared_ptr<IConfigurable> *intf) override;
+
+protected:
+    std::shared_ptr<C2ComponentInterface> mInterface;
+    std::shared_ptr<CachedConfigurable> mConfigurable;
+    c2_status_t mInit;
+};
+
+
+}  // namespace utils
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
+#endif  // CODEC2_AIDL_UTILS_COMPONENT_INTERFACE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
new file mode 100644
index 0000000..7fc5d2f
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_AIDL_UTILS_COMPONENTSTORE_H
+#define CODEC2_AIDL_UTILS_COMPONENTSTORE_H
+
+#include <android/binder_auto_utils.h>
+#include <codec2/aidl/ComponentInterface.h>
+#include <codec2/aidl/Configurable.h>
+
+#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
+#include <aidl/android/hardware/media/c2/BnComponentStore.h>
+
+#include <C2Component.h>
+#include <C2Param.h>
+#include <C2.h>
+
+#include <chrono>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <vector>
+
+namespace android {
+class FilterWrapper;
+}  // namespace android
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+struct Component;
+
+using ::aidl::android::hardware::media::bufferpool2::IClientManager;
+
+struct ComponentStore : public BnComponentStore,
+                        public std::enable_shared_from_this<ComponentStore> {
+    ComponentStore(const std::shared_ptr<C2ComponentStore>& store);
+    virtual ~ComponentStore();
+
+    /**
+     * Returns the status of the construction of this object.
+     */
+    c2_status_t status() const;
+
+    /**
+     * This function is called by CachedConfigurable::init() to validate
+     * supported parameters.
+     */
+    c2_status_t validateSupportedParams(
+            const std::vector<std::shared_ptr<C2ParamDescriptor>>& params);
+
+    /**
+     * Returns the store's ParameterCache. This is used for validation by
+     * Configurable::init().
+     */
+    std::shared_ptr<ParameterCache> getParameterCache() const;
+
+    static std::shared_ptr<::android::FilterWrapper> GetFilterWrapper();
+
+    // Methods from ::aidl::android::hardware::media::c2::IComponentStore.
+    virtual ::ndk::ScopedAStatus createComponent(
+            const std::string& name,
+            const std::shared_ptr<IComponentListener>& listener,
+            const std::shared_ptr<IClientManager>& pool,
+            std::shared_ptr<IComponent> *component) override;
+    virtual ::ndk::ScopedAStatus createInterface(
+            const std::string& name,
+            std::shared_ptr<IComponentInterface> *intf) override;
+    virtual ::ndk::ScopedAStatus listComponents(
+            std::vector<IComponentStore::ComponentTraits>* traits) override;
+    virtual ::ndk::ScopedAStatus getStructDescriptors(
+            const std::vector<int32_t>& indices,
+            std::vector<StructDescriptor> *descs) override;
+    virtual ::ndk::ScopedAStatus getPoolClientManager(
+            std::shared_ptr<IClientManager> *manager) override;
+    virtual ::ndk::ScopedAStatus copyBuffer(
+            const Buffer& src,
+            const Buffer& dst) override;
+    virtual ::ndk::ScopedAStatus getConfigurable(
+            std::shared_ptr<IConfigurable> *configurable) override;
+
+    /**
+     * Dumps information when lshal is called.
+     */
+    virtual binder_status_t dump(
+            int fd, const char** args, uint32_t numArgs) override;
+
+protected:
+    std::shared_ptr<CachedConfigurable> mConfigurable;
+    struct StoreParameterCache;
+    std::shared_ptr<StoreParameterCache> mParameterCache;
+
+    // Does bookkeeping for an interface that has been loaded.
+    void onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf);
+
+    c2_status_t mInit;
+    std::shared_ptr<C2ComponentStore> mStore;
+    std::shared_ptr<C2ParamReflector> mParamReflector;
+
+    std::map<C2Param::CoreIndex, std::shared_ptr<C2StructDescriptor>> mStructDescriptors;
+    std::set<C2Param::CoreIndex> mUnsupportedStructDescriptors;
+    std::set<C2String> mLoadedInterfaces;
+    mutable std::mutex mStructDescriptorsMutex;
+
+    // ComponentStore keeps track of live Components.
+
+    struct ComponentStatus {
+        std::shared_ptr<C2Component> c2Component;
+        std::chrono::system_clock::time_point birthTime;
+    };
+
+    mutable std::mutex mComponentRosterMutex;
+    std::map<Component*, ComponentStatus> mComponentRoster;
+
+    // Called whenever Component is created.
+    void reportComponentBirth(Component* component);
+    // Called only from the destructor of Component.
+    void reportComponentDeath(Component* component);
+
+    friend Component;
+
+    // Helper functions for dumping.
+
+    std::ostream& dump(
+            std::ostream& out,
+            const std::shared_ptr<const C2Component::Traits>& comp);
+
+    std::ostream& dump(
+            std::ostream& out,
+            ComponentStatus& compStatus);
+
+};
+
+}  // namespace utils
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
+#endif  // CODEC2_AIDL_UTILS_COMPONENTSTORE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h b/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
new file mode 100644
index 0000000..6cc2c1b
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_AIDL_UTILS_CONFIGURABLE_H
+#define CODEC2_AIDL_UTILS_CONFIGURABLE_H
+
+#include <aidl/android/hardware/media/c2/BnConfigurable.h>
+
+#include <C2Component.h>
+#include <C2Param.h>
+#include <C2.h>
+
+#include <memory>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+struct ComponentStore;
+
+/**
+ * Codec2 objects of different types may have different querying and configuring
+ * functions, but across the Treble boundary, they share the same HIDL
+ * interface, IConfigurable.
+ *
+ * ConfigurableC2Intf is an abstract class that a Codec2 object can implement to
+ * easily expose an IConfigurable instance. See CachedConfigurable below.
+ */
+struct ConfigurableC2Intf {
+    C2String getName() const { return mName; }
+    uint32_t getId() const { return mId; }
+    /** C2ComponentInterface::query_vb sans stack params */
+    virtual c2_status_t query(
+            const std::vector<C2Param::Index> &indices,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2Param>>* const params) const = 0;
+    /** C2ComponentInterface::config_vb */
+    virtual c2_status_t config(
+            const std::vector<C2Param*> &params,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
+    /** C2ComponentInterface::querySupportedParams_nb */
+    virtual c2_status_t querySupportedParams(
+            std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const = 0;
+    /** C2ComponentInterface::querySupportedParams_nb */
+    virtual c2_status_t querySupportedValues(
+            std::vector<C2FieldSupportedValuesQuery>& fields, c2_blocking_t mayBlock) const = 0;
+
+    virtual ~ConfigurableC2Intf() = default;
+
+    ConfigurableC2Intf(const C2String& name, uint32_t id)
+          : mName{name}, mId{id} {}
+
+protected:
+    C2String mName; /* cached component name */
+    uint32_t mId;
+};
+
+/**
+ * Type for validating and caching parameters when CachedConfigurable is
+ * initialized.
+ *
+ * This is meant to be created by the ComponentStore. The purpose of abstracting
+ * this is to allow different versions of ComponentStore to work with this
+ * CachedConfigurable.
+ */
+struct ParameterCache {
+    virtual c2_status_t validate(
+            const std::vector<std::shared_ptr<C2ParamDescriptor>>&) = 0;
+    virtual ~ParameterCache() = default;
+};
+
+/**
+ * Implementation of the IConfigurable interface that supports caching of
+ * supported parameters from a supplied ComponentStore.
+ *
+ * CachedConfigurable essentially converts a ConfigurableC2Intf into HIDL's
+ * IConfigurable. A Codec2 object generally implements ConfigurableC2Intf and
+ * passes the implementation to the constructor of CachedConfigurable.
+ *
+ * Note that caching happens
+ */
+struct CachedConfigurable : public BnConfigurable {
+    CachedConfigurable(std::unique_ptr<ConfigurableC2Intf>&& intf);
+
+    // Populates mSupportedParams.
+    c2_status_t init(const std::shared_ptr<ParameterCache> &cache);
+
+    // Methods from ::android::hardware::media::c2::V1_0::IConfigurable
+
+    virtual ::ndk::ScopedAStatus getId(int32_t* id) override;
+
+    virtual ::ndk::ScopedAStatus getName(std::string* name) override;
+
+    virtual ::ndk::ScopedAStatus query(
+            const std::vector<int32_t>& indices,
+            bool mayBlock,
+            Params* params) override;
+
+    virtual ::ndk::ScopedAStatus config(
+            const ::aidl::android::hardware::media::c2::Params& params,
+            bool mayBlock,
+            ConfigResult* result) override;
+
+    virtual ::ndk::ScopedAStatus querySupportedParams(
+            int32_t start,
+            int32_t count,
+            std::vector<ParamDescriptor>* paramDesc) override;
+
+    virtual ::ndk::ScopedAStatus querySupportedValues(
+            const std::vector<FieldSupportedValuesQuery>& fields,
+            bool mayBlock,
+            std::vector<FieldSupportedValuesQueryResult>* result) override;
+
+protected:
+    // Common Codec2.0 interface wrapper
+    std::unique_ptr<ConfigurableC2Intf> mIntf;
+
+    // Cached supported params
+    std::vector<std::shared_ptr<C2ParamDescriptor>> mSupportedParams;
+};
+
+}  // namespace utils
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
+#endif  // CODEC2_AIDL_UTILS_CONFIGURABLE_H
+
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h b/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h
new file mode 100644
index 0000000..4e107a8
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_AIDL_UTILS_INPUT_BUFFER_MANAGER_H
+#define CODEC2_AIDL_UTILS_INPUT_BUFFER_MANAGER_H
+
+#include <aidl/android/hardware/media/c2/IComponentListener.h>
+#include <utils/Timers.h>
+
+#include <C2Buffer.h>
+#include <C2Work.h>
+
+#include <set>
+#include <map>
+#include <thread>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+/**
+ * InputBufferManager
+ * ==================
+ *
+ * InputBufferManager presents a way to track and untrack input buffers in this
+ * (codec) process and send a notification to a listener, possibly in a
+ * different process, when a tracked buffer no longer has any references in this
+ * process.
+ *
+ * InputBufferManager holds a collection of records representing tracked buffers
+ * and their callback listeners. Conceptually, one record is a triple (listener,
+ * frameIndex, bufferIndex) where
+ *
+ * - (frameIndex, bufferIndex) is a pair of indices used to identify the buffer.
+ * - listener is of type IComponentListener. Its onInputBuffersReleased()
+ *   function will be called after the associated buffer dies. The argument of
+ *   onInputBuffersReleased() is a list of InputBuffer objects, each of which
+ *   has the following members:
+ *
+ *     uint64_t frameIndex
+ *     uint32_t arrayIndex
+ *
+ * When a tracked buffer associated to the triple (listener, frameIndex,
+ * bufferIndex) goes out of scope, listener->onInputBuffersReleased() will be
+ * called with an InputBuffer object whose members are set as follows:
+ *
+ *     inputBuffer.frameIndex = frameIndex
+ *     inputBuffer.arrayIndex = bufferIndex
+ *
+ * IPC Optimization
+ * ----------------
+ *
+ * Since onInputBuffersReleased() is an IPC call, InputBufferManager tries not
+ * to call it too often. Any two calls to the same listener are at least
+ * mNotificationIntervalNs nanoseconds apart, where mNotificationIntervalNs is
+ * configurable via calling setNotificationInterval(). The default value of
+ * mNotificationIntervalNs is kDefaultNotificationInternalNs.
+ *
+ * Public Member Functions
+ * -----------------------
+ *
+ * InputBufferManager is a singleton class. Its only instance is accessible via
+ * the following public functions:
+ *
+ * - registerFrameData(const sp<IComponentListener>& listener,
+ *                     const C2FrameData& input)
+ *
+ * - unregisterFrameData(const sp<IComponentListener>& listener,
+ *                       const C2FrameData& input)
+ *
+ * - unregisterFrameData(const sp<IComponentListener>& listener)
+ *
+ * - setNotificationInterval(nsecs_t notificationIntervalNs)
+ *
+ */
+
+struct InputBufferManager {
+
+    /**
+     * The default value for the time interval between 2 subsequent IPCs.
+     */
+    static constexpr nsecs_t kDefaultNotificationIntervalNs = 1000000; /* 1ms */
+
+    /**
+     * Track all buffers in a C2FrameData object.
+     *
+     * input (C2FrameData) has the following two members that are of interest:
+     *
+     *   C2WorkOrdinal                ordinal
+     *   vector<shared_ptr<C2Buffer>> buffers
+     *
+     * Calling registerFrameData(listener, input) will register multiple
+     * triples (listener, frameIndex, bufferIndex) where frameIndex is equal to
+     * input.ordinal.frameIndex and bufferIndex runs through the indices of
+     * input.buffers such that input.buffers[bufferIndex] is not null.
+     *
+     * This should be called from queue().
+     *
+     * \param listener Listener of death notifications.
+     * \param input Input frame data whose input buffers are to be tracked.
+     */
+    static void registerFrameData(
+            const std::shared_ptr<IComponentListener>& listener,
+            const C2FrameData& input);
+
+    /**
+     * Untrack all buffers in a C2FrameData object.
+     *
+     * Calling unregisterFrameData(listener, input) will unregister and remove
+     * pending notifications for all triples (l, fi, bufferIndex) such that
+     * l = listener and fi = input.ordinal.frameIndex.
+     *
+     * This should be called from onWorkDone() and flush().
+     *
+     * \param listener Previously registered listener.
+     * \param input Previously registered frame data.
+     */
+    static void unregisterFrameData(
+            const std::weak_ptr<IComponentListener>& listener,
+            const C2FrameData& input);
+
+    /**
+     * Untrack all buffers associated to a given listener.
+     *
+     * Calling unregisterFrameData(listener) will unregister and remove
+     * pending notifications for all triples (l, frameIndex, bufferIndex) such
+     * that l = listener.
+     *
+     * This should be called when the component cleans up all input buffers,
+     * i.e., when reset(), release(), stop() or ~Component() is called.
+     *
+     * \param listener Previously registered listener.
+     */
+    static void unregisterFrameData(
+            const std::weak_ptr<IComponentListener>& listener);
+
+    /**
+     * Set the notification interval.
+     *
+     * \param notificationIntervalNs New notification interval, in nanoseconds.
+     */
+    static void setNotificationInterval(nsecs_t notificationIntervalNs);
+
+private:
+    void _registerFrameData(
+            const std::shared_ptr<IComponentListener>& listener,
+            const C2FrameData& input);
+    void _unregisterFrameData(
+            const std::weak_ptr<IComponentListener>& listener,
+            const C2FrameData& input);
+    void _unregisterFrameData(
+            const std::weak_ptr<IComponentListener>& listener);
+    void _setNotificationInterval(nsecs_t notificationIntervalNs);
+
+    // The callback function tied to C2Buffer objects.
+    //
+    // Note: This function assumes that sInstance is the only instance of this
+    //       class.
+    static void onBufferDestroyed(const C2Buffer* buf, void* arg);
+    void _onBufferDestroyed(const C2Buffer* buf, void* arg);
+
+    // Persistent data to be passed as "arg" in onBufferDestroyed().
+    // This is essentially the triple (listener, frameIndex, bufferIndex) plus a
+    // weak pointer to the C2Buffer object.
+    //
+    // Note that the "key" is bufferIndex according to operator<(). This is
+    // designed to work with TrackedBuffersMap defined below.
+    struct TrackedBuffer {
+        std::weak_ptr<IComponentListener> listener;
+        uint64_t frameIndex;
+        size_t bufferIndex;
+        std::weak_ptr<C2Buffer> buffer;
+        TrackedBuffer(const std::weak_ptr<IComponentListener>& listener,
+                      uint64_t frameIndex,
+                      size_t bufferIndex,
+                      const std::shared_ptr<C2Buffer>& buffer)
+              : listener(listener),
+                frameIndex(frameIndex),
+                bufferIndex(bufferIndex),
+                buffer(buffer) {}
+    };
+
+    // Map: listener -> frameIndex -> set<TrackedBuffer*>.
+    // Essentially, this is used to store triples (listener, frameIndex,
+    // bufferIndex) that's searchable by listener and (listener, frameIndex).
+    // However, the value of the innermost map is TrackedBuffer, which also
+    // contains an extra copy of listener and frameIndex. This is needed
+    // because onBufferDestroyed() needs to know listener and frameIndex too.
+    typedef std::map<std::weak_ptr<IComponentListener>,
+                     std::map<uint64_t,
+                              std::set<TrackedBuffer*>>,
+                     std::owner_less<std::weak_ptr<IComponentListener>>> TrackedBuffersMap;
+
+    // Storage for pending (unsent) death notifications for one listener.
+    // Each pair in member named "indices" are (frameIndex, bufferIndex) from
+    // the (listener, frameIndex, bufferIndex) triple.
+    struct DeathNotifications {
+
+        // The number of pending notifications for this listener.
+        // count may be 0, in which case the DeathNotifications object will
+        // remain valid for only a small period (specified
+        // nanoseconds).
+        size_t count;
+
+        // The timestamp of the most recent callback on this listener. This is
+        // used to guarantee that callbacks do not occur too frequently, and
+        // also to trigger expiration of a DeathNotifications object that has
+        // count = 0.
+        nsecs_t lastSentNs;
+
+        // Map: frameIndex -> vector of bufferIndices
+        // This is essentially a collection of (framdeIndex, bufferIndex).
+        std::map<uint64_t, std::vector<size_t>> indices;
+
+        DeathNotifications(
+                nsecs_t notificationIntervalNs = kDefaultNotificationIntervalNs)
+              : count(0),
+                lastSentNs(systemTime() - notificationIntervalNs),
+                indices() {}
+    };
+
+    // The minimum time period between IPC calls to notify the client about the
+    // destruction of input buffers.
+    std::atomic<nsecs_t> mNotificationIntervalNs{kDefaultNotificationIntervalNs};
+
+    // Mutex for the management of all input buffers.
+    std::mutex mMutex;
+
+    // Cache for all TrackedBuffers.
+    //
+    // Whenever registerOnDestroyNotify() is called, an argument of type
+    // TrackedBuffer is created and stored into this cache.
+    // Whenever unregisterOnDestroyNotify() or onBufferDestroyed() is called,
+    // the TrackedBuffer is removed from this cache.
+    //
+    // mTrackedBuffersMap stores references to TrackedBuffers inside this cache.
+    std::set<TrackedBuffer*> mTrackedBufferCache;
+
+    // Tracked input buffers.
+    TrackedBuffersMap mTrackedBuffersMap;
+
+    // Death notifications to be sent.
+    //
+    // A DeathNotifications object is associated to each listener. An entry in
+    // this map will be removed if its associated DeathNotifications has count =
+    // 0 and lastSentNs < systemTime() - mNotificationIntervalNs.
+    std::map<std::weak_ptr<IComponentListener>,
+             DeathNotifications,
+             std::owner_less<std::weak_ptr<IComponentListener>>> mDeathNotifications;
+
+    // Condition variable signaled when an entry is added to mDeathNotifications.
+    std::condition_variable mOnBufferDestroyed;
+
+    // Notify the clients about buffer destructions.
+    // Return false if all destructions have been notified.
+    // Return true and set timeToRetry to the duration to wait for before
+    // retrying if some destructions have not been notified.
+    bool processNotifications(nsecs_t* timeToRetryNs);
+
+    // Main function for the input buffer manager thread.
+    void main();
+
+    // The thread that manages notifications.
+    //
+    // Note: This variable is declared last so its initialization will happen
+    // after all other member variables have been initialized.
+    std::thread mMainThread;
+
+    // Private constructor.
+    InputBufferManager();
+
+    // The only instance of this class.
+    static InputBufferManager& getInstance();
+
+};
+
+}  // namespace utils
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
+#endif  // CODEC2_AIDL_UTILS_INPUT_BUFFER_MANAGER_H
+
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h b/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h
index ff69039..3f82ee3 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h
@@ -37,11 +37,14 @@
 namespace c2 {
 namespace utils {
 
+// Returns true iff AIDL c2 HAL is enabled
+bool IsEnabled();
+
 // Make asString() and operator<< work with Status as well as c2_status_t.
 C2_DECLARE_AS_STRING_AND_DEFINE_STREAM_OUT(Status);
 
 /**
- * All objcpy() functions will return a boolean value indicating whether the
+ * All To/FromAidl() functions will return a boolean value indicating whether the
  * conversion succeeds or not.
  */
 
diff --git a/media/codec2/hal/client/Android.bp b/media/codec2/hal/client/Android.bp
index 61ec10e..0b5b940 100644
--- a/media/codec2/hal/client/Android.bp
+++ b/media/codec2/hal/client/Android.bp
@@ -23,6 +23,7 @@
     name: "libcodec2_client",
 
     srcs: [
+        "GraphicBufferAllocator.cpp",
         "GraphicsTracker.cpp",
         "client.cpp",
         "output.cpp",
@@ -42,6 +43,7 @@
         "android.hardware.media.c2@1.0",
         "android.hardware.media.c2@1.1",
         "android.hardware.media.c2@1.2",
+        "android.hardware.media.bufferpool2-V1-ndk",
         "android.hardware.media.c2-V1-ndk",
         "libbase",
         "libbinder",
@@ -56,11 +58,16 @@
         "libhidlbase",
         "liblog",
         "libnativewindow",
+        "libstagefright_aidl_bufferpool2",
         "libstagefright_bufferpool@2.0.1",
         "libui",
         "libutils",
     ],
 
+    static_libs: [
+        "libaidlcommonsupport",
+    ],
+
     export_include_dirs: [
         "include",
     ],
diff --git a/media/codec2/hal/client/GraphicBufferAllocator.cpp b/media/codec2/hal/client/GraphicBufferAllocator.cpp
new file mode 100644
index 0000000..bbef1b5
--- /dev/null
+++ b/media/codec2/hal/client/GraphicBufferAllocator.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/IProducerListener.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+#include <codec2/aidl/GraphicBufferAllocator.h>
+#include <codec2/aidl/GraphicsTracker.h>
+
+namespace aidl::android::hardware::media::c2::implementation {
+
+class OnBufferReleasedListener : public ::android::BnProducerListener {
+private:
+    uint32_t mGeneration;
+    std::weak_ptr<GraphicBufferAllocator> mAllocator;
+public:
+    OnBufferReleasedListener(
+            uint32_t generation,
+            const std::shared_ptr<GraphicBufferAllocator> &allocator)
+            : mGeneration(generation), mAllocator(allocator) {}
+    virtual ~OnBufferReleasedListener() = default;
+    virtual void onBufferReleased() {
+        auto p = mAllocator.lock();
+        if (p) {
+            p->onBufferReleased(mGeneration);
+        }
+    }
+    virtual bool needsReleaseNotify() { return true; }
+};
+
+::ndk::ScopedAStatus GraphicBufferAllocator::allocate(
+        const IGraphicBufferAllocator::Description& in_desc,
+        IGraphicBufferAllocator::Allocation* _aidl_return) {
+    AHardwareBuffer *buf;
+    ::android::sp<::android::Fence> fence;
+    c2_status_t ret = allocate(
+            in_desc.width, in_desc.height, in_desc.format, in_desc.usage,
+            &buf, &fence);
+    if (ret == C2_OK) {
+        _aidl_return->buffer.reset(buf);
+        _aidl_return->fence = ::ndk::ScopedFileDescriptor(fence->dup());
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return ::ndk::ScopedAStatus::fromServiceSpecificError(ret);
+}
+
+::ndk::ScopedAStatus GraphicBufferAllocator::deallocate(int64_t in_id, bool* _aidl_return) {
+    *_aidl_return = deallocate(in_id, ::android::Fence::NO_FENCE);
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus GraphicBufferAllocator::getWaitableFds(
+        IGraphicBufferAllocator::WaitableFds* _aidl_return) {
+    int allocFd;
+    int statusFd;
+    c2_status_t ret = mGraphicsTracker->getWaitableFds(&allocFd, &statusFd);
+    if (ret == C2_OK) {
+        _aidl_return->allocEvent.set(allocFd);
+        _aidl_return->statusEvent.set(statusFd);
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return ::ndk::ScopedAStatus::fromServiceSpecificError(ret);
+}
+
+bool GraphicBufferAllocator::configure(
+        const ::android::sp<IGraphicBufferProducer>& igbp,
+        uint32_t generation,
+        int maxDequeueBufferCount) {
+    c2_status_t ret = C2_OK;
+
+    ret = mGraphicsTracker->configureGraphics(igbp, generation);
+    if (ret != C2_OK) {
+        ALOGE("configuring igbp failed gen #(%d), configuring max dequeue count didn't happen",
+              (unsigned int)generation);
+        return false;
+    }
+
+    ret = mGraphicsTracker->configureMaxDequeueCount(maxDequeueBufferCount);
+    if (ret != C2_OK) {
+        ALOGE("configuring max dequeue count to %d failed", maxDequeueBufferCount);
+        return false;
+    }
+    return true;
+}
+
+void GraphicBufferAllocator::updateMaxDequeueBufferCount(int count) {
+    c2_status_t ret = mGraphicsTracker->configureMaxDequeueCount(count);
+    if (ret != C2_OK) {
+        ALOGE("updating max dequeue buffer count failed %d", ret);
+    }
+}
+
+void GraphicBufferAllocator::reset() {
+    mGraphicsTracker->stop();
+}
+
+const ::android::sp<::android::IProducerListener> GraphicBufferAllocator::createReleaseListener(
+      uint32_t generation) {
+    return new OnBufferReleasedListener(generation, ref<GraphicBufferAllocator>());
+}
+
+void GraphicBufferAllocator::onBufferReleased(uint32_t generation) {
+    mGraphicsTracker->onReleased(generation);
+}
+
+c2_status_t GraphicBufferAllocator::allocate(
+        uint32_t width, uint32_t height, ::android::PixelFormat format, uint64_t usage,
+        AHardwareBuffer **buf, ::android::sp<::android::Fence> *fence) {
+    return mGraphicsTracker->allocate(width, height, format, usage, buf, fence);
+}
+
+bool GraphicBufferAllocator::deallocate(const uint64_t id,
+                                        const ::android::sp<::android::Fence> &fence) {
+    c2_status_t ret = mGraphicsTracker->deallocate(id, fence);
+    if (ret != C2_OK) {
+        ALOGW("deallocate() %llu was not successful %d", (unsigned long long)id, ret);
+        return false;
+    }
+    return true;
+}
+
+c2_status_t GraphicBufferAllocator::displayBuffer(
+        const C2ConstGraphicBlock& block,
+        const IGraphicBufferProducer::QueueBufferInput& input,
+        IGraphicBufferProducer::QueueBufferOutput *output) {
+    return mGraphicsTracker->render(block, input, output);
+}
+
+GraphicBufferAllocator::~GraphicBufferAllocator() {}
+
+std::shared_ptr<GraphicBufferAllocator> GraphicBufferAllocator::CreateGraphicBufferAllocator(
+        int maxDequeueCount) {
+    return ::ndk::SharedRefBase::make<GraphicBufferAllocator>(maxDequeueCount);
+}
+
+GraphicBufferAllocator::GraphicBufferAllocator(int maxDequeueCount)
+        : mGraphicsTracker(GraphicsTracker::CreateGraphicsTracker(maxDequeueCount)) {}
+
+} // namespace aidl::android::hardware::media::c2::implementation
diff --git a/media/codec2/hal/client/client.cpp b/media/codec2/hal/client/client.cpp
index 00820eb..accb9fd 100644
--- a/media/codec2/hal/client/client.cpp
+++ b/media/codec2/hal/client/client.cpp
@@ -24,7 +24,6 @@
 #include <C2Config.h> // for C2StreamUsageTuning
 #include <C2PlatformSupport.h>
 
-#include <android/binder_auto_utils.h>
 #include <android/hardware/media/bufferpool/2.0/IClientManager.h>
 #include <android/hardware/media/c2/1.0/IComponent.h>
 #include <android/hardware/media/c2/1.0/IComponentInterface.h>
@@ -33,6 +32,8 @@
 #include <android/hardware/media/c2/1.0/IConfigurable.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
 
+#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
+#include <aidl/android/hardware/media/c2/BnComponentListener.h>
 #include <aidl/android/hardware/media/c2/FieldSupportedValues.h>
 #include <aidl/android/hardware/media/c2/FieldSupportedValuesQuery.h>
 #include <aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.h>
@@ -41,9 +42,17 @@
 #include <aidl/android/hardware/media/c2/IComponentStore.h>
 #include <aidl/android/hardware/media/c2/IConfigurable.h>
 #include <aidl/android/hardware/media/c2/ParamDescriptor.h>
+#include <aidl/android/hardware/media/c2/StructDescriptor.h>
 
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
 #include <android-base/properties.h>
+#include <android-base/stringprintf.h>
 #include <bufferpool/ClientManager.h>
+#include <bufferpool2/ClientManager.h>
+#include <codec2/aidl/BufferTypes.h>
 #include <codec2/aidl/ParamTypes.h>
 #include <codec2/hidl/1.0/types.h>
 #include <codec2/hidl/1.1/types.h>
@@ -85,6 +94,7 @@
         V2_0::utils::H2BGraphicBufferProducer;
 using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
 
+namespace bufferpool2_aidl = ::aidl::android::hardware::media::bufferpool2;
 namespace bufferpool_hidl = ::android::hardware::media::bufferpool::V2_0;
 namespace c2_aidl = ::aidl::android::hardware::media::c2;
 namespace c2_hidl_base = ::android::hardware::media::c2;
@@ -178,6 +188,20 @@
     }
 };
 
+c2_status_t GetC2Status(const ::ndk::ScopedAStatus &transStatus, const char *method) {
+    if (!transStatus.isOk()) {
+        if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+            c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
+            LOG(DEBUG) << method << " -- call failed: " << status << ".";
+            return status;
+        } else {
+            LOG(ERROR) << method << " -- transaction failed.";
+            return C2_TRANSACTION_FAILED;
+        }
+    }
+    return C2_OK;
+}
+
 }  // unnamed namespace
 
 // This class caches a Codec2Client object and its component traits. The client
@@ -605,18 +629,11 @@
     }
     c2_aidl::Params result;
     ndk::ScopedAStatus transStatus = mBase->query(indices, (mayBlock == C2_MAY_BLOCK), &result);
-    if (!transStatus.isOk()) {
-        if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
-            c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
-            LOG(DEBUG) << "query -- call failed: " << status << ".";
-            return status;
-        } else {
-            LOG(ERROR) << "query -- transaction failed.";
-            return C2_TRANSACTION_FAILED;
-        }
+    c2_status_t status = GetC2Status(transStatus, "query");
+    if (status != C2_OK) {
+        return status;
     }
 
-    c2_status_t status = C2_OK;
     std::vector<C2Param*> paramPointers;
     if (!c2_aidl::utils::ParseParamsBlob(&paramPointers, result)) {
         LOG(ERROR) << "query -- error while parsing params.";
@@ -685,17 +702,10 @@
     }
     c2_aidl::IConfigurable::ConfigResult result;
     ndk::ScopedAStatus transStatus = mBase->config(aidlParams, (mayBlock == C2_MAY_BLOCK), &result);
-    if (!transStatus.isOk()) {
-        if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
-            c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
-            LOG(DEBUG) << "config -- call failed: " << status << ".";
-            return status;
-        } else {
-            LOG(ERROR) << "config -- transaction failed.";
-            return C2_TRANSACTION_FAILED;
-        }
+    c2_status_t status = GetC2Status(transStatus, "config");
+    if (status != C2_OK) {
+        return status;
     }
-    c2_status_t status = C2_OK;
     size_t i = failures->size();
     failures->resize(i + result.failures.size());
     for (const c2_aidl::SettingResult& sf : result.failures) {
@@ -720,17 +730,10 @@
             std::numeric_limits<uint32_t>::min(),
             std::numeric_limits<uint32_t>::max(),
             &result);
-    if (!transStatus.isOk()) {
-        if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
-            c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
-            LOG(DEBUG) << "querySupportedParams -- call failed: " << status << ".";
-            return status;
-        } else {
-            LOG(ERROR) << "querySupportedParams -- transaction failed.";
-            return C2_TRANSACTION_FAILED;
-        }
+    c2_status_t status = GetC2Status(transStatus, "querySupportedParams");
+    if (status != C2_OK) {
+        return status;
     }
-    c2_status_t status = C2_OK;
     size_t i = params->size();
     params->resize(i + result.size());
     for (const c2_aidl::ParamDescriptor& sp : result) {
@@ -756,17 +759,10 @@
     std::vector<c2_aidl::FieldSupportedValuesQueryResult> result;
     ndk::ScopedAStatus transStatus = mBase->querySupportedValues(
             inFields, (mayBlock == C2_MAY_BLOCK), &result);
-    if (!transStatus.isOk()) {
-        if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
-            c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
-            LOG(DEBUG) << "querySupportedValues -- call failed: " << status << ".";
-            return status;
-        } else {
-            LOG(ERROR) << "querySupportedValues -- transaction failed.";
-            return C2_TRANSACTION_FAILED;
-        }
+    c2_status_t status = GetC2Status(transStatus, "querySupportedValues");
+    if (status != C2_OK) {
+        return status;
     }
-    c2_status_t status = C2_OK;
     if (result.size() != fields.size()) {
         LOG(ERROR) << "querySupportedValues -- "
                       "input and output lists "
@@ -922,14 +918,119 @@
 
 };
 
-// Codec2Client::Component::BufferPoolSender
-struct Codec2Client::Component::BufferPoolSender :
+// Codec2Client::Component::AidlListener
+struct Codec2Client::Component::AidlListener : public c2_aidl::BnComponentListener {
+    std::weak_ptr<Component> component;
+    std::weak_ptr<Listener> base;
+
+    virtual ::ndk::ScopedAStatus onWorkDone(const c2_aidl::WorkBundle& workBundle) override {
+        std::list<std::unique_ptr<C2Work>> workItems;
+        if (!c2_aidl::utils::FromAidl(&workItems, workBundle)) {
+            LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
+            return ::ndk::ScopedAStatus::ok();
+        }
+        // release input buffers potentially held by the component from queue
+        std::shared_ptr<Codec2Client::Component> strongComponent =
+                component.lock();
+        if (strongComponent) {
+            strongComponent->handleOnWorkDone(workItems);
+        }
+        if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
+            listener->onWorkDone(component, workItems);
+        } else {
+            LOG(DEBUG) << "onWorkDone -- listener died.";
+        }
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    virtual ::ndk::ScopedAStatus onTripped(
+            const std::vector<c2_aidl::SettingResult>& settingResults) override {
+        std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
+                settingResults.size());
+        for (size_t i = 0; i < settingResults.size(); ++i) {
+            std::unique_ptr<C2SettingResult> c2SettingResult;
+            if (!c2_aidl::utils::FromAidl(&c2SettingResult, settingResults[i])) {
+                LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
+                return ::ndk::ScopedAStatus::ok();
+            }
+            c2SettingResults[i] = std::move(c2SettingResult);
+        }
+        if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
+            listener->onTripped(component, c2SettingResults);
+        } else {
+            LOG(DEBUG) << "onTripped -- listener died.";
+        }
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    virtual ::ndk::ScopedAStatus onError(const c2_aidl::Status &s, int32_t errorCode) override {
+        LOG(DEBUG) << "onError --"
+                   << " status = " << s.status
+                   << ", errorCode = " << errorCode
+                   << ".";
+        if (std::shared_ptr<Listener> listener = base.lock()) {
+            listener->onError(component, s.status == c2_aidl::Status::OK ?
+                    errorCode : static_cast<c2_status_t>(s.status));
+        } else {
+            LOG(DEBUG) << "onError -- listener died.";
+        }
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    virtual ::ndk::ScopedAStatus onFramesRendered(
+            const std::vector<RenderedFrame>& renderedFrames) override {
+        std::shared_ptr<Listener> listener = base.lock();
+        if (!listener) {
+            LOG(DEBUG) << "onFramesRendered -- listener died.";
+            return ::ndk::ScopedAStatus::ok();
+        }
+        for (const RenderedFrame& renderedFrame : renderedFrames) {
+            listener->onFrameRendered(
+                    renderedFrame.bufferQueueId,
+                    renderedFrame.slotId,
+                    renderedFrame.timestampNs);
+        }
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    virtual ::ndk::ScopedAStatus onInputBuffersReleased(
+            const std::vector<InputBuffer>& inputBuffers) override {
+        std::shared_ptr<Listener> listener = base.lock();
+        if (!listener) {
+            LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
+            return ::ndk::ScopedAStatus::ok();
+        }
+        for (const InputBuffer& inputBuffer : inputBuffers) {
+            LOG(VERBOSE) << "onInputBuffersReleased --"
+                            " received death notification of"
+                            " input buffer:"
+                            " frameIndex = " << inputBuffer.frameIndex
+                         << ", bufferIndex = " << inputBuffer.arrayIndex
+                         << ".";
+            listener->onInputBufferDone(
+                    inputBuffer.frameIndex, inputBuffer.arrayIndex);
+        }
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+};
+
+// Codec2Client::Component::HidlBufferPoolSender
+struct Codec2Client::Component::HidlBufferPoolSender :
         hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
-    BufferPoolSender()
+    HidlBufferPoolSender()
           : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
     }
 };
 
+// Codec2Client::Component::AidlBufferPoolSender
+struct Codec2Client::Component::AidlBufferPoolSender :
+        c2_aidl::utils::DefaultBufferPoolSender {
+    AidlBufferPoolSender()
+          : c2_aidl::utils::DefaultBufferPoolSender() {
+    }
+};
+
 // Codec2Client::Component::OutputBufferQueue
 struct Codec2Client::Component::OutputBufferQueue :
         hardware::media::c2::OutputBufferQueue {
@@ -939,36 +1040,53 @@
 };
 
 // Codec2Client
-Codec2Client::Codec2Client(sp<Base> const& base,
+Codec2Client::Codec2Client(sp<HidlBase> const& base,
                            sp<c2_hidl::IConfigurable> const& configurable,
                            size_t serviceIndex)
       : Configurable{configurable},
-        mBase1_0{base},
-        mBase1_1{Base1_1::castFrom(base)},
-        mBase1_2{Base1_2::castFrom(base)},
+        mHidlBase1_0{base},
+        mHidlBase1_1{HidlBase1_1::castFrom(base)},
+        mHidlBase1_2{HidlBase1_2::castFrom(base)},
         mServiceIndex{serviceIndex} {
     Return<sp<bufferpool_hidl::IClientManager>> transResult = base->getPoolClientManager();
     if (!transResult.isOk()) {
         LOG(ERROR) << "getPoolClientManager -- transaction failed.";
     } else {
-        mHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
+        mHidlHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
     }
 }
 
-sp<Codec2Client::Base> const& Codec2Client::getBase() const {
-    return mBase1_0;
+Codec2Client::Codec2Client(std::shared_ptr<AidlBase> const& base,
+                           std::shared_ptr<c2_aidl::IConfigurable> const& configurable,
+                           size_t serviceIndex)
+      : Configurable{configurable},
+        mAidlBase{base},
+        mServiceIndex{serviceIndex} {
+    ::ndk::ScopedAStatus transStatus = base->getPoolClientManager(&mAidlHostPoolManager);
+    if (!transStatus.isOk()) {
+        LOG(ERROR) << "getPoolClientManager -- transaction failed.";
+        mAidlHostPoolManager.reset();
+    }
 }
 
-sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
-    return mBase1_0;
+sp<Codec2Client::HidlBase> const& Codec2Client::getHidlBase() const {
+    return mHidlBase1_0;
 }
 
-sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
-    return mBase1_1;
+sp<Codec2Client::HidlBase1_0> const& Codec2Client::getHidlBase1_0() const {
+    return mHidlBase1_0;
 }
 
-sp<Codec2Client::Base1_2> const& Codec2Client::getBase1_2() const {
-    return mBase1_2;
+sp<Codec2Client::HidlBase1_1> const& Codec2Client::getHidlBase1_1() const {
+    return mHidlBase1_1;
+}
+
+sp<Codec2Client::HidlBase1_2> const& Codec2Client::getHidlBase1_2() const {
+    return mHidlBase1_2;
+}
+
+::ndk::SpAIBinder Codec2Client::getAidlBase() const {
+    return mAidlBase ? mAidlBase->asBinder() : nullptr;
 }
 
 std::string const& Codec2Client::getServiceName() const {
@@ -979,13 +1097,41 @@
         const C2String& name,
         const std::shared_ptr<Codec2Client::Listener>& listener,
         std::shared_ptr<Codec2Client::Component>* const component) {
+    if (mAidlBase) {
+        std::shared_ptr<Component::AidlListener> aidlListener =
+                Component::AidlListener::make<Component::AidlListener>();
+        aidlListener->base = listener;
+        std::shared_ptr<c2_aidl::IComponent> aidlComponent;
+        ::ndk::ScopedAStatus transStatus = mAidlBase->createComponent(
+                name,
+                aidlListener,
+                bufferpool2_aidl::implementation::ClientManager::getInstance(),
+                &aidlComponent);
+        c2_status_t status = GetC2Status(transStatus, "createComponent");
+        if (status != C2_OK) {
+            return status;
+        } else if (!aidlComponent) {
+            LOG(ERROR) << "createComponent(" << name.c_str()
+                       << ") -- null component.";
+            return C2_CORRUPTED;
+        }
+        *component = std::make_shared<Codec2Client::Component>(aidlComponent);
+        status = (*component)->setDeathListener((*component), listener);
+        if (status != C2_OK) {
+            LOG(ERROR) << "createComponent(" << name.c_str()
+                       << ") -- failed to set up death listener: "
+                       << status << ".";
+        }
+        (*component)->mAidlBufferPoolSender->setReceiver(mAidlHostPoolManager);
+        return status;
+    }
 
     c2_status_t status;
     sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
     hidlListener->base = listener;
     Return<void> transStatus;
-    if (mBase1_2) {
-        transStatus = mBase1_2->createComponent_1_2(
+    if (mHidlBase1_2) {
+        transStatus = mHidlBase1_2->createComponent_1_2(
             name,
             hidlListener,
             bufferpool_hidl::implementation::ClientManager::getInstance(),
@@ -1000,8 +1146,8 @@
                 hidlListener->component = *component;
             });
     }
-    else if (mBase1_1) {
-        transStatus = mBase1_1->createComponent_1_1(
+    else if (mHidlBase1_1) {
+        transStatus = mHidlBase1_1->createComponent_1_1(
             name,
             hidlListener,
             bufferpool_hidl::implementation::ClientManager::getInstance(),
@@ -1015,8 +1161,8 @@
                 *component = std::make_shared<Codec2Client::Component>(c);
                 hidlListener->component = *component;
             });
-    } else if (mBase1_0) { // ver1_0
-        transStatus = mBase1_0->createComponent(
+    } else if (mHidlBase1_0) { // ver1_0
+        transStatus = mHidlBase1_0->createComponent(
             name,
             hidlListener,
             bufferpool_hidl::implementation::ClientManager::getInstance(),
@@ -1059,15 +1205,32 @@
                    << status << ".";
     }
 
-    (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
+    (*component)->mHidlBufferPoolSender->setReceiver(mHidlHostPoolManager);
     return status;
 }
 
 c2_status_t Codec2Client::createInterface(
         const C2String& name,
         std::shared_ptr<Codec2Client::Interface>* const interface) {
+    if (mAidlBase) {
+        std::shared_ptr<c2_aidl::IComponentInterface> aidlInterface;
+        ::ndk::ScopedAStatus transStatus = mAidlBase->createInterface(
+                name,
+                &aidlInterface);
+        c2_status_t status = GetC2Status(transStatus, "createInterface");
+        if (status != C2_OK) {
+            return status;
+        } else if (!aidlInterface) {
+            LOG(ERROR) << "createInterface(" << name.c_str()
+                       << ") -- null interface.";
+            return C2_CORRUPTED;
+        }
+        interface->reset(new Codec2Client::Interface(aidlInterface));
+        return C2_OK;
+    }
+
     c2_status_t status;
-    Return<void> transStatus = mBase1_0->createInterface(
+    Return<void> transStatus = mHidlBase1_0->createInterface(
             name,
             [&status, interface](
                     c2_hidl::Status s,
@@ -1098,8 +1261,13 @@
 
 c2_status_t Codec2Client::createInputSurface(
         std::shared_ptr<InputSurface>* const inputSurface) {
+    if (mAidlBase) {
+        // FIXME
+        return C2_OMITTED;
+    }
+
     c2_status_t status;
-    Return<void> transStatus = mBase1_0->createInputSurface(
+    Return<void> transStatus = mHidlBase1_0->createInputSurface(
             [&status, inputSurface](
                     c2_hidl::Status s,
                     const sp<c2_hidl::IInputSurface>& i) {
@@ -1127,7 +1295,29 @@
         bool* success) const {
     std::vector<C2Component::Traits> traits;
     std::string const& serviceName = getServiceName();
-    Return<void> transStatus = mBase1_0->listComponents(
+
+    if (mAidlBase) {
+        std::vector<c2_aidl::IComponentStore::ComponentTraits> aidlTraits;
+        ::ndk::ScopedAStatus transStatus = mAidlBase->listComponents(&aidlTraits);
+        if (!transStatus.isOk()) {
+            LOG(ERROR) << "_listComponents -- transaction failed.";
+            *success = false;
+        } else {
+            traits.resize(aidlTraits.size());
+            *success = true;
+            for (size_t i = 0; i < aidlTraits.size(); ++i) {
+                if (!c2_aidl::utils::FromAidl(&traits[i], aidlTraits[i])) {
+                    LOG(ERROR) << "_listComponents -- corrupted output.";
+                    *success = false;
+                    traits.clear();
+                    break;
+                }
+                traits[i].owner = serviceName;
+            }
+        }
+        return traits;
+    }
+    Return<void> transStatus = mHidlBase1_0->listComponents(
             [&traits, &serviceName](c2_hidl::Status s,
                    const hidl_vec<c2_hidl::IComponentStore::ComponentTraits>& t) {
                 if (s != c2_hidl::Status::OK) {
@@ -1163,12 +1353,12 @@
     return C2_OMITTED;
 }
 
-std::shared_ptr<C2ParamReflector>
-        Codec2Client::getParamReflector() {
+std::shared_ptr<C2ParamReflector> Codec2Client::getParamReflector() {
     // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
     // should reflect the HAL API.
-    struct SimpleParamReflector : public C2ParamReflector {
-        virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
+    struct HidlSimpleParamReflector : public C2ParamReflector {
+        std::unique_ptr<C2StructDescriptor> describe(
+                C2Param::CoreIndex coreIndex) const override {
             hidl_vec<c2_hidl::ParamIndex> indices(1);
             indices[0] = static_cast<c2_hidl::ParamIndex>(coreIndex.coreIndex());
             std::unique_ptr<C2StructDescriptor> descriptor;
@@ -1210,80 +1400,112 @@
             return descriptor;
         }
 
-        SimpleParamReflector(sp<Base> base)
+        HidlSimpleParamReflector(sp<HidlBase> base)
             : mBase(base) { }
 
-        sp<Base> mBase;
+        sp<HidlBase> mBase;
+    };
+    struct AidlSimpleParamReflector : public C2ParamReflector {
+        std::unique_ptr<C2StructDescriptor> describe(
+                C2Param::CoreIndex coreIndex) const override {
+            std::vector<c2_aidl::StructDescriptor> aidlDesc;
+            std::unique_ptr<C2StructDescriptor> descriptor;
+            ::ndk::ScopedAStatus transStatus = mBase->getStructDescriptors(
+                    {int32_t(coreIndex.coreIndex())},
+                    &aidlDesc);
+            c2_status_t status = GetC2Status(transStatus, "describe");
+            if (status != C2_OK) {
+                descriptor.reset();
+            } else if (!c2_aidl::utils::FromAidl(&descriptor, aidlDesc[0])) {
+                LOG(ERROR) << "describe -- conversion failed.";
+                descriptor.reset();
+            }
+            return descriptor;
+        }
+
+        AidlSimpleParamReflector(const std::shared_ptr<AidlBase> &base)
+            : mBase(base) { }
+
+        std::shared_ptr<AidlBase> mBase;
     };
 
-    return std::make_shared<SimpleParamReflector>(mBase1_0);
+    if (mAidlBase) {
+        return std::make_shared<AidlSimpleParamReflector>(mAidlBase);
+    }
+    return std::make_shared<HidlSimpleParamReflector>(mHidlBase1_0);
 };
 
-std::vector<std::string> const& Codec2Client::GetServiceNames() {
-    static std::vector<std::string> sServiceNames{[]() {
-        using ::android::hardware::media::c2::V1_0::IComponentStore;
-        using ::android::hidl::manager::V1_2::IServiceManager;
+std::vector<std::string> Codec2Client::CacheServiceNames() {
+    std::vector<std::string> names;
 
-        while (true) {
-            sp<IServiceManager> serviceManager = IServiceManager::getService();
-            CHECK(serviceManager) << "Hardware service manager is not running.";
+    if (c2_aidl::utils::IsEnabled()) {
+        // Get AIDL service names
+        AServiceManager_forEachDeclaredInstance(
+                AidlBase::descriptor, &names, [](const char *name, void *context) {
+                    std::vector<std::string> *names = (std::vector<std::string> *)context;
+                    names->emplace_back(name);
+                });
+    }
 
-            // There are three categories of services based on names.
-            std::vector<std::string> defaultNames; // Prefixed with "default"
-            std::vector<std::string> vendorNames;  // Prefixed with "vendor"
-            std::vector<std::string> otherNames;   // Others
-            Return<void> transResult;
-            transResult = serviceManager->listManifestByInterface(
-                    IComponentStore::descriptor,
-                    [&defaultNames, &vendorNames, &otherNames](
-                            hidl_vec<hidl_string> const& instanceNames) {
-                        for (hidl_string const& instanceName : instanceNames) {
-                            char const* name = instanceName.c_str();
-                            if (strncmp(name, "default", 7) == 0) {
-                                defaultNames.emplace_back(name);
-                            } else if (strncmp(name, "vendor", 6) == 0) {
-                                vendorNames.emplace_back(name);
-                            } else {
-                                otherNames.emplace_back(name);
-                            }
-                        }
-                    });
-            if (transResult.isOk()) {
-                // Sort service names in each category.
-                std::sort(defaultNames.begin(), defaultNames.end());
-                std::sort(vendorNames.begin(), vendorNames.end());
-                std::sort(otherNames.begin(), otherNames.end());
+    // Get HIDL service names
+    using ::android::hardware::media::c2::V1_0::IComponentStore;
+    using ::android::hidl::manager::V1_2::IServiceManager;
+    while (true) {
+        sp<IServiceManager> serviceManager = IServiceManager::getService();
+        CHECK(serviceManager) << "Hardware service manager is not running.";
 
-                // Concatenate the three lists in this order: default, vendor,
-                // other.
-                std::vector<std::string>& names = defaultNames;
-                names.reserve(names.size() + vendorNames.size() + otherNames.size());
-                names.insert(names.end(),
-                             std::make_move_iterator(vendorNames.begin()),
-                             std::make_move_iterator(vendorNames.end()));
-                names.insert(names.end(),
-                             std::make_move_iterator(otherNames.begin()),
-                             std::make_move_iterator(otherNames.end()));
-
-                // Summarize to logcat.
-                if (names.empty()) {
-                    LOG(INFO) << "No Codec2 services declared in the manifest.";
-                } else {
-                    std::stringstream stringOutput;
-                    stringOutput << "Available Codec2 services:";
-                    for (std::string const& name : names) {
-                        stringOutput << " \"" << name << "\"";
-                    }
-                    LOG(INFO) << stringOutput.str();
-                }
-
-                return names;
-            }
-            LOG(ERROR) << "Could not retrieve the list of service instances of "
-                       << IComponentStore::descriptor
-                       << ". Retrying...";
+        Return<void> transResult;
+        transResult = serviceManager->listManifestByInterface(
+                IComponentStore::descriptor,
+                [&names](
+                        hidl_vec<hidl_string> const& instanceNames) {
+                    names.insert(names.end(), instanceNames.begin(), instanceNames.end());
+                });
+        if (transResult.isOk()) {
+            break;
         }
-    }()};
+        LOG(ERROR) << "Could not retrieve the list of service instances of "
+                   << IComponentStore::descriptor
+                   << ". Retrying...";
+    }
+    // Sort service names in each category.
+    std::stable_sort(
+        names.begin(), names.end(),
+        [](const std::string &a, const std::string &b) {
+            // First compare by prefix: default -> vendor -> {everything else}
+            constexpr int DEFAULT = 1;
+            constexpr int VENDOR = 2;
+            constexpr int OTHER = 3;
+            int aPrefix = ((a.compare(0, 7, "default") == 0) ? DEFAULT :
+                           (a.compare(0, 6, "vendor") == 0) ? VENDOR :
+                           OTHER);
+            int bPrefix = ((b.compare(0, 7, "default") == 0) ? DEFAULT :
+                           (b.compare(0, 6, "vendor") == 0) ? VENDOR :
+                           OTHER);
+            if (aPrefix != bPrefix) {
+                return aPrefix < bPrefix;
+            }
+            // If the prefix is the same, compare alphabetically
+            return a < b;
+        });
+
+    // Summarize to logcat.
+    if (names.empty()) {
+        LOG(INFO) << "No Codec2 services declared in the manifest.";
+    } else {
+        std::stringstream stringOutput;
+        stringOutput << "Available Codec2 services:";
+        for (std::string const& name : names) {
+            stringOutput << " \"" << name << "\"";
+        }
+        LOG(INFO) << stringOutput.str();
+    }
+
+    return names;
+}
+
+std::vector<std::string> const& Codec2Client::GetServiceNames() {
+    static std::vector<std::string> sServiceNames = CacheServiceNames();
     return sServiceNames;
 }
 
@@ -1322,14 +1544,34 @@
 std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
     std::string const& name = GetServiceNames()[index];
     LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
-    sp<Base> baseStore = Base::getService(name);
+
+    if (c2_aidl::utils::IsEnabled()) {
+        std::string instanceName =
+            ::android::base::StringPrintf("%s/%s", AidlBase::descriptor, name.c_str());
+        if (AServiceManager_isDeclared(instanceName.c_str())) {
+            std::shared_ptr<AidlBase> baseStore = AidlBase::fromBinder(
+                    ::ndk::SpAIBinder(AServiceManager_waitForService(instanceName.c_str())));
+            CHECK(baseStore) << "Codec2 AIDL service \"" << name << "\""
+                                " inaccessible for unknown reasons.";
+            LOG(VERBOSE) << "Client to Codec2 AIDL service \"" << name << "\" created";
+            std::shared_ptr<c2_aidl::IConfigurable> configurable;
+            ::ndk::ScopedAStatus transStatus = baseStore->getConfigurable(&configurable);
+            CHECK(transStatus.isOk()) << "Codec2 AIDL service \"" << name << "\""
+                                        "does not have IConfigurable.";
+            return std::make_shared<Codec2Client>(baseStore, configurable, index);
+        }
+    }
+
+    std::string instanceName = "android.hardware.media.c2/" + name;
+    sp<HidlBase> baseStore = HidlBase::getService(name);
     CHECK(baseStore) << "Codec2 service \"" << name << "\""
                         " inaccessible for unknown reasons.";
     LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
-    Return<sp<IConfigurable>> transResult = baseStore->getConfigurable();
+    Return<sp<c2_hidl::IConfigurable>> transResult = baseStore->getConfigurable();
     CHECK(transResult.isOk()) << "Codec2 service \"" << name << "\""
                                 "does not have IConfigurable.";
-    sp<IConfigurable> configurable = static_cast<sp<IConfigurable>>(transResult);
+    sp<c2_hidl::IConfigurable> configurable =
+        static_cast<sp<c2_hidl::IConfigurable>>(transResult);
     return std::make_shared<Codec2Client>(baseStore, configurable, index);
 }
 
@@ -1431,8 +1673,7 @@
     return status;
 }
 
-std::shared_ptr<Codec2Client::Interface>
-        Codec2Client::CreateInterfaceByName(
+std::shared_ptr<Codec2Client::Interface> Codec2Client::CreateInterfaceByName(
         const char* interfaceName,
         std::shared_ptr<Codec2Client>* owner,
         size_t numberOfAttempts) {
@@ -1518,13 +1759,8 @@
     return nullptr;
 }
 
-// Codec2Client::Listener
-
-Codec2Client::Listener::~Listener() {
-}
-
 // Codec2Client::Interface
-Codec2Client::Interface::Interface(const sp<Base>& base)
+Codec2Client::Interface::Interface(const sp<HidlBase>& base)
       : Configurable{
             [base]() -> sp<c2_hidl::IConfigurable> {
                 Return<sp<c2_hidl::IConfigurable>> transResult =
@@ -1534,11 +1770,91 @@
                         nullptr;
             }()
         },
-        mBase{base} {
+        mHidlBase{base} {
+}
+
+Codec2Client::Interface::Interface(const std::shared_ptr<AidlBase>& base)
+      : Configurable{
+            [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
+                std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
+                ::ndk::ScopedAStatus transStatus =
+                    base->getConfigurable(&aidlConfigurable);
+                return transStatus.isOk() ? aidlConfigurable : nullptr;
+            }()
+        },
+        mAidlBase{base} {
 }
 
 // Codec2Client::Component
-Codec2Client::Component::Component(const sp<Base>& base)
+
+class Codec2Client::Component::AidlDeathManager {
+public:
+    AidlDeathManager()
+        : mSeq(0),
+          mDeathRecipient(AIBinder_DeathRecipient_new(OnBinderDied)) {
+    }
+
+    ~AidlDeathManager() = default;
+
+    bool linkToDeath(
+            const std::shared_ptr<Component> &comp,
+            const std::shared_ptr<Listener> &listener,
+            size_t *seqPtr) {
+        std::unique_lock lock(mMutex);
+        size_t seq = mSeq++;
+        if (!mMap.try_emplace(seq, comp, listener).second) {
+            return false;
+        }
+        if (STATUS_OK != AIBinder_linkToDeath(
+                comp->mAidlBase->asBinder().get(), mDeathRecipient.get(), (void *)seq)) {
+            mMap.erase(seq);
+            return false;
+        }
+        *seqPtr = seq;
+        return true;
+    }
+
+    void unlinkToDeath(size_t seq, const std::shared_ptr<AidlBase> &base) {
+        std::unique_lock lock(mMutex);
+        AIBinder_unlinkToDeath(base->asBinder().get(), mDeathRecipient.get(), (void *)seq);
+        mMap.erase(seq);
+    }
+
+private:
+    std::mutex mMutex;
+    size_t mSeq;
+    typedef std::tuple<std::weak_ptr<Component>, std::weak_ptr<Listener>> Context;
+    std::map<size_t, Context> mMap;
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+
+    bool extractContext(size_t seq, Context *context) {
+        std::unique_lock lock(mMutex);
+        auto node = mMap.extract(seq);
+        if (!node) {
+            return false;
+        }
+        *context = node.mapped();
+        return true;
+    }
+
+    static void OnBinderDied(void *cookie) {
+        size_t seq = size_t(cookie);
+        Context context;
+        if (!Component::GetAidlDeathManager()->extractContext(seq, &context)) {
+            return;
+        }
+        std::weak_ptr<Component> weakComponent;
+        std::weak_ptr<Listener> weakListener;
+        std::tie(weakComponent, weakListener) = context;
+        if (std::shared_ptr<Listener> listener = weakListener.lock()) {
+            listener->onDeath(weakComponent);
+        } else {
+            LOG(DEBUG) << "onDeath -- listener died.";
+        }
+    }
+};
+
+Codec2Client::Component::Component(const sp<HidlBase>& base)
       : Configurable{
             [base]() -> sp<c2_hidl::IConfigurable> {
                 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
@@ -1554,14 +1870,14 @@
                         nullptr;
             }()
         },
-        mBase1_0{base},
-        mBase1_1{Base1_1::castFrom(base)},
-        mBase1_2{Base1_2::castFrom(base)},
-        mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+        mHidlBase1_0{base},
+        mHidlBase1_1{HidlBase1_1::castFrom(base)},
+        mHidlBase1_2{HidlBase1_2::castFrom(base)},
+        mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
         mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
 }
 
-Codec2Client::Component::Component(const sp<Base1_1>& base)
+Codec2Client::Component::Component(const sp<HidlBase1_1>& base)
       : Configurable{
             [base]() -> sp<c2_hidl::IConfigurable> {
                 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
@@ -1577,14 +1893,14 @@
                         nullptr;
             }()
         },
-        mBase1_0{base},
-        mBase1_1{base},
-        mBase1_2{Base1_2::castFrom(base)},
-        mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+        mHidlBase1_0{base},
+        mHidlBase1_1{base},
+        mHidlBase1_2{HidlBase1_2::castFrom(base)},
+        mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
         mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
 }
 
-Codec2Client::Component::Component(const sp<Base1_2>& base)
+Codec2Client::Component::Component(const sp<HidlBase1_2>& base)
       : Configurable{
             [base]() -> sp<c2_hidl::IConfigurable> {
                 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
@@ -1600,22 +1916,54 @@
                         nullptr;
             }()
         },
-        mBase1_0{base},
-        mBase1_1{base},
-        mBase1_2{base},
-        mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+        mHidlBase1_0{base},
+        mHidlBase1_1{base},
+        mHidlBase1_2{base},
+        mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
+        mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
+}
+
+Codec2Client::Component::Component(const std::shared_ptr<AidlBase> &base)
+      : Configurable{
+            [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
+                std::shared_ptr<c2_aidl::IComponentInterface> aidlIntf;
+                ::ndk::ScopedAStatus transStatus = base->getInterface(&aidlIntf);
+                if (!transStatus.isOk()) {
+                    return nullptr;
+                }
+                std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
+                transStatus = aidlIntf->getConfigurable(&aidlConfigurable);
+                return transStatus.isOk() ? aidlConfigurable : nullptr;
+            }()
+        },
+        mAidlBase{base},
+        mAidlBufferPoolSender{std::make_unique<AidlBufferPoolSender>()},
         mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
 }
 
 Codec2Client::Component::~Component() {
+    if (mAidlDeathSeq) {
+        GetAidlDeathManager()->unlinkToDeath(*mAidlDeathSeq, mAidlBase);
+    }
 }
 
 c2_status_t Codec2Client::Component::createBlockPool(
         C2Allocator::id_t id,
         C2BlockPool::local_id_t* blockPoolId,
         std::shared_ptr<Codec2Client::Configurable>* configurable) {
+    if (mAidlBase) {
+        c2_aidl::IComponent::BlockPool aidlBlockPool;
+        ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(id, &aidlBlockPool);
+        c2_status_t status = GetC2Status(transStatus, "createBlockPool");
+        if (status != C2_OK) {
+            return status;
+        }
+        *blockPoolId = aidlBlockPool.blockPoolId;
+        *configurable = std::make_shared<Configurable>(aidlBlockPool.configurable);
+        return C2_OK;
+    }
     c2_status_t status;
-    Return<void> transStatus = mBase1_0->createBlockPool(
+    Return<void> transStatus = mHidlBase1_0->createBlockPool(
             static_cast<uint32_t>(id),
             [&status, blockPoolId, configurable](
                     c2_hidl::Status s,
@@ -1640,7 +1988,11 @@
 
 c2_status_t Codec2Client::Component::destroyBlockPool(
         C2BlockPool::local_id_t localId) {
-    Return<c2_hidl::Status> transResult = mBase1_0->destroyBlockPool(
+    if (mAidlBase) {
+        ::ndk::ScopedAStatus transStatus = mAidlBase->destroyBlockPool(localId);
+        return GetC2Status(transStatus, "destroyBlockPool");
+    }
+    Return<c2_hidl::Status> transResult = mHidlBase1_0->destroyBlockPool(
             static_cast<uint64_t>(localId));
     if (!transResult.isOk()) {
         LOG(ERROR) << "destroyBlockPool -- transaction failed.";
@@ -1657,12 +2009,21 @@
 
 c2_status_t Codec2Client::Component::queue(
         std::list<std::unique_ptr<C2Work>>* const items) {
+    if (mAidlBase) {
+        c2_aidl::WorkBundle workBundle;
+        if (!c2_aidl::utils::ToAidl(&workBundle, *items, mAidlBufferPoolSender.get())) {
+            LOG(ERROR) << "queue -- bad input.";
+            return C2_TRANSACTION_FAILED;
+        }
+        ::ndk::ScopedAStatus transStatus = mAidlBase->queue(workBundle);
+        return GetC2Status(transStatus, "queue");
+    }
     c2_hidl::WorkBundle workBundle;
-    if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
+    if (!c2_hidl::utils::objcpy(&workBundle, *items, mHidlBufferPoolSender.get())) {
         LOG(ERROR) << "queue -- bad input.";
         return C2_TRANSACTION_FAILED;
     }
-    Return<c2_hidl::Status> transStatus = mBase1_0->queue(workBundle);
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->queue(workBundle);
     if (!transStatus.isOk()) {
         LOG(ERROR) << "queue -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1678,25 +2039,38 @@
 c2_status_t Codec2Client::Component::flush(
         C2Component::flush_mode_t mode,
         std::list<std::unique_ptr<C2Work>>* const flushedWork) {
-    (void)mode; // Flush mode isn't supported in HIDL yet.
-    c2_status_t status;
-    Return<void> transStatus = mBase1_0->flush(
-            [&status, flushedWork](
-                    c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
-                status = static_cast<c2_status_t>(s);
-                if (status != C2_OK) {
-                    LOG(DEBUG) << "flush -- call failed: " << status << ".";
-                    return;
-                }
-                if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
-                    status = C2_CORRUPTED;
-                } else {
-                    status = C2_OK;
-                }
-            });
-    if (!transStatus.isOk()) {
-        LOG(ERROR) << "flush -- transaction failed.";
-        return C2_TRANSACTION_FAILED;
+    (void)mode; // Flush mode isn't supported in HIDL/AIDL yet.
+    c2_status_t status = C2_OK;
+    if (mAidlBase) {
+        c2_aidl::WorkBundle workBundle;
+        ::ndk::ScopedAStatus transStatus = mAidlBase->flush(&workBundle);
+        c2_status_t status = GetC2Status(transStatus, "flush");
+        if (status != C2_OK) {
+            return status;
+        }
+        if (!c2_aidl::utils::FromAidl(flushedWork, workBundle)) {
+            LOG(DEBUG) << "flush -- flushedWork corrupted.";
+            return C2_CORRUPTED;
+        }
+    } else {
+        Return<void> transStatus = mHidlBase1_0->flush(
+                [&status, flushedWork](
+                        c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
+                    status = static_cast<c2_status_t>(s);
+                    if (status != C2_OK) {
+                        LOG(DEBUG) << "flush -- call failed: " << status << ".";
+                        return;
+                    }
+                    if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
+                        status = C2_CORRUPTED;
+                    } else {
+                        status = C2_OK;
+                    }
+                });
+        if (!transStatus.isOk()) {
+            LOG(ERROR) << "flush -- transaction failed.";
+            return C2_TRANSACTION_FAILED;
+        }
     }
 
     // Indices of flushed work items.
@@ -1721,7 +2095,12 @@
 }
 
 c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
-    Return<c2_hidl::Status> transStatus = mBase1_0->drain(
+    if (mAidlBase) {
+        ::ndk::ScopedAStatus transStatus = mAidlBase->drain(
+                mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
+        return GetC2Status(transStatus, "drain");
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->drain(
             mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
     if (!transStatus.isOk()) {
         LOG(ERROR) << "drain -- transaction failed.";
@@ -1736,7 +2115,11 @@
 }
 
 c2_status_t Codec2Client::Component::start() {
-    Return<c2_hidl::Status> transStatus = mBase1_0->start();
+    if (mAidlBase) {
+        ::ndk::ScopedAStatus transStatus = mAidlBase->start();
+        return GetC2Status(transStatus, "start");
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->start();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "start -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1750,7 +2133,11 @@
 }
 
 c2_status_t Codec2Client::Component::stop() {
-    Return<c2_hidl::Status> transStatus = mBase1_0->stop();
+    if (mAidlBase) {
+        ::ndk::ScopedAStatus transStatus = mAidlBase->stop();
+        return GetC2Status(transStatus, "stop");
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->stop();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "stop -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1764,7 +2151,11 @@
 }
 
 c2_status_t Codec2Client::Component::reset() {
-    Return<c2_hidl::Status> transStatus = mBase1_0->reset();
+    if (mAidlBase) {
+        ::ndk::ScopedAStatus transStatus = mAidlBase->reset();
+        return GetC2Status(transStatus, "reset");
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->reset();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "reset -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1778,7 +2169,11 @@
 }
 
 c2_status_t Codec2Client::Component::release() {
-    Return<c2_hidl::Status> transStatus = mBase1_0->release();
+    if (mAidlBase) {
+        ::ndk::ScopedAStatus transStatus = mAidlBase->release();
+        return GetC2Status(transStatus, "release");
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->release();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "release -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1795,11 +2190,25 @@
         uint32_t avSyncHwId,
         native_handle_t** sidebandHandle) {
     *sidebandHandle = nullptr;
-    if (!mBase1_1) {
+    if (mAidlBase) {
+        ::aidl::android::hardware::common::NativeHandle handle;
+        ::ndk::ScopedAStatus transStatus = mAidlBase->configureVideoTunnel(avSyncHwId, &handle);
+        c2_status_t status = GetC2Status(transStatus, "configureVideoTunnel");
+        if (status != C2_OK) {
+            return status;
+        }
+        if (isAidlNativeHandleEmpty(handle)) {
+            LOG(DEBUG) << "configureVideoTunnel -- empty handle returned";
+        } else {
+            *sidebandHandle = dupFromAidl(handle);
+        }
+        return C2_OK;
+    }
+    if (!mHidlBase1_1) {
         return C2_OMITTED;
     }
     c2_status_t status{};
-    Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
+    Return<void> transStatus = mHidlBase1_1->configureVideoTunnel(avSyncHwId,
             [&status, sidebandHandle](
                     c2_hidl::Status s, hardware::hidl_handle const& h) {
                 status = static_cast<c2_status_t>(s);
@@ -1840,8 +2249,8 @@
         bqId = 0;
         mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
     } else {
-        mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount, mBase1_2 ?
-                                      &syncObj : nullptr);
+        mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount,
+                                      mHidlBase1_2 ? &syncObj : nullptr);
     }
 
     // set consumer bits
@@ -1880,11 +2289,15 @@
     ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
             generation, (long long)consumerUsage, syncObj ? " sync" : "");
 
+    if (mAidlBase) {
+        // FIXME
+        return C2_OMITTED;
+    }
     Return<c2_hidl::Status> transStatus = syncObj ?
-            mBase1_2->setOutputSurfaceWithSyncObj(
+            mHidlBase1_2->setOutputSurfaceWithSyncObj(
                     static_cast<uint64_t>(blockPoolId),
                     bqId == 0 ? nullHgbp : igbp, *syncObj) :
-            mBase1_0->setOutputSurface(
+            mHidlBase1_0->setOutputSurface(
                     static_cast<uint64_t>(blockPoolId),
                     bqId == 0 ? nullHgbp : igbp);
 
@@ -1923,7 +2336,11 @@
         C2BlockPool::local_id_t blockPoolId) {
     std::scoped_lock lock(mOutputMutex);
     mOutputBufferQueue->stop();
-    Return<c2_hidl::Status> transStatus = mBase1_0->setOutputSurface(
+    if (mAidlBase) {
+        // FIXME
+        return;
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->setOutputSurface(
             static_cast<uint64_t>(blockPoolId), nullptr);
     if (!transStatus.isOk()) {
         LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
@@ -1941,8 +2358,12 @@
 c2_status_t Codec2Client::Component::connectToInputSurface(
         const std::shared_ptr<InputSurface>& inputSurface,
         std::shared_ptr<InputSurfaceConnection>* connection) {
+    if (mAidlBase) {
+        // FIXME
+        return C2_OMITTED;
+    }
     c2_status_t status;
-    Return<void> transStatus = mBase1_0->connectToInputSurface(
+    Return<void> transStatus = mHidlBase1_0->connectToInputSurface(
             inputSurface->mBase,
             [&status, connection](
                     c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
@@ -1965,8 +2386,12 @@
         const sp<HGraphicBufferProducer1>& producer,
         const sp<HGraphicBufferSource>& source,
         std::shared_ptr<InputSurfaceConnection>* connection) {
+    if (mAidlBase) {
+        LOG(WARNING) << "Connecting to OMX input surface is not supported for AIDL C2 HAL";
+        return C2_OMITTED;
+    }
     c2_status_t status;
-    Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
+    Return<void> transStatus = mHidlBase1_0->connectToOmxInputSurface(
             producer, source,
             [&status, connection](
                     c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
@@ -1986,7 +2411,11 @@
 }
 
 c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
-    Return<c2_hidl::Status> transStatus = mBase1_0->disconnectFromInputSurface();
+    if (mAidlBase) {
+        // FIXME
+        return C2_OMITTED;
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->disconnectFromInputSurface();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -2000,6 +2429,12 @@
     return status;
 }
 
+Codec2Client::Component::AidlDeathManager *Codec2Client::Component::GetAidlDeathManager() {
+    // This object never gets destructed
+    static AidlDeathManager *sManager = new AidlDeathManager();
+    return sManager;
+}
+
 c2_status_t Codec2Client::Component::setDeathListener(
         const std::shared_ptr<Component>& component,
         const std::shared_ptr<Listener>& listener) {
@@ -2020,12 +2455,20 @@
         }
     };
 
+    if (component->mAidlBase) {
+        size_t seq;
+        if (GetAidlDeathManager()->linkToDeath(component, listener, &seq)) {
+            component->mAidlDeathSeq = seq;
+        }
+        return C2_OK;
+    }
+
     sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
     deathRecipient->base = listener;
     deathRecipient->component = component;
 
     component->mDeathRecipient = deathRecipient;
-    Return<bool> transResult = component->mBase1_0->linkToDeath(
+    Return<bool> transResult = component->mHidlBase1_0->linkToDeath(
             component->mDeathRecipient, 0);
     if (!transResult.isOk()) {
         LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
diff --git a/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h b/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h
new file mode 100644
index 0000000..f9c8aca
--- /dev/null
+++ b/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/media/c2/BnGraphicBufferAllocator.h>
+
+#include <android-base/unique_fd.h>
+#include <gui/IGraphicBufferProducer.h>
+
+#include <memory>
+
+#include <C2Buffer.h>
+
+namespace aidl::android::hardware::media::c2::implementation {
+
+// forward declarations
+class GraphicsTracker;
+
+struct GraphicBufferAllocator : public BnGraphicBufferAllocator {
+public:
+    // HAL interfaces
+    ::ndk::ScopedAStatus allocate(const IGraphicBufferAllocator::Description& in_desc,
+                                  IGraphicBufferAllocator::Allocation* _aidl_return) override;
+
+    ::ndk::ScopedAStatus deallocate(int64_t in_id, bool* _aidl_return) override;
+
+    ::ndk::ScopedAStatus getWaitableFds(
+            IGraphicBufferAllocator::WaitableFds* _aidl_return) override;
+
+    /**
+     * Configuring Surface/BufferQueue for the interface.
+     *
+     * Configure Surface, generation # and max dequeueBuffer() count for
+     * allocate interface.
+     *
+     * @param   igbp              Surface where to allocate.
+     * @param   generation        Generation # for allocations.
+     * @param   maxDequeueBufferCount
+     *                            Maximum # of pending allocations.
+     */
+    bool configure(const ::android::sp<::android::IGraphicBufferProducer>& igbp,
+                   uint32_t generation,
+                   int maxDequeueBufferCount);
+
+    /**
+     * Update max dequeue buffer count of BufferQueue.
+     *
+     * BufferQueue does not update this value if count is smaller
+     * than the currently dequeued count.
+     * TODO: better to update the value inside this interface.
+     * for return value inspection from BQ, also for delayed updates.
+     *
+     * @param   count             the new value to update
+     */
+    void updateMaxDequeueBufferCount(int count);
+
+    void reset();
+
+    /**
+     * Create a listener for buffer being released.
+     *
+     * Surface will register this listener and notify whenever the consumer
+     * releases a buffer.
+     *
+     * @param   generation        generation # for the BufferQueue.
+     * @return  IProducerListener can be used when connect# to Surface.
+     */
+    const ::android::sp<::android::IProducerListener> createReleaseListener(
+            uint32_t generation);
+
+    /**
+     * Notifies a buffer being released.
+     *
+     * @param   generation        generation # for the BufferQueue.
+     */
+    void onBufferReleased(uint32_t generation);
+
+    /**
+     * Allocates a buffer.
+     *
+     * @param   width             width of the requested buffer.
+     * @param   height            height of the requested buffer.
+     * @param   format            format of the requested buffer.
+     * @param   usage             usage of the requested buffer.
+     * @param   buf               out param for created buffer.
+     * @param   fence             out param for a pending fence.
+     *
+     * @return  OK                When an allocation was created.
+     *          C2_BAD_STATE      Client is not in the state for allocating
+     *          C2_BLOCKING       operation is blocked. Waitable fds can be
+     *                            used to know when it unblocks.
+     *          C2_CORRUPTED      Failed with a serious reason.
+     */
+    c2_status_t allocate(uint32_t width, uint32_t height,
+                         ::android::PixelFormat format, uint64_t usage,
+                         AHardwareBuffer **buf, ::android::sp<::android::Fence> *fence);
+
+    /**
+     * De-allocate a buffer.
+     *
+     * @param   id                unique id for a buffer.
+     * @param   fence             write fence if it's deallocated due to
+     *                            cancellation of displaying
+     */
+    bool deallocate(const uint64_t id, const ::android::sp<::android::Fence> &fence);
+
+    /**
+     * Display a graphic buffer to BufferQueue.
+     *
+     * @param   block             block to display to Surface.
+     * @param   input             input parameter for displaying.
+     * @param   output            out parameter from Surface.
+     */
+    c2_status_t displayBuffer(
+            const C2ConstGraphicBlock& block,
+            const ::android::IGraphicBufferProducer::QueueBufferInput& input,
+            ::android::IGraphicBufferProducer::QueueBufferOutput *output);
+
+    ~GraphicBufferAllocator();
+
+    /**
+     * Create the interface.
+     *
+     * The interface and codec instance's relationship is 1 to 1.
+     * The interface will be cretaed in the beginning of Codec createion. And
+     * lives until the instance destroyed.
+     *
+     * @param   maxDequeueCount   Initial max allocatable count
+     */
+    static std::shared_ptr<GraphicBufferAllocator> CreateGraphicBufferAllocator(
+            int maxDequeueCount);
+private:
+    GraphicBufferAllocator(int maxDequeueCount);
+
+    std::shared_ptr<GraphicsTracker> mGraphicsTracker;
+
+    friend class ::ndk::SharedRefBase;
+};
+
+} // namespace aidl::android::hardware::media::c2::implementation
diff --git a/media/codec2/hal/client/include/codec2/hidl/client.h b/media/codec2/hal/client/include/codec2/hidl/client.h
index 6fa19b0..0c7dd77 100644
--- a/media/codec2/hal/client/include/codec2/hidl/client.h
+++ b/media/codec2/hal/client/include/codec2/hidl/client.h
@@ -95,6 +95,11 @@
 struct IClientManager;
 }  // namespace android::hardware::media::bufferpool::V2_0
 
+namespace aidl::android::hardware::media::bufferpool2 {
+class IClientManager;
+}  // namespace aidl::android::hardware::media::c2
+
+
 namespace android::hardware::graphics::bufferqueue::V1_0 {
 struct IGraphicBufferProducer;
 }  // android::hardware::graphics::bufferqueue::V1_0
@@ -173,12 +178,12 @@
 
 struct Codec2Client : public Codec2ConfigurableClient {
 
-    typedef ::android::hardware::media::c2::V1_0::IComponentStore Base1_0;
-    typedef ::android::hardware::media::c2::V1_1::IComponentStore Base1_1;
-    typedef ::android::hardware::media::c2::V1_2::IComponentStore Base1_2;
-    typedef Base1_0 Base;
+    typedef ::android::hardware::media::c2::V1_0::IComponentStore HidlBase1_0;
+    typedef ::android::hardware::media::c2::V1_1::IComponentStore HidlBase1_1;
+    typedef ::android::hardware::media::c2::V1_2::IComponentStore HidlBase1_2;
+    typedef HidlBase1_0 HidlBase;
 
-    typedef ::android::hardware::media::c2::V1_0::IConfigurable IConfigurable;
+    typedef ::aidl::android::hardware::media::c2::IComponentStore AidlBase;
 
     struct Listener;
 
@@ -194,10 +199,11 @@
 
     typedef Codec2Client Store;
 
-    sp<Base> const& getBase() const;
-    sp<Base1_0> const& getBase1_0() const;
-    sp<Base1_1> const& getBase1_1() const;
-    sp<Base1_2> const& getBase1_2() const;
+    sp<HidlBase> const& getHidlBase() const;
+    sp<HidlBase1_0> const& getHidlBase1_0() const;
+    sp<HidlBase1_1> const& getHidlBase1_1() const;
+    sp<HidlBase1_2> const& getHidlBase1_2() const;
+    ::ndk::SpAIBinder getAidlBase() const;
 
     std::string const& getServiceName() const;
 
@@ -266,14 +272,19 @@
 
     // base and/or configurable cannot be null.
     Codec2Client(
-            sp<Base> const& base,
-            sp<IConfigurable> const& configurable,
+            sp<HidlBase> const& base,
+            sp<Codec2ConfigurableClient::HidlBase> const& configurable,
+            size_t serviceIndex);
+    Codec2Client(
+            std::shared_ptr<AidlBase> const& base,
+            std::shared_ptr<Codec2ConfigurableClient::AidlBase> const& configurable,
             size_t serviceIndex);
 
 protected:
-    sp<Base1_0> mBase1_0;
-    sp<Base1_1> mBase1_1;
-    sp<Base1_2> mBase1_2;
+    sp<HidlBase1_0> mHidlBase1_0;
+    sp<HidlBase1_1> mHidlBase1_1;
+    sp<HidlBase1_2> mHidlBase1_2;
+    std::shared_ptr<AidlBase> mAidlBase;
 
     // Finds the first store where the predicate returns C2_OK and returns the
     // last predicate result. The predicate will be tried on all stores. The
@@ -301,8 +312,11 @@
     mutable std::vector<C2Component::Traits> mTraitsList;
 
     sp<::android::hardware::media::bufferpool::V2_0::IClientManager>
-            mHostPoolManager;
+            mHidlHostPoolManager;
+    std::shared_ptr<::aidl::android::hardware::media::bufferpool2::IClientManager>
+            mAidlHostPoolManager;
 
+    static std::vector<std::string> CacheServiceNames();
     static std::shared_ptr<Codec2Client> _CreateFromIndex(size_t index);
 
     std::vector<C2Component::Traits> _listComponents(bool* success) const;
@@ -312,12 +326,15 @@
 
 struct Codec2Client::Interface : public Codec2Client::Configurable {
 
-    typedef ::android::hardware::media::c2::V1_0::IComponentInterface Base;
+    typedef ::android::hardware::media::c2::V1_0::IComponentInterface HidlBase;
+    typedef ::aidl::android::hardware::media::c2::IComponentInterface AidlBase;
 
-    Interface(const sp<Base>& base);
+    Interface(const sp<HidlBase>& base);
+    Interface(const std::shared_ptr<AidlBase>& base);
 
 protected:
-    sp<Base> mBase;
+    sp<HidlBase> mHidlBase;
+    std::shared_ptr<AidlBase> mAidlBase;
 };
 
 struct Codec2Client::Listener {
@@ -356,16 +373,17 @@
             int32_t slotId,
             int64_t timestampNs) = 0;
 
-    virtual ~Listener();
-
+    virtual ~Listener() = default;
 };
 
 struct Codec2Client::Component : public Codec2Client::Configurable {
 
-    typedef ::android::hardware::media::c2::V1_0::IComponent Base1_0;
-    typedef ::android::hardware::media::c2::V1_1::IComponent Base1_1;
-    typedef ::android::hardware::media::c2::V1_2::IComponent Base1_2;
-    typedef Base1_0 Base;
+    typedef ::android::hardware::media::c2::V1_0::IComponent HidlBase1_0;
+    typedef ::android::hardware::media::c2::V1_1::IComponent HidlBase1_1;
+    typedef ::android::hardware::media::c2::V1_2::IComponent HidlBase1_2;
+    typedef HidlBase1_0 HidlBase;
+
+    typedef ::aidl::android::hardware::media::c2::IComponent AidlBase;
 
     c2_status_t createBlockPool(
             C2Allocator::id_t id,
@@ -469,19 +487,23 @@
     c2_status_t disconnectFromInputSurface();
 
     // base cannot be null.
-    Component(const sp<Base>& base);
-    Component(const sp<Base1_1>& base);
-    Component(const sp<Base1_2>& base);
+    Component(const sp<HidlBase>& base);
+    Component(const sp<HidlBase1_1>& base);
+    Component(const sp<HidlBase1_2>& base);
+    Component(const std::shared_ptr<AidlBase>& base);
 
     ~Component();
 
 protected:
-    sp<Base1_0> mBase1_0;
-    sp<Base1_1> mBase1_1;
-    sp<Base1_2> mBase1_2;
+    sp<HidlBase1_0> mHidlBase1_0;
+    sp<HidlBase1_1> mHidlBase1_1;
+    sp<HidlBase1_2> mHidlBase1_2;
+    std::shared_ptr<AidlBase> mAidlBase;
 
-    struct BufferPoolSender;
-    std::unique_ptr<BufferPoolSender> mBufferPoolSender;
+    struct HidlBufferPoolSender;
+    struct AidlBufferPoolSender;
+    std::unique_ptr<HidlBufferPoolSender> mHidlBufferPoolSender;
+    std::unique_ptr<AidlBufferPoolSender> mAidlBufferPoolSender;
 
     struct OutputBufferQueue;
     std::unique_ptr<OutputBufferQueue> mOutputBufferQueue;
@@ -491,6 +513,10 @@
     // In order to prevent the race condition mutex is added.
     std::mutex mOutputMutex;
 
+    class AidlDeathManager;
+    static AidlDeathManager *GetAidlDeathManager();
+    std::optional<size_t> mAidlDeathSeq;
+
     static c2_status_t setDeathListener(
             const std::shared_ptr<Component>& component,
             const std::shared_ptr<Listener>& listener);
@@ -499,16 +525,15 @@
     friend struct Codec2Client;
 
     struct HidlListener;
+    struct AidlListener;
     void handleOnWorkDone(const std::list<std::unique_ptr<C2Work>> &workItems);
-
 };
 
 struct Codec2Client::InputSurface : public Codec2Client::Configurable {
 public:
     typedef ::android::hardware::media::c2::V1_0::IInputSurface Base;
 
-    typedef ::android::hardware::media::c2::V1_0::IInputSurfaceConnection
-            ConnectionBase;
+    typedef ::android::hardware::media::c2::V1_0::IInputSurfaceConnection ConnectionBase;
 
     typedef Codec2Client::InputSurfaceConnection Connection;
 
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/Android.bp b/media/codec2/hal/hidl/1.0/vts/functional/Android.bp
index 0ae133c..1c5c7d6 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/Android.bp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/Android.bp
@@ -29,10 +29,8 @@
     srcs: [
         "res/bbb_aac_stereo_128kbps_48000hz.aac",
         "res/bbb_aac_stereo_128kbps_48000hz.info",
-        "res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info",
         "res/bbb_amrwb_1ch_14kbps_16000hz.amrwb",
         "res/bbb_amrwb_1ch_14kbps_16000hz.info",
-        "res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info",
         "res/bbb_flac_stereo_680kbps_48000hz.flac",
         "res/bbb_flac_stereo_680kbps_48000hz.info",
         "res/bbb_g711alaw_1ch_8khz.info",
@@ -43,7 +41,6 @@
         "res/bbb_gsm_1ch_8khz_13kbps.raw",
         "res/bbb_mp3_stereo_192kbps_48000hz.info",
         "res/bbb_mp3_stereo_192kbps_48000hz.mp3",
-        "res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info",
         "res/bbb_opus_stereo_128kbps_48000hz.info",
         "res/bbb_opus_stereo_128kbps_48000hz.opus",
         "res/bbb_raw_1ch_8khz_s32le.info",
@@ -52,7 +49,6 @@
         "res/bbb_vorbis_stereo_128kbps_48000hz.vorbis",
         "res/sine_amrnb_1ch_12kbps_8000hz.amrnb",
         "res/sine_amrnb_1ch_12kbps_8000hz.info",
-        "res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info",
     ],
 }
 
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index d47ef67..222c3d2 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -44,17 +44,9 @@
 
 std::vector<CompToFiles> gCompToFiles = {
         {"mp4a-latm", "bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz.info"},
-        {"mp4a-latm", "bbb_aac_stereo_128kbps_48000hz.aac",
-         "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"},
         {"mpeg", "bbb_mp3_stereo_192kbps_48000hz.mp3", "bbb_mp3_stereo_192kbps_48000hz.info"},
-        {"mpeg", "bbb_mp3_stereo_192kbps_48000hz.mp3",
-         "bbb_mp3_stereo_192kbps_48000hz_multi_frame.info"},
         {"3gpp", "sine_amrnb_1ch_12kbps_8000hz.amrnb", "sine_amrnb_1ch_12kbps_8000hz.info"},
-        {"3gpp", "sine_amrnb_1ch_12kbps_8000hz.amrnb",
-         "sine_amrnb_1ch_12kbps_8000hz_multi_frame.info"},
         {"amr-wb", "bbb_amrwb_1ch_14kbps_16000hz.amrwb", "bbb_amrwb_1ch_14kbps_16000hz.info"},
-        {"amr-wb", "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
-         "bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info"},
         {"vorbis", "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
          "bbb_vorbis_stereo_128kbps_48000hz.info"},
         {"opus", "bbb_opus_stereo_128kbps_48000hz.opus", "bbb_opus_stereo_128kbps_48000hz.info"},
@@ -341,7 +333,7 @@
             ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout";
         }
         int64_t timestamp = (*Info)[frameID].timestamp;
-        if ((*Info)[frameID].flags) flags = 1u << ((*Info)[frameID].flags - 1);
+        flags = ((*Info)[frameID].flags == FLAG_CONFIG_DATA) ? C2FrameData::FLAG_CODEC_CONFIG : 0;
         if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1))))
             flags |= C2FrameData::FLAG_END_OF_STREAM;
 
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
index a22f8cf..6c04683 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
+++ b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
@@ -23,10 +23,8 @@
         <!-- Files used for audio testing -->
         <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.aac" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.aac" />
         <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.info" />
-        <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz_multi_frame.info" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz_multi_frame.info" />
         <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.amrwb" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.amrwb" />
         <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.info" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.info" />
-        <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info" />
         <option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.flac" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.flac" />
         <option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.info" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.info" />
         <option name="push-file" key="bbb_g711alaw_1ch_8khz.info" value="/data/local/tmp/media/bbb_g711alaw_1ch_8khz.info" />
@@ -37,7 +35,6 @@
         <option name="push-file" key="bbb_gsm_1ch_8khz_13kbps.raw" value="/data/local/tmp/media/bbb_gsm_1ch_8khz_13kbps.raw" />
         <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.info" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.info" />
         <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.mp3" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.mp3" />
-        <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz_multi_frame.info" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info" />
         <option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.info" />
         <option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.opus" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.opus" />
         <option name="push-file" key="bbb_raw_1ch_8khz_s32le.info" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le.info" />
@@ -46,7 +43,6 @@
         <option name="push-file" key="bbb_vorbis_stereo_128kbps_48000hz.vorbis" value="/data/local/tmp/media/bbb_vorbis_stereo_128kbps_48000hz.vorbis" />
         <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.amrnb" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.amrnb" />
         <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.info" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.info" />
-        <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz_multi_frame.info" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info" />
 
     </target_preparer>
 
@@ -55,4 +51,4 @@
         <option name="module-name" value="vts_media_c2_v1_0_audio_dec_test" />
         <option name="native-test-flag" value="-P /data/local/tmp/media/" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
index 2222aaf..ecab0cb 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
@@ -28,6 +28,8 @@
 #include <fstream>
 
 #define FLAG_NON_DISPLAY_FRAME (1 << 4)
+#define FLAG_CONFIG_DATA (1 << 5)
+
 #define MAX_RETRY 20
 #define TIME_OUT 400ms
 #define MAX_INPUT_BUFFERS 8
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info b/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info
deleted file mode 100644
index 182af20..0000000
--- a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info
+++ /dev/null
@@ -1,443 +0,0 @@
-5 32 0
-5 32 0
-337 1 0
-322 1 21333
-279 1 42666
-563 1 64000
-635 1 106666
-634 1 149333
-629 1 192000
-680 1 234666
-688 1 277333
-1036 1 320000
-1040 1 384000
-1009 1 448000
-1020 1 512000
-1357 1 576000
-1353 1 661333
-1351 1 746666
-1351 1 832000
-343 1 917333
-335 1 938666
-339 1 960000
-342 1 981333
-348 1 1002666
-350 1 1024000
-351 1 1045333
-342 1 1066666
-366 1 1088000
-340 1 1109333
-354 1 1130666
-340 1 1152000
-334 1 1173333
-338 1 1194666
-340 1 1216000
-351 1 1237333
-346 1 1258666
-331 1 1280000
-321 1 1301333
-343 1 1322666
-342 1 1344000
-345 1 1365333
-326 1 1386666
-342 1 1408000
-356 1 1429333
-351 1 1450666
-343 1 1472000
-347 1 1493333
-349 1 1514666
-350 1 1536000
-330 1 1557333
-341 1 1578666
-340 1 1600000
-330 1 1621333
-340 1 1642666
-335 1 1664000
-344 1 1685333
-359 1 1706666
-337 1 1728000
-346 1 1749333
-330 1 1770666
-351 1 1792000
-355 1 1813333
-352 1 1834666
-325 1 1856000
-342 1 1877333
-327 1 1898666
-349 1 1920000
-326 1 1941333
-337 1 1962666
-378 1 1984000
-321 1 2005333
-319 1 2026666
-346 1 2048000
-352 1 2069333
-349 1 2090666
-331 1 2112000
-330 1 2133333
-329 1 2154666
-333 1 2176000
-367 1 2197333
-362 1 2218666
-337 1 2240000
-337 1 2261333
-360 1 2282666
-333 1 2304000
-317 1 2325333
-344 1 2346666
-335 1 2368000
-337 1 2389333
-349 1 2410666
-336 1 2432000
-348 1 2453333
-349 1 2474666
-342 1 2496000
-359 1 2517333
-340 1 2538666
-340 1 2560000
-348 1 2581333
-334 1 2602666
-328 1 2624000
-341 1 2645333
-339 1 2666666
-337 1 2688000
-350 1 2709333
-326 1 2730666
-360 1 2752000
-344 1 2773333
-340 1 2794666
-343 1 2816000
-361 1 2837333
-329 1 2858666
-345 1 2880000
-345 1 2901333
-330 1 2922666
-342 1 2944000
-344 1 2965333
-330 1 2986666
-329 1 3008000
-335 1 3029333
-366 1 3050666
-328 1 3072000
-349 1 3093333
-339 1 3114666
-340 1 3136000
-335 1 3157333
-327 1 3178666
-348 1 3200000
-339 1 3221333
-334 1 3242666
-350 1 3264000
-325 1 3285333
-361 1 3306666
-338 1 3328000
-350 1 3349333
-353 1 3370666
-327 1 3392000
-346 1 3413333
-348 1 3434666
-339 1 3456000
-342 1 3477333
-334 1 3498666
-350 1 3520000
-354 1 3541333
-363 1 3562666
-322 1 3584000
-337 1 3605333
-355 1 3626666
-329 1 3648000
-324 1 3669333
-338 1 3690666
-356 1 3712000
-330 1 3733333
-321 1 3754666
-337 1 3776000
-345 1 3797333
-335 1 3818666
-348 1 3840000
-342 1 3861333
-348 1 3882666
-335 1 3904000
-344 1 3925333
-357 1 3946666
-368 1 3968000
-324 1 3989333
-343 1 4010666
-341 1 4032000
-329 1 4053333
-356 1 4074666
-317 1 4096000
-351 1 4117333
-340 1 4138666
-340 1 4160000
-332 1 4181333
-355 1 4202666
-357 1 4224000
-327 1 4245333
-338 1 4266666
-323 1 4288000
-346 1 4309333
-352 1 4330666
-347 1 4352000
-343 1 4373333
-311 1 4394666
-338 1 4416000
-365 1 4437333
-349 1 4458666
-327 1 4480000
-355 1 4501333
-319 1 4522666
-349 1 4544000
-351 1 4565333
-337 1 4586666
-340 1 4608000
-349 1 4629333
-316 1 4650666
-344 1 4672000
-334 1 4693333
-344 1 4714666
-347 1 4736000
-348 1 4757333
-334 1 4778666
-338 1 4800000
-331 1 4821333
-344 1 4842666
-342 1 4864000
-336 1 4885333
-326 1 4906666
-364 1 4928000
-350 1 4949333
-350 1 4970666
-363 1 4992000
-358 1 5013333
-305 1 5034666
-344 1 5056000
-346 1 5077333
-342 1 5098666
-330 1 5120000
-318 1 5141333
-361 1 5162666
-354 1 5184000
-313 1 5205333
-330 1 5226666
-350 1 5248000
-347 1 5269333
-346 1 5290666
-357 1 5312000
-325 1 5333333
-335 1 5354666
-331 1 5376000
-366 1 5397333
-329 1 5418666
-349 1 5440000
-371 1 5461333
-326 1 5482666
-333 1 5504000
-319 1 5525333
-327 1 5546666
-353 1 5568000
-356 1 5589333
-348 1 5610666
-338 1 5632000
-331 1 5653333
-341 1 5674666
-362 1 5696000
-326 1 5717333
-359 1 5738666
-315 1 5760000
-376 1 5781333
-343 1 5802666
-354 1 5824000
-353 1 5845333
-344 1 5866666
-334 1 5888000
-345 1 5909333
-355 1 5930666
-322 1 5952000
-334 1 5973333
-353 1 5994666
-338 1 6016000
-351 1 6037333
-334 1 6058666
-339 1 6080000
-345 1 6101333
-347 1 6122666
-355 1 6144000
-312 1 6165333
-352 1 6186666
-354 1 6208000
-318 1 6229333
-344 1 6250666
-363 1 6272000
-321 1 6293333
-339 1 6314666
-356 1 6336000
-334 1 6357333
-354 1 6378666
-325 1 6400000
-321 1 6421333
-341 1 6442666
-337 1 6464000
-351 1 6485333
-343 1 6506666
-341 1 6528000
-344 1 6549333
-341 1 6570666
-364 1 6592000
-319 1 6613333
-348 1 6634666
-332 1 6656000
-333 1 6677333
-343 1 6698666
-348 1 6720000
-347 1 6741333
-350 1 6762666
-342 1 6784000
-341 1 6805333
-326 1 6826666
-351 1 6848000
-329 1 6869333
-323 1 6890666
-350 1 6912000
-361 1 6933333
-326 1 6954666
-345 1 6976000
-345 1 6997333
-311 1 7018666
-349 1 7040000
-358 1 7061333
-352 1 7082666
-347 1 7104000
-364 1 7125333
-328 1 7146666
-318 1 7168000
-351 1 7189333
-340 1 7210666
-341 1 7232000
-355 1 7253333
-336 1 7274666
-352 1 7296000
-341 1 7317333
-334 1 7338666
-348 1 7360000
-342 1 7381333
-335 1 7402666
-342 1 7424000
-359 1 7445333
-349 1 7466666
-329 1 7488000
-356 1 7509333
-292 1 7530666
-316 1 7552000
-318 1 7573333
-320 1 7594666
-342 1 7616000
-285 1 7637333
-326 1 7658666
-352 1 7680000
-392 1 7701333
-364 1 7722666
-384 1 7744000
-334 1 7765333
-317 1 7786666
-326 1 7808000
-373 1 7829333
-354 1 7850666
-329 1 7872000
-347 1 7893333
-353 1 7914666
-338 1 7936000
-317 1 7957333
-354 1 7978666
-345 1 8000000
-350 1 8021333
-351 1 8042666
-332 1 8064000
-358 1 8085333
-315 1 8106666
-336 1 8128000
-358 1 8149333
-343 1 8170666
-319 1 8192000
-370 1 8213333
-344 1 8234666
-361 1 8256000
-343 1 8277333
-337 1 8298666
-354 1 8320000
-332 1 8341333
-348 1 8362666
-328 1 8384000
-345 1 8405333
-340 1 8426666
-346 1 8448000
-341 1 8469333
-344 1 8490666
-342 1 8512000
-341 1 8533333
-345 1 8554666
-337 1 8576000
-335 1 8597333
-335 1 8618666
-340 1 8640000
-345 1 8661333
-341 1 8682666
-342 1 8704000
-338 1 8725333
-343 1 8746666
-336 1 8768000
-338 1 8789333
-353 1 8810666
-339 1 8832000
-329 1 8853333
-349 1 8874666
-323 1 8896000
-351 1 8917333
-359 1 8938666
-357 1 8960000
-341 1 8981333
-333 1 9002666
-335 1 9024000
-328 1 9045333
-347 1 9066666
-343 1 9088000
-369 1 9109333
-331 1 9130666
-344 1 9152000
-330 1 9173333
-346 1 9194666
-337 1 9216000
-341 1 9237333
-338 1 9258666
-329 1 9280000
-360 1 9301333
-336 1 9322666
-341 1 9344000
-341 1 9365333
-345 1 9386666
-351 1 9408000
-349 1 9429333
-336 1 9450666
-326 1 9472000
-349 1 9493333
-343 1 9514666
-357 1 9536000
-342 1 9557333
-325 1 9578666
-346 1 9600000
-326 1 9621333
-402 1 9642666
-331 1 9664000
-339 1 9685333
-371 1 9706666
-314 1 9728000
-310 1 9749333
-364 1 9770666
-338 1 9792000
-339 1 9813333
-337 1 9834666
-355 1 9856000
-351 1 9877333
-332 1 9898666
-316 1 9920000
-474 1 9941333
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info b/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info
deleted file mode 100644
index c420009..0000000
--- a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info
+++ /dev/null
@@ -1,460 +0,0 @@
-41 1 0
-41 1 20000
-82 1 40000
-82 1 80000
-82 1 120000
-82 1 160000
-82 1 200000
-82 1 240000
-82 1 280000
-82 1 320000
-82 1 360000
-123 1 400000
-123 1 460000
-123 1 520000
-123 1 580000
-123 1 640000
-164 1 700000
-164 1 780000
-164 1 860000
-164 1 940000
-164 1 1020000
-41 1 1100000
-41 1 1120000
-41 1 1140000
-41 1 1160000
-41 1 1180000
-41 1 1200000
-41 1 1220000
-41 1 1240000
-41 1 1260000
-41 1 1280000
-41 1 1300000
-41 1 1320000
-41 1 1340000
-41 1 1360000
-41 1 1380000
-41 1 1400000
-41 1 1420000
-41 1 1440000
-41 1 1460000
-41 1 1480000
-41 1 1500000
-41 1 1520000
-41 1 1540000
-41 1 1560000
-41 1 1580000
-41 1 1600000
-41 1 1620000
-41 1 1640000
-41 1 1660000
-41 1 1680000
-41 1 1700000
-41 1 1720000
-41 1 1740000
-41 1 1760000
-41 1 1780000
-41 1 1800000
-41 1 1820000
-41 1 1840000
-41 1 1860000
-41 1 1880000
-41 1 1900000
-41 1 1920000
-41 1 1940000
-41 1 1960000
-41 1 1980000
-41 1 2000000
-41 1 2020000
-41 1 2040000
-41 1 2060000
-41 1 2080000
-41 1 2100000
-41 1 2120000
-41 1 2140000
-41 1 2160000
-41 1 2180000
-41 1 2200000
-41 1 2220000
-41 1 2240000
-41 1 2260000
-41 1 2280000
-41 1 2300000
-41 1 2320000
-41 1 2340000
-41 1 2360000
-41 1 2380000
-41 1 2400000
-41 1 2420000
-41 1 2440000
-41 1 2460000
-41 1 2480000
-41 1 2500000
-41 1 2520000
-41 1 2540000
-41 1 2560000
-41 1 2580000
-41 1 2600000
-41 1 2620000
-41 1 2640000
-41 1 2660000
-41 1 2680000
-41 1 2700000
-41 1 2720000
-41 1 2740000
-41 1 2760000
-41 1 2780000
-41 1 2800000
-41 1 2820000
-41 1 2840000
-41 1 2860000
-41 1 2880000
-41 1 2900000
-41 1 2920000
-41 1 2940000
-41 1 2960000
-41 1 2980000
-41 1 3000000
-41 1 3020000
-41 1 3040000
-41 1 3060000
-41 1 3080000
-41 1 3100000
-41 1 3120000
-41 1 3140000
-41 1 3160000
-41 1 3180000
-41 1 3200000
-41 1 3220000
-41 1 3240000
-41 1 3260000
-41 1 3280000
-41 1 3300000
-41 1 3320000
-41 1 3340000
-41 1 3360000
-41 1 3380000
-41 1 3400000
-41 1 3420000
-41 1 3440000
-41 1 3460000
-41 1 3480000
-41 1 3500000
-41 1 3520000
-41 1 3540000
-41 1 3560000
-41 1 3580000
-41 1 3600000
-41 1 3620000
-41 1 3640000
-41 1 3660000
-41 1 3680000
-41 1 3700000
-41 1 3720000
-41 1 3740000
-41 1 3760000
-41 1 3780000
-41 1 3800000
-41 1 3820000
-41 1 3840000
-41 1 3860000
-41 1 3880000
-41 1 3900000
-41 1 3920000
-41 1 3940000
-41 1 3960000
-41 1 3980000
-41 1 4000000
-41 1 4020000
-41 1 4040000
-41 1 4060000
-41 1 4080000
-41 1 4100000
-41 1 4120000
-41 1 4140000
-41 1 4160000
-41 1 4180000
-41 1 4200000
-41 1 4220000
-41 1 4240000
-41 1 4260000
-41 1 4280000
-41 1 4300000
-41 1 4320000
-41 1 4340000
-41 1 4360000
-41 1 4380000
-41 1 4400000
-41 1 4420000
-41 1 4440000
-41 1 4460000
-41 1 4480000
-41 1 4500000
-41 1 4520000
-41 1 4540000
-41 1 4560000
-41 1 4580000
-41 1 4600000
-41 1 4620000
-41 1 4640000
-41 1 4660000
-41 1 4680000
-41 1 4700000
-41 1 4720000
-41 1 4740000
-41 1 4760000
-41 1 4780000
-41 1 4800000
-41 1 4820000
-41 1 4840000
-41 1 4860000
-41 1 4880000
-41 1 4900000
-41 1 4920000
-41 1 4940000
-41 1 4960000
-41 1 4980000
-41 1 5000000
-41 1 5020000
-41 1 5040000
-41 1 5060000
-41 1 5080000
-41 1 5100000
-41 1 5120000
-41 1 5140000
-41 1 5160000
-41 1 5180000
-41 1 5200000
-41 1 5220000
-41 1 5240000
-41 1 5260000
-41 1 5280000
-41 1 5300000
-41 1 5320000
-41 1 5340000
-41 1 5360000
-41 1 5380000
-41 1 5400000
-41 1 5420000
-41 1 5440000
-41 1 5460000
-41 1 5480000
-41 1 5500000
-41 1 5520000
-41 1 5540000
-41 1 5560000
-41 1 5580000
-41 1 5600000
-41 1 5620000
-41 1 5640000
-41 1 5660000
-41 1 5680000
-41 1 5700000
-41 1 5720000
-41 1 5740000
-41 1 5760000
-41 1 5780000
-41 1 5800000
-41 1 5820000
-41 1 5840000
-41 1 5860000
-41 1 5880000
-41 1 5900000
-41 1 5920000
-41 1 5940000
-41 1 5960000
-41 1 5980000
-41 1 6000000
-41 1 6020000
-41 1 6040000
-41 1 6060000
-41 1 6080000
-41 1 6100000
-41 1 6120000
-41 1 6140000
-41 1 6160000
-41 1 6180000
-41 1 6200000
-41 1 6220000
-41 1 6240000
-41 1 6260000
-41 1 6280000
-41 1 6300000
-41 1 6320000
-41 1 6340000
-41 1 6360000
-41 1 6380000
-41 1 6400000
-41 1 6420000
-41 1 6440000
-41 1 6460000
-41 1 6480000
-41 1 6500000
-41 1 6520000
-41 1 6540000
-41 1 6560000
-41 1 6580000
-41 1 6600000
-41 1 6620000
-41 1 6640000
-41 1 6660000
-41 1 6680000
-41 1 6700000
-41 1 6720000
-41 1 6740000
-41 1 6760000
-41 1 6780000
-41 1 6800000
-41 1 6820000
-41 1 6840000
-41 1 6860000
-41 1 6880000
-41 1 6900000
-41 1 6920000
-41 1 6940000
-41 1 6960000
-41 1 6980000
-41 1 7000000
-41 1 7020000
-41 1 7040000
-41 1 7060000
-41 1 7080000
-41 1 7100000
-41 1 7120000
-41 1 7140000
-41 1 7160000
-41 1 7180000
-41 1 7200000
-41 1 7220000
-41 1 7240000
-41 1 7260000
-41 1 7280000
-41 1 7300000
-41 1 7320000
-41 1 7340000
-41 1 7360000
-41 1 7380000
-41 1 7400000
-41 1 7420000
-41 1 7440000
-41 1 7460000
-41 1 7480000
-41 1 7500000
-41 1 7520000
-41 1 7540000
-41 1 7560000
-41 1 7580000
-41 1 7600000
-41 1 7620000
-41 1 7640000
-41 1 7660000
-41 1 7680000
-41 1 7700000
-41 1 7720000
-41 1 7740000
-41 1 7760000
-41 1 7780000
-41 1 7800000
-41 1 7820000
-41 1 7840000
-41 1 7860000
-41 1 7880000
-41 1 7900000
-41 1 7920000
-41 1 7940000
-41 1 7960000
-41 1 7980000
-41 1 8000000
-41 1 8020000
-41 1 8040000
-41 1 8060000
-41 1 8080000
-41 1 8100000
-41 1 8120000
-41 1 8140000
-41 1 8160000
-41 1 8180000
-41 1 8200000
-41 1 8220000
-41 1 8240000
-41 1 8260000
-41 1 8280000
-41 1 8300000
-41 1 8320000
-41 1 8340000
-41 1 8360000
-41 1 8380000
-41 1 8400000
-41 1 8420000
-41 1 8440000
-41 1 8460000
-41 1 8480000
-41 1 8500000
-41 1 8520000
-41 1 8540000
-41 1 8560000
-41 1 8580000
-41 1 8600000
-41 1 8620000
-41 1 8640000
-41 1 8660000
-41 1 8680000
-41 1 8700000
-41 1 8720000
-41 1 8740000
-41 1 8760000
-41 1 8780000
-41 1 8800000
-41 1 8820000
-41 1 8840000
-41 1 8860000
-41 1 8880000
-41 1 8900000
-41 1 8920000
-41 1 8940000
-41 1 8960000
-41 1 8980000
-41 1 9000000
-41 1 9020000
-41 1 9040000
-41 1 9060000
-41 1 9080000
-41 1 9100000
-41 1 9120000
-41 1 9140000
-41 1 9160000
-41 1 9180000
-41 1 9200000
-41 1 9220000
-41 1 9240000
-41 1 9260000
-41 1 9280000
-41 1 9300000
-41 1 9320000
-41 1 9340000
-41 1 9360000
-41 1 9380000
-41 1 9400000
-41 1 9420000
-41 1 9440000
-41 1 9460000
-41 1 9480000
-41 1 9500000
-41 1 9520000
-41 1 9540000
-41 1 9560000
-41 1 9580000
-41 1 9600000
-41 1 9620000
-41 1 9640000
-41 1 9660000
-41 1 9680000
-41 1 9700000
-41 1 9720000
-41 1 9740000
-41 1 9760000
-41 1 9780000
-41 1 9800000
-41 1 9820000
-41 1 9840000
-41 1 9860000
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info b/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info
deleted file mode 100644
index 575c75f..0000000
--- a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info
+++ /dev/null
@@ -1,385 +0,0 @@
-576 1 0
-576 1 24000
-1152 1 48000
-1152 1 96000
-1152 1 144000
-1152 1 192000
-1728 1 240000
-1728 1 312000
-1728 1 384000
-1728 1 456000
-1728 1 528000
-2304 1 600000
-2304 1 696000
-2304 1 792000
-2304 1 888000
-2304 1 984000
-576 1 1080000
-576 1 1104000
-576 1 1128000
-576 1 1152000
-576 1 1176000
-576 1 1200000
-576 1 1224000
-576 1 1248000
-576 1 1272000
-576 1 1296000
-576 1 1320000
-576 1 1344000
-576 1 1368000
-576 1 1392000
-576 1 1416000
-576 1 1440000
-576 1 1464000
-576 1 1488000
-576 1 1512000
-576 1 1536000
-576 1 1560000
-576 1 1584000
-576 1 1608000
-576 1 1632000
-576 1 1656000
-576 1 1680000
-576 1 1704000
-576 1 1728000
-576 1 1752000
-576 1 1776000
-576 1 1800000
-576 1 1824000
-576 1 1848000
-576 1 1872000
-576 1 1896000
-576 1 1920000
-576 1 1944000
-576 1 1968000
-576 1 1992000
-576 1 2016000
-576 1 2040000
-576 1 2064000
-576 1 2088000
-576 1 2112000
-576 1 2136000
-576 1 2160000
-576 1 2184000
-576 1 2208000
-576 1 2232000
-576 1 2256000
-576 1 2280000
-576 1 2304000
-576 1 2328000
-576 1 2352000
-576 1 2376000
-576 1 2400000
-576 1 2424000
-576 1 2448000
-576 1 2472000
-576 1 2496000
-576 1 2520000
-576 1 2544000
-576 1 2568000
-576 1 2592000
-576 1 2616000
-576 1 2640000
-576 1 2664000
-576 1 2688000
-576 1 2712000
-576 1 2736000
-576 1 2760000
-576 1 2784000
-576 1 2808000
-576 1 2832000
-576 1 2856000
-576 1 2880000
-576 1 2904000
-576 1 2928000
-576 1 2952000
-576 1 2976000
-576 1 3000000
-576 1 3024000
-576 1 3048000
-576 1 3072000
-576 1 3096000
-576 1 3120000
-576 1 3144000
-576 1 3168000
-576 1 3192000
-576 1 3216000
-576 1 3240000
-576 1 3264000
-576 1 3288000
-576 1 3312000
-576 1 3336000
-576 1 3360000
-576 1 3384000
-576 1 3408000
-576 1 3432000
-576 1 3456000
-576 1 3480000
-576 1 3504000
-576 1 3528000
-576 1 3552000
-576 1 3576000
-576 1 3600000
-576 1 3624000
-576 1 3648000
-576 1 3672000
-576 1 3696000
-576 1 3720000
-576 1 3744000
-576 1 3768000
-576 1 3792000
-576 1 3816000
-576 1 3840000
-576 1 3864000
-576 1 3888000
-576 1 3912000
-576 1 3936000
-576 1 3960000
-576 1 3984000
-576 1 4008000
-576 1 4032000
-576 1 4056000
-576 1 4080000
-576 1 4104000
-576 1 4128000
-576 1 4152000
-576 1 4176000
-576 1 4200000
-576 1 4224000
-576 1 4248000
-576 1 4272000
-576 1 4296000
-576 1 4320000
-576 1 4344000
-576 1 4368000
-576 1 4392000
-576 1 4416000
-576 1 4440000
-576 1 4464000
-576 1 4488000
-576 1 4512000
-576 1 4536000
-576 1 4560000
-576 1 4584000
-576 1 4608000
-576 1 4632000
-576 1 4656000
-576 1 4680000
-576 1 4704000
-576 1 4728000
-576 1 4752000
-576 1 4776000
-576 1 4800000
-576 1 4824000
-576 1 4848000
-576 1 4872000
-576 1 4896000
-576 1 4920000
-576 1 4944000
-576 1 4968000
-576 1 4992000
-576 1 5016000
-576 1 5040000
-576 1 5064000
-576 1 5088000
-576 1 5112000
-576 1 5136000
-576 1 5160000
-576 1 5184000
-576 1 5208000
-576 1 5232000
-576 1 5256000
-576 1 5280000
-576 1 5304000
-576 1 5328000
-576 1 5352000
-576 1 5376000
-576 1 5400000
-576 1 5424000
-576 1 5448000
-576 1 5472000
-576 1 5496000
-576 1 5520000
-576 1 5544000
-576 1 5568000
-576 1 5592000
-576 1 5616000
-576 1 5640000
-576 1 5664000
-576 1 5688000
-576 1 5712000
-576 1 5736000
-576 1 5760000
-576 1 5784000
-576 1 5808000
-576 1 5832000
-576 1 5856000
-576 1 5880000
-576 1 5904000
-576 1 5928000
-576 1 5952000
-576 1 5976000
-576 1 6000000
-576 1 6024000
-576 1 6048000
-576 1 6072000
-576 1 6096000
-576 1 6120000
-576 1 6144000
-576 1 6168000
-576 1 6192000
-576 1 6216000
-576 1 6240000
-576 1 6264000
-576 1 6288000
-576 1 6312000
-576 1 6336000
-576 1 6360000
-576 1 6384000
-576 1 6408000
-576 1 6432000
-576 1 6456000
-576 1 6480000
-576 1 6504000
-576 1 6528000
-576 1 6552000
-576 1 6576000
-576 1 6600000
-576 1 6624000
-576 1 6648000
-576 1 6672000
-576 1 6696000
-576 1 6720000
-576 1 6744000
-576 1 6768000
-576 1 6792000
-576 1 6816000
-576 1 6840000
-576 1 6864000
-576 1 6888000
-576 1 6912000
-576 1 6936000
-576 1 6960000
-576 1 6984000
-576 1 7008000
-576 1 7032000
-576 1 7056000
-576 1 7080000
-576 1 7104000
-576 1 7128000
-576 1 7152000
-576 1 7176000
-576 1 7200000
-576 1 7224000
-576 1 7248000
-576 1 7272000
-576 1 7296000
-576 1 7320000
-576 1 7344000
-576 1 7368000
-576 1 7392000
-576 1 7416000
-576 1 7440000
-576 1 7464000
-576 1 7488000
-576 1 7512000
-576 1 7536000
-576 1 7560000
-576 1 7584000
-576 1 7608000
-576 1 7632000
-576 1 7656000
-576 1 7680000
-576 1 7704000
-576 1 7728000
-576 1 7752000
-576 1 7776000
-576 1 7800000
-576 1 7824000
-576 1 7848000
-576 1 7872000
-576 1 7896000
-576 1 7920000
-576 1 7944000
-576 1 7968000
-576 1 7992000
-576 1 8016000
-576 1 8040000
-576 1 8064000
-576 1 8088000
-576 1 8112000
-576 1 8136000
-576 1 8160000
-576 1 8184000
-576 1 8208000
-576 1 8232000
-576 1 8256000
-576 1 8280000
-576 1 8304000
-576 1 8328000
-576 1 8352000
-576 1 8376000
-576 1 8400000
-576 1 8424000
-576 1 8448000
-576 1 8472000
-576 1 8496000
-576 1 8520000
-576 1 8544000
-576 1 8568000
-576 1 8592000
-576 1 8616000
-576 1 8640000
-576 1 8664000
-576 1 8688000
-576 1 8712000
-576 1 8736000
-576 1 8760000
-576 1 8784000
-576 1 8808000
-576 1 8832000
-576 1 8856000
-576 1 8880000
-576 1 8904000
-576 1 8928000
-576 1 8952000
-576 1 8976000
-576 1 9000000
-576 1 9024000
-576 1 9048000
-576 1 9072000
-576 1 9096000
-576 1 9120000
-576 1 9144000
-576 1 9168000
-576 1 9192000
-576 1 9216000
-576 1 9240000
-576 1 9264000
-576 1 9288000
-576 1 9312000
-576 1 9336000
-576 1 9360000
-576 1 9384000
-576 1 9408000
-576 1 9432000
-576 1 9456000
-576 1 9480000
-576 1 9504000
-576 1 9528000
-576 1 9552000
-576 1 9576000
-576 1 9600000
-576 1 9624000
-576 1 9648000
-576 1 9672000
-576 1 9696000
-576 1 9720000
-576 1 9744000
-576 1 9768000
-576 1 9792000
-576 1 9816000
-576 1 9840000
-576 1 9864000
-576 1 9888000
-576 1 9912000
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info b/media/codec2/hal/hidl/1.0/vts/functional/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info
deleted file mode 100644
index 0176eaf4..0000000
--- a/media/codec2/hal/hidl/1.0/vts/functional/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info
+++ /dev/null
@@ -1,807 +0,0 @@
-32 1 0
-32 1 20000
-64 1 40000
-64 1 80000
-64 1 120000
-96 1 160000
-96 1 220000
-96 1 280000
-96 1 340000
-128 1 400000
-128 1 480000
-128 1 560000
-128 1 640000
-128 1 720000
-32 1 800000
-32 1 820000
-32 1 840000
-32 1 860000
-32 1 880000
-32 1 900000
-32 1 920000
-32 1 940000
-32 1 960000
-32 1 980000
-32 1 1000000
-32 1 1020000
-32 1 1040000
-32 1 1060000
-32 1 1080000
-32 1 1100000
-32 1 1120000
-32 1 1140000
-32 1 1160000
-32 1 1180000
-32 1 1200000
-32 1 1220000
-32 1 1240000
-32 1 1260000
-32 1 1280000
-32 1 1300000
-32 1 1320000
-32 1 1340000
-32 1 1360000
-32 1 1380000
-32 1 1400000
-32 1 1420000
-32 1 1440000
-32 1 1460000
-32 1 1480000
-32 1 1500000
-32 1 1520000
-32 1 1540000
-32 1 1560000
-32 1 1580000
-32 1 1600000
-32 1 1620000
-32 1 1640000
-32 1 1660000
-32 1 1680000
-32 1 1700000
-32 1 1720000
-32 1 1740000
-32 1 1760000
-32 1 1780000
-32 1 1800000
-32 1 1820000
-32 1 1840000
-32 1 1860000
-32 1 1880000
-32 1 1900000
-32 1 1920000
-32 1 1940000
-32 1 1960000
-32 1 1980000
-32 1 2000000
-32 1 2020000
-32 1 2040000
-32 1 2060000
-32 1 2080000
-32 1 2100000
-32 1 2120000
-32 1 2140000
-32 1 2160000
-32 1 2180000
-32 1 2200000
-32 1 2220000
-32 1 2240000
-32 1 2260000
-32 1 2280000
-32 1 2300000
-32 1 2320000
-32 1 2340000
-32 1 2360000
-32 1 2380000
-32 1 2400000
-32 1 2420000
-32 1 2440000
-32 1 2460000
-32 1 2480000
-32 1 2500000
-32 1 2520000
-32 1 2540000
-32 1 2560000
-32 1 2580000
-32 1 2600000
-32 1 2620000
-32 1 2640000
-32 1 2660000
-32 1 2680000
-32 1 2700000
-32 1 2720000
-32 1 2740000
-32 1 2760000
-32 1 2780000
-32 1 2800000
-32 1 2820000
-32 1 2840000
-32 1 2860000
-32 1 2880000
-32 1 2900000
-32 1 2920000
-32 1 2940000
-32 1 2960000
-32 1 2980000
-32 1 3000000
-32 1 3020000
-32 1 3040000
-32 1 3060000
-32 1 3080000
-32 1 3100000
-32 1 3120000
-32 1 3140000
-32 1 3160000
-32 1 3180000
-32 1 3200000
-32 1 3220000
-32 1 3240000
-32 1 3260000
-32 1 3280000
-32 1 3300000
-32 1 3320000
-32 1 3340000
-32 1 3360000
-32 1 3380000
-32 1 3400000
-32 1 3420000
-32 1 3440000
-32 1 3460000
-32 1 3480000
-32 1 3500000
-32 1 3520000
-32 1 3540000
-32 1 3560000
-32 1 3580000
-32 1 3600000
-32 1 3620000
-32 1 3640000
-32 1 3660000
-32 1 3680000
-32 1 3700000
-32 1 3720000
-32 1 3740000
-32 1 3760000
-32 1 3780000
-32 1 3800000
-32 1 3820000
-32 1 3840000
-32 1 3860000
-32 1 3880000
-32 1 3900000
-32 1 3920000
-32 1 3940000
-32 1 3960000
-32 1 3980000
-32 1 4000000
-32 1 4020000
-32 1 4040000
-32 1 4060000
-32 1 4080000
-32 1 4100000
-32 1 4120000
-32 1 4140000
-32 1 4160000
-32 1 4180000
-32 1 4200000
-32 1 4220000
-32 1 4240000
-32 1 4260000
-32 1 4280000
-32 1 4300000
-32 1 4320000
-32 1 4340000
-32 1 4360000
-32 1 4380000
-32 1 4400000
-32 1 4420000
-32 1 4440000
-32 1 4460000
-32 1 4480000
-32 1 4500000
-32 1 4520000
-32 1 4540000
-32 1 4560000
-32 1 4580000
-32 1 4600000
-32 1 4620000
-32 1 4640000
-32 1 4660000
-32 1 4680000
-32 1 4700000
-32 1 4720000
-32 1 4740000
-32 1 4760000
-32 1 4780000
-32 1 4800000
-32 1 4820000
-32 1 4840000
-32 1 4860000
-32 1 4880000
-32 1 4900000
-32 1 4920000
-32 1 4940000
-32 1 4960000
-32 1 4980000
-32 1 5000000
-32 1 5020000
-32 1 5040000
-32 1 5060000
-32 1 5080000
-32 1 5100000
-32 1 5120000
-32 1 5140000
-32 1 5160000
-32 1 5180000
-32 1 5200000
-32 1 5220000
-32 1 5240000
-32 1 5260000
-32 1 5280000
-32 1 5300000
-32 1 5320000
-32 1 5340000
-32 1 5360000
-32 1 5380000
-32 1 5400000
-32 1 5420000
-32 1 5440000
-32 1 5460000
-32 1 5480000
-32 1 5500000
-32 1 5520000
-32 1 5540000
-32 1 5560000
-32 1 5580000
-32 1 5600000
-32 1 5620000
-32 1 5640000
-32 1 5660000
-32 1 5680000
-32 1 5700000
-32 1 5720000
-32 1 5740000
-32 1 5760000
-32 1 5780000
-32 1 5800000
-32 1 5820000
-32 1 5840000
-32 1 5860000
-32 1 5880000
-32 1 5900000
-32 1 5920000
-32 1 5940000
-32 1 5960000
-32 1 5980000
-32 1 6000000
-32 1 6020000
-32 1 6040000
-32 1 6060000
-32 1 6080000
-32 1 6100000
-32 1 6120000
-32 1 6140000
-32 1 6160000
-32 1 6180000
-32 1 6200000
-32 1 6220000
-32 1 6240000
-32 1 6260000
-32 1 6280000
-32 1 6300000
-32 1 6320000
-32 1 6340000
-32 1 6360000
-32 1 6380000
-32 1 6400000
-32 1 6420000
-32 1 6440000
-32 1 6460000
-32 1 6480000
-32 1 6500000
-32 1 6520000
-32 1 6540000
-32 1 6560000
-32 1 6580000
-32 1 6600000
-32 1 6620000
-32 1 6640000
-32 1 6660000
-32 1 6680000
-32 1 6700000
-32 1 6720000
-32 1 6740000
-32 1 6760000
-32 1 6780000
-32 1 6800000
-32 1 6820000
-32 1 6840000
-32 1 6860000
-32 1 6880000
-32 1 6900000
-32 1 6920000
-32 1 6940000
-32 1 6960000
-32 1 6980000
-32 1 7000000
-32 1 7020000
-32 1 7040000
-32 1 7060000
-32 1 7080000
-32 1 7100000
-32 1 7120000
-32 1 7140000
-32 1 7160000
-32 1 7180000
-32 1 7200000
-32 1 7220000
-32 1 7240000
-32 1 7260000
-32 1 7280000
-32 1 7300000
-32 1 7320000
-32 1 7340000
-32 1 7360000
-32 1 7380000
-32 1 7400000
-32 1 7420000
-32 1 7440000
-32 1 7460000
-32 1 7480000
-32 1 7500000
-32 1 7520000
-32 1 7540000
-32 1 7560000
-32 1 7580000
-32 1 7600000
-32 1 7620000
-32 1 7640000
-32 1 7660000
-32 1 7680000
-32 1 7700000
-32 1 7720000
-32 1 7740000
-32 1 7760000
-32 1 7780000
-32 1 7800000
-32 1 7820000
-32 1 7840000
-32 1 7860000
-32 1 7880000
-32 1 7900000
-32 1 7920000
-32 1 7940000
-32 1 7960000
-32 1 7980000
-32 1 8000000
-32 1 8020000
-32 1 8040000
-32 1 8060000
-32 1 8080000
-32 1 8100000
-32 1 8120000
-32 1 8140000
-32 1 8160000
-32 1 8180000
-32 1 8200000
-32 1 8220000
-32 1 8240000
-32 1 8260000
-32 1 8280000
-32 1 8300000
-32 1 8320000
-32 1 8340000
-32 1 8360000
-32 1 8380000
-32 1 8400000
-32 1 8420000
-32 1 8440000
-32 1 8460000
-32 1 8480000
-32 1 8500000
-32 1 8520000
-32 1 8540000
-32 1 8560000
-32 1 8580000
-32 1 8600000
-32 1 8620000
-32 1 8640000
-32 1 8660000
-32 1 8680000
-32 1 8700000
-32 1 8720000
-32 1 8740000
-32 1 8760000
-32 1 8780000
-32 1 8800000
-32 1 8820000
-32 1 8840000
-32 1 8860000
-32 1 8880000
-32 1 8900000
-32 1 8920000
-32 1 8940000
-32 1 8960000
-32 1 8980000
-32 1 9000000
-32 1 9020000
-32 1 9040000
-32 1 9060000
-32 1 9080000
-32 1 9100000
-32 1 9120000
-32 1 9140000
-32 1 9160000
-32 1 9180000
-32 1 9200000
-32 1 9220000
-32 1 9240000
-32 1 9260000
-32 1 9280000
-32 1 9300000
-32 1 9320000
-32 1 9340000
-32 1 9360000
-32 1 9380000
-32 1 9400000
-32 1 9420000
-32 1 9440000
-32 1 9460000
-32 1 9480000
-32 1 9500000
-32 1 9520000
-32 1 9540000
-32 1 9560000
-32 1 9580000
-32 1 9600000
-32 1 9620000
-32 1 9640000
-32 1 9660000
-32 1 9680000
-32 1 9700000
-32 1 9720000
-32 1 9740000
-32 1 9760000
-32 1 9780000
-32 1 9800000
-32 1 9820000
-32 1 9840000
-32 1 9860000
-32 1 9880000
-32 1 9900000
-32 1 9920000
-32 1 9940000
-32 1 9960000
-32 1 9980000
-32 1 10000000
-32 1 10020000
-32 1 10040000
-32 1 10060000
-32 1 10080000
-32 1 10100000
-32 1 10120000
-32 1 10140000
-32 1 10160000
-32 1 10180000
-32 1 10200000
-32 1 10220000
-32 1 10240000
-32 1 10260000
-32 1 10280000
-32 1 10300000
-32 1 10320000
-32 1 10340000
-32 1 10360000
-32 1 10380000
-32 1 10400000
-32 1 10420000
-32 1 10440000
-32 1 10460000
-32 1 10480000
-32 1 10500000
-32 1 10520000
-32 1 10540000
-32 1 10560000
-32 1 10580000
-32 1 10600000
-32 1 10620000
-32 1 10640000
-32 1 10660000
-32 1 10680000
-32 1 10700000
-32 1 10720000
-32 1 10740000
-32 1 10760000
-32 1 10780000
-32 1 10800000
-32 1 10820000
-32 1 10840000
-32 1 10860000
-32 1 10880000
-32 1 10900000
-32 1 10920000
-32 1 10940000
-32 1 10960000
-32 1 10980000
-32 1 11000000
-32 1 11020000
-32 1 11040000
-32 1 11060000
-32 1 11080000
-32 1 11100000
-32 1 11120000
-32 1 11140000
-32 1 11160000
-32 1 11180000
-32 1 11200000
-32 1 11220000
-32 1 11240000
-32 1 11260000
-32 1 11280000
-32 1 11300000
-32 1 11320000
-32 1 11340000
-32 1 11360000
-32 1 11380000
-32 1 11400000
-32 1 11420000
-32 1 11440000
-32 1 11460000
-32 1 11480000
-32 1 11500000
-32 1 11520000
-32 1 11540000
-32 1 11560000
-32 1 11580000
-32 1 11600000
-32 1 11620000
-32 1 11640000
-32 1 11660000
-32 1 11680000
-32 1 11700000
-32 1 11720000
-32 1 11740000
-32 1 11760000
-32 1 11780000
-32 1 11800000
-32 1 11820000
-32 1 11840000
-32 1 11860000
-32 1 11880000
-32 1 11900000
-32 1 11920000
-32 1 11940000
-32 1 11960000
-32 1 11980000
-32 1 12000000
-32 1 12020000
-32 1 12040000
-32 1 12060000
-32 1 12080000
-32 1 12100000
-32 1 12120000
-32 1 12140000
-32 1 12160000
-32 1 12180000
-32 1 12200000
-32 1 12220000
-32 1 12240000
-32 1 12260000
-32 1 12280000
-32 1 12300000
-32 1 12320000
-32 1 12340000
-32 1 12360000
-32 1 12380000
-32 1 12400000
-32 1 12420000
-32 1 12440000
-32 1 12460000
-32 1 12480000
-32 1 12500000
-32 1 12520000
-32 1 12540000
-32 1 12560000
-32 1 12580000
-32 1 12600000
-32 1 12620000
-32 1 12640000
-32 1 12660000
-32 1 12680000
-32 1 12700000
-32 1 12720000
-32 1 12740000
-32 1 12760000
-32 1 12780000
-32 1 12800000
-32 1 12820000
-32 1 12840000
-32 1 12860000
-32 1 12880000
-32 1 12900000
-32 1 12920000
-32 1 12940000
-32 1 12960000
-32 1 12980000
-32 1 13000000
-32 1 13020000
-32 1 13040000
-32 1 13060000
-32 1 13080000
-32 1 13100000
-32 1 13120000
-32 1 13140000
-32 1 13160000
-32 1 13180000
-32 1 13200000
-32 1 13220000
-32 1 13240000
-32 1 13260000
-32 1 13280000
-32 1 13300000
-32 1 13320000
-32 1 13340000
-32 1 13360000
-32 1 13380000
-32 1 13400000
-32 1 13420000
-32 1 13440000
-32 1 13460000
-32 1 13480000
-32 1 13500000
-32 1 13520000
-32 1 13540000
-32 1 13560000
-32 1 13580000
-32 1 13600000
-32 1 13620000
-32 1 13640000
-32 1 13660000
-32 1 13680000
-32 1 13700000
-32 1 13720000
-32 1 13740000
-32 1 13760000
-32 1 13780000
-32 1 13800000
-32 1 13820000
-32 1 13840000
-32 1 13860000
-32 1 13880000
-32 1 13900000
-32 1 13920000
-32 1 13940000
-32 1 13960000
-32 1 13980000
-32 1 14000000
-32 1 14020000
-32 1 14040000
-32 1 14060000
-32 1 14080000
-32 1 14100000
-32 1 14120000
-32 1 14140000
-32 1 14160000
-32 1 14180000
-32 1 14200000
-32 1 14220000
-32 1 14240000
-32 1 14260000
-32 1 14280000
-32 1 14300000
-32 1 14320000
-32 1 14340000
-32 1 14360000
-32 1 14380000
-32 1 14400000
-32 1 14420000
-32 1 14440000
-32 1 14460000
-32 1 14480000
-32 1 14500000
-32 1 14520000
-32 1 14540000
-32 1 14560000
-32 1 14580000
-32 1 14600000
-32 1 14620000
-32 1 14640000
-32 1 14660000
-32 1 14680000
-32 1 14700000
-32 1 14720000
-32 1 14740000
-32 1 14760000
-32 1 14780000
-32 1 14800000
-32 1 14820000
-32 1 14840000
-32 1 14860000
-32 1 14880000
-32 1 14900000
-32 1 14920000
-32 1 14940000
-32 1 14960000
-32 1 14980000
-32 1 15000000
-32 1 15020000
-32 1 15040000
-32 1 15060000
-32 1 15080000
-32 1 15100000
-32 1 15120000
-32 1 15140000
-32 1 15160000
-32 1 15180000
-32 1 15200000
-32 1 15220000
-32 1 15240000
-32 1 15260000
-32 1 15280000
-32 1 15300000
-32 1 15320000
-32 1 15340000
-32 1 15360000
-32 1 15380000
-32 1 15400000
-32 1 15420000
-32 1 15440000
-32 1 15460000
-32 1 15480000
-32 1 15500000
-32 1 15520000
-32 1 15540000
-32 1 15560000
-32 1 15580000
-32 1 15600000
-32 1 15620000
-32 1 15640000
-32 1 15660000
-32 1 15680000
-32 1 15700000
-32 1 15720000
-32 1 15740000
-32 1 15760000
-32 1 15780000
-32 1 15800000
-32 1 15820000
-32 1 15840000
-32 1 15860000
-32 1 15880000
-32 1 15900000
-32 1 15920000
-32 1 15940000
-32 1 15960000
-32 1 15980000
-32 1 16000000
-32 1 16020000
-32 1 16040000
-32 1 16060000
-32 1 16080000
-32 1 16100000
-32 1 16120000
-32 1 16140000
-32 1 16160000
-32 1 16180000
-32 1 16200000
-32 1 16220000
-32 1 16240000
-32 1 16260000
-32 1 16280000
-32 1 16300000
-32 1 16320000
-32 1 16340000
-32 1 16360000
-32 1 16380000
-32 1 16400000
-32 1 16420000
-32 1 16440000
-32 1 16460000
-32 1 16480000
-32 1 16500000
-32 1 16520000
-32 1 16540000
-32 1 16560000
-32 1 16580000
-32 1 16600000
-32 1 16620000
-32 1 16640000
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 3dc5b29..d561adc 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -460,7 +460,8 @@
             ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout";
         }
         int64_t timestamp = (*Info)[frameID].timestamp;
-        if ((*Info)[frameID].flags) flags = (1 << ((*Info)[frameID].flags - 1));
+
+        flags = ((*Info)[frameID].flags == FLAG_CONFIG_DATA) ? C2FrameData::FLAG_CODEC_CONFIG : 0;
         if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1))))
             flags |= C2FrameData::FLAG_END_OF_STREAM;
 
@@ -684,7 +685,7 @@
     if (mDisableTest) GTEST_SKIP() << "Test is disabled";
     if (!(strcasestr(mMime.c_str(), "avc") || strcasestr(mMime.c_str(), "hevc") ||
           strcasestr(mMime.c_str(), "vp8") || strcasestr(mMime.c_str(), "vp9") ||
-          strcasestr(mMime.c_str(), "mpeg2"))) {
+          strcasestr(mMime.c_str(), "mpeg2") || strcasestr(mMime.c_str(), "av01"))) {
         return;
     }
 
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
index 8305feb..db68b96 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
@@ -500,7 +500,7 @@
     description("Encodes input file");
     if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
-    bool signalEOS = std::get<3>(GetParam());
+    bool signalEOS = std::get<2>(GetParam());
     // Send an empty frame to receive CSD data from encoder.
     bool sendEmptyFirstFrame = std::get<3>(GetParam());
     mConfigBPictures = std::get<4>(GetParam());
diff --git a/media/codec2/hal/services/Android.bp b/media/codec2/hal/services/Android.bp
index 524519c..663e159 100644
--- a/media/codec2/hal/services/Android.bp
+++ b/media/codec2/hal/services/Android.bp
@@ -39,13 +39,17 @@
 }
 
 cc_binary {
-    name: "android.hardware.media.c2@1.2-default-service",
+    name: "android.hardware.media.c2-default-service",
     vendor: true,
     relative_install_path: "hw",
 
-    init_rc: ["android.hardware.media.c2@1.2-default-service.rc"],
+    init_rc: ["android.hardware.media.c2-default-service.rc"],
 
-    defaults: ["libcodec2-hidl-defaults"],
+    defaults: [
+        "libcodec2-hidl-defaults",
+        "libcodec2-aidl-defaults",
+    ],
+
     srcs: [
         "vendor.cpp",
     ],
@@ -54,13 +58,14 @@
     shared_libs: [
         "libavservices_minijail",
         "libbinder",
+        "libbinder_ndk",
     ],
-    required: ["android.hardware.media.c2@1.2-default-seccomp_policy"],
+    required: ["android.hardware.media.c2-default-seccomp_policy"],
 
-    // The content in manifest_media_c2_V1_1_default.xml can be included
+    // The content in manifest_media_c2_default.xml can be included
     // directly in the main device manifest.xml file or via vintf_fragments.
     // (Remove the line below if the entry is already in the main manifest.)
-    vintf_fragments: ["manifest_media_c2_V1_1_default.xml"],
+    vintf_fragments: ["manifest_media_c2_default.xml"],
 
     // Remove this line to enable this module.
     enabled: false,
@@ -73,30 +78,29 @@
 // Files in the "seccomp_policy" subdirectory are only provided as examples.
 // They may not work on some devices and/or architectures without modification.
 prebuilt_etc {
-    name: "android.hardware.media.c2@1.2-default-seccomp_policy",
+    name: "android.hardware.media.c2-default-seccomp_policy",
     vendor: true,
     sub_dir: "seccomp_policy",
 
     // If a specific architecture is targeted, multiple choices are not needed.
     arch: {
         arm: {
-            src: "seccomp_policy/android.hardware.media.c2@1.2-default-arm.policy",
+            src: "seccomp_policy/android.hardware.media.c2-default-arm.policy",
         },
         arm64: {
-            src: "seccomp_policy/android.hardware.media.c2@1.2-default-arm64.policy",
+            src: "seccomp_policy/android.hardware.media.c2-default-arm64.policy",
         },
         riscv64: {
-            src: "seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy",
+            src: "seccomp_policy/android.hardware.media.c2-default-riscv64.policy",
         },
         x86: {
-            src: "seccomp_policy/android.hardware.media.c2@1.2-default-x86.policy",
+            src: "seccomp_policy/android.hardware.media.c2-default-x86.policy",
         },
         x86_64: {
-            src: "seccomp_policy/android.hardware.media.c2@1.2-default-x86_64.policy",
+            src: "seccomp_policy/android.hardware.media.c2-default-x86_64.policy",
         },
     },
 
     // This may be removed.
     required: ["crash_dump.policy"],
 }
-
diff --git a/media/codec2/hal/services/android.hardware.media.c2-default-service.rc b/media/codec2/hal/services/android.hardware.media.c2-default-service.rc
new file mode 100644
index 0000000..dcc8e71
--- /dev/null
+++ b/media/codec2/hal/services/android.hardware.media.c2-default-service.rc
@@ -0,0 +1,7 @@
+service android-hardware-media-c2-hal /vendor/bin/hw/android.hardware.media.c2-default-service
+    class hal
+    user mediacodec
+    group camera mediadrm drmrpc
+    ioprio rt 4
+    task_profiles ProcessCapacityHigh
+
diff --git a/media/codec2/hal/services/android.hardware.media.c2@1.2-default-service.rc b/media/codec2/hal/services/android.hardware.media.c2@1.2-default-service.rc
deleted file mode 100644
index 12da593..0000000
--- a/media/codec2/hal/services/android.hardware.media.c2@1.2-default-service.rc
+++ /dev/null
@@ -1,7 +0,0 @@
-service android-hardware-media-c2-hal-1-2 /vendor/bin/hw/android.hardware.media.c2@1.2-default-service
-    class hal
-    user mediacodec
-    group camera mediadrm drmrpc
-    ioprio rt 4
-    task_profiles ProcessCapacityHigh
-
diff --git a/media/codec2/hal/services/manifest_media_c2_V1_0_default.xml b/media/codec2/hal/services/manifest_media_c2_V1_0_default.xml
deleted file mode 100644
index e97c3ce..0000000
--- a/media/codec2/hal/services/manifest_media_c2_V1_0_default.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
-    <hal>
-        <name>android.hardware.media.c2</name>
-        <transport>hwbinder</transport>
-        <version>1.0</version>
-        <interface>
-            <name>IComponentStore</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-</manifest>
diff --git a/media/codec2/hal/services/manifest_media_c2_V1_1_default.xml b/media/codec2/hal/services/manifest_media_c2_V1_1_default.xml
deleted file mode 100644
index bf0d72f..0000000
--- a/media/codec2/hal/services/manifest_media_c2_V1_1_default.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
-    <hal>
-        <name>android.hardware.media.c2</name>
-        <transport>hwbinder</transport>
-        <version>1.1</version>
-        <interface>
-            <name>IComponentStore</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-</manifest>
diff --git a/media/codec2/hal/services/manifest_media_c2_V1_2_default.xml b/media/codec2/hal/services/manifest_media_c2_V1_2_default.xml
deleted file mode 100644
index a5e8d87..0000000
--- a/media/codec2/hal/services/manifest_media_c2_V1_2_default.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
-    <hal>
-        <name>android.hardware.media.c2</name>
-        <transport>hwbinder</transport>
-        <version>1.2</version>
-        <interface>
-            <name>IComponentStore</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-</manifest>
diff --git a/media/codec2/hal/services/manifest_media_c2_default.xml b/media/codec2/hal/services/manifest_media_c2_default.xml
new file mode 100644
index 0000000..5e3d060
--- /dev/null
+++ b/media/codec2/hal/services/manifest_media_c2_default.xml
@@ -0,0 +1,18 @@
+<manifest version="1.0" type="device">
+  <!-- HIDL fragment -->
+  <hal>
+      <name>android.hardware.media.c2</name>
+      <transport>hwbinder</transport>
+      <version>1.2</version>
+      <interface>
+          <name>IComponentStore</name>
+          <instance>default</instance>
+      </interface>
+  </hal>
+  <!-- AIDL fragment -->
+  <hal format="aidl">
+    <name>android.hardware.media.c2</name>
+    <version>1</version>
+    <fqname>IComponentStore/default</fqname>
+  </hal>
+</manifest>
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-arm.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-arm.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-arm.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-arm.policy
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-arm64.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-arm64.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-arm64.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-arm64.policy
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-riscv64.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-riscv64.policy
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-x86.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-x86.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-x86.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-x86.policy
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-x86_64.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-x86_64.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-x86_64.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-x86_64.policy
diff --git a/media/codec2/hal/services/vendor.cpp b/media/codec2/hal/services/vendor.cpp
index 0d0684d..7cb7e6d 100644
--- a/media/codec2/hal/services/vendor.cpp
+++ b/media/codec2/hal/services/vendor.cpp
@@ -15,29 +15,43 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "android.hardware.media.c2@1.2-service"
+#define LOG_TAG "android.hardware.media.c2-service"
 
 #include <android-base/logging.h>
-#include <binder/ProcessState.h>
-#include <codec2/hidl/1.2/ComponentStore.h>
-#include <hidl/HidlTransportSupport.h>
 #include <minijail.h>
 
 #include <util/C2InterfaceHelper.h>
 #include <C2Component.h>
 #include <C2Config.h>
 
+// HIDL
+#include <binder/ProcessState.h>
+#include <codec2/hidl/1.2/ComponentStore.h>
+#include <hidl/HidlTransportSupport.h>
+
+// AIDL
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <codec2/aidl/ComponentStore.h>
+#include <codec2/aidl/ParamTypes.h>
+
 // This is the absolute on-device path of the prebuild_etc module
-// "android.hardware.media.c2@1.1-default-seccomp_policy" in Android.bp.
+// "android.hardware.media.c2-default-seccomp_policy" in Android.bp.
 static constexpr char kBaseSeccompPolicyPath[] =
         "/vendor/etc/seccomp_policy/"
-        "android.hardware.media.c2@1.2-default-seccomp-policy";
+        "android.hardware.media.c2-default-seccomp_policy";
 
 // Additional seccomp permissions can be added in this file.
 // This file does not exist by default.
 static constexpr char kExtSeccompPolicyPath[] =
         "/vendor/etc/seccomp_policy/"
-        "android.hardware.media.c2@1.2-extended-seccomp-policy";
+        "android.hardware.media.c2-extended-seccomp_policy";
+
+// We want multiple threads to be running so that a blocking operation
+// on one codec does not block the other codecs.
+// For HIDL: Extra threads may be needed to handle a stacked IPC sequence that
+// contains alternating binder and hwbinder calls. (See b/35283480.)
+static constexpr int kThreadCount = 8;
 
 class StoreImpl : public C2ComponentStore {
 public:
@@ -125,12 +139,12 @@
 
             addParameter(
                 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
-                .withDefault(new C2StoreDmaBufUsageInfo())
+                .withDefault(C2StoreDmaBufUsageInfo::AllocShared(128))
                 .withFields({
-                    C2F(mDmaBufUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
-                    C2F(mDmaBufUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
-                    C2F(mDmaBufUsageInfo, heapName).any(),
-                    C2F(mDmaBufUsageInfo, allocFlags).flags({}),
+                    C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
+                    C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
+                    C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
+                    C2F(mDmaBufUsageInfo, m.heapName).any(),
                 })
                 .withSetter(SetDmaBufUsage)
                 .build());
@@ -162,21 +176,49 @@
     Interface mInterface;
 };
 
-int main(int /* argc */, char** /* argv */) {
-    using namespace ::android;
-    LOG(DEBUG) << "android.hardware.media.c2@1.2-service starting...";
+void runAidlService() {
+    ABinderProcess_setThreadPoolMaxThreadCount(kThreadCount);
+    ABinderProcess_startThreadPool();
 
-    // Set up minijail to limit system calls.
-    signal(SIGPIPE, SIG_IGN);
-    SetUpMinijail(kBaseSeccompPolicyPath, kExtSeccompPolicyPath);
+    // Create IComponentStore service.
+    using namespace ::aidl::android::hardware::media::c2;
+    std::shared_ptr<IComponentStore> store;
+
+    // TODO: Replace this with
+    // store = new utils::ComponentStore(
+    //         /* implementation of C2ComponentStore */);
+    LOG(DEBUG) << "Instantiating Codec2's IComponentStore service...";
+    store = ::ndk::SharedRefBase::make<utils::ComponentStore>(
+            std::make_shared<StoreImpl>());
+
+    if (store == nullptr) {
+        LOG(ERROR) << "Cannot create Codec2's IComponentStore service.";
+    } else {
+        const std::string serviceName =
+            std::string(IComponentStore::descriptor) + "/default";
+        binder_exception_t ex = AServiceManager_addService(
+                store->asBinder().get(), serviceName.c_str());
+        if (ex != EX_NONE) {
+            LOG(ERROR) << "Cannot register Codec2's IComponentStore service"
+                          " with instance name << \""
+                       << serviceName << "\".";
+        } else {
+            LOG(DEBUG) << "Codec2's IComponentStore service registered. "
+                          "Instance name: \"" << serviceName << "\".";
+        }
+    }
+
+    ABinderProcess_joinThreadPool();
+}
+
+void runHidlService() {
+    using namespace ::android;
 
     // Enable vndbinder to allow vendor-to-vendor binder calls.
     ProcessState::initWithDriver("/dev/vndbinder");
 
     ProcessState::self()->startThreadPool();
-    // Extra threads may be needed to handle a stacked IPC sequence that
-    // contains alternating binder and hwbinder calls. (See b/35283480.)
-    hardware::configureRpcThreadpool(8, true /* callerWillJoin */);
+    hardware::configureRpcThreadpool(kThreadCount, true /* callerWillJoin */);
 
     // Create IComponentStore service.
     {
@@ -206,5 +248,20 @@
     }
 
     hardware::joinRpcThreadpool();
+}
+
+int main(int /* argc */, char** /* argv */) {
+    const bool aidlEnabled = ::aidl::android::hardware::media::c2::utils::IsEnabled();
+    LOG(DEBUG) << "android.hardware.media.c2" << (aidlEnabled ? "-V1" : "@1.2")
+               << "-service starting...";
+
+    // Set up minijail to limit system calls.
+    signal(SIGPIPE, SIG_IGN);
+    android::SetUpMinijail(kBaseSeccompPolicyPath, kExtSeccompPolicyPath);
+    if (aidlEnabled) {
+        runAidlService();
+    } else {
+        runHidlService();
+    }
     return 0;
 }
diff --git a/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp b/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
index 43533fd..7492cab 100644
--- a/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
@@ -114,7 +114,6 @@
             .usage = AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
                      AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
                      AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
-                     AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY |
                      AHARDWAREBUFFER_USAGE_VIDEO_ENCODE,
             .stride = 0,
             .rfu0 = 0,
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index f272499..0803dc3 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -23,6 +23,7 @@
 #include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
 #include <android/hardware/graphics/common/1.2/types.h>
 #include <cutils/native_handle.h>
+#include <drm/drm_fourcc.h>
 #include <gralloctypes/Gralloc4.h>
 #include <hardware/gralloc.h>
 #include <ui/GraphicBufferAllocator.h>
@@ -478,7 +479,25 @@
     // 'NATIVE' on Android means LITTLE_ENDIAN
     constexpr C2PlaneInfo::endianness_t kEndianness = C2PlaneInfo::NATIVE;
 
-    switch (mFormat) {
+    // Try to resolve IMPLEMENTATION_DEFINED format to accurate format if
+    // possible.
+    uint32_t format = mFormat;
+    uint32_t fourCc;
+    if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
+        !GraphicBufferMapper::get().getPixelFormatFourCC(mBuffer, &fourCc)) {
+        switch (fourCc)  {
+            case DRM_FORMAT_XBGR8888:
+                 format = static_cast<uint32_t>(PixelFormat4::RGBX_8888);
+                 break;
+            case DRM_FORMAT_ABGR8888:
+                 format = static_cast<uint32_t>(PixelFormat4::RGBA_8888);
+                 break;
+            default:
+                 break;
+        }
+    }
+
+    switch (format) {
         case static_cast<uint32_t>(PixelFormat4::RGBA_1010102): {
             // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
             // Surface. In all other cases it is RGBA. We don't know which case it is here, so
diff --git a/media/codec2/vndk/internal/C2BlockInternal.h b/media/codec2/vndk/internal/C2BlockInternal.h
index 1eefd87..81cdb43 100644
--- a/media/codec2/vndk/internal/C2BlockInternal.h
+++ b/media/codec2/vndk/internal/C2BlockInternal.h
@@ -17,10 +17,14 @@
 #ifndef ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
 #define ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
 
-#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
-
 #include <C2Buffer.h>
 
+#include <utils/RefBase.h>
+
+namespace android::hardware::graphics::bufferqueue::V2_0 {
+struct IGraphicBufferProducer;
+}
+
 // Note: HIDL-BufferPool and AIDL-BufferPool are not compatible
 namespace android::hardware::media::bufferpool {
 
diff --git a/media/libaudioclient/tests/audiosystem_tests.cpp b/media/libaudioclient/tests/audiosystem_tests.cpp
index 45baa94..d9789f1 100644
--- a/media/libaudioclient/tests/audiosystem_tests.cpp
+++ b/media/libaudioclient/tests/audiosystem_tests.cpp
@@ -21,9 +21,9 @@
 #include <set>
 
 #include <gtest/gtest.h>
+#include <log/log.h>
 #include <media/AidlConversionCppNdk.h>
 #include <media/IAudioFlinger.h>
-#include <utils/Log.h>
 
 #include "audio_test_utils.h"
 
@@ -277,23 +277,30 @@
         GTEST_SKIP() << "No output devices returned by the audio system";
     }
 
+    bool sourceFound = false, sinkFound = false;
     for (const auto& port : ports) {
         if (port.role == AUDIO_PORT_ROLE_SOURCE && port.type == AUDIO_PORT_TYPE_DEVICE) {
             sourcePort = port;
+            sourceFound = true;
         }
         if (port.role == AUDIO_PORT_ROLE_SINK && port.type == AUDIO_PORT_TYPE_DEVICE &&
             port.ext.device.type == AUDIO_DEVICE_OUT_SPEAKER) {
             sinkPort = port;
+            sinkFound = true;
         }
+        if (sourceFound && sinkFound) break;
+    }
+    if (!sourceFound || !sinkFound) {
+        GTEST_SKIP() << "No ports suitable for testing";
     }
 
     audioPatch.sources[0] = sourcePort.active_config;
     audioPatch.sinks[0] = sinkPort.active_config;
 
     status = AudioSystem::createAudioPatch(&audioPatch, &audioPatchHandle);
-    EXPECT_EQ(OK, status) << "AudioSystem::createAudiopatch failed between source "
-                          << sourcePort.ext.device.address << " and sink "
-                          << sinkPort.ext.device.address;
+    EXPECT_EQ(OK, status) << "AudioSystem::createAudioPatch failed between source "
+                          << audio_device_to_string(sourcePort.ext.device.type) << " and sink "
+                          << audio_device_to_string(sinkPort.ext.device.type);
 
     // verify that patch is established between source and the sink.
     ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(sourcePort.id, patchFound));
@@ -302,8 +309,8 @@
     EXPECT_NE(AUDIO_PORT_HANDLE_NONE, audioPatchHandle);
     status = AudioSystem::releaseAudioPatch(audioPatchHandle);
     EXPECT_EQ(OK, status) << "AudioSystem::releaseAudioPatch failed between source "
-                          << sourcePort.ext.device.address << " and sink "
-                          << sinkPort.ext.device.address;
+                          << audio_device_to_string(sourcePort.ext.device.type) << " and sink "
+                          << audio_device_to_string(sinkPort.ext.device.type);
 
     // verify that no patch is established between source and the sink after releaseAudioPatch.
     ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(sourcePort.id, patchFound));
@@ -608,28 +615,37 @@
 
 android::media::audio::common::AudioPort GenerateUniqueDeviceAddress(
         const android::media::audio::common::AudioPort& port) {
+    // Point-to-point connections do not use addresses.
+    static const std::set<std::string> kPointToPointConnections = {
+            AudioDeviceDescription::CONNECTION_ANALOG(), AudioDeviceDescription::CONNECTION_HDMI(),
+            AudioDeviceDescription::CONNECTION_HDMI_ARC(),
+            AudioDeviceDescription::CONNECTION_HDMI_EARC(),
+            AudioDeviceDescription::CONNECTION_SPDIF()};
     static int nextId = 0;
     using Tag = AudioDeviceAddress::Tag;
+    const auto& deviceDescription = port.ext.get<AudioPortExt::Tag::device>().device.type;
     AudioDeviceAddress address;
-    switch (suggestDeviceAddressTag(port.ext.get<AudioPortExt::Tag::device>().device.type)) {
-        case Tag::id:
-            address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
-            break;
-        case Tag::mac:
-            address = AudioDeviceAddress::make<Tag::mac>(
-                    std::vector<uint8_t>{1, 2, 3, 4, 5, static_cast<uint8_t>(++nextId & 0xff)});
-            break;
-        case Tag::ipv4:
-            address = AudioDeviceAddress::make<Tag::ipv4>(
-                    std::vector<uint8_t>{192, 168, 0, static_cast<uint8_t>(++nextId & 0xff)});
-            break;
-        case Tag::ipv6:
-            address = AudioDeviceAddress::make<Tag::ipv6>(std::vector<int32_t>{
-                    0xfc00, 0x0123, 0x4567, 0x89ab, 0xcdef, 0, 0, ++nextId & 0xffff});
-            break;
-        case Tag::alsa:
-            address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
-            break;
+    if (kPointToPointConnections.count(deviceDescription.connection) == 0) {
+        switch (suggestDeviceAddressTag(deviceDescription)) {
+            case Tag::id:
+                address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
+                break;
+            case Tag::mac:
+                address = AudioDeviceAddress::make<Tag::mac>(
+                        std::vector<uint8_t>{1, 2, 3, 4, 5, static_cast<uint8_t>(++nextId & 0xff)});
+                break;
+            case Tag::ipv4:
+                address = AudioDeviceAddress::make<Tag::ipv4>(
+                        std::vector<uint8_t>{192, 168, 0, static_cast<uint8_t>(++nextId & 0xff)});
+                break;
+            case Tag::ipv6:
+                address = AudioDeviceAddress::make<Tag::ipv6>(std::vector<int32_t>{
+                        0xfc00, 0x0123, 0x4567, 0x89ab, 0xcdef, 0, 0, ++nextId & 0xffff});
+                break;
+            case Tag::alsa:
+                address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
+                break;
+        }
     }
     android::media::audio::common::AudioPort result = port;
     result.ext.get<AudioPortExt::Tag::device>().device.address = std::move(address);
@@ -689,3 +705,24 @@
         EXPECT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, deviceState);
     }
 }
+
+class TestExecutionTracer : public ::testing::EmptyTestEventListener {
+  public:
+    void OnTestStart(const ::testing::TestInfo& test_info) override {
+        TraceTestState("Started", test_info);
+    }
+    void OnTestEnd(const ::testing::TestInfo& test_info) override {
+        TraceTestState("Completed", test_info);
+    }
+
+  private:
+    static void TraceTestState(const std::string& state, const ::testing::TestInfo& test_info) {
+        ALOGI("%s %s::%s", state.c_str(), test_info.test_suite_name(), test_info.name());
+    }
+};
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
+    return RUN_ALL_TESTS();
+}
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index c911ac8..835080f 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -42,6 +42,7 @@
 using aidl::android::media::audio::common::AudioDevice;
 using aidl::android::media::audio::common::AudioDeviceAddress;
 using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatDescription;
 using aidl::android::media::audio::common::AudioFormatType;
 using aidl::android::media::audio::common::AudioInputFlags;
 using aidl::android::media::audio::common::AudioIoFlags;
@@ -97,9 +98,15 @@
 }
 
 void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
-    portConfig->sampleRate = Int{ .value = config.base.sampleRate };
-    portConfig->channelMask = config.base.channelMask;
-    portConfig->format = config.base.format;
+    if (config.base.sampleRate != 0) {
+        portConfig->sampleRate = Int{ .value = config.base.sampleRate };
+    }
+    if (config.base.channelMask != AudioChannelLayout{}) {
+        portConfig->channelMask = config.base.channelMask;
+    }
+    if (config.base.format != AudioFormatDescription{}) {
+        portConfig->format = config.base.format;
+    }
 }
 
 // Note: these converters are for types defined in different AIDL files. Although these
@@ -706,7 +713,11 @@
         aidlPatch.sourcePortConfigIds.clear();
         aidlPatch.sinkPortConfigIds.clear();
     }
-    ALOGD("%s: sources: %s, sinks: %s",
+    // The IDs will be found by 'fillPortConfigs', however the original 'aidlSources' and
+    // 'aidlSinks' will not be updated because 'setAudioPatch' only needs IDs. Here we log
+    // the source arguments, where only the audio configuration and device specifications
+    // are relevant.
+    ALOGD("%s: [disregard IDs] sources: %s, sinks: %s",
             __func__, ::android::internal::ToString(aidlSources).c_str(),
             ::android::internal::ToString(aidlSinks).c_str());
     auto fillPortConfigs = [&](
@@ -999,7 +1010,7 @@
     return mModule->dump(fd, Args(args).args(), args.size());
 }
 
-int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
+status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
     TIME_CHECK();
     if (!mModule) return NO_INIT;
     if (supports == nullptr) {
@@ -1032,11 +1043,12 @@
     // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
     // Call `setConnectedState` instead.
     // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
-    const status_t status = setConnectedState(port, false /*connected*/);
-    if (status == NO_ERROR) {
+    if (const status_t status = setConnectedState(port, false /*connected*/); status == NO_ERROR) {
         mDeviceDisconnectionNotified.insert(port->id);
     }
-    return status;
+    // Return that there was no error as otherwise the disconnection procedure will not be
+    // considered complete for upper layers, and 'setConnectedState' will not be called again.
+    return NO_ERROR;
 }
 
 status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
@@ -1069,10 +1081,14 @@
         matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
         auto portsIt = findPort(matchDevice);
         if (portsIt == mPorts.end()) {
-            ALOGW("%s: device port for device %s is not found in the module %s",
-                    __func__, matchDevice.toString().c_str(), mInstance.c_str());
+            // Since 'setConnectedState' is called for all modules, it is normal when the device
+            // port not found in every one of them.
             return BAD_VALUE;
+        } else {
+            ALOGD("%s: device port for device %s found in the module %s",
+                    __func__, matchDevice.toString().c_str(), mInstance.c_str());
         }
+        resetUnusedPatchesAndPortConfigs();
         // Use the ID of the "template" port, use all the information from the provided port.
         aidlPort.id = portsIt->first;
         AudioPort connectedPort;
@@ -1083,20 +1099,32 @@
                 "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
                 __func__, mInstance.c_str(), connectedPort.toString().c_str(),
                 it->second.toString().c_str());
+        mConnectedPorts[connectedPort.id] = false;
     } else {  // !connected
         AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
         auto portsIt = findPort(matchDevice);
         if (portsIt == mPorts.end()) {
-            ALOGW("%s: device port for device %s is not found in the module %s",
-                    __func__, matchDevice.toString().c_str(), mInstance.c_str());
+            // Since 'setConnectedState' is called for all modules, it is normal when the device
+            // port not found in every one of them.
             return BAD_VALUE;
+        } else {
+            ALOGD("%s: device port for device %s found in the module %s",
+                    __func__, matchDevice.toString().c_str(), mInstance.c_str());
         }
-        // Any streams opened on the external device must be closed by this time,
-        // thus we can clean up patches and port configs that were created for them.
         resetUnusedPatchesAndPortConfigs();
-        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
-                                portsIt->second.id)));
-        mPorts.erase(portsIt);
+        // Streams are closed by AudioFlinger independently from device disconnections.
+        // It is possible that the stream has not been closed yet.
+        const int32_t portId = portsIt->second.id;
+        if (!isPortHeldByAStream(portId)) {
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+                            mModule->disconnectExternalDevice(portId)));
+            mPorts.erase(portsIt);
+            mConnectedPorts.erase(portId);
+        } else {
+            ALOGD("%s: since device port ID %d is used by a stream, "
+                    "external device disconnection postponed", __func__, portId);
+            mConnectedPorts[portId] = true;
+        }
     }
     return updateRoutes();
 }
@@ -1104,6 +1132,7 @@
 status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
     TIME_CHECK();
     if (!mModule) return NO_INIT;
+    resetUnusedPatchesAndPortConfigs();
     ModuleDebug debug{ .simulateDeviceConnections = enabled };
     status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
     // This is important to log as it affects HAL behavior.
@@ -1518,7 +1547,7 @@
         }
         RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
                 created));
-    } else if (!flags.has_value()) {
+    } else if (portConfigIt == mPortConfigs.end() && !flags.has_value()) {
         ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
                 "and was not created as flags are not specified",
                 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
@@ -1593,8 +1622,25 @@
     } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
         return mPorts.find(mDefaultOutputPortId);
     }
-    return std::find_if(mPorts.begin(), mPorts.end(),
-            [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
+    if (device.address.getTag() != AudioDeviceAddress::id ||
+            !device.address.get<AudioDeviceAddress::id>().empty()) {
+        return std::find_if(mPorts.begin(), mPorts.end(),
+                [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
+    }
+    // For connection w/o an address, two ports can be found: the template port,
+    // and a connected port (if exists). Make sure we return the connected port.
+    DeviceHalAidl::Ports::iterator portIt = mPorts.end();
+    for (auto it = mPorts.begin(); it != mPorts.end(); ++it) {
+        if (audioDeviceMatches(device, it->second)) {
+            if (mConnectedPorts.find(it->first) != mConnectedPorts.end()) {
+                return it;
+            } else {
+                // Will return 'it' if there is no connected port.
+                portIt = it;
+            }
+        }
+    }
+    return portIt;
 }
 
 DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
@@ -1672,6 +1718,28 @@
                         p.ext.template get<Tag::mix>().handle == ioHandle; });
 }
 
+bool DeviceHalAidl::isPortHeldByAStream(int32_t portId) {
+    // It is assumed that mStreams has already been cleaned up.
+    for (const auto& streamPair : mStreams) {
+        int32_t patchId = streamPair.second;
+        auto patchIt = mPatches.find(patchId);
+        if (patchIt == mPatches.end()) continue;
+        for (int32_t id : patchIt->second.sourcePortConfigIds) {
+            auto portConfigIt = mPortConfigs.find(id);
+            if (portConfigIt != mPortConfigs.end() && portConfigIt->second.portId == portId) {
+                return true;
+            }
+        }
+        for (int32_t id : patchIt->second.sinkPortConfigIds) {
+            auto portConfigIt = mPortConfigs.find(id);
+            if (portConfigIt != mPortConfigs.end() && portConfigIt->second.portId == portId) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
 void DeviceHalAidl::resetPatch(int32_t patchId) {
     if (auto it = mPatches.find(patchId); it != mPatches.end()) {
         mPatches.erase(it);
@@ -1721,10 +1789,10 @@
     // The assumption is that port configs are used to create patches
     // (or to open streams, but that involves creation of patches, too). Thus,
     // orphaned port configs can and should be reset.
-    std::set<int32_t> portConfigIds;
+    std::map<int32_t, int32_t /*portID*/> portConfigIds;
     std::transform(mPortConfigs.begin(), mPortConfigs.end(),
             std::inserter(portConfigIds, portConfigIds.end()),
-            [](const auto& pcPair) { return pcPair.first; });
+            [](const auto& pcPair) { return std::make_pair(pcPair.first, pcPair.second.portId); });
     for (const auto& p : mPatches) {
         for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
         for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
@@ -1732,7 +1800,28 @@
     for (int32_t id : mInitialPortConfigIds) {
         portConfigIds.erase(id);
     }
-    for (int32_t id : portConfigIds) resetPortConfig(id);
+    std::set<int32_t> retryDeviceDisconnection;
+    for (const auto& portConfigAndIdPair : portConfigIds) {
+        resetPortConfig(portConfigAndIdPair.first);
+        if (const auto it = mConnectedPorts.find(portConfigAndIdPair.second);
+                it != mConnectedPorts.end() && it->second) {
+            retryDeviceDisconnection.insert(portConfigAndIdPair.second);
+        }
+    }
+    for (int32_t portId : retryDeviceDisconnection) {
+        if (!isPortHeldByAStream(portId)) {
+            TIME_CHECK();
+            if (auto status = mModule->disconnectExternalDevice(portId); status.isOk()) {
+                mPorts.erase(portId);
+                mConnectedPorts.erase(portId);
+                ALOGD("%s: executed postponed external device disconnection for port ID %d",
+                        __func__, portId);
+            }
+        }
+    }
+    if (!retryDeviceDisconnection.empty()) {
+        updateRoutes();
+    }
 }
 
 status_t DeviceHalAidl::updateRoutes() {
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 8f27369..6f45f1f 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -165,7 +165,7 @@
 
     error::Result<audio_hw_sync_t> getHwAvSync() override;
 
-    int32_t supportsBluetoothVariableLatency(bool* supports __unused) override;
+    status_t supportsBluetoothVariableLatency(bool* supports __unused) override;
 
     status_t getSoundDoseInterface(const std::string& module,
                                    ::ndk::SpAIBinder* soundDoseBinder) override;
@@ -191,6 +191,8 @@
         Status status = Status::UNKNOWN;
         MicrophoneInfoProvider::Info info;
     };
+    // IDs of ports for connected external devices, and whether they are held by streams.
+    using ConnectedPorts = std::map<int32_t /*port ID*/, bool>;
     using Patches = std::map<int32_t /*patch ID*/,
             ::aidl::android::hardware::audio::core::AudioPatch>;
     using PortConfigs = std::map<int32_t /*port config ID*/,
@@ -261,6 +263,7 @@
             const ::aidl::android::media::audio::common::AudioConfig& config,
             const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
             int32_t ioHandle);
+    bool isPortHeldByAStream(int32_t portId);
     status_t prepareToOpenStream(
         int32_t aidlHandle,
         const ::aidl::android::media::audio::common::AudioDevice& aidlDevice,
@@ -318,6 +321,7 @@
     std::mutex mLock;
     std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
     std::set<audio_port_handle_t> mDeviceDisconnectionNotified;
+    ConnectedPorts mConnectedPorts;
 };
 
 } // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index f96d419..0d71fd3 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -684,4 +684,26 @@
 }
 #endif
 
+status_t DeviceHalHidl::supportsBluetoothVariableLatency(bool* supports) {
+    if (supports == nullptr) {
+        return BAD_VALUE;
+    }
+    *supports = false;
+
+    String8 reply;
+    status_t status = getParameters(
+            String8(AUDIO_PARAMETER_BT_VARIABLE_LATENCY_SUPPORTED), &reply);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    AudioParameter replyParams(reply);
+    String8 trueOrFalse;
+    status = replyParams.get(
+            String8(AUDIO_PARAMETER_BT_VARIABLE_LATENCY_SUPPORTED), trueOrFalse);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    *supports = trueOrFalse == AudioParameter::valueTrue;
+    return NO_ERROR;
+}
 } // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 989c1f5..1a1db33 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -127,10 +127,7 @@
         return INVALID_OPERATION;
     }
 
-    int32_t supportsBluetoothVariableLatency(bool* supports __unused) override {
-        // TODO: Implement the HAL query when moving to AIDL HAL.
-        return INVALID_OPERATION;
-    }
+    status_t supportsBluetoothVariableLatency(bool* supports) override;
 
     status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override;
 
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 4e34fca..ae73262 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -101,6 +101,8 @@
                                                 const void* pCmdData __unused, uint32_t* replySize,
                                                 void* pReplyData) {
     if (!replySize || *replySize < sizeof(int) || !pReplyData) {
+        ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+              numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
 
@@ -110,8 +112,10 @@
 
 status_t EffectConversionHelperAidl::handleSetParameter(uint32_t cmdSize, const void* pCmdData,
                                                         uint32_t* replySize, void* pReplyData) {
-    if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize ||
-        *replySize < sizeof(int) || !pReplyData) {
+    if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize || *replySize < sizeof(int) ||
+        !pReplyData) {
+        ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+              cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
 
@@ -130,8 +134,8 @@
 status_t EffectConversionHelperAidl::handleGetParameter(uint32_t cmdSize, const void* pCmdData,
                                                         uint32_t* replySize, void* pReplyData) {
     if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize || !pReplyData) {
-        ALOGE("%s illegal cmdSize %u pCmdData %p replySize %p replyData %p", __func__, cmdSize,
-              pCmdData, replySize, pReplyData);
+        ALOGE("%s illegal cmdSize %u pCmdData %p replySize %s replyData %p", __func__, cmdSize,
+              pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
 
@@ -158,28 +162,29 @@
                                                      uint32_t* replySize, void* pReplyData) {
     if (!replySize || *replySize != sizeof(int) || !pReplyData ||
         cmdSize != sizeof(effect_config_t)) {
-        ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
-              pReplyData);
+        ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+              cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
 
     effect_config_t* config = (effect_config_t*)pCmdData;
     Parameter::Common common = {
+            .session = mCommon.session,
+            .ioHandle = mCommon.ioHandle,
             .input =
                     VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfig(
                             config->inputCfg, mIsInputStream)),
             .output =
                     VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfig(
-                            config->outputCfg, mIsInputStream)),
-            .session = mCommon.session,
-            .ioHandle = mCommon.ioHandle};
+                            config->outputCfg, mIsInputStream))};
 
     State state;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
     // in case of buffer/ioHandle re-configure for an opened effect, close it and re-open
     if (state != State::INIT && mCommon != common) {
-        ALOGI("%s at state %s, closing effect", __func__,
-              android::internal::ToString(state).c_str());
+        ALOGI("%s at state %s, common parameter change from %s to %s, closing effect", __func__,
+              android::internal::ToString(state).c_str(), mCommon.toString().c_str(),
+              common.toString().c_str());
         RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->close()));
         RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
         mStatusQ.reset();
@@ -224,13 +229,19 @@
                                                      const void* pCmdData __unused,
                                                      uint32_t* replySize, void* pReplyData) {
     if (!replySize || *replySize != sizeof(effect_config_t) || !pReplyData) {
-        ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+        ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+              numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
 
     Parameter param;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(
             Parameter::Id::make<Parameter::Id::commonTag>(Parameter::common), &param)));
+    if (param.getTag() != Parameter::common) {
+        *replySize = 0;
+        ALOGW("%s no valid common tag return from HAL: %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
 
     const auto& common = param.get<Parameter::common>();
     effect_config_t* pConfig = (effect_config_t*)pReplyData;
@@ -245,7 +256,8 @@
                                                  const void* pCmdData __unused, uint32_t* replySize,
                                                  void* pReplyData) {
     if (!replySize || !pReplyData) {
-        ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+        ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+              numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
 
@@ -256,7 +268,8 @@
                                                   const void* pCmdData __unused,
                                                   uint32_t* replySize, void* pReplyData) {
     if (!replySize || !pReplyData) {
-        ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+        ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+              numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
 
@@ -267,7 +280,8 @@
                                                    const void* pCmdData __unused,
                                                    uint32_t* replySize, void* pReplyData) {
     if (!replySize || !pReplyData) {
-        ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+        ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+              numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
 
@@ -277,8 +291,8 @@
 status_t EffectConversionHelperAidl::handleSetAudioSource(uint32_t cmdSize, const void* pCmdData,
                                                           uint32_t* replySize, void* pReplyData) {
     if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
-        ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
-              pReplyData);
+        ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+              cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
     if (!getDescriptor().common.flags.audioSourceIndication) {
@@ -297,8 +311,8 @@
 status_t EffectConversionHelperAidl::handleSetAudioMode(uint32_t cmdSize, const void* pCmdData,
                                                         uint32_t* replySize, void* pReplyData) {
     if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
-        ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
-              pReplyData);
+        ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+              cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
     if (!getDescriptor().common.flags.audioModeIndication) {
@@ -316,8 +330,8 @@
 status_t EffectConversionHelperAidl::handleSetDevice(uint32_t cmdSize, const void* pCmdData,
                                                      uint32_t* replySize, void* pReplyData) {
     if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
-        ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
-              pReplyData);
+        ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+              cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
     if (!getDescriptor().common.flags.deviceIndication) {
@@ -353,14 +367,28 @@
     }
 
     constexpr uint32_t unityGain = 1 << 24;
-    Parameter::VolumeStereo volume = {.left = (float)(*(uint32_t*)pCmdData) / unityGain,
-                                      .right = (float)(*(uint32_t*)pCmdData + 1) / unityGain};
+    uint32_t vl = *(uint32_t*)pCmdData;
+    uint32_t vr = *((uint32_t*)pCmdData + 1);
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
-            mEffect->setParameter(Parameter::make<Parameter::volumeStereo>(volume))));
+            mEffect->setParameter(Parameter::make<Parameter::volumeStereo>(Parameter::VolumeStereo(
+                    {.left = (float)vl / unityGain, .right = (float)vr / unityGain})))));
 
-    // write unity gain back if volume was successfully set
+    // get volume from effect and set if changed, return the volume in command if HAL not return
+    // correct parameter.
+    Parameter::Id id = Parameter::Id::make<Parameter::Id::commonTag>(Parameter::volumeStereo);
+    Parameter volParam;
+    const status_t getParamStatus = statusTFromBinderStatus(mEffect->getParameter(id, &volParam));
+    if (getParamStatus != OK || volParam.getTag() != Parameter::volumeStereo) {
+        ALOGW("%s no valid volume return from HAL, status %d: %s, return volume in command",
+              __func__, getParamStatus, volParam.toString().c_str());
+    } else {
+        Parameter::VolumeStereo appliedVolume = volParam.get<Parameter::volumeStereo>();
+        vl = (uint32_t)(appliedVolume.left * unityGain);
+        vr = (uint32_t)(appliedVolume.right * unityGain);
+    }
+
     if (replySize && *replySize == 2 * sizeof(uint32_t) && pReplyData) {
-        constexpr uint32_t vol_ret[2] = {unityGain, unityGain};
+        uint32_t vol_ret[2] = {vl, vr};
         memcpy(pReplyData, vol_ret, sizeof(vol_ret));
     }
     return OK;
@@ -369,8 +397,8 @@
 status_t EffectConversionHelperAidl::handleSetOffload(uint32_t cmdSize, const void* pCmdData,
                                                       uint32_t* replySize, void* pReplyData) {
     if (cmdSize < sizeof(effect_offload_param_t) || !pCmdData || !replySize || !pReplyData) {
-        ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
-              pReplyData);
+        ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+              cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
     effect_offload_param_t* offload = (effect_offload_param_t*)pCmdData;
@@ -402,7 +430,8 @@
                                                              uint32_t* replySize,
                                                              void* pReplyData) {
     if (!replySize || !pReplyData) {
-        ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+        ALOGE("%s parameter invalid replySize %s pReplyData %p", __func__,
+              numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
 
@@ -422,7 +451,8 @@
                                                              uint32_t* replySize,
                                                              void* pReplyData) {
     if (!replySize || !pReplyData) {
-        ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+        ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+              numericPointerToString(replySize).c_str(), pReplyData);
         return BAD_VALUE;
     }
 
@@ -447,8 +477,9 @@
                   efGroup);
             status = (status == OK) ? BAD_VALUE : status;
         }
-    } else if (isBypassing()) {
-        // for effect with bypass (no processing) flag, it's okay to not have statusQ
+    } else if (isBypassingOrTunnel()) {
+        // for effect with bypass (no processing) or offloadIndication flag, it's okay to not have
+        // statusQ
         return OK;
     }
 
@@ -456,12 +487,22 @@
     return status;
 }
 
+bool EffectConversionHelperAidl::isBypassingOrTunnel() const {
+    return isBypassing() || isTunnel();
+}
+
 bool EffectConversionHelperAidl::isBypassing() const {
     return mEffect &&
            (mDesc.common.flags.bypass ||
             (mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isBypassing()));
 }
 
+bool EffectConversionHelperAidl::isTunnel() const {
+    return mEffect &&
+           (mDesc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL ||
+            (mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isTunnel()));
+}
+
 Descriptor EffectConversionHelperAidl::getDescriptor() const {
     if (!mIsProxyEffect) {
         return mDesc;
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 85e877e..5db334c 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -41,7 +41,10 @@
     std::shared_ptr<DataMQ> getInputMQ() { return mInputQ; }
     std::shared_ptr<DataMQ> getOutputMQ() { return mOutputQ; }
     std::shared_ptr<android::hardware::EventFlag> getEventFlagGroup() { return mEfGroup; }
+
     bool isBypassing() const;
+    bool isTunnel() const;
+    bool isBypassingOrTunnel() const;
 
     ::aidl::android::hardware::audio::effect::Descriptor getDescriptor() const;
 
@@ -72,6 +75,11 @@
 
     static constexpr int kDefaultframeCount = 0x100;
 
+    template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
+    static inline std::string numericPointerToString(T* pt) {
+        return pt ? std::to_string(*pt) : "nullptr";
+    }
+
     using AudioChannelLayout = aidl::android::media::audio::common::AudioChannelLayout;
     const aidl::android::media::audio::common::AudioConfig kDefaultAudioConfig = {
             .base = {.sampleRate = 44100,
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index 7b5e195..1099b6d 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -278,6 +278,11 @@
     return mSubEffects[mActiveSubIdx].descriptor.common.flags.bypass;
 }
 
+bool EffectProxy::isTunnel() const {
+    return mSubEffects[mActiveSubIdx].descriptor.common.flags.hwAcceleratorMode ==
+           Flags::HardwareAccelerator::TUNNEL;
+}
+
 binder_status_t EffectProxy::dump(int fd, const char** args, uint32_t numArgs) {
     const std::string dumpString = toString();
     write(fd, dumpString.c_str(), dumpString.size());
diff --git a/media/libaudiohal/impl/EffectProxy.h b/media/libaudiohal/impl/EffectProxy.h
index 18e1567..0d62642 100644
--- a/media/libaudiohal/impl/EffectProxy.h
+++ b/media/libaudiohal/impl/EffectProxy.h
@@ -98,6 +98,7 @@
     }
 
     bool isBypassing() const;
+    bool isTunnel() const;
 
     // call dump for all sub-effects
     binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index f9aea37..c058386 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -840,7 +840,7 @@
                 parameters, String8(AudioParameter::keyOffloadCodecDelaySamples),
                 [&](int value) {
                     // The legacy keys are misnamed, the value is in frames.
-                    return value > 0 ? mOffloadMetadata.delayFrames = value, OK : BAD_VALUE;
+                    return value >= 0 ? mOffloadMetadata.delayFrames = value, OK : BAD_VALUE;
                 }))) {
         updateMetadata = true;
     }
@@ -848,7 +848,7 @@
                 parameters, String8(AudioParameter::keyOffloadCodecPaddingSamples),
                 [&](int value) {
                     // The legacy keys are misnamed, the value is in frames.
-                    return value > 0 ? mOffloadMetadata.paddingFrames = value, OK : BAD_VALUE;
+                    return value >= 0 ? mOffloadMetadata.paddingFrames = value, OK : BAD_VALUE;
                 }))) {
         updateMetadata = true;
     }
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
index 89f8b83..f77c093 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
@@ -227,7 +227,7 @@
     RETURN_IF_ERROR(param.readFromValue(&enable));
 
     return DynamicsProcessing::ChannelConfig(
-            {.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable)), .channel = channel});
+            {.channel = channel, .enable = VALUE_OR_RETURN(convertIntegral<bool>(enable))});
 }
 
 ConversionResult<DynamicsProcessing::EqBandConfig>
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index a965709..dd14135 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -142,7 +142,7 @@
     virtual int32_t getAAudioMixerBurstCount() = 0;
     virtual int32_t getAAudioHardwareBurstMinUsec() = 0;
 
-    virtual int32_t supportsBluetoothVariableLatency(bool* supports) = 0;
+    virtual status_t supportsBluetoothVariableLatency(bool* supports) = 0;
 
     // Update the connection status of an external device.
     virtual status_t setConnectedState(const struct audio_port_v7* port, bool connected) = 0;
diff --git a/media/libmedia/include/media/mediametadataretriever.h b/media/libmedia/include/media/mediametadataretriever.h
index fba1a30..9074574 100644
--- a/media/libmedia/include/media/mediametadataretriever.h
+++ b/media/libmedia/include/media/mediametadataretriever.h
@@ -96,13 +96,19 @@
     status_t setDataSource(
             const sp<IDataSource>& dataSource, const char *mime = NULL);
     sp<IMemory> getFrameAtTime(int64_t timeUs, int option,
-            int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false);
+            int colorFormat, bool metaOnly = false);
+    sp<IMemory> getFrameAtTime(int64_t timeUs, int option,
+            bool metaOnly = false);
     sp<IMemory> getImageAtIndex(int index,
-            int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false, bool thumbnail = false);
+            int colorFormat, bool metaOnly = false, bool thumbnail = false);
+    sp<IMemory> getImageAtIndex(int index,
+            bool metaOnly = false, bool thumbnail = false);
     sp<IMemory> getImageRectAtIndex(
             int index, int colorFormat, int left, int top, int right, int bottom);
     sp<IMemory>  getFrameAtIndex(
-            int index, int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false);
+            int index, int colorFormat, bool metaOnly = false);
+    sp<IMemory>  getFrameAtIndex(
+            int index, bool metaOnly = false);
     sp<IMemory> extractAlbumArt();
     const char* extractMetadata(int keyCode);
 
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 2ae76b3..427a3bd 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -142,6 +142,11 @@
 }
 
 sp<IMemory> MediaMetadataRetriever::getFrameAtTime(
+        int64_t timeUs, int option, bool metaOnly) {
+    return getFrameAtTime(timeUs, option, HAL_PIXEL_FORMAT_RGB_565, metaOnly);
+}
+
+sp<IMemory> MediaMetadataRetriever::getFrameAtTime(
         int64_t timeUs, int option, int colorFormat, bool metaOnly)
 {
     ALOGV("getFrameAtTime: time(%" PRId64 " us) option(%d) colorFormat(%d) metaOnly(%d)",
@@ -155,6 +160,11 @@
 }
 
 sp<IMemory> MediaMetadataRetriever::getImageAtIndex(
+        int index, bool metaOnly, bool thumbnail) {
+    return getImageAtIndex(index, HAL_PIXEL_FORMAT_RGB_565, metaOnly, thumbnail);
+}
+
+sp<IMemory> MediaMetadataRetriever::getImageAtIndex(
         int index, int colorFormat, bool metaOnly, bool thumbnail) {
     ALOGV("getImageAtIndex: index(%d) colorFormat(%d) metaOnly(%d) thumbnail(%d)",
             index, colorFormat, metaOnly, thumbnail);
@@ -180,6 +190,11 @@
 }
 
 sp<IMemory>  MediaMetadataRetriever::getFrameAtIndex(
+        int index, bool metaOnly) {
+    return getFrameAtIndex(index, HAL_PIXEL_FORMAT_RGB_565, metaOnly);
+}
+
+sp<IMemory>  MediaMetadataRetriever::getFrameAtIndex(
         int index, int colorFormat, bool metaOnly) {
     ALOGV("getFrameAtIndex: index(%d), colorFormat(%d) metaOnly(%d)",
             index, colorFormat, metaOnly);
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 44e78d6..718f782 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -47,6 +47,7 @@
         "framework-permission-aidl-cpp",
         "libaudioclient_aidl_conversion",
         "libbase",
+        "libbinder_ndk",
         "libactivitymanager_aidl",
         "libandroid_net",
         "libaudioclient",
diff --git a/media/libmediaplayerservice/DeathNotifier.cpp b/media/libmediaplayerservice/DeathNotifier.cpp
index d13bdf5..ab22f67 100644
--- a/media/libmediaplayerservice/DeathNotifier.cpp
+++ b/media/libmediaplayerservice/DeathNotifier.cpp
@@ -31,6 +31,10 @@
     DeathRecipient(Notify const& notify): mNotify{notify} {
     }
 
+    void initNdk() {
+        mNdkRecipient.set(AIBinder_DeathRecipient_new(OnBinderDied));
+    }
+
     virtual void binderDied(wp<IBinder> const&) override {
         mNotify();
     }
@@ -39,8 +43,18 @@
         mNotify();
     }
 
+    static void OnBinderDied(void *cookie) {
+        DeathRecipient *thiz = (DeathRecipient *)cookie;
+        thiz->mNotify();
+    }
+
+    AIBinder_DeathRecipient *getNdkRecipient() {
+        return mNdkRecipient.get();;
+    }
+
 private:
     Notify mNotify;
+    ::ndk::ScopedAIBinder_DeathRecipient mNdkRecipient;
 };
 
 DeathNotifier::DeathNotifier(sp<IBinder> const& service, Notify const& notify)
@@ -55,6 +69,14 @@
     service->linkToDeath(mDeathRecipient, 0);
 }
 
+DeathNotifier::DeathNotifier(::ndk::SpAIBinder const& service, Notify const& notify)
+      : mService{std::in_place_index<3>, service},
+        mDeathRecipient{new DeathRecipient(notify)} {
+    mDeathRecipient->initNdk();
+    AIBinder_linkToDeath(
+            service.get(), mDeathRecipient->getNdkRecipient(), mDeathRecipient.get());
+}
+
 DeathNotifier::DeathNotifier(DeathNotifier&& other)
       : mService{other.mService}, mDeathRecipient{other.mDeathRecipient} {
     other.mService.emplace<0>();
@@ -71,6 +93,12 @@
     case 2:
         std::get<2>(mService)->unlinkToDeath(mDeathRecipient);
         break;
+    case 3:
+        AIBinder_unlinkToDeath(
+                std::get<3>(mService).get(),
+                mDeathRecipient->getNdkRecipient(),
+                mDeathRecipient.get());
+        break;
     default:
         CHECK(false) << "Corrupted service type during destruction.";
     }
diff --git a/media/libmediaplayerservice/DeathNotifier.h b/media/libmediaplayerservice/DeathNotifier.h
index 7bc2611..24e45a3 100644
--- a/media/libmediaplayerservice/DeathNotifier.h
+++ b/media/libmediaplayerservice/DeathNotifier.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_MEDIASERVICE_DEATHNOTIFIER_H
 #define ANDROID_MEDIASERVICE_DEATHNOTIFIER_H
 
+#include <android/binder_auto_utils.h>
 #include <android/hidl/base/1.0/IBase.h>
 #include <binder/Binder.h>
 #include <hidl/HidlSupport.h>
@@ -32,11 +33,12 @@
 
     DeathNotifier(sp<IBinder> const& service, Notify const& notify);
     DeathNotifier(sp<HBase> const& service, Notify const& notify);
+    DeathNotifier(::ndk::SpAIBinder const& service, Notify const& notify);
     DeathNotifier(DeathNotifier&& other);
     ~DeathNotifier();
 
 private:
-    std::variant<std::monostate, sp<IBinder>, sp<HBase>> mService;
+    std::variant<std::monostate, sp<IBinder>, sp<HBase>, ::ndk::SpAIBinder> mService;
 
     class DeathRecipient;
     sp<DeathRecipient> mDeathRecipient;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 91599e7..10a1da7 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -927,10 +927,10 @@
         {
             for (std::shared_ptr<Codec2Client> const& client :
                     Codec2Client::CreateFromAllServices()) {
-                sp<IBase> base = client->getBase();
-                deathNotifiers.emplace_back(
-                        base, [l = wp<MediaPlayerBase>(p),
-                               name = std::string(client->getServiceName())]() {
+                sp<IBase> hidlBase = client->getHidlBase();
+                ::ndk::SpAIBinder aidlBase = client->getAidlBase();
+                auto onBinderDied = [l = wp<MediaPlayerBase>(p),
+                                     name = std::string(client->getServiceName())]() {
                     sp<MediaPlayerBase> listener = l.promote();
                     if (listener) {
                         ALOGI("Codec2 service \"%s\" died. "
@@ -944,7 +944,12 @@
                               "without a death handler.",
                               name.c_str());
                     }
-                });
+                };
+                if (hidlBase) {
+                    deathNotifiers.emplace_back(hidlBase, onBinderDied);
+                } else if (aidlBase.get() != nullptr) {
+                    deathNotifiers.emplace_back(aidlBase, onBinderDied);
+                }
             }
         }
     }
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index d6b1c90..ed3ec89 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -22,6 +22,7 @@
 #include "MediaPlayerService.h"
 #include "StagefrightRecorder.h"
 
+#include <android/binder_auto_utils.h>
 #include <android/hardware/media/omx/1.0/IOmx.h>
 #include <android/hardware/media/c2/1.0/IComponentStore.h>
 #include <binder/IPCThreadState.h>
@@ -490,9 +491,9 @@
         {
             for (std::shared_ptr<Codec2Client> const& client :
                     Codec2Client::CreateFromAllServices()) {
-                sp<IBase> base = client->getBase();
-                mDeathNotifiers.emplace_back(
-                        base, [l = wp<IMediaRecorderClient>(listener),
+                sp<IBase> hidlBase = client->getHidlBase();
+                ::ndk::SpAIBinder aidlBase = client->getAidlBase();
+                auto onBinderDied = [l = wp<IMediaRecorderClient>(listener),
                                name = std::string(client->getServiceName())]() {
                     sp<IMediaRecorderClient> listener = l.promote();
                     if (listener) {
@@ -507,7 +508,12 @@
                               "without a death handler",
                               name.c_str());
                     }
-                });
+                };
+                if (hidlBase) {
+                    mDeathNotifiers.emplace_back(hidlBase, onBinderDied);
+                } else if (aidlBase.get() != nullptr) {
+                    mDeathNotifiers.emplace_back(aidlBase, onBinderDied);
+                }
             }
         }
     }
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index 017f403..c3d6c89 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -35,6 +35,7 @@
     shared_libs: [
         "framework-permission-aidl-cpp",
         "libbinder",
+        "libbinder_ndk",
         "libcutils",
         "libmedia",
         "libstagefright",
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 91286b9..e75ca2e 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1791,23 +1791,21 @@
         mFramesInput++;
     }
 
-    const int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
-    BufferFlightTiming_t startdata = { presentationUs, nowNs };
+    // mutex access to mBuffersInFlight and other stats
+    Mutex::Autolock al(mLatencyLock);
 
-    {
-        // mutex access to mBuffersInFlight and other stats
-        Mutex::Autolock al(mLatencyLock);
-
-
-        // XXX: we *could* make sure that the time is later than the end of queue
-        // as part of a consistency check...
+    // XXX: we *could* make sure that the time is later than the end of queue
+    // as part of a consistency check...
+    if (!mTunneled) {
+        const int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
+        BufferFlightTiming_t startdata = { presentationUs, nowNs };
         mBuffersInFlight.push_back(startdata);
-
-        if (mIsLowLatencyModeOn && mIndexOfFirstFrameWhenLowLatencyOn < 0) {
-            mIndexOfFirstFrameWhenLowLatencyOn = mInputBufferCounter;
-        }
-        ++mInputBufferCounter;
     }
+
+    if (mIsLowLatencyModeOn && mIndexOfFirstFrameWhenLowLatencyOn < 0) {
+        mIndexOfFirstFrameWhenLowLatencyOn = mInputBufferCounter;
+    }
+    ++mInputBufferCounter;
 }
 
 // when we get a buffer back from the codec
diff --git a/media/libstagefright/exports.lds b/media/libstagefright/exports.lds
index 7fe6d6c..ee38550 100644
--- a/media/libstagefright/exports.lds
+++ b/media/libstagefright/exports.lds
@@ -171,7 +171,6 @@
         FixedDiv1_C;
         FixedDiv_C;
         fixed_invtbl8;
-        GetARGBBlend;
         H420ToABGR;
         H420ToARGB;
         H422ToABGR;
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 41e9aff..bc57ef7 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -105,6 +105,7 @@
 
     mRTCPAddr = mRTPAddr;
     mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1);
+    mVPSBuf = NULL;
     mSPSBuf = NULL;
     mPPSBuf = NULL;
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index fcf3833..a6a0355 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1910,7 +1910,7 @@
     config->type = AUDIO_PORT_TYPE_MIX;
     config->ext.mix.handle = mId;
     config->sample_rate = mSampleRate;
-    config->format = mFormat;
+    config->format = mHALFormat;
     config->channel_mask = mChannelMask;
     config->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
                             AUDIO_PORT_CONFIG_FORMAT;
@@ -6557,12 +6557,11 @@
     // Ensure volumeshaper state always advances even when muted.
     const sp<AudioTrackServerProxy> proxy = track->audioTrackServerProxy();
 
-    const size_t framesReleased = proxy->framesReleased();
     const int64_t frames = mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
     const int64_t time = mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
 
-    ALOGV("%s: Direct/Offload bufferConsumed:%zu  timestamp frames:%lld  time:%lld",
-            __func__, framesReleased, (long long)frames, (long long)time);
+    ALOGVV("%s: Direct/Offload bufferConsumed:%zu  timestamp frames:%lld  time:%lld",
+            __func__, proxy->framesReleased(), (long long)frames, (long long)time);
 
     const int64_t volumeShaperFrames =
             mMonotonicFrameCounter.updateAndGetMonotonicFrameCount(frames, time);
@@ -9619,6 +9618,7 @@
     Mutex::Autolock _l(mLock);
     AudioStreamIn *input = mInput;
     mInput = NULL;
+    mInputSource.clear();
     return input;
 }
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 3d5c1d2..6f19a7a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -618,13 +618,15 @@
     }
     // Convert Sink name to port pointer
     sp<PolicyAudioPort> sink = ctx->findPortByTagName(sinkAttr);
-    if (sink == NULL && !mIgnoreVendorExtensions) {
-        ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
-        return BAD_VALUE;
-    } else if (sink == NULL) {
-        ALOGW("Skipping route to sink \"%s\" as it likely has vendor extension type",
-                sinkAttr.c_str());
-        return NO_INIT;
+    if (sink == NULL) {
+        if (!mIgnoreVendorExtensions) {
+            ALOGE("%s: no sink found with name \"%s\"", __func__, sinkAttr.c_str());
+            return BAD_VALUE;
+        } else {
+            ALOGW("%s: skipping route to sink \"%s\" as it likely has vendor extension type",
+                  __func__, sinkAttr.c_str());
+            return NO_INIT;
+        }
     }
     route->setSink(sink);
 
@@ -641,12 +643,14 @@
     while (devTag != NULL) {
         if (strlen(devTag) != 0) {
             sp<PolicyAudioPort> source = ctx->findPortByTagName(devTag);
-            if (source == NULL && !mIgnoreVendorExtensions) {
-                ALOGE("%s: no source found with name=%s", __func__, devTag);
-                return BAD_VALUE;
-            } else if (source == NULL) {
-                ALOGW("Skipping route source \"%s\" as it likely has vendor extension type",
-                        devTag);
+            if (source == NULL) {
+                if (!mIgnoreVendorExtensions) {
+                    ALOGE("%s: no source found with name \"%s\"", __func__, devTag);
+                    return BAD_VALUE;
+                } else {
+                    ALOGW("%s: skipping route source \"%s\" as it likely has vendor extension type",
+                          __func__, devTag);
+                }
             } else {
                 sources.add(source);
             }
@@ -728,10 +732,16 @@
                         sp<DeviceDescriptor> device = module->getDeclaredDevices().
                                 getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
                                                         attachedDevice.get())));
-                        if (device == nullptr && mIgnoreVendorExtensions) {
-                            ALOGW("Skipped attached device \"%s\" because it likely uses a vendor"
-                                    "extension type",
-                                    reinterpret_cast<const char*>(attachedDevice.get()));
+                        if (device == NULL) {
+                            if (mIgnoreVendorExtensions) {
+                                ALOGW("%s: skipped attached device \"%s\" because it likely uses a "
+                                      "vendor extension type",
+                                      __func__,
+                                      reinterpret_cast<const char*>(attachedDevice.get()));
+                            } else {
+                                ALOGE("%s: got null device in %s, \"%s\"", __func__, child->name,
+                                      reinterpret_cast<const char*>(attachedDevice.get()));
+                            }
                             continue;
                         }
                         ctx->addDevice(device);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index a2ec576..28be652 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -86,6 +86,7 @@
 };
 
 #define CAMERA_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0)
+#define CAMERA_DEVICE_API_VERSION_1_2 HARDWARE_DEVICE_API_VERSION(1, 2)
 #define CAMERA_DEVICE_API_VERSION_3_0 HARDWARE_DEVICE_API_VERSION(3, 0)
 #define CAMERA_DEVICE_API_VERSION_3_1 HARDWARE_DEVICE_API_VERSION(3, 1)
 #define CAMERA_DEVICE_API_VERSION_3_2 HARDWARE_DEVICE_API_VERSION(3, 2)
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index a0e2778..7db3787 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -51,6 +51,7 @@
 #include <cutils/properties.h>
 #include <camera/StringUtils.h>
 
+#include <android-base/properties.h>
 #include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
 #include <android/hardware/camera2/ICameraDeviceUser.h>
 
@@ -770,8 +771,7 @@
         auto firstRequest = requestList->begin();
         for (auto& outputStream : (*firstRequest)->mOutputStreams) {
             if (outputStream->isVideoStream()) {
-                (*firstRequest)->mBatchSize = requestList->size();
-                outputStream->setBatchSize(requestList->size());
+                applyMaxBatchSizeLocked(requestList, outputStream);
                 break;
             }
         }
@@ -2339,6 +2339,9 @@
     // deadlocks (http://b/143513518)
     nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
 
+    // Make sure status tracker is flushed
+    mStatusTracker->flushPendingStates();
+
     Mutex::Autolock l(mLock);
     if (checkAbandonedStreamsLocked()) {
         ALOGW("%s: Abandoned stream detected, session parameters can't be applied correctly!",
@@ -3032,6 +3035,7 @@
         mDoPause(false),
         mPaused(true),
         mNotifyPipelineDrain(false),
+        mPrevTriggers(0),
         mFrameNumber(0),
         mLatestRequestId(NAME_NOT_FOUND),
         mCurrentAfTriggerId(0),
@@ -3040,7 +3044,6 @@
         mAutoframingOverride(ANDROID_CONTROL_AUTOFRAMING_OFF),
         mComposerOutput(false),
         mCameraMute(ANDROID_SENSOR_TEST_PATTERN_MODE_OFF),
-        mCameraMuteChanged(false),
         mSettingsOverride(ANDROID_CONTROL_SETTINGS_OVERRIDE_OFF),
         mRepeatingLastFrameNumber(
             hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
@@ -4235,7 +4238,6 @@
     Mutex::Autolock l(mTriggerMutex);
     if (muteMode != mCameraMute) {
         mCameraMute = muteMode;
-        mCameraMuteChanged = true;
     }
     return OK;
 }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 0c1bbcb..dfa3b19 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -703,6 +703,15 @@
     status_t initializeCommonLocked();
 
     /**
+     * Update capture request list so that each batch size honors the batch_size_max report from
+     * the HAL. Set the batch size to output stream for buffer operations.
+     *
+     * Must be called with mLock held.
+     */
+    virtual void applyMaxBatchSizeLocked(
+            RequestList* requestList, const sp<camera3::Camera3OutputStreamInterface>& stream) = 0;
+
+    /**
      * Get the last request submitted to the hal by the request thread.
      *
      * Must be called with mLock held.
@@ -1156,7 +1165,6 @@
         camera_metadata_enum_android_control_autoframing_t mAutoframingOverride;
         bool               mComposerOutput;
         int32_t            mCameraMute; // 0 = no mute, otherwise the TEST_PATTERN_MODE to use
-        bool               mCameraMuteChanged;
         int32_t            mSettingsOverride; // -1 = use original, otherwise
                                               // the settings override to use.
 
diff --git a/services/camera/libcameraservice/device3/StatusTracker.cpp b/services/camera/libcameraservice/device3/StatusTracker.cpp
index bd78e0a..f13109a 100644
--- a/services/camera/libcameraservice/device3/StatusTracker.cpp
+++ b/services/camera/libcameraservice/device3/StatusTracker.cpp
@@ -34,7 +34,8 @@
         mParent(parent),
         mNextComponentId(0),
         mIdleFence(new Fence()),
-        mDeviceState(IDLE) {
+        mDeviceState(IDLE),
+        mFlushed(true) {
 }
 
 StatusTracker::~StatusTracker() {
@@ -111,16 +112,33 @@
         const sp<Fence>& componentFence) {
     ALOGV("%s: Component %d is now %s", __FUNCTION__, id,
             state == IDLE ? "idle" : "active");
-    Mutex::Autolock l(mPendingLock);
 
-    StateChange newState = {
-        id,
-        state,
-        componentFence
-    };
+    // If any component state changes, the status tracker is considered
+    // not flushed.
+    {
+        Mutex::Autolock l(mFlushLock);
+        mFlushed = false;
+    }
 
-    mPendingChangeQueue.add(newState);
-    mPendingChangeSignal.signal();
+    {
+        Mutex::Autolock l(mPendingLock);
+
+        StateChange newState = {
+            id,
+            state,
+            componentFence
+        };
+
+        mPendingChangeQueue.add(newState);
+        mPendingChangeSignal.signal();
+    }
+}
+
+void StatusTracker::flushPendingStates()  {
+    Mutex::Autolock l(mFlushLock);
+    while (!mFlushed && isRunning()) {
+        mFlushCondition.waitRelative(mFlushLock, kWaitDuration);
+    }
 }
 
 void StatusTracker::requestExit() {
@@ -128,6 +146,7 @@
     Thread::requestExit();
     // Then exit any waits
     mPendingChangeSignal.signal();
+    mFlushCondition.signal();
 }
 
 StatusTracker::ComponentState StatusTracker::getDeviceStateLocked() {
@@ -231,6 +250,17 @@
     }
     mStateTransitions.clear();
 
+    // After all pending changes are cleared and notified, mark the tracker
+    // as flushed.
+    {
+        Mutex::Autolock fl(mFlushLock);
+        Mutex::Autolock pl(mPendingLock);
+        if (mPendingChangeQueue.size() == 0) {
+            mFlushed = true;
+            mFlushCondition.signal();
+        }
+    }
+
     if (waitForIdleFence) {
         auto ret = mIdleFence->wait(kWaitDuration);
         if (ret == NO_ERROR) {
diff --git a/services/camera/libcameraservice/device3/StatusTracker.h b/services/camera/libcameraservice/device3/StatusTracker.h
index 069bff6..fc65502 100644
--- a/services/camera/libcameraservice/device3/StatusTracker.h
+++ b/services/camera/libcameraservice/device3/StatusTracker.h
@@ -70,6 +70,10 @@
 
     void dumpActiveComponents();
 
+    // Flush all pending states inflight in the tracker, and return upon
+    // completion.
+    void flushPendingStates();
+
     virtual void requestExit();
   protected:
 
@@ -113,6 +117,11 @@
     // Current overall device state
     ComponentState mDeviceState;
 
+    // For flushing all pending states transitions
+    bool mFlushed;
+    Mutex mFlushLock;
+    Condition mFlushCondition;
+
     // Private to threadLoop
 
     // Determine current overall device state
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index af48dd6..272c390 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -51,6 +51,7 @@
 
 #include <aidl/android/hardware/camera/device/ICameraInjectionSession.h>
 #include <aidlcommonsupport/NativeHandle.h>
+#include <android-base/properties.h>
 #include <android/binder_ibinder_platform.h>
 #include <android/hardware/camera2/ICameraDeviceUser.h>
 #include <camera/StringUtils.h>
@@ -313,6 +314,20 @@
         }
     }
 
+    // batch size limit is applied to the device with camera device version larger than 3.2 which is
+    // AIDL v2
+    hardware::hidl_version maxVersion{0, 0};
+    IPCTransport transport = IPCTransport::AIDL;
+    res = manager->getHighestSupportedVersion(mId, &maxVersion, &transport);
+    if (res != OK) {
+        ALOGE("%s: Error in getting camera device version id: %s (%d)", __FUNCTION__,
+              strerror(-res), res);
+        return res;
+    }
+    int deviceVersion = HARDWARE_DEVICE_API_VERSION(maxVersion.get_major(), maxVersion.get_minor());
+
+    mBatchSizeLimitEnabled = (deviceVersion >= CAMERA_DEVICE_API_VERSION_1_2);
+
     return initializeCommonLocked();
 }
 
@@ -1580,6 +1595,66 @@
     return OK;
 }
 
+void AidlCamera3Device::applyMaxBatchSizeLocked(
+        RequestList* requestList, const sp<camera3::Camera3OutputStreamInterface>& stream) {
+    int batchSize = requestList->size();
+
+    if (!mBatchSizeLimitEnabled) {
+        (*requestList->begin())->mBatchSize = batchSize;
+        stream->setBatchSize(batchSize);
+        return;
+    }
+
+    const auto& metadata = (*requestList->begin())->mSettingsList.begin()->metadata;
+
+    uint32_t tag = ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS;
+    auto sensorPixelModeEntry = metadata.find(ANDROID_SENSOR_PIXEL_MODE);
+    if (sensorPixelModeEntry.count != 0) {
+        if (ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION == sensorPixelModeEntry.data.u8[0]) {
+            tag = ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION;
+        }
+    }
+
+    const auto fpsRange = metadata.find(ANDROID_CONTROL_AE_TARGET_FPS_RANGE);
+    if (fpsRange.count > 1) {
+        auto configEntry = mDeviceInfo.find(tag);
+        for (size_t index = 4; index < configEntry.count; index += 5) {
+            if (stream->getWidth() == static_cast<uint32_t>(configEntry.data.i32[index - 4]) &&
+                stream->getHeight() == static_cast<uint32_t>(configEntry.data.i32[index - 3]) &&
+                fpsRange.data.i32[0] == configEntry.data.i32[index - 2] &&
+                fpsRange.data.i32[1] == configEntry.data.i32[index - 1]) {
+                const int maxBatchSize = configEntry.data.i32[index - 1] / 30;
+                const int reportedSize = configEntry.data.i32[index];
+
+                if (maxBatchSize % reportedSize == 0 && requestList->size() % reportedSize == 0) {
+                    batchSize = reportedSize;
+                    ALOGVV("Matching high speed configuration found. Limit batch size to %d",
+                           batchSize);
+                } else if (maxBatchSize % reportedSize == 0 &&
+                           reportedSize % requestList->size() == 0) {
+                    ALOGVV("Matching high speed configuration found, but requested batch size is "
+                           "divisor of batch_size_max. No need to limit batch size.");
+                } else {
+                    ALOGW("Matching high speed configuration found, but batch_size_max is not a "
+                          "divisor of corresponding fps_max/30 or requested batch size is not a "
+                          "divisor of batch_size_max, (fps_max %d, batch_size_max %d, requested "
+                          "batch size %zu)",
+                          configEntry.data.i32[index - 1], reportedSize, requestList->size());
+                }
+                break;
+            }
+        }
+    }
+
+    for (auto request = requestList->begin(); request != requestList->end(); request++) {
+        if (requestList->distance(requestList->begin(), request) % batchSize == 0) {
+            (*request)->mBatchSize = batchSize;
+        }
+    }
+
+    stream->setBatchSize(batchSize);
+}
+
 status_t AidlCamera3Device::injectionCameraInitialize(const std::string &injectedCamId,
             sp<CameraProviderManager> manager) {
         return (static_cast<AidlCamera3DeviceInjectionMethods *>
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
index e0be367..21813d4 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
@@ -257,6 +257,10 @@
     };
 
   private:
+    virtual void applyMaxBatchSizeLocked(
+            RequestList* requestList,
+            const sp<camera3::Camera3OutputStreamInterface>& stream) override;
+
     virtual status_t injectionCameraInitialize(const std::string &injectCamId,
             sp<CameraProviderManager> manager) override;
 
@@ -277,6 +281,9 @@
 
     std::shared_ptr<AidlCameraDeviceCallbacks> mCallbacks = nullptr;
 
+    // Whether the batch_size_max field in the high speed configuration actually applied to
+    // capture requests.
+    bool mBatchSizeLimitEnabled = false;
 
 }; // class AidlCamera3Device
 
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
index 06af5ff..4488067 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
@@ -699,6 +699,14 @@
     // Java side to make sure the CameraCaptureSession is properly closed
 }
 
+void HidlCamera3Device::applyMaxBatchSizeLocked(
+        RequestList* requestList, const sp<camera3::Camera3OutputStreamInterface>& stream) {
+    int batchSize = requestList->size();
+
+    (*requestList->begin())->mBatchSize = batchSize;
+    stream->setBatchSize(batchSize);
+}
+
 sp<Camera3Device::RequestThread> HidlCamera3Device::createNewRequestThread(
                 wp<Camera3Device> parent, sp<camera3::StatusTracker> statusTracker,
                 sp<Camera3Device::HalInterface> interface,
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
index 2cfdf9d..350b072 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
@@ -218,6 +218,10 @@
     hardware::Return<void> notifyHelper(
             const hardware::hidl_vec<NotifyMsgType>& msgs);
 
+    virtual void applyMaxBatchSizeLocked(
+            RequestList* requestList,
+            const sp<camera3::Camera3OutputStreamInterface>& stream) override;
+
     virtual status_t injectionCameraInitialize(const std::string &injectCamId,
             sp<CameraProviderManager> manager) override;