Merge "mediadrm: use stable C interface to record metrics"
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 3e8992a..62dbb5e 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -87,6 +87,7 @@
     ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks,
             String cameraId,
             String opPackageName,
+            @nullable String featureId,
             int clientUid);
 
     /**
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 9d40fd7..8eb030a 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -517,7 +517,7 @@
     // No way to get package name from native.
     // Send a zero length package name and let camera service figure it out from UID
     binder::Status serviceRet = cs->connectDevice(
-            callbacks, String16(cameraId), String16(""),
+            callbacks, String16(cameraId), String16(""), std::unique_ptr<String16>(),
             hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
 
     if (!serviceRet.isOk()) {
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index f07a1e6..9a18b10 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -361,7 +361,8 @@
         sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
         sp<hardware::camera2::ICameraDeviceUser> device;
         res = service->connectDevice(callbacks, cameraId, String16("meeeeeeeee!"),
-                hardware::ICameraService::USE_CALLING_UID, /*out*/&device);
+                std::unique_ptr<String16>(), hardware::ICameraService::USE_CALLING_UID,
+                /*out*/&device);
         EXPECT_TRUE(res.isOk()) << res;
         ASSERT_NE(nullptr, device.get());
         device->disconnect();
@@ -403,7 +404,8 @@
         {
             SCOPED_TRACE("openNewDevice");
             binder::Status res = service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"),
-                    hardware::ICameraService::USE_CALLING_UID, /*out*/&device);
+                    std::unique_ptr<String16>(), hardware::ICameraService::USE_CALLING_UID,
+                    /*out*/&device);
             EXPECT_TRUE(res.isOk()) << res;
         }
         auto p = std::make_pair(callbacks, device);
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 8ff0802..34a2f69 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -17,10 +17,6 @@
     srcs: [
         "DrmPluginPath.cpp",
         "DrmSessionManager.cpp",
-        "ICrypto.cpp",
-        "IDrm.cpp",
-        "IDrmClient.cpp",
-        "IMediaDrmService.cpp",
         "SharedLibrary.cpp",
         "DrmHal.cpp",
         "CryptoHal.cpp",
@@ -42,6 +38,7 @@
 
     shared_libs: [
         "libbinder",
+        "libbinder_ndk",
         "libcutils",
         "libdl",
         "liblog",
@@ -49,7 +46,6 @@
         "libmediadrmmetrics_lite",
         "libmediametrics#1",
         "libmediautils",
-        "libresourcemanagerservice",
         "libstagefright_foundation",
         "libutils",
         "android.hardware.drm@1.0",
@@ -59,6 +55,10 @@
         "libhidlbase",
     ],
 
+    static_libs: [
+        "resourcemanager_aidl_interface-ndk_platform",
+    ],
+
     export_shared_lib_headers: [
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.1",
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index bc207f3..8c2d8f2 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -23,9 +23,9 @@
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 
+#include <aidl/android/media/BnResourceManagerClient.h>
 #include <android/hardware/drm/1.2/types.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
-#include <android/media/BnResourceManagerClient.h>
 #include <hidl/ServiceManagement.h>
 #include <media/EventMetric.h>
 #include <media/MediaMetrics.h>
@@ -299,17 +299,16 @@
 
 Mutex DrmHal::mLock;
 
-struct DrmHal::DrmSessionClient : public android::media::BnResourceManagerClient {
+struct DrmHal::DrmSessionClient : public aidl::android::media::BnResourceManagerClient {
     explicit DrmSessionClient(DrmHal* drm, const Vector<uint8_t>& sessionId)
       : mSessionId(sessionId),
         mDrm(drm) {}
 
-    ::android::binder::Status reclaimResource(bool* _aidl_return) override;
-    ::android::binder::Status getName(::std::string* _aidl_return) override;
+    ::ndk::ScopedAStatus reclaimResource(bool* _aidl_return) override;
+    ::ndk::ScopedAStatus getName(::std::string* _aidl_return) override;
 
     const Vector<uint8_t> mSessionId;
 
-protected:
     virtual ~DrmSessionClient();
 
 private:
@@ -318,24 +317,25 @@
     DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
 };
 
-::android::binder::Status DrmHal::DrmSessionClient::reclaimResource(bool* _aidl_return) {
+::ndk::ScopedAStatus DrmHal::DrmSessionClient::reclaimResource(bool* _aidl_return) {
+    auto sessionId = mSessionId;
     sp<DrmHal> drm = mDrm.promote();
     if (drm == NULL) {
         *_aidl_return = true;
-        return ::android::binder::Status::ok();
+        return ::ndk::ScopedAStatus::ok();
     }
-    status_t err = drm->closeSession(mSessionId);
+    status_t err = drm->closeSession(sessionId);
     if (err != OK) {
         *_aidl_return = false;
-        return ::android::binder::Status::ok();
+        return ::ndk::ScopedAStatus::ok();
     }
     drm->sendEvent(EventType::SESSION_RECLAIMED,
-            toHidlVec(mSessionId), hidl_vec<uint8_t>());
+            toHidlVec(sessionId), hidl_vec<uint8_t>());
     *_aidl_return = true;
-    return ::android::binder::Status::ok();
+    return ::ndk::ScopedAStatus::ok();
 }
 
-::android::binder::Status DrmHal::DrmSessionClient::getName(::std::string* _aidl_return) {
+::ndk::ScopedAStatus DrmHal::DrmSessionClient::getName(::std::string* _aidl_return) {
     String8 name;
     sp<DrmHal> drm = mDrm.promote();
     if (drm == NULL) {
@@ -350,7 +350,7 @@
     }
     name.append("]");
     *_aidl_return = name;
-    return ::android::binder::Status::ok();
+    return ::ndk::ScopedAStatus::ok();
 }
 
 DrmHal::DrmSessionClient::~DrmSessionClient() {
@@ -481,12 +481,6 @@
 status_t DrmHal::setListener(const sp<IDrmClient>& listener)
 {
     Mutex::Autolock lock(mEventLock);
-    if (mListener != NULL){
-        IInterface::asBinder(mListener)->unlinkToDeath(this);
-    }
-    if (listener != NULL) {
-        IInterface::asBinder(listener)->linkToDeath(this);
-    }
     mListener = listener;
     return NO_ERROR;
 }
@@ -765,9 +759,10 @@
     } while (retry);
 
     if (err == OK) {
-        sp<DrmSessionClient> client(new DrmSessionClient(this, sessionId));
-        DrmSessionManager::Instance()->addSession(getCallingPid(), client, sessionId);
-        mOpenSessions.push(client);
+        std::shared_ptr<DrmSessionClient> client(new DrmSessionClient(this, sessionId));
+        DrmSessionManager::Instance()->addSession(getCallingPid(),
+                std::static_pointer_cast<IResourceManagerClient>(client), sessionId);
+        mOpenSessions.push_back(client);
         mMetrics.SetSessionStart(sessionId);
     }
 
@@ -783,9 +778,9 @@
     if (status.isOk()) {
         if (status == Status::OK) {
             DrmSessionManager::Instance()->removeSession(sessionId);
-            for (size_t i = 0; i < mOpenSessions.size(); i++) {
-                if (isEqualSessionId(mOpenSessions[i]->mSessionId, sessionId)) {
-                    mOpenSessions.removeAt(i);
+            for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) {
+                if (isEqualSessionId((*i)->mSessionId, sessionId)) {
+                    mOpenSessions.erase(i);
                     break;
                 }
             }
@@ -1569,11 +1564,6 @@
     return hResult.isOk() ? err : DEAD_OBJECT;
 }
 
-void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
-{
-    cleanup();
-}
-
 void DrmHal::reportFrameworkMetrics() const
 {
     mediametrics_handle_t item(mediametrics_create("mediadrm"));
diff --git a/drm/libmediadrm/DrmSessionManager.cpp b/drm/libmediadrm/DrmSessionManager.cpp
index 165a4d6..7a4e1ae 100644
--- a/drm/libmediadrm/DrmSessionManager.cpp
+++ b/drm/libmediadrm/DrmSessionManager.cpp
@@ -18,13 +18,12 @@
 #define LOG_TAG "DrmSessionManager"
 #include <utils/Log.h>
 
-#include <android/media/IResourceManagerClient.h>
-#include <android/media/IResourceManagerService.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IProcessInfoService.h>
-#include <binder/IServiceManager.h>
+#include <aidl/android/media/IResourceManagerClient.h>
+#include <aidl/android/media/IResourceManagerService.h>
+#include <aidl/android/media/MediaResourceParcel.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
 #include <cutils/properties.h>
-#include <media/MediaResource.h>
 #include <mediadrm/DrmUtils.h>
 #include <mediadrm/DrmSessionManager.h>
 #include <unistd.h>
@@ -32,10 +31,18 @@
 
 #include <vector>
 
-#include "ResourceManagerService.h"
-
 namespace android {
-using android::binder::Status;
+
+using aidl::android::media::MediaResourceParcel;
+
+namespace {
+void ResourceManagerServiceDied(void* cookie) {
+    auto thiz = static_cast<DrmSessionManager*>(cookie);
+    thiz->binderDied();
+}
+}
+
+using ::ndk::ScopedAStatus;
 
 static String8 GetSessionIdString(const Vector<uint8_t> &sessionId) {
     String8 sessionIdStr;
@@ -45,34 +52,28 @@
     return sessionIdStr;
 }
 
-static std::vector<uint8_t> toStdVec(const Vector<uint8_t> &vector) {
-    const uint8_t *v = vector.array();
-    std::vector<uint8_t> vec(v, v + vector.size());
+template <typename Byte = uint8_t>
+static std::vector<Byte> toStdVec(const Vector<uint8_t> &vector) {
+    auto v = reinterpret_cast<const Byte *>(vector.array());
+    std::vector<Byte> vec(v, v + vector.size());
     return vec;
 }
 
-static uint64_t toClientId(const sp<IResourceManagerClient>& drm) {
-    return reinterpret_cast<int64_t>(drm.get());
-}
-
 static std::vector<MediaResourceParcel> toResourceVec(
         const Vector<uint8_t> &sessionId, int64_t value) {
+    using Type = aidl::android::media::MediaResourceType;
+    using SubType = aidl::android::media::MediaResourceSubType;
     std::vector<MediaResourceParcel> resources;
-    resources.push_back(MediaResource::DrmSessionResource(toStdVec(sessionId), value));
+    MediaResourceParcel resource{
+            Type::kDrmSession, SubType::kUnspecifiedSubType,
+            toStdVec<int8_t>(sessionId), value};
+    resources.push_back(resource);
     return resources;
 }
 
-static sp<IResourceManagerService> getResourceManagerService() {
-    if (DrmUtils::UseDrmService()) {
-        // Create ResourceManagerService object in mediadrmserver process
-        return new android::media::ResourceManagerService();
-    }
-    sp<IServiceManager> sm = defaultServiceManager();
-    if (sm == NULL) {
-        return NULL;
-    }
-    sp<IBinder> binder = sm->getService(String16("media.resource_manager"));
-    return interface_cast<IResourceManagerService>(binder);
+static std::shared_ptr<IResourceManagerService> getResourceManagerService() {
+    ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager"));
+    return IResourceManagerService::fromBinder(binder);
 }
 
 bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2) {
@@ -88,7 +89,7 @@
 }
 
 sp<DrmSessionManager> DrmSessionManager::Instance() {
-    static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager();
+    auto drmSessionManager = new DrmSessionManager();
     drmSessionManager->init();
     return drmSessionManager;
 }
@@ -97,9 +98,10 @@
     : DrmSessionManager(getResourceManagerService()) {
 }
 
-DrmSessionManager::DrmSessionManager(const sp<IResourceManagerService> &service)
+DrmSessionManager::DrmSessionManager(const std::shared_ptr<IResourceManagerService> &service)
     : mService(service),
-      mInitialized(false) {
+      mInitialized(false),
+      mDeathRecipient(AIBinder_DeathRecipient_new(ResourceManagerServiceDied)) {
     if (mService == NULL) {
         ALOGE("Failed to init ResourceManagerService");
     }
@@ -107,7 +109,7 @@
 
 DrmSessionManager::~DrmSessionManager() {
     if (mService != NULL) {
-        IInterface::asBinder(mService)->unlinkToDeath(this);
+        AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
     }
 }
 
@@ -118,13 +120,13 @@
     }
     mInitialized = true;
     if (mService != NULL) {
-        IInterface::asBinder(mService)->linkToDeath(this);
+        AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
     }
 }
 
 void DrmSessionManager::addSession(int pid,
-        const sp<IResourceManagerClient>& drm, const Vector<uint8_t> &sessionId) {
-    uid_t uid = IPCThreadState::self()->getCallingUid();
+        const std::shared_ptr<IResourceManagerClient>& drm, const Vector<uint8_t> &sessionId) {
+    uid_t uid = AIBinder_getCallingUid();
     ALOGV("addSession(pid %d, uid %d, drm %p, sessionId %s)", pid, uid, drm.get(),
             GetSessionIdString(sessionId).string());
 
@@ -133,9 +135,9 @@
         return;
     }
 
-    int64_t clientId = toClientId(drm);
+    static int64_t clientId = 0;
     mSessionMap[toStdVec(sessionId)] = (SessionInfo){pid, uid, clientId};
-    mService->addResource(pid, uid, clientId, drm, toResourceVec(sessionId, INT64_MAX));
+    mService->addResource(pid, uid, clientId++, drm, toResourceVec(sessionId, INT64_MAX));
 }
 
 void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
@@ -170,7 +172,7 @@
 
     // unlock early because reclaimResource might callback into removeSession
     mLock.lock();
-    sp<IResourceManagerService> service(mService);
+    std::shared_ptr<IResourceManagerService> service(mService);
     mLock.unlock();
 
     if (service == NULL) {
@@ -181,7 +183,7 @@
     // we rely on IResourceManagerClient to removeSession in reclaimResource
     Vector<uint8_t> dummy;
     bool success;
-    Status status = service->reclaimResource(callingPid, toResourceVec(dummy, INT64_MAX), &success);
+    ScopedAStatus status = service->reclaimResource(callingPid, toResourceVec(dummy, INT64_MAX), &success);
     return status.isOk() && success;
 }
 
@@ -195,10 +197,10 @@
     return mSessionMap.count(toStdVec(sessionId));
 }
 
-void DrmSessionManager::binderDied(const wp<IBinder>& /*who*/) {
+void DrmSessionManager::binderDied() {
     ALOGW("ResourceManagerService died.");
     Mutex::Autolock lock(mLock);
-    mService.clear();
+    mService.reset();
 }
 
 }  // namespace android
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index dd30744..a126a1d 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -17,9 +17,20 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "DrmUtils"
 
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.1/ICryptoFactory.h>
+#include <android/hardware/drm/1.1/IDrmFactory.h>
+#include <android/hardware/drm/1.2/ICryptoFactory.h>
+#include <android/hardware/drm/1.2/IDrmFactory.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <hidl/HidlSupport.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
 #include <utils/String16.h>
-#include <binder/IInterface.h>
-#include <binder/IServiceManager.h>
 #include <cutils/properties.h>
 
 #include <mediadrm/CryptoHal.h>
@@ -27,31 +38,23 @@
 #include <mediadrm/DrmUtils.h>
 #include <mediadrm/ICrypto.h>
 #include <mediadrm/IDrm.h>
-#include <mediadrm/IMediaDrmService.h>
+
+using HServiceManager = ::android::hidl::manager::V1_0::IServiceManager;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using namespace ::android::hardware::drm;
 
 namespace android {
 namespace DrmUtils {
 
 namespace {
-template<typename Iface>
-sp<Iface> MakeObjectWithService(status_t *pstatus) {
+
+template<typename Hal>
+Hal *MakeObject(status_t *pstatus) {
     status_t err = OK;
     status_t &status = pstatus ? *pstatus : err;
-    sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->getService(String16("media.drm"));
-
-    sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
-    if (service == NULL) {
-        status = UNKNOWN_ERROR;
-        return NULL;
-    }
-
-    auto obj = service->makeObject<Iface>();
-    if (obj == NULL) {
-        status = UNKNOWN_ERROR;
-        return NULL;
-    }
-
+    auto obj = new Hal();
     status = obj->initCheck();
     if (status != OK && status != NO_INIT) {
         return NULL;
@@ -59,14 +62,69 @@
     return obj;
 }
 
-template<typename Iface, typename Hal>
-sp<Iface> MakeObject(status_t *pstatus) {
-    if (UseDrmService()) {
-        return MakeObjectWithService<Iface>(pstatus);
-    } else {
-        return new Hal();
+template <typename Hal, typename V>
+void MakeHidlFactories(const uint8_t uuid[16], V &factories) {
+    sp<HServiceManager> serviceManager = HServiceManager::getService();
+    if (serviceManager == nullptr) {
+        ALOGE("Failed to get service manager");
+        exit(-1);
     }
+
+    serviceManager->listByInterface(Hal::descriptor, [&](const hidl_vec<hidl_string> &registered) {
+        for (const auto &instance : registered) {
+            auto factory = Hal::getService(instance);
+            if (factory != nullptr) {
+                ALOGI("found %s %s", Hal::descriptor, instance.c_str());
+                if (factory->isCryptoSchemeSupported(uuid)) {
+                    factories.push_back(factory);
+                }
+            }
+        }
+    });
 }
+
+hidl_vec<uint8_t> toHidlVec(const void *ptr, size_t size) {
+    hidl_vec<uint8_t> vec(size);
+    if (ptr != nullptr) {
+        memcpy(vec.data(), ptr, size);
+    }
+    return vec;
+}
+
+hidl_array<uint8_t, 16> toHidlArray16(const uint8_t *ptr) {
+    if (ptr == nullptr) {
+        return hidl_array<uint8_t, 16>();
+    }
+    return hidl_array<uint8_t, 16>(ptr);
+}
+
+sp<::V1_0::IDrmPlugin> MakeDrmPlugin(const sp<::V1_0::IDrmFactory> &factory,
+                                     const uint8_t uuid[16], const char *appPackageName) {
+    sp<::V1_0::IDrmPlugin> plugin;
+    factory->createPlugin(toHidlArray16(uuid), hidl_string(appPackageName),
+                          [&](::V1_0::Status status, const sp<::V1_0::IDrmPlugin> &hPlugin) {
+                              if (status != ::V1_0::Status::OK) {
+                                  return;
+                              }
+                              plugin = hPlugin;
+                          });
+    return plugin;
+}
+
+sp<::V1_0::ICryptoPlugin> MakeCryptoPlugin(const sp<::V1_0::ICryptoFactory> &factory,
+                                           const uint8_t uuid[16], const void *initData,
+                                           size_t initDataSize) {
+    sp<::V1_0::ICryptoPlugin> plugin;
+    factory->createPlugin(toHidlArray16(uuid), toHidlVec(initData, initDataSize),
+                          [&](::V1_0::Status status, const sp<::V1_0::ICryptoPlugin> &hPlugin) {
+                              if (status != ::V1_0::Status::OK) {
+                                  return;
+                              }
+                              plugin = hPlugin;
+                          });
+    return plugin;
+}
+
 } // namespace
 
 bool UseDrmService() {
@@ -74,14 +132,45 @@
 }
 
 sp<IDrm> MakeDrm(status_t *pstatus) {
-    return MakeObject<IDrm, DrmHal>(pstatus);
+    return MakeObject<DrmHal>(pstatus);
 }
 
 sp<ICrypto> MakeCrypto(status_t *pstatus) {
-    if (pstatus) {
-        *pstatus = OK;
+    return MakeObject<CryptoHal>(pstatus);
+}
+
+std::vector<sp<::V1_0::IDrmFactory>> MakeDrmFactories(const uint8_t uuid[16]) {
+    std::vector<sp<::V1_0::IDrmFactory>> drmFactories;
+    MakeHidlFactories<::V1_0::IDrmFactory>(uuid, drmFactories);
+    MakeHidlFactories<::V1_1::IDrmFactory>(uuid, drmFactories);
+    MakeHidlFactories<::V1_2::IDrmFactory>(uuid, drmFactories);
+    return drmFactories;
+}
+
+std::vector<sp<::V1_0::IDrmPlugin>> MakeDrmPlugins(const uint8_t uuid[16],
+                                              const char *appPackageName) {
+    std::vector<sp<::V1_0::IDrmPlugin>> plugins;
+    for (const auto &factory : MakeDrmFactories(uuid)) {
+        plugins.push_back(MakeDrmPlugin(factory, uuid, appPackageName));
     }
-    return new CryptoHal();
+    return plugins;
+}
+
+std::vector<sp<::V1_0::ICryptoFactory>> MakeCryptoFactories(const uint8_t uuid[16]) {
+    std::vector<sp<::V1_0::ICryptoFactory>> cryptoFactories;
+    MakeHidlFactories<::V1_0::ICryptoFactory>(uuid, cryptoFactories);
+    MakeHidlFactories<::V1_1::ICryptoFactory>(uuid, cryptoFactories);
+    MakeHidlFactories<::V1_2::ICryptoFactory>(uuid, cryptoFactories);
+    return cryptoFactories;
+}
+
+std::vector<sp<ICryptoPlugin>> MakeCryptoPlugins(const uint8_t uuid[16], const void *initData,
+                                                 size_t initDataSize) {
+    std::vector<sp<ICryptoPlugin>> plugins;
+    for (const auto &factory : MakeCryptoFactories(uuid)) {
+        plugins.push_back(MakeCryptoPlugin(factory, uuid, initData, initDataSize));
+    }
+    return plugins;
 }
 
 }  // namespace DrmUtils
diff --git a/drm/libmediadrm/ICrypto.cpp b/drm/libmediadrm/ICrypto.cpp
deleted file mode 100644
index a2594aa..0000000
--- a/drm/libmediadrm/ICrypto.cpp
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * Copyright (C) 2012 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 "ICrypto"
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <cutils/log.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AString.h>
-#include <mediadrm/ICrypto.h>
-#include <utils/Log.h>
-
-namespace android {
-
-enum {
-    INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
-    IS_CRYPTO_SUPPORTED,
-    CREATE_PLUGIN,
-    DESTROY_PLUGIN,
-    REQUIRES_SECURE_COMPONENT,
-    DECRYPT,
-    NOTIFY_RESOLUTION,
-    SET_MEDIADRM_SESSION,
-    SET_HEAP,
-    UNSET_HEAP,
-};
-
-struct BpCrypto : public BpInterface<ICrypto> {
-    explicit BpCrypto(const sp<IBinder> &impl)
-        : BpInterface<ICrypto>(impl) {
-    }
-
-    virtual status_t initCheck() const {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        remote()->transact(INIT_CHECK, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.write(uuid, 16);
-        remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
-
-        return reply.readInt32() != 0;
-    }
-
-    virtual status_t createPlugin(
-            const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.write(uuid, 16);
-        data.writeInt32(opaqueSize);
-
-        if (opaqueSize > 0) {
-            data.write(opaqueData, opaqueSize);
-        }
-
-        remote()->transact(CREATE_PLUGIN, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t destroyPlugin() {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        remote()->transact(DESTROY_PLUGIN, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual bool requiresSecureDecoderComponent(
-            const char *mime) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeCString(mime);
-        remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply);
-
-        return reply.readInt32() != 0;
-    }
-
-    virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
-            CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
-            const SourceBuffer &source, size_t offset,
-            const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
-            const DestinationBuffer &destination, AString *errorDetailMsg) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeInt32(mode);
-        data.writeInt32(pattern.mEncryptBlocks);
-        data.writeInt32(pattern.mSkipBlocks);
-
-        static const uint8_t kDummy[16] = { 0 };
-
-        if (key == NULL) {
-            key = kDummy;
-        }
-
-        if (iv == NULL) {
-            iv = kDummy;
-        }
-
-        data.write(key, 16);
-        data.write(iv, 16);
-
-        size_t totalSize = 0;
-        for (size_t i = 0; i < numSubSamples; ++i) {
-            totalSize += subSamples[i].mNumBytesOfEncryptedData;
-            totalSize += subSamples[i].mNumBytesOfClearData;
-        }
-
-        data.writeInt32(totalSize);
-        data.writeStrongBinder(IInterface::asBinder(source.mSharedMemory));
-        data.writeInt32(source.mHeapSeqNum);
-        data.writeInt32(offset);
-
-        data.writeInt32(numSubSamples);
-        data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
-
-        data.writeInt32((int32_t)destination.mType);
-        if (destination.mType == kDestinationTypeNativeHandle) {
-            if (destination.mHandle == NULL) {
-                return BAD_VALUE;
-            }
-            data.writeNativeHandle(destination.mHandle);
-        } else {
-            if (destination.mSharedMemory == NULL) {
-                return BAD_VALUE;
-            }
-            data.writeStrongBinder(IInterface::asBinder(destination.mSharedMemory));
-        }
-
-        remote()->transact(DECRYPT, data, &reply);
-
-        ssize_t result = reply.readInt32();
-
-        if (isCryptoError(result)) {
-            AString msg = reply.readCString();
-            if (errorDetailMsg) {
-                *errorDetailMsg = msg;
-            }
-        }
-
-        return result;
-    }
-
-    virtual void notifyResolution(
-        uint32_t width, uint32_t height) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeInt32(width);
-        data.writeInt32(height);
-        remote()->transact(NOTIFY_RESOLUTION, data, &reply);
-    }
-
-    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        remote()->transact(SET_MEDIADRM_SESSION, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual int32_t setHeap(const sp<IMemoryHeap> &heap) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(heap));
-        status_t err = remote()->transact(SET_HEAP, data, &reply);
-        if (err != NO_ERROR) {
-            return -1;
-        }
-        int32_t seqNum;
-        if (reply.readInt32(&seqNum) != NO_ERROR) {
-            return -1;
-        }
-        return seqNum;
-    }
-
-    virtual void unsetHeap(int32_t seqNum) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeInt32(seqNum);
-        remote()->transact(UNSET_HEAP, data, &reply);
-        return;
-    }
-
-
-private:
-    void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
-        uint32_t size = reply.readInt32();
-        vector.insertAt((size_t)0, size);
-        reply.read(vector.editArray(), size);
-    }
-
-    void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
-        data.writeInt32(vector.size());
-        data.write(vector.array(), vector.size());
-    }
-
-    DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
-};
-
-IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
-
-////////////////////////////////////////////////////////////////////////////////
-
-void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
-    uint32_t size = data.readInt32();
-    if (vector.insertAt((size_t)0, size) < 0) {
-        vector.clear();
-    }
-    if (data.read(vector.editArray(), size) != NO_ERROR) {
-        vector.clear();
-        android_errorWriteWithInfoLog(0x534e4554, "62872384", -1, NULL, 0);
-    }
-}
-
-void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
-    reply->writeInt32(vector.size());
-    reply->write(vector.array(), vector.size());
-}
-
-status_t BnCrypto::onTransact(
-    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
-    switch (code) {
-        case INIT_CHECK:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-            reply->writeInt32(initCheck());
-
-            return OK;
-        }
-
-        case IS_CRYPTO_SUPPORTED:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-            uint8_t uuid[16];
-            data.read(uuid, sizeof(uuid));
-            reply->writeInt32(isCryptoSchemeSupported(uuid));
-
-            return OK;
-        }
-
-        case CREATE_PLUGIN:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-
-            uint8_t uuid[16];
-            data.read(uuid, sizeof(uuid));
-
-            size_t opaqueSize = data.readInt32();
-            void *opaqueData = NULL;
-
-            const size_t kMaxOpaqueSize = 100 * 1024;
-            if (opaqueSize > kMaxOpaqueSize) {
-                return BAD_VALUE;
-            }
-
-            opaqueData = malloc(opaqueSize);
-            if (NULL == opaqueData) {
-                return NO_MEMORY;
-            }
-
-            data.read(opaqueData, opaqueSize);
-            reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
-
-            free(opaqueData);
-            opaqueData = NULL;
-
-            return OK;
-        }
-
-        case DESTROY_PLUGIN:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-            reply->writeInt32(destroyPlugin());
-
-            return OK;
-        }
-
-        case REQUIRES_SECURE_COMPONENT:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-
-            const char *mime = data.readCString();
-            if (mime == NULL) {
-                reply->writeInt32(BAD_VALUE);
-            } else {
-                reply->writeInt32(requiresSecureDecoderComponent(mime));
-            }
-
-            return OK;
-        }
-
-        case DECRYPT:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-
-            CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
-            CryptoPlugin::Pattern pattern;
-            pattern.mEncryptBlocks = data.readInt32();
-            pattern.mSkipBlocks = data.readInt32();
-
-            uint8_t key[16];
-            data.read(key, sizeof(key));
-
-            uint8_t iv[16];
-            data.read(iv, sizeof(iv));
-
-            size_t totalSize = data.readInt32();
-
-            SourceBuffer source;
-
-            source.mSharedMemory =
-                interface_cast<IMemory>(data.readStrongBinder());
-            if (source.mSharedMemory == NULL) {
-                reply->writeInt32(BAD_VALUE);
-                return OK;
-            }
-            source.mHeapSeqNum = data.readInt32();
-
-            int32_t offset = data.readInt32();
-
-            int32_t numSubSamples = data.readInt32();
-            if (numSubSamples < 0 || numSubSamples > 0xffff) {
-                reply->writeInt32(BAD_VALUE);
-                return OK;
-            }
-
-            std::unique_ptr<CryptoPlugin::SubSample[]> subSamples =
-                    std::make_unique<CryptoPlugin::SubSample[]>(numSubSamples);
-
-            data.read(subSamples.get(),
-                    sizeof(CryptoPlugin::SubSample) * numSubSamples);
-
-            DestinationBuffer destination;
-            destination.mType = (DestinationType)data.readInt32();
-            if (destination.mType == kDestinationTypeNativeHandle) {
-                destination.mHandle = data.readNativeHandle();
-                if (destination.mHandle == NULL) {
-                    reply->writeInt32(BAD_VALUE);
-                    return OK;
-                }
-            } else if (destination.mType == kDestinationTypeSharedMemory) {
-                destination.mSharedMemory =
-                        interface_cast<IMemory>(data.readStrongBinder());
-                if (destination.mSharedMemory == NULL) {
-                    reply->writeInt32(BAD_VALUE);
-                    return OK;
-                }
-                sp<IMemory> dest = destination.mSharedMemory;
-                if (totalSize > dest->size() ||
-                        (size_t)dest->offset() > dest->size() - totalSize) {
-                    reply->writeInt32(BAD_VALUE);
-                    android_errorWriteLog(0x534e4554, "71389378");
-                    return OK;
-                }
-            } else {
-                reply->writeInt32(BAD_VALUE);
-                android_errorWriteLog(0x534e4554, "70526702");
-                return OK;
-            }
-
-            AString errorDetailMsg;
-            ssize_t result;
-
-            size_t sumSubsampleSizes = 0;
-            bool overflow = false;
-            for (int32_t i = 0; i < numSubSamples; ++i) {
-                CryptoPlugin::SubSample &ss = subSamples[i];
-                if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) {
-                    sumSubsampleSizes += ss.mNumBytesOfEncryptedData;
-                } else {
-                    overflow = true;
-                }
-                if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) {
-                    sumSubsampleSizes += ss.mNumBytesOfClearData;
-                } else {
-                    overflow = true;
-                }
-            }
-
-            if (overflow || sumSubsampleSizes != totalSize) {
-                result = -EINVAL;
-            } else if (totalSize > source.mSharedMemory->size()) {
-                result = -EINVAL;
-            } else if ((size_t)offset > source.mSharedMemory->size() - totalSize) {
-                result = -EINVAL;
-            } else {
-                result = decrypt(key, iv, mode, pattern, source, offset,
-                        subSamples.get(), numSubSamples, destination, &errorDetailMsg);
-            }
-
-            reply->writeInt32(result);
-
-            if (isCryptoError(result)) {
-                reply->writeCString(errorDetailMsg.c_str());
-            }
-
-            if (destination.mType == kDestinationTypeNativeHandle) {
-                int err;
-                if ((err = native_handle_close(destination.mHandle)) < 0) {
-                    ALOGW("secure buffer native_handle_close failed: %d", err);
-                }
-                if ((err = native_handle_delete(destination.mHandle)) < 0) {
-                    ALOGW("secure buffer native_handle_delete failed: %d", err);
-                }
-            }
-
-            subSamples.reset();
-            return OK;
-        }
-
-        case NOTIFY_RESOLUTION:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-
-            int32_t width = data.readInt32();
-            int32_t height = data.readInt32();
-            notifyResolution(width, height);
-
-            return OK;
-        }
-
-        case SET_MEDIADRM_SESSION:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            readVector(data, sessionId);
-            reply->writeInt32(setMediaDrmSession(sessionId));
-            return OK;
-        }
-
-        case SET_HEAP:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-            sp<IMemoryHeap> heap =
-                interface_cast<IMemoryHeap>(data.readStrongBinder());
-            reply->writeInt32(setHeap(heap));
-            return OK;
-        }
-
-        case UNSET_HEAP:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-            int32_t seqNum = data.readInt32();
-            unsetHeap(seqNum);
-            return OK;
-        }
-
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-}  // namespace android
diff --git a/drm/libmediadrm/IDrm.cpp b/drm/libmediadrm/IDrm.cpp
deleted file mode 100644
index 51274d1..0000000
--- a/drm/libmediadrm/IDrm.cpp
+++ /dev/null
@@ -1,1242 +0,0 @@
-/*
- * Copyright (C) 2013 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 "IDrm"
-#include <utils/Log.h>
-
-#include <binder/Parcel.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AString.h>
-#include <mediadrm/IDrm.h>
-
-namespace android {
-
-enum {
-    INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
-    IS_CRYPTO_SUPPORTED,
-    CREATE_PLUGIN,
-    DESTROY_PLUGIN,
-    OPEN_SESSION,
-    CLOSE_SESSION,
-    GET_KEY_REQUEST,
-    PROVIDE_KEY_RESPONSE,
-    REMOVE_KEYS,
-    RESTORE_KEYS,
-    QUERY_KEY_STATUS,
-    GET_PROVISION_REQUEST,
-    PROVIDE_PROVISION_RESPONSE,
-    GET_SECURE_STOPS,
-    RELEASE_SECURE_STOPS,
-    GET_PROPERTY_STRING,
-    GET_PROPERTY_BYTE_ARRAY,
-    SET_PROPERTY_STRING,
-    SET_PROPERTY_BYTE_ARRAY,
-    GET_METRICS,
-    SET_CIPHER_ALGORITHM,
-    SET_MAC_ALGORITHM,
-    ENCRYPT,
-    DECRYPT,
-    SIGN,
-    SIGN_RSA,
-    VERIFY,
-    SET_LISTENER,
-    GET_SECURE_STOP,
-    REMOVE_ALL_SECURE_STOPS,
-    GET_HDCP_LEVELS,
-    GET_NUMBER_OF_SESSIONS,
-    GET_SECURITY_LEVEL,
-    REMOVE_SECURE_STOP,
-    GET_SECURE_STOP_IDS,
-    GET_OFFLINE_LICENSE_KEYSET_IDS,
-    REMOVE_OFFLINE_LICENSE,
-    GET_OFFLINE_LICENSE_STATE
-};
-
-struct BpDrm : public BpInterface<IDrm> {
-    explicit BpDrm(const sp<IBinder> &impl)
-        : BpInterface<IDrm>(impl) {
-    }
-
-    virtual status_t initCheck() const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        status_t status = remote()->transact(INIT_CHECK, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType,
-            DrmPlugin::SecurityLevel level, bool *isSupported) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        data.write(uuid, 16);
-        data.writeString8(mimeType);
-        data.writeInt32(level);
-
-        status_t status = remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
-        if (status != OK) {
-            ALOGE("isCryptoSchemeSupported: binder call failed: %d", status);
-            return status;
-        }
-        *isSupported = static_cast<bool>(reply.readInt32());
-
-        return reply.readInt32();
-    }
-
-    virtual status_t createPlugin(const uint8_t uuid[16],
-                                  const String8& appPackageName) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        data.write(uuid, 16);
-        data.writeString8(appPackageName);
-        status_t status = remote()->transact(CREATE_PLUGIN, data, &reply);
-        if (status != OK) {
-            ALOGE("createPlugin: binder call failed: %d", status);
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t destroyPlugin() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        status_t status = remote()->transact(DESTROY_PLUGIN, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t openSession(DrmPlugin::SecurityLevel level,
-            Vector<uint8_t> &sessionId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        data.writeInt32(level);
-
-        status_t status = remote()->transact(OPEN_SESSION, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        readVector(reply, sessionId);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t closeSession(Vector<uint8_t> const &sessionId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        status_t status = remote()->transact(CLOSE_SESSION, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t
-        getKeyRequest(Vector<uint8_t> const &sessionId,
-                      Vector<uint8_t> const &initData,
-                      String8 const &mimeType, DrmPlugin::KeyType keyType,
-                      KeyedVector<String8, String8> const &optionalParameters,
-                      Vector<uint8_t> &request, String8 &defaultUrl,
-                      DrmPlugin::KeyRequestType *keyRequestType) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        writeVector(data, initData);
-        data.writeString8(mimeType);
-        data.writeInt32((uint32_t)keyType);
-
-        data.writeInt32(optionalParameters.size());
-        for (size_t i = 0; i < optionalParameters.size(); ++i) {
-            data.writeString8(optionalParameters.keyAt(i));
-            data.writeString8(optionalParameters.valueAt(i));
-        }
-
-        status_t status = remote()->transact(GET_KEY_REQUEST, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        readVector(reply, request);
-        defaultUrl = reply.readString8();
-        *keyRequestType = static_cast<DrmPlugin::KeyRequestType>(reply.readInt32());
-
-        return reply.readInt32();
-    }
-
-    virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
-                                        Vector<uint8_t> const &response,
-                                        Vector<uint8_t> &keySetId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        writeVector(data, sessionId);
-        writeVector(data, response);
-
-        status_t status = remote()->transact(PROVIDE_KEY_RESPONSE, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        readVector(reply, keySetId);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t removeKeys(Vector<uint8_t> const &keySetId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, keySetId);
-        status_t status = remote()->transact(REMOVE_KEYS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
-                                 Vector<uint8_t> const &keySetId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        writeVector(data, keySetId);
-        status_t status = remote()->transact(RESTORE_KEYS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
-                                        KeyedVector<String8, String8> &infoMap) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        status_t status = remote()->transact(QUERY_KEY_STATUS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        infoMap.clear();
-        size_t count = reply.readInt32();
-        for (size_t i = 0; i < count; i++) {
-            String8 key = reply.readString8();
-            String8 value = reply.readString8();
-            infoMap.add(key, value);
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t getProvisionRequest(String8 const &certType,
-                                         String8 const &certAuthority,
-                                         Vector<uint8_t> &request,
-                                         String8 &defaultUrl) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        data.writeString8(certType);
-        data.writeString8(certAuthority);
-        status_t status = remote()->transact(GET_PROVISION_REQUEST, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        readVector(reply, request);
-        defaultUrl = reply.readString8();
-
-        return reply.readInt32();
-    }
-
-    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
-                                              Vector<uint8_t> &certificate,
-                                              Vector<uint8_t> &wrappedKey) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, response);
-        status_t status = remote()->transact(PROVIDE_PROVISION_RESPONSE, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        readVector(reply, certificate);
-        readVector(reply, wrappedKey);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(GET_SECURE_STOPS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        secureStops.clear();
-        uint32_t count = reply.readInt32();
-        for (size_t i = 0; i < count; i++) {
-            Vector<uint8_t> secureStop;
-            readVector(reply, secureStop);
-            secureStops.push_back(secureStop);
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t getSecureStopIds(List<Vector<uint8_t> > &secureStopIds) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(GET_SECURE_STOP_IDS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        secureStopIds.clear();
-        uint32_t count = reply.readInt32();
-        for (size_t i = 0; i < count; i++) {
-            Vector<uint8_t> secureStopId;
-            readVector(reply, secureStopId);
-            secureStopIds.push_back(secureStopId);
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, ssid);
-        status_t status = remote()->transact(GET_SECURE_STOP, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        readVector(reply, secureStop);
-        return reply.readInt32();
-    }
-
-    virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, ssRelease);
-        status_t status = remote()->transact(RELEASE_SECURE_STOPS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, ssid);
-        status_t status = remote()->transact(REMOVE_SECURE_STOP, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t removeAllSecureStops() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(REMOVE_ALL_SECURE_STOPS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t> > &keySetIds) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(GET_OFFLINE_LICENSE_KEYSET_IDS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        keySetIds.clear();
-        uint32_t count = reply.readInt32();
-        for (size_t i = 0; i < count; i++) {
-            Vector<uint8_t> keySetId;
-            readVector(reply, keySetId);
-            keySetIds.push_back(keySetId);
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, keySetId);
-        status_t status = remote()->transact(REMOVE_OFFLINE_LICENSE, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
-            DrmPlugin::OfflineLicenseState *licenseState) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, keySetId);
-        status_t status = remote()->transact(GET_OFFLINE_LICENSE_STATE, data, &reply);
-        if (status != OK) {
-            *licenseState = DrmPlugin::OfflineLicenseState::kOfflineLicenseStateUnknown;
-            return status;
-        }
-        *licenseState = static_cast<DrmPlugin::OfflineLicenseState>(reply.readInt32());
-        return reply.readInt32();
-    }
-
-    virtual status_t getPropertyString(String8 const &name, String8 &value) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        data.writeString8(name);
-        status_t status = remote()->transact(GET_PROPERTY_STRING, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        value = reply.readString8();
-        return reply.readInt32();
-    }
-
-    virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connected,
-            DrmPlugin::HdcpLevel *max) const {
-        Parcel data, reply;
-
-        if (connected == NULL || max == NULL) {
-            return BAD_VALUE;
-        }
-
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(GET_HDCP_LEVELS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        *connected = static_cast<DrmPlugin::HdcpLevel>(reply.readInt32());
-        *max = static_cast<DrmPlugin::HdcpLevel>(reply.readInt32());
-        return reply.readInt32();
-    }
-
-    virtual status_t getNumberOfSessions(uint32_t *open, uint32_t *max) const {
-        Parcel data, reply;
-
-        if (open == NULL || max == NULL) {
-            return BAD_VALUE;
-        }
-
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(GET_NUMBER_OF_SESSIONS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        *open = reply.readInt32();
-        *max = reply.readInt32();
-        return reply.readInt32();
-    }
-
-    virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
-            DrmPlugin::SecurityLevel *level) const {
-        Parcel data, reply;
-
-        if (level == NULL) {
-            return BAD_VALUE;
-        }
-
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        status_t status = remote()->transact(GET_SECURITY_LEVEL, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        *level = static_cast<DrmPlugin::SecurityLevel>(reply.readInt32());
-        return reply.readInt32();
-    }
-
-    virtual status_t getPropertyByteArray(String8 const &name, Vector<uint8_t> &value) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        data.writeString8(name);
-        status_t status = remote()->transact(GET_PROPERTY_BYTE_ARRAY, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        readVector(reply, value);
-        return reply.readInt32();
-    }
-
-    virtual status_t setPropertyString(String8 const &name, String8 const &value) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        data.writeString8(name);
-        data.writeString8(value);
-        status_t status = remote()->transact(SET_PROPERTY_STRING, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t setPropertyByteArray(String8 const &name,
-                                          Vector<uint8_t> const &value) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        data.writeString8(name);
-        writeVector(data, value);
-        status_t status = remote()->transact(SET_PROPERTY_BYTE_ARRAY, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t getMetrics(os::PersistableBundle *metrics) {
-        if (metrics == NULL) {
-            return BAD_VALUE;
-        }
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(GET_METRICS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        // The reply data is ordered as
-        // 1) 32 bit integer reply followed by
-        // 2) Serialized PersistableBundle containing metrics.
-        status_t reply_status;
-        if (reply.readInt32(&reply_status) != OK
-           || reply_status != OK) {
-          ALOGE("Failed to read getMetrics response code from parcel. %d",
-                reply_status);
-          return reply_status;
-        }
-
-        status = metrics->readFromParcel(&reply);
-        if (status != OK) {
-            ALOGE("Failed to read metrics from parcel. %d", status);
-            return status;
-        }
-        return reply_status;
-    }
-
-    virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
-                                        String8 const &algorithm) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        data.writeString8(algorithm);
-        status_t status = remote()->transact(SET_CIPHER_ALGORITHM, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
-                                     String8 const &algorithm) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        data.writeString8(algorithm);
-        status_t status = remote()->transact(SET_MAC_ALGORITHM, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t encrypt(Vector<uint8_t> const &sessionId,
-                             Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        writeVector(data, keyId);
-        writeVector(data, input);
-        writeVector(data, iv);
-
-        status_t status = remote()->transact(ENCRYPT, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        readVector(reply, output);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t decrypt(Vector<uint8_t> const &sessionId,
-                             Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        writeVector(data, keyId);
-        writeVector(data, input);
-        writeVector(data, iv);
-
-        status_t status = remote()->transact(DECRYPT, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        readVector(reply, output);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t sign(Vector<uint8_t> const &sessionId,
-                          Vector<uint8_t> const &keyId,
-                          Vector<uint8_t> const &message,
-                          Vector<uint8_t> &signature) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        writeVector(data, keyId);
-        writeVector(data, message);
-
-        status_t status = remote()->transact(SIGN, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        readVector(reply, signature);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t verify(Vector<uint8_t> const &sessionId,
-                            Vector<uint8_t> const &keyId,
-                            Vector<uint8_t> const &message,
-                            Vector<uint8_t> const &signature,
-                            bool &match) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        writeVector(data, keyId);
-        writeVector(data, message);
-        writeVector(data, signature);
-
-        status_t status = remote()->transact(VERIFY, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        match = (bool)reply.readInt32();
-        return reply.readInt32();
-    }
-
-    virtual status_t signRSA(Vector<uint8_t> const &sessionId,
-                             String8 const &algorithm,
-                             Vector<uint8_t> const &message,
-                             Vector<uint8_t> const &wrappedKey,
-                             Vector<uint8_t> &signature) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        data.writeString8(algorithm);
-        writeVector(data, message);
-        writeVector(data, wrappedKey);
-
-        status_t status = remote()->transact(SIGN_RSA, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        readVector(reply, signature);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t setListener(const sp<IDrmClient>& listener) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(listener));
-        status_t status = remote()->transact(SET_LISTENER, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        return reply.readInt32();
-    }
-
-private:
-    void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
-        uint32_t size = reply.readInt32();
-        vector.insertAt((size_t)0, size);
-        reply.read(vector.editArray(), size);
-    }
-
-    void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
-        data.writeInt32(vector.size());
-        data.write(vector.array(), vector.size());
-    }
-
-    DISALLOW_EVIL_CONSTRUCTORS(BpDrm);
-};
-
-IMPLEMENT_META_INTERFACE(Drm, "android.drm.IDrm");
-
-////////////////////////////////////////////////////////////////////////////////
-
-void BnDrm::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
-    uint32_t size = data.readInt32();
-    if (vector.insertAt((size_t)0, size) < 0) {
-        vector.clear();
-    }
-    if (data.read(vector.editArray(), size) != NO_ERROR) {
-        vector.clear();
-        android_errorWriteWithInfoLog(0x534e4554, "62872384", -1, NULL, 0);
-    }
-}
-
-void BnDrm::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
-    reply->writeInt32(vector.size());
-    reply->write(vector.array(), vector.size());
-}
-
-status_t BnDrm::onTransact(
-    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
-    switch (code) {
-        case INIT_CHECK:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            reply->writeInt32(initCheck());
-            return OK;
-        }
-
-        case IS_CRYPTO_SUPPORTED:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            uint8_t uuid[16];
-            data.read(uuid, sizeof(uuid));
-            String8 mimeType = data.readString8();
-            DrmPlugin::SecurityLevel level =
-                    static_cast<DrmPlugin::SecurityLevel>(data.readInt32());
-            bool isSupported = false;
-            status_t result = isCryptoSchemeSupported(uuid, mimeType, level, &isSupported);
-            reply->writeInt32(isSupported);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case CREATE_PLUGIN:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            uint8_t uuid[16];
-            data.read(uuid, sizeof(uuid));
-            String8 appPackageName = data.readString8();
-            reply->writeInt32(createPlugin(uuid, appPackageName));
-            return OK;
-        }
-
-        case DESTROY_PLUGIN:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            reply->writeInt32(destroyPlugin());
-            return OK;
-        }
-
-        case OPEN_SESSION:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            DrmPlugin::SecurityLevel level =
-                    static_cast<DrmPlugin::SecurityLevel>(data.readInt32());
-            Vector<uint8_t> sessionId;
-            status_t result = openSession(level, sessionId);
-            writeVector(reply, sessionId);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case CLOSE_SESSION:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            readVector(data, sessionId);
-            reply->writeInt32(closeSession(sessionId));
-            return OK;
-        }
-
-        case GET_KEY_REQUEST:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, initData;
-
-            readVector(data, sessionId);
-            readVector(data, initData);
-            String8 mimeType = data.readString8();
-            DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)data.readInt32();
-
-            KeyedVector<String8, String8> optionalParameters;
-            uint32_t count = data.readInt32();
-            for (size_t i = 0; i < count; ++i) {
-                String8 key, value;
-                key = data.readString8();
-                value = data.readString8();
-                optionalParameters.add(key, value);
-            }
-
-            Vector<uint8_t> request;
-            String8 defaultUrl;
-            DrmPlugin::KeyRequestType keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
-
-            status_t result = getKeyRequest(sessionId, initData, mimeType,
-                    keyType, optionalParameters, request, defaultUrl,
-                    &keyRequestType);
-
-            writeVector(reply, request);
-            reply->writeString8(defaultUrl);
-            reply->writeInt32(static_cast<int32_t>(keyRequestType));
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case PROVIDE_KEY_RESPONSE:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, response, keySetId;
-            readVector(data, sessionId);
-            readVector(data, response);
-            uint32_t result = provideKeyResponse(sessionId, response, keySetId);
-            writeVector(reply, keySetId);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case REMOVE_KEYS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> keySetId;
-            readVector(data, keySetId);
-            reply->writeInt32(removeKeys(keySetId));
-            return OK;
-        }
-
-        case RESTORE_KEYS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, keySetId;
-            readVector(data, sessionId);
-            readVector(data, keySetId);
-            reply->writeInt32(restoreKeys(sessionId, keySetId));
-            return OK;
-        }
-
-        case QUERY_KEY_STATUS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            readVector(data, sessionId);
-            KeyedVector<String8, String8> infoMap;
-            status_t result = queryKeyStatus(sessionId, infoMap);
-            size_t count = infoMap.size();
-            reply->writeInt32(count);
-            for (size_t i = 0; i < count; ++i) {
-                reply->writeString8(infoMap.keyAt(i));
-                reply->writeString8(infoMap.valueAt(i));
-            }
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_PROVISION_REQUEST:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            String8 certType = data.readString8();
-            String8 certAuthority = data.readString8();
-
-            Vector<uint8_t> request;
-            String8 defaultUrl;
-            status_t result = getProvisionRequest(certType, certAuthority,
-                                                  request, defaultUrl);
-            writeVector(reply, request);
-            reply->writeString8(defaultUrl);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case PROVIDE_PROVISION_RESPONSE:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> response;
-            Vector<uint8_t> certificate;
-            Vector<uint8_t> wrappedKey;
-            readVector(data, response);
-            status_t result = provideProvisionResponse(response, certificate, wrappedKey);
-            writeVector(reply, certificate);
-            writeVector(reply, wrappedKey);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_SECURE_STOPS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            List<Vector<uint8_t> > secureStops;
-            status_t result = getSecureStops(secureStops);
-            size_t count = secureStops.size();
-            reply->writeInt32(count);
-            List<Vector<uint8_t> >::iterator iter = secureStops.begin();
-            while(iter != secureStops.end()) {
-                size_t size = iter->size();
-                reply->writeInt32(size);
-                reply->write(iter->array(), iter->size());
-                iter++;
-            }
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_SECURE_STOP_IDS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            List<Vector<uint8_t> > secureStopIds;
-            status_t result = getSecureStopIds(secureStopIds);
-            size_t count = secureStopIds.size();
-            reply->writeInt32(count);
-            List<Vector<uint8_t> >::iterator iter = secureStopIds.begin();
-            while(iter != secureStopIds.end()) {
-                size_t size = iter->size();
-                reply->writeInt32(size);
-                reply->write(iter->array(), iter->size());
-                iter++;
-            }
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_SECURE_STOP:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> ssid, secureStop;
-            readVector(data, ssid);
-            status_t result = getSecureStop(ssid, secureStop);
-            writeVector(reply, secureStop);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case RELEASE_SECURE_STOPS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> ssRelease;
-            readVector(data, ssRelease);
-            reply->writeInt32(releaseSecureStops(ssRelease));
-            return OK;
-        }
-
-        case REMOVE_SECURE_STOP:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> ssid;
-            readVector(data, ssid);
-            reply->writeInt32(removeSecureStop(ssid));
-            return OK;
-        }
-
-        case REMOVE_ALL_SECURE_STOPS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            reply->writeInt32(removeAllSecureStops());
-            return OK;
-        }
-
-        case GET_HDCP_LEVELS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
-            DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
-            status_t result = getHdcpLevels(&connected, &max);
-            reply->writeInt32(connected);
-            reply->writeInt32(max);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_NUMBER_OF_SESSIONS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            uint32_t open = 0, max = 0;
-            status_t result = getNumberOfSessions(&open, &max);
-            reply->writeInt32(open);
-            reply->writeInt32(max);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_SECURITY_LEVEL:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            readVector(data, sessionId);
-            DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
-            status_t result = getSecurityLevel(sessionId, &level);
-            reply->writeInt32(level);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_OFFLINE_LICENSE_KEYSET_IDS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            List<Vector<uint8_t> > keySetIds;
-            status_t result = getOfflineLicenseKeySetIds(keySetIds);
-            size_t count = keySetIds.size();
-            reply->writeInt32(count);
-            List<Vector<uint8_t> >::iterator iter = keySetIds.begin();
-            while(iter != keySetIds.end()) {
-                size_t size = iter->size();
-                reply->writeInt32(size);
-                reply->write(iter->array(), iter->size());
-                iter++;
-            }
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case REMOVE_OFFLINE_LICENSE:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> keySetId;
-            readVector(data, keySetId);
-            reply->writeInt32(removeOfflineLicense(keySetId));
-            return OK;
-        }
-
-        case GET_OFFLINE_LICENSE_STATE:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> keySetId;
-            readVector(data, keySetId);
-            DrmPlugin::OfflineLicenseState state;
-            status_t result = getOfflineLicenseState(keySetId, &state);
-            reply->writeInt32(static_cast<DrmPlugin::OfflineLicenseState>(state));
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_PROPERTY_STRING:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            String8 name = data.readString8();
-            String8 value;
-            status_t result = getPropertyString(name, value);
-            reply->writeString8(value);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_PROPERTY_BYTE_ARRAY:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            String8 name = data.readString8();
-            Vector<uint8_t> value;
-            status_t result = getPropertyByteArray(name, value);
-            writeVector(reply, value);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case SET_PROPERTY_STRING:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            String8 name = data.readString8();
-            String8 value = data.readString8();
-            reply->writeInt32(setPropertyString(name, value));
-            return OK;
-        }
-
-        case SET_PROPERTY_BYTE_ARRAY:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            String8 name = data.readString8();
-            Vector<uint8_t> value;
-            readVector(data, value);
-            reply->writeInt32(setPropertyByteArray(name, value));
-            return OK;
-        }
-
-        case GET_METRICS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-
-            os::PersistableBundle metrics;
-            status_t result = getMetrics(&metrics);
-            // The reply data is ordered as
-            // 1) 32 bit integer reply followed by
-            // 2) Serialized PersistableBundle containing metrics.
-            // Only write the metrics if the getMetrics result was
-            // OK and we successfully added the status to reply.
-            status_t parcel_result = reply->writeInt32(result);
-            if (result == OK && parcel_result == OK) {
-                parcel_result = metrics.writeToParcel(reply);
-            }
-            return parcel_result;
-        }
-
-        case SET_CIPHER_ALGORITHM:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            readVector(data, sessionId);
-            String8 algorithm = data.readString8();
-            reply->writeInt32(setCipherAlgorithm(sessionId, algorithm));
-            return OK;
-        }
-
-        case SET_MAC_ALGORITHM:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            readVector(data, sessionId);
-            String8 algorithm = data.readString8();
-            reply->writeInt32(setMacAlgorithm(sessionId, algorithm));
-            return OK;
-        }
-
-        case ENCRYPT:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, keyId, input, iv, output;
-            readVector(data, sessionId);
-            readVector(data, keyId);
-            readVector(data, input);
-            readVector(data, iv);
-            uint32_t result = encrypt(sessionId, keyId, input, iv, output);
-            writeVector(reply, output);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case DECRYPT:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, keyId, input, iv, output;
-            readVector(data, sessionId);
-            readVector(data, keyId);
-            readVector(data, input);
-            readVector(data, iv);
-            uint32_t result = decrypt(sessionId, keyId, input, iv, output);
-            writeVector(reply, output);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case SIGN:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, keyId, message, signature;
-            readVector(data, sessionId);
-            readVector(data, keyId);
-            readVector(data, message);
-            uint32_t result = sign(sessionId, keyId, message, signature);
-            writeVector(reply, signature);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case VERIFY:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, keyId, message, signature;
-            readVector(data, sessionId);
-            readVector(data, keyId);
-            readVector(data, message);
-            readVector(data, signature);
-            bool match = false;
-            uint32_t result = verify(sessionId, keyId, message, signature, match);
-            reply->writeInt32(match);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case SIGN_RSA:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, message, wrappedKey, signature;
-            readVector(data, sessionId);
-            String8 algorithm = data.readString8();
-            readVector(data, message);
-            readVector(data, wrappedKey);
-            uint32_t result = signRSA(sessionId, algorithm, message, wrappedKey, signature);
-            writeVector(reply, signature);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-    case SET_LISTENER: {
-        CHECK_INTERFACE(IDrm, data, reply);
-        sp<IDrmClient> listener =
-            interface_cast<IDrmClient>(data.readStrongBinder());
-        reply->writeInt32(setListener(listener));
-        return NO_ERROR;
-    } break;
-
-    default:
-        return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-}  // namespace android
diff --git a/drm/libmediadrm/IDrmClient.cpp b/drm/libmediadrm/IDrmClient.cpp
deleted file mode 100644
index 2e05093..0000000
--- a/drm/libmediadrm/IDrmClient.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
-**
-** Copyright 2013, 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 "IDrmClient"
-
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <hidl/HidlSupport.h>
-
-#include <media/IMediaPlayerClient.h>
-#include <mediadrm/DrmUtils.h>
-#include <mediadrm/IDrmClient.h>
-
-#include <cstddef>
-#include <cstdint>
-#include <vector>
-
-namespace android {
-
-enum {
-    SEND_EVENT = IBinder::FIRST_CALL_TRANSACTION,
-    SEND_EXPIRATION_UPDATE,
-    SEND_KEYS_CHANGE,
-    SEND_SESSION_LOST_STATE,
-};
-
-namespace {
-
-hardware::hidl_vec<uint8_t> ReadByteArray(const Parcel &obj, status_t *err)
-{
-    int32_t len = obj.readInt32();
-    hardware::hidl_vec<uint8_t> ret;
-    if (len < 0) {
-        ALOGE("Invalid array len");
-        *err = BAD_VALUE;
-        return ret;
-    }
-    ret.resize(static_cast<size_t>(len));
-    *err = obj.read(ret.data(), ret.size());
-    return ret;
-}
-
-}
-
-class BpDrmClient: public BpInterface<IDrmClient>
-{
-    template <typename F>
-    void notify(uint32_t code, F fillParcel) {
-        Parcel obj, reply;
-        obj.writeInterfaceToken(IDrmClient::getInterfaceDescriptor());
-        fillParcel(obj);
-        remote()->transact(code, obj, &reply, IBinder::FLAG_ONEWAY);
-    }
-
-public:
-    explicit BpDrmClient(const sp<IBinder>& impl)
-        : BpInterface<IDrmClient>(impl)
-    {
-    }
-
-    virtual void sendEvent(
-            DrmPlugin::EventType eventType,
-            const hardware::hidl_vec<uint8_t> &sessionId,
-            const hardware::hidl_vec<uint8_t> &data)
-    {
-        auto fillParcel = [&] (Parcel &p) {
-            DrmUtils::WriteEventToParcel(p, eventType, sessionId, data);
-        };
-        notify(SEND_EVENT, fillParcel);
-    }
-
-    virtual void sendExpirationUpdate(
-            const hardware::hidl_vec<uint8_t> &sessionId,
-            int64_t expiryTimeInMS)
-    {
-        auto fillParcel = [&] (Parcel &p) {
-            DrmUtils::WriteExpirationUpdateToParcel(p, sessionId, expiryTimeInMS);
-        };
-        notify(SEND_EXPIRATION_UPDATE, fillParcel);
-    }
-
-    virtual void sendKeysChange(
-            const hardware::hidl_vec<uint8_t> &sessionId,
-            const std::vector<DrmKeyStatus> &keyStatusList,
-            bool hasNewUsableKey)
-    {
-        auto fillParcel = [&] (Parcel &p) {
-            DrmUtils::WriteKeysChange(p, sessionId, keyStatusList, hasNewUsableKey);
-        };
-        notify(SEND_KEYS_CHANGE, fillParcel);
-    }
-
-    virtual void sendSessionLostState(
-            const hardware::hidl_vec<uint8_t> &sessionId)
-    {
-        auto fillParcel = [&] (Parcel &p) {
-            DrmUtils::WriteByteArray(p, sessionId);
-        };
-        notify(SEND_SESSION_LOST_STATE, fillParcel);
-    }
-};
-
-IMPLEMENT_META_INTERFACE(DrmClient, "android.media.IDrmClient");
-
-// ----------------------------------------------------------------------
-
-status_t BnDrmClient::onTransact(
-    uint32_t code, const Parcel& obj, Parcel* reply, uint32_t flags)
-{
-    CHECK_INTERFACE(IDrmClient, obj, reply);
-    status_t err = NO_ERROR;
-    hardware::hidl_vec<uint8_t> sessionId(ReadByteArray(obj, &err));
-    if (err != NO_ERROR) {
-        ALOGE("Failed to read session id, error=%d", err);
-        return err;
-    }
-
-    switch (code) {
-        case SEND_EVENT: {
-            hardware::hidl_vec<uint8_t> data(ReadByteArray(obj, &err));
-            int eventType = obj.readInt32();
-            if (err == NO_ERROR) {
-                sendEvent(static_cast<DrmPlugin::EventType>(eventType), sessionId, data);
-            }
-            return err;
-        } break;
-        case SEND_EXPIRATION_UPDATE: {
-            int64_t expiryTimeInMS = obj.readInt64();
-            sendExpirationUpdate(sessionId, expiryTimeInMS);
-            return NO_ERROR;
-        } break;
-        case SEND_KEYS_CHANGE: {
-            // ...
-            int32_t n = obj.readInt32();
-            if (n < 0) {
-                return BAD_VALUE;
-            }
-            std::vector<DrmKeyStatus> keyStatusList;
-            for (int32_t i = 0; i < n; ++i) {
-                hardware::hidl_vec<uint8_t> keyId(ReadByteArray(obj, &err));
-                if (err != NO_ERROR) {
-                    return err;
-                }
-                int32_t type = obj.readInt32();
-                if (type < 0) {
-                    return BAD_VALUE;
-                }
-                keyStatusList.push_back({static_cast<uint32_t>(type), keyId});
-            }
-            int32_t hasNewUsableKey = obj.readInt32();
-            sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
-            return NO_ERROR;
-        } break;
-        case SEND_SESSION_LOST_STATE: {
-            sendSessionLostState(sessionId);
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, obj, reply, flags);
-    }
-}
-
-} // namespace android
diff --git a/drm/libmediadrm/IMediaDrmService.cpp b/drm/libmediadrm/IMediaDrmService.cpp
deleted file mode 100644
index 020c063..0000000
--- a/drm/libmediadrm/IMediaDrmService.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-**
-** Copyright 2015, 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 <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <mediadrm/ICrypto.h>
-#include <mediadrm/IDrm.h>
-#include <mediadrm/IMediaDrmService.h>
-
-#include <utils/Errors.h>  // for status_t
-#include <utils/String8.h>
-
-namespace android {
-
-enum {
-    MAKE_CRYPTO = IBinder::FIRST_CALL_TRANSACTION,
-    MAKE_DRM,
-};
-
-class BpMediaDrmService: public BpInterface<IMediaDrmService>
-{
-public:
-    explicit BpMediaDrmService(const sp<IBinder>& impl)
-        : BpInterface<IMediaDrmService>(impl)
-    {
-    }
-
-    virtual sp<IDrm> makeDrm() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaDrmService::getInterfaceDescriptor());
-        remote()->transact(MAKE_DRM, data, &reply);
-        return interface_cast<IDrm>(reply.readStrongBinder());
-    }
-
-};
-
-IMPLEMENT_META_INTERFACE(MediaDrmService, "android.media.IMediaDrmService");
-
-// ----------------------------------------------------------------------
-
-status_t BnMediaDrmService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch (code) {
-        case MAKE_DRM: {
-            CHECK_INTERFACE(IMediaDrmService, data, reply);
-            sp<IDrm> drm = makeDrm();
-            reply->writeStrongBinder(IInterface::asBinder(drm));
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-template<>
-sp<IDrm> IMediaDrmService::makeObject<IDrm>() {
-    return makeDrm();
-}
-
-} // namespace android
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHal.h b/drm/libmediadrm/include/mediadrm/CryptoHal.h
index 9e61777..865ca38 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHal.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHal.h
@@ -36,7 +36,7 @@
 
 namespace android {
 
-struct CryptoHal : public BnCrypto {
+struct CryptoHal : public ICrypto {
     CryptoHal();
     virtual ~CryptoHal();
 
diff --git a/drm/libmediadrm/include/mediadrm/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
index cc7dd41..f261d89 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHal.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -56,8 +56,7 @@
     return memcmp(l.array(), r.array(), l.size()) == 0;
 }
 
-struct DrmHal : public BnDrm,
-                public IBinder::DeathRecipient,
+struct DrmHal : public IDrm,
                 public IDrmPluginListener_V1_2 {
 
     struct DrmSessionClient;
@@ -191,8 +190,6 @@
 
     Return<void> sendSessionLostState(const hidl_vec<uint8_t>& sessionId);
 
-    virtual void binderDied(const wp<IBinder> &the_late_who);
-
 private:
     static Mutex mLock;
 
@@ -209,7 +206,7 @@
     // Mutable to allow modification within GetPropertyByteArray.
     mutable MediaDrmMetrics mMetrics;
 
-    Vector<sp<DrmSessionClient>> mOpenSessions;
+    std::vector<std::shared_ptr<DrmSessionClient>> mOpenSessions;
     void closeOpenSessions();
     void cleanup();
 
diff --git a/drm/libmediadrm/include/mediadrm/DrmSessionManager.h b/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
index 3258f7a..9e43504 100644
--- a/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
+++ b/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
@@ -18,7 +18,9 @@
 
 #define DRM_SESSION_MANAGER_H_
 
-#include <binder/IBinder.h>
+#include <aidl/android/media/IResourceManagerClient.h>
+#include <aidl/android/media/IResourceManagerService.h>
+#include <android/binder_auto_utils.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <utils/RefBase.h>
 #include <utils/KeyedVector.h>
@@ -26,6 +28,7 @@
 #include <utils/Vector.h>
 
 #include <map>
+#include <memory>
 #include <utility>
 #include <vector>
 
@@ -33,12 +36,8 @@
 
 class DrmSessionManagerTest;
 
-namespace media {
-class IResourceManagerClient;
-class IResourceManagerService;
-}
-using android::media::IResourceManagerClient;
-using android::media::IResourceManagerService;
+using aidl::android::media::IResourceManagerClient;
+using aidl::android::media::IResourceManagerService;
 
 bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2);
 
@@ -50,13 +49,15 @@
 
 typedef std::map<std::vector<uint8_t>, SessionInfo> SessionInfoMap;
 
-struct DrmSessionManager : public IBinder::DeathRecipient {
+struct DrmSessionManager : public RefBase {
     static sp<DrmSessionManager> Instance();
 
     DrmSessionManager();
-    explicit DrmSessionManager(const sp<IResourceManagerService> &service);
+    explicit DrmSessionManager(const std::shared_ptr<IResourceManagerService> &service);
 
-    void addSession(int pid, const sp<IResourceManagerClient>& drm, const Vector<uint8_t>& sessionId);
+    void addSession(int pid,
+            const std::shared_ptr<IResourceManagerClient>& drm,
+            const Vector<uint8_t>& sessionId);
     void useSession(const Vector<uint8_t>& sessionId);
     void removeSession(const Vector<uint8_t>& sessionId);
     bool reclaimSession(int callingPid);
@@ -66,7 +67,7 @@
     bool containsSession(const Vector<uint8_t>& sessionId) const;
 
     // implements DeathRecipient
-    virtual void binderDied(const wp<IBinder>& /*who*/);
+    void binderDied();
 
 protected:
     virtual ~DrmSessionManager();
@@ -74,10 +75,11 @@
 private:
     void init();
 
-    sp<IResourceManagerService> mService;
+    std::shared_ptr<IResourceManagerService> mService;
     mutable Mutex mLock;
     SessionInfoMap mSessionMap;
     bool mInitialized;
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
 
     DISALLOW_EVIL_CONSTRUCTORS(DrmSessionManager);
 };
diff --git a/drm/libmediadrm/include/mediadrm/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
index 6a2c63e..4103d5d 100644
--- a/drm/libmediadrm/include/mediadrm/IDrm.h
+++ b/drm/libmediadrm/include/mediadrm/IDrm.h
@@ -28,8 +28,9 @@
 
 struct AString;
 
-struct IDrm : public IInterface {
-    DECLARE_META_INTERFACE(Drm);
+struct IDrm : public virtual RefBase {
+
+    virtual ~IDrm() {}
 
     virtual status_t initCheck() const = 0;
 
@@ -145,19 +146,13 @@
 
     virtual status_t setListener(const sp<IDrmClient>& listener) = 0;
 
+protected:
+    IDrm() {}
+
 private:
     DISALLOW_EVIL_CONSTRUCTORS(IDrm);
 };
 
-struct BnDrm : public BnInterface<IDrm> {
-    virtual status_t onTransact(
-            uint32_t code, const Parcel &data, Parcel *reply,
-            uint32_t flags = 0);
-private:
-    void readVector(const Parcel &data, Vector<uint8_t> &vector) const;
-    void writeVector(Parcel *reply, Vector<uint8_t> const &vector) const;
-};
-
 }  // namespace android
 
 #endif // ANDROID_IDRM_H_
diff --git a/drm/libmediadrm/include/mediadrm/IDrmClient.h b/drm/libmediadrm/include/mediadrm/IDrmClient.h
index f8f2b25..fe25ae1 100644
--- a/drm/libmediadrm/include/mediadrm/IDrmClient.h
+++ b/drm/libmediadrm/include/mediadrm/IDrmClient.h
@@ -18,12 +18,8 @@
 #define ANDROID_IDRMCLIENT_H
 
 #include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <media/drm/DrmAPI.h>
-
-#include <android/hardware/drm/1.2/types.h>
 #include <hidl/HidlSupport.h>
+#include <media/drm/DrmAPI.h>
 
 #include <cstdint>
 #include <vector>
@@ -35,10 +31,10 @@
     const hardware::hidl_vec<uint8_t> keyId;
 };
 
-class IDrmClient: public IInterface
+class IDrmClient: public virtual RefBase
 {
 public:
-    DECLARE_META_INTERFACE(DrmClient);
+    ~IDrmClient() {}
 
     virtual void sendEvent(
             DrmPlugin::EventType eventType,
@@ -57,17 +53,11 @@
     virtual void sendSessionLostState(
             const hardware::hidl_vec<uint8_t> &sessionId) = 0;
 
-};
+protected:
+    IDrmClient() {}
 
-// ----------------------------------------------------------------------------
-
-class BnDrmClient: public BnInterface<IDrmClient>
-{
-public:
-    virtual status_t onTransact(uint32_t code,
-                                const Parcel& data,
-                                Parcel* reply,
-                                uint32_t flags = 0);
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(IDrmClient);
 };
 
 }; // namespace android
diff --git a/drm/libmediadrm/include/mediadrm/IMediaDrmService.h b/drm/libmediadrm/include/mediadrm/IMediaDrmService.h
deleted file mode 100644
index 899362f..0000000
--- a/drm/libmediadrm/include/mediadrm/IMediaDrmService.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2015 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 ANDROID_IMEDIADRMSERVICE_H
-#define ANDROID_IMEDIADRMSERVICE_H
-
-#include <utils/Errors.h>  // for status_t
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-struct IDrm;
-
-class IMediaDrmService: public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(MediaDrmService);
-
-    virtual sp<IDrm>            makeDrm() = 0;
-
-    template<typename I> sp<I>  makeObject();
-
-};
-
-// ----------------------------------------------------------------------------
-
-class BnMediaDrmService: public BnInterface<IMediaDrmService>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IMEDIADRMSERVICE_H
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
index a5bc09b..3017274 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -17,9 +17,14 @@
 #ifndef ANDROID_DRMUTILS_H
 #define ANDROID_DRMUTILS_H
 
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <android/hardware/drm/1.0/IDrmFactory.h>
 #include <utils/Errors.h>  // for status_t
 #include <utils/StrongPointer.h>
 #include <binder/Parcel.h>
+#include <vector>
+
+using namespace ::android::hardware::drm;
 
 namespace android {
 
@@ -77,6 +82,16 @@
     obj.writeInt32(hasNewUsableKey);
 }
 
+std::vector<sp<::V1_0::IDrmFactory>> MakeDrmFactories(const uint8_t uuid[16]);
+
+std::vector<sp<::V1_0::IDrmPlugin>> MakeDrmPlugins(const uint8_t uuid[16],
+                                                   const char *appPackageName);
+
+std::vector<sp<::V1_0::ICryptoFactory>> MakeCryptoFactories(const uint8_t uuid[16]);
+
+std::vector<sp<::V1_0::ICryptoPlugin>> MakeCryptoPlugins(const uint8_t uuid[16],
+                                                         const void *initData, size_t initDataSize);
+
 } // namespace DrmUtils
 
 } // namespace android
diff --git a/drm/libmediadrm/interface/mediadrm/ICrypto.h b/drm/libmediadrm/interface/mediadrm/ICrypto.h
index 6d896b8..48a0c44 100644
--- a/drm/libmediadrm/interface/mediadrm/ICrypto.h
+++ b/drm/libmediadrm/interface/mediadrm/ICrypto.h
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#include <binder/IInterface.h>
 #include <cutils/native_handle.h>
 #include <media/hardware/CryptoAPI.h>
 #include <media/stagefright/foundation/ABase.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
 
 #ifndef ANDROID_ICRYPTO_H_
 
@@ -29,8 +30,9 @@
 class IMemory;
 class IMemoryHeap;
 
-struct ICrypto : public IInterface {
-    DECLARE_META_INTERFACE(Crypto);
+struct ICrypto : public RefBase {
+
+    virtual ~ICrypto() {}
 
     virtual status_t initCheck() const = 0;
 
@@ -79,19 +81,13 @@
     virtual int32_t setHeap(const sp<IMemoryHeap>& heap) = 0;
     virtual void unsetHeap(int32_t seqNum) = 0;
 
+protected:
+    ICrypto() {}
+
 private:
     DISALLOW_EVIL_CONSTRUCTORS(ICrypto);
 };
 
-struct BnCrypto : public BnInterface<ICrypto> {
-    virtual status_t onTransact(
-            uint32_t code, const Parcel &data, Parcel *reply,
-            uint32_t flags = 0);
-private:
-    void readVector(const Parcel &data, Vector<uint8_t> &vector) const;
-    void writeVector(Parcel *reply, Vector<uint8_t> const &vector) const;
-};
-
 }  // namespace android
 
 #endif // ANDROID_ICRYPTO_H_
diff --git a/include/drm/drm_framework_common.h b/include/drm/drm_framework_common.h
index d75f71c..d5f3ba2 100644
--- a/include/drm/drm_framework_common.h
+++ b/include/drm/drm_framework_common.h
@@ -317,14 +317,6 @@
     ~DecryptHandle() {
         delete decryptInfo; decryptInfo = NULL;
     }
-
-    bool operator<(const DecryptHandle& handle) const {
-        return (decryptId < handle.decryptId);
-    }
-
-    bool operator==(const DecryptHandle& handle) const {
-        return (decryptId == handle.decryptId);
-    }
 };
 
 };
diff --git a/media/codec2/components/aac/C2SoftAacDec.cpp b/media/codec2/components/aac/C2SoftAacDec.cpp
index 2d4e126..3568f7b 100644
--- a/media/codec2/components/aac/C2SoftAacDec.cpp
+++ b/media/codec2/components/aac/C2SoftAacDec.cpp
@@ -78,7 +78,8 @@
                 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
                 .withDefault(new C2StreamSampleRateInfo::output(0u, 44100))
                 .withFields({C2F(mSampleRate, value).oneOf({
-                    7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+                    7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000,
+                    44100, 48000, 64000, 88200, 96000
                 })})
                 .withSetter(Setter<decltype(*mSampleRate)>::NonStrictValueWithNoDeps)
                 .build());
diff --git a/media/codec2/components/opus/C2SoftOpusDec.cpp b/media/codec2/components/opus/C2SoftOpusDec.cpp
index 6b6974f..b7c1556 100644
--- a/media/codec2/components/opus/C2SoftOpusDec.cpp
+++ b/media/codec2/components/opus/C2SoftOpusDec.cpp
@@ -62,7 +62,7 @@
         addParameter(
                 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
                 .withDefault(new C2StreamSampleRateInfo::output(0u, 48000))
-                .withFields({C2F(mSampleRate, value).equalTo(48000)})
+                .withFields({C2F(mSampleRate, value).inRange(8000, 48000)})
                 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
                 .build());
 
diff --git a/media/codec2/components/xaac/C2SoftXaacDec.cpp b/media/codec2/components/xaac/C2SoftXaacDec.cpp
index 60ae93c..951d058 100644
--- a/media/codec2/components/xaac/C2SoftXaacDec.cpp
+++ b/media/codec2/components/xaac/C2SoftXaacDec.cpp
@@ -87,7 +87,8 @@
                 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
                 .withDefault(new C2StreamSampleRateInfo::output(0u, 44100))
                 .withFields({C2F(mSampleRate, value).oneOf({
-                    7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+                    7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000,
+                    44100, 48000, 64000, 88200, 96000
                 })})
                 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
                 .build());
diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp
index 4a9dc55..b96d29b 100644
--- a/media/codec2/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hidl/1.0/utils/Android.bp
@@ -104,7 +104,7 @@
 
 // public dependency for Codec 2.0 HAL service implementations
 cc_defaults {
-    name: "libcodec2-hidl-defaults",
+    name: "libcodec2-hidl-defaults@1.0",
     defaults: ["libcodec2-impl-defaults"],
 
     shared_libs: [
@@ -115,7 +115,7 @@
 
 // public dependency for Codec 2.0 HAL client
 cc_defaults {
-    name: "libcodec2-hidl-client-defaults",
+    name: "libcodec2-hidl-client-defaults@1.0",
     defaults: ["libcodec2-impl-defaults"],
 
     shared_libs: [
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
index 8f21cf8..062dcd9 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
@@ -57,6 +57,12 @@
             const sp<IInputSink>& sink,
             connect_cb _hidl_cb) override;
 
+    InputSurface(
+            const std::shared_ptr<ParameterCache>& cache,
+            const std::shared_ptr<C2ReflectorHelper>& reflector,
+            const sp<HGraphicBufferProducer>& base,
+            const sp<GraphicBufferSource>& source);
+
 protected:
 
     class Interface;
@@ -68,19 +74,9 @@
     std::shared_ptr<Interface> mIntf;
     sp<CachedConfigurable> mConfigurable;
 
-    InputSurface(
-            const std::shared_ptr<ParameterCache>& cache,
-            const std::shared_ptr<C2ReflectorHelper>& reflector,
-            const sp<HGraphicBufferProducer>& base,
-            const sp<GraphicBufferSource>& source);
-
     virtual ~InputSurface() override = default;
-
-    friend struct ComponentStore;
-
 };
 
-
 }  // namespace utils
 }  // namespace V1_0
 }  // namespace c2
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index 6469735..9656eb4 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -203,7 +203,7 @@
     uint32_t mFramesReceived;
     std::list<uint64_t> mFlushedIndices;
     std::list<uint64_t> mTimestampUslist;
-    ::android::List<outputMetaData> oBufferMetaData;
+    std::list<outputMetaData> oBufferMetaData;
 
     C2BlockPool::local_id_t mBlockPoolId;
     std::shared_ptr<C2BlockPool> mLinearPool;
@@ -594,7 +594,7 @@
         int nSampleRate = bitStreamInfo[0];
         int nChannels = bitStreamInfo[1];
         std::list<uint64_t>::iterator itIn = mTimestampUslist.begin();
-        android::List<outputMetaData>::iterator itOut = oBufferMetaData.begin();
+        auto itOut = oBufferMetaData.begin();
         EXPECT_EQ(*itIn, itOut->timestampUs);
         expTs = *itIn;
         while (itOut != oBufferMetaData.end()) {
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
index d73b731..2f02913 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
@@ -20,6 +20,13 @@
 
 #include "media_c2_hidl_test_common.h"
 
+#include <android/hardware/media/c2/1.0/IComponentStore.h>
+
+void ComponentTestEnvironment::registerTestServices() {
+    registerTestService<::android::hardware::media::c2::V1_0::
+                        IComponentStore>();
+}
+
 // Test the codecs for NullBuffer, Empty Input Buffer with(out) flags set
 void testInputBuffer(
     const std::shared_ptr<android::Codec2Client::Component>& component,
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
index db59e54..23e332a 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
@@ -17,32 +17,23 @@
 #ifndef MEDIA_C2_HIDL_TEST_COMMON_H
 #define MEDIA_C2_HIDL_TEST_COMMON_H
 
-#include <codec2/hidl/client.h>
-
-#include <android/hardware/media/c2/1.0/types.h>
-
 #include <C2Component.h>
 #include <C2Config.h>
+
+#include <codec2/hidl/client.h>
 #include <getopt.h>
 #include <hidl/HidlSupport.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/foundation/Mutexed.h>
-
-using namespace ::android::hardware::media::c2::V1_0;
-using namespace ::android::hardware::media::c2::V1_0::utils;
-
-using ::android::Mutexed;
-using ::android::hardware::Void;
-using ::android::hardware::Return;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::hidl_string;
-
 #include <VtsHalHidlTargetTestEnvBase.h>
 
 #define MAX_RETRY 20
 #define TIME_OUT 400ms
 #define MAX_INPUT_BUFFERS 8
 
+using ::android::hardware::Void;
+using ::android::hardware::Return;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+
 /*
  * Handle Callback functions onWorkDone(), onTripped(),
  * onError(), onDeath(), onFramesRendered()
@@ -114,9 +105,7 @@
     typedef ::testing::VtsHalHidlTargetTestEnvBase Super;
 
    public:
-    virtual void registerTestServices() override {
-        registerTestService<IComponentStore>();
-    }
+    virtual void registerTestServices() override;
 
     ComponentTestEnvironment() : res("/data/local/tmp/media/") {}
 
diff --git a/media/codec2/hidl/1.0/vts/functional/video/Android.bp b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
index be35b02..b737323 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
@@ -18,6 +18,14 @@
     name: "VtsHalMediaC2V1_0TargetVideoDecTest",
     defaults: ["VtsHalMediaC2V1_0Defaults"],
     srcs: ["VtsHalMediaC2V1_0TargetVideoDecTest.cpp"],
+    header_libs: [
+        "libnativewindow_headers",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libgui",
+        "libutils",
+    ],
 }
 
 cc_test {
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 5e28750..9404aa8 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -28,6 +28,10 @@
 #include <C2Debug.h>
 #include <C2Buffer.h>
 #include <C2BufferPriv.h>
+#include <gui/BufferQueue.h>
+#include <gui/IConsumerListener.h>
+#include <gui/IProducerListener.h>
+#include <system/window.h>
 
 using android::C2AllocatorIon;
 
@@ -426,6 +430,48 @@
     ASSERT_EQ(mDisableTest, false);
 }
 
+TEST_F(Codec2VideoDecHidlTest, configureTunnel) {
+    description("Attempts to configure tunneling");
+    if (mDisableTest) return;
+    ALOGV("Checks if the component can be configured for tunneling");
+    native_handle_t* sidebandStream{};
+    c2_status_t err = mComponent->configureVideoTunnel(0, &sidebandStream);
+    if (err == C2_OMITTED) {
+        return;
+    }
+
+    using namespace android;
+    sp<NativeHandle> nativeHandle = NativeHandle::create(sidebandStream, true);
+
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+
+    class DummyConsumerListener : public BnConsumerListener {
+    public:
+        DummyConsumerListener() : BnConsumerListener() {}
+        void onFrameAvailable(const BufferItem&) override {}
+        void onBuffersReleased() override {}
+        void onSidebandStreamChanged() override {}
+    };
+    consumer->consumerConnect(new DummyConsumerListener(), false);
+
+    class DummyProducerListener : public BnProducerListener {
+    public:
+        DummyProducerListener() : BnProducerListener() {}
+        virtual void onBufferReleased() override {}
+        virtual bool needsReleaseNotify() override { return false; }
+        virtual void onBuffersDiscarded(const std::vector<int32_t>&) override {}
+    };
+    IGraphicBufferProducer::QueueBufferOutput qbo{};
+    producer->connect(new DummyProducerListener(),
+                      NATIVE_WINDOW_API_MEDIA,
+                      false,
+                      &qbo);
+
+    ASSERT_EQ(producer->setSidebandStream(nativeHandle), NO_ERROR);
+}
+
 class Codec2VideoDecDecodeTest
     : public Codec2VideoDecHidlTest,
       public ::testing::WithParamInterface<std::pair<int32_t, bool>> {
diff --git a/media/codec2/hidl/1.1/utils/Android.bp b/media/codec2/hidl/1.1/utils/Android.bp
new file mode 100644
index 0000000..d48197b
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/Android.bp
@@ -0,0 +1,154 @@
+// DO NOT DEPEND ON THIS DIRECTLY
+// use libcodec2-hidl-client-defaults instead
+cc_library {
+    name: "libcodec2_hidl_client@1.1",
+
+    defaults: ["hidl_defaults"],
+
+    srcs: [
+        "OutputBufferQueue.cpp",
+        "types.cpp",
+    ],
+
+    header_libs: [
+        "libcodec2_internal", // private
+    ],
+
+    shared_libs: [
+        "android.hardware.media.bufferpool@2.0",
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
+        "libbase",
+        "libcodec2",
+        "libcodec2_hidl_client@1.0",
+        "libcodec2_vndk",
+        "libcutils",
+        "libgui",
+        "libhidlbase",
+        "liblog",
+        "libstagefright_bufferpool@2.0.1",
+        "libui",
+        "libutils",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    export_shared_lib_headers: [
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
+        "libcodec2",
+        "libcodec2_hidl_client@1.0",
+        "libgui",
+        "libstagefright_bufferpool@2.0.1",
+        "libui",
+    ],
+}
+
+
+// DO NOT DEPEND ON THIS DIRECTLY
+// use libcodec2-hidl-defaults instead
+cc_library {
+    name: "libcodec2_hidl@1.1",
+    vendor_available: true,
+
+    defaults: ["hidl_defaults"],
+
+    srcs: [
+        "Component.cpp",
+        "ComponentInterface.cpp",
+        "ComponentStore.cpp",
+        "Configurable.cpp",
+        "InputBufferManager.cpp",
+        "InputSurface.cpp",
+        "InputSurfaceConnection.cpp",
+        "types.cpp",
+    ],
+
+    header_libs: [
+        "libbinder_headers",
+        "libsystem_headers",
+        "libcodec2_internal", // private
+    ],
+
+    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.c2@1.1",
+        "android.hardware.media.omx@1.0",
+        "libbase",
+        "libcodec2",
+        "libcodec2_hidl@1.0",
+        "libcodec2_vndk",
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libstagefright_bufferpool@2.0.1",
+        "libstagefright_bufferqueue_helper",
+        "libui",
+        "libutils",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    export_shared_lib_headers: [
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
+        "libcodec2",
+        "libcodec2_hidl@1.0",
+        "libcodec2_vndk",
+        "libhidlbase",
+        "libstagefright_bufferpool@2.0.1",
+        "libstagefright_bufferqueue_helper",
+        "libui",
+    ],
+}
+
+// public dependency for Codec 2.0 HAL service implementations
+cc_defaults {
+    name: "libcodec2-hidl-defaults@1.1",
+    defaults: ["libcodec2-impl-defaults"],
+
+    shared_libs: [
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
+        "libcodec2_hidl@1.0",
+        "libcodec2_hidl@1.1",
+        "libcodec2_vndk",
+        "libhidlbase",
+    ],
+}
+
+// public dependency for Codec 2.0 HAL client
+cc_defaults {
+    name: "libcodec2-hidl-client-defaults@1.1",
+    defaults: ["libcodec2-impl-defaults"],
+
+    shared_libs: [
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
+        "libcodec2_hidl_client@1.0",
+        "libcodec2_hidl_client@1.1",
+        "libcodec2_vndk",
+        "libhidlbase",
+    ],
+}
+
+// Alias to the latest "defaults" for Codec 2.0 HAL service implementations
+cc_defaults {
+    name: "libcodec2-hidl-defaults",
+    defaults: ["libcodec2-hidl-defaults@1.1"],
+}
+
+// Alias to the latest "defaults" for Codec 2.0 HAL client
+cc_defaults {
+    name: "libcodec2-hidl-client-defaults",
+    defaults: ["libcodec2-hidl-client-defaults@1.1"],
+}
diff --git a/media/codec2/hidl/1.1/utils/Component.cpp b/media/codec2/hidl/1.1/utils/Component.cpp
new file mode 100644
index 0000000..ed281e6
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/Component.cpp
@@ -0,0 +1,493 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-Component@1.1"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.1/Component.h>
+#include <codec2/hidl/1.1/ComponentStore.h>
+#include <codec2/hidl/1.1/InputBufferManager.h>
+
+#include <hidl/HidlBinderSupport.h>
+#include <utils/Timers.h>
+
+#include <C2BqBufferPriv.h>
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using namespace ::android;
+
+// ComponentListener wrapper
+struct Component::Listener : public C2Component::Listener {
+
+    Listener(const sp<Component>& component) :
+        mComponent(component),
+        mListener(component->mListener) {
+    }
+
+    virtual void onError_nb(
+            std::weak_ptr<C2Component> /* c2component */,
+            uint32_t errorCode) override {
+        sp<IComponentListener> listener = mListener.promote();
+        if (listener) {
+            Return<void> transStatus = listener->onError(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 {
+        sp<IComponentListener> listener = mListener.promote();
+        if (listener) {
+            hidl_vec<SettingResult> settingResults(c2settingResult.size());
+            size_t ix = 0;
+            for (const std::shared_ptr<C2SettingResult> &c2result :
+                    c2settingResult) {
+                if (c2result) {
+                    if (!objcpy(&settingResults[ix++], *c2result)) {
+                        break;
+                    }
+                }
+            }
+            settingResults.resize(ix);
+            Return<void> 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);
+                }
+            }
+        }
+
+        sp<IComponentListener> listener = mListener.promote();
+        if (listener) {
+            WorkBundle workBundle;
+
+            sp<Component> strongComponent = mComponent.promote();
+            beginTransferBufferQueueBlocks(c2workItems, true);
+            if (!objcpy(&workBundle, c2workItems, strongComponent ?
+                    &strongComponent->mBufferPoolSender : nullptr)) {
+                LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
+                           << "received corrupted work items.";
+                endTransferBufferQueueBlocks(c2workItems, false, true);
+                return;
+            }
+            Return<void> transStatus = listener->onWorkDone(workBundle);
+            if (!transStatus.isOk()) {
+                LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
+                           << "transaction failed.";
+                endTransferBufferQueueBlocks(c2workItems, false, true);
+                return;
+            }
+            endTransferBufferQueueBlocks(c2workItems, true, true);
+        }
+    }
+
+protected:
+    wp<Component> mComponent;
+    wp<IComponentListener> mListener;
+};
+
+// Component::Sink
+struct Component::Sink : public IInputSink {
+    std::shared_ptr<Component> mComponent;
+    sp<IConfigurable> mConfigurable;
+
+    virtual Return<Status> queue(const WorkBundle& workBundle) override {
+        return mComponent->queue(workBundle);
+    }
+
+    virtual Return<sp<IConfigurable>> getConfigurable() override {
+        return mConfigurable;
+    }
+
+    Sink(const std::shared_ptr<Component>& component);
+    virtual ~Sink() override;
+
+    // Process-wide map: Component::Sink -> C2Component.
+    static std::mutex sSink2ComponentMutex;
+    static std::map<IInputSink*, std::weak_ptr<C2Component>> sSink2Component;
+
+    static std::shared_ptr<C2Component> findLocalComponent(
+            const sp<IInputSink>& sink);
+};
+
+std::mutex
+        Component::Sink::sSink2ComponentMutex{};
+std::map<IInputSink*, std::weak_ptr<C2Component>>
+        Component::Sink::sSink2Component{};
+
+Component::Sink::Sink(const std::shared_ptr<Component>& component)
+        : mComponent{component},
+          mConfigurable{[&component]() -> sp<IConfigurable> {
+              Return<sp<IComponentInterface>> ret1 = component->getInterface();
+              if (!ret1.isOk()) {
+                  LOG(ERROR) << "Sink::Sink -- component's transaction failed.";
+                  return nullptr;
+              }
+              Return<sp<IConfigurable>> ret2 =
+                      static_cast<sp<IComponentInterface>>(ret1)->
+                      getConfigurable();
+              if (!ret2.isOk()) {
+                  LOG(ERROR) << "Sink::Sink -- interface's transaction failed.";
+                  return nullptr;
+              }
+              return static_cast<sp<IConfigurable>>(ret2);
+          }()} {
+    std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
+    sSink2Component.emplace(this, component->mComponent);
+}
+
+Component::Sink::~Sink() {
+    std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
+    sSink2Component.erase(this);
+}
+
+std::shared_ptr<C2Component> Component::Sink::findLocalComponent(
+        const sp<IInputSink>& sink) {
+    std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
+    auto i = sSink2Component.find(sink.get());
+    if (i == sSink2Component.end()) {
+        return nullptr;
+    }
+    return i->second.lock();
+}
+
+// Component
+Component::Component(
+        const std::shared_ptr<C2Component>& component,
+        const sp<IComponentListener>& listener,
+        const sp<ComponentStore>& store,
+        const sp<::android::hardware::media::bufferpool::V2_0::
+        IClientManager>& clientPoolManager)
+      : mComponent{component},
+        mInterface{new ComponentInterface(component->intf(),
+                                          store->getParameterCache())},
+        mListener{listener},
+        mStore{store},
+        mBufferPoolSender{clientPoolManager} {
+    // 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
+Return<Status> Component::queue(const WorkBundle& workBundle) {
+    std::list<std::unique_ptr<C2Work>> c2works;
+
+    if (!objcpy(&c2works, workBundle)) {
+        return Status::CORRUPTED;
+    }
+
+    // Register input buffers.
+    for (const std::unique_ptr<C2Work>& work : c2works) {
+        if (work) {
+            InputBufferManager::
+                    registerFrameData(mListener, work->input);
+        }
+    }
+
+    return static_cast<Status>(mComponent->queue_nb(&c2works));
+}
+
+Return<void> Component::flush(flush_cb _hidl_cb) {
+    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);
+            }
+        }
+    }
+
+    WorkBundle flushedWorkBundle;
+    Status res = static_cast<Status>(c2res);
+    beginTransferBufferQueueBlocks(c2flushedWorks, true);
+    if (c2res == C2_OK) {
+        if (!objcpy(&flushedWorkBundle, c2flushedWorks, &mBufferPoolSender)) {
+            res = Status::CORRUPTED;
+        }
+    }
+    _hidl_cb(res, flushedWorkBundle);
+    endTransferBufferQueueBlocks(c2flushedWorks, true, true);
+    return Void();
+}
+
+Return<Status> Component::drain(bool withEos) {
+    return static_cast<Status>(mComponent->drain_nb(withEos ?
+            C2Component::DRAIN_COMPONENT_WITH_EOS :
+            C2Component::DRAIN_COMPONENT_NO_EOS));
+}
+
+Return<Status> Component::setOutputSurface(
+        uint64_t blockPoolId,
+        const sp<HGraphicBufferProducer2>& surface) {
+    std::shared_ptr<C2BlockPool> pool;
+    GetCodec2BlockPool(blockPoolId, mComponent, &pool);
+    if (pool && pool->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
+        std::shared_ptr<C2BufferQueueBlockPool> bqPool =
+                std::static_pointer_cast<C2BufferQueueBlockPool>(pool);
+        C2BufferQueueBlockPool::OnRenderCallback cb =
+            [this](uint64_t producer, int32_t slot, int64_t nsecs) {
+                // TODO: batch this
+                hidl_vec<IComponentListener::RenderedFrame> rendered;
+                rendered.resize(1);
+                rendered[0] = { producer, slot, nsecs };
+                (void)mListener->onFramesRendered(rendered).isOk();
+        };
+        if (bqPool) {
+            bqPool->setRenderCallback(cb);
+            bqPool->configureProducer(surface);
+        }
+    }
+    return Status::OK;
+}
+
+Return<void> Component::connectToInputSurface(
+        const sp<IInputSurface>& inputSurface,
+        connectToInputSurface_cb _hidl_cb) {
+    Status status;
+    sp<IInputSurfaceConnection> connection;
+    auto transStatus = inputSurface->connect(
+            asInputSink(),
+            [&status, &connection](
+                    Status s, const sp<IInputSurfaceConnection>& c) {
+                status = s;
+                connection = c;
+            }
+        );
+    _hidl_cb(status, connection);
+    return Void();
+}
+
+Return<void> Component::connectToOmxInputSurface(
+        const sp<HGraphicBufferProducer1>& producer,
+        const sp<::android::hardware::media::omx::V1_0::
+        IGraphicBufferSource>& source,
+        connectToOmxInputSurface_cb _hidl_cb) {
+    (void)producer;
+    (void)source;
+    (void)_hidl_cb;
+    return Void();
+}
+
+Return<Status> Component::disconnectFromInputSurface() {
+    // TODO implement
+    return Status::OK;
+}
+
+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
+
+Return<void> Component::createBlockPool(
+        uint32_t allocatorId,
+        createBlockPool_cb _hidl_cb) {
+    std::shared_ptr<C2BlockPool> blockPool;
+    c2_status_t status = CreateCodec2BlockPool(
+            static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
+            mComponent,
+            &blockPool);
+    if (status != C2_OK) {
+        blockPool = nullptr;
+    }
+    if (blockPool) {
+        mBlockPoolsMutex.lock();
+        mBlockPools.emplace(blockPool->getLocalId(), blockPool);
+        mBlockPoolsMutex.unlock();
+    } else if (status == C2_OK) {
+        status = C2_CORRUPTED;
+    }
+
+    _hidl_cb(static_cast<Status>(status),
+            blockPool ? blockPool->getLocalId() : 0,
+            new CachedConfigurable(
+            std::make_unique<BlockPoolIntf>(blockPool)));
+    return Void();
+}
+
+Return<Status> Component::destroyBlockPool(uint64_t blockPoolId) {
+    std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+    return mBlockPools.erase(blockPoolId) == 1 ?
+            Status::OK : Status::CORRUPTED;
+}
+
+Return<Status> Component::start() {
+    return static_cast<Status>(mComponent->start());
+}
+
+Return<Status> Component::stop() {
+    InputBufferManager::unregisterFrameData(mListener);
+    return static_cast<Status>(mComponent->stop());
+}
+
+Return<Status> Component::reset() {
+    Status status = static_cast<Status>(mComponent->reset());
+    {
+        std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+        mBlockPools.clear();
+    }
+    InputBufferManager::unregisterFrameData(mListener);
+    return status;
+}
+
+Return<Status> Component::release() {
+    Status status = static_cast<Status>(mComponent->release());
+    {
+        std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+        mBlockPools.clear();
+    }
+    InputBufferManager::unregisterFrameData(mListener);
+    return status;
+}
+
+Return<sp<IComponentInterface>> Component::getInterface() {
+    return sp<IComponentInterface>(mInterface);
+}
+
+Return<sp<IInputSink>> Component::asInputSink() {
+    std::lock_guard<std::mutex> lock(mSinkMutex);
+    if (!mSink) {
+        mSink = new Sink(shared_from_this());
+    }
+    return {mSink};
+}
+
+Return<void> Component::configureVideoTunnel(
+        uint32_t avSyncHwId, configureVideoTunnel_cb _hidl_cb) {
+    (void)avSyncHwId;
+    _hidl_cb(Status::OMITTED, hidl_handle{});
+    return Void();
+}
+
+std::shared_ptr<C2Component> Component::findLocalComponent(
+        const sp<IInputSink>& sink) {
+    return Component::Sink::findLocalComponent(sink);
+}
+
+void Component::initListener(const sp<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;
+    }
+}
+
+Component::~Component() {
+    InputBufferManager::unregisterFrameData(mListener);
+    mStore->reportComponentDeath(this);
+}
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
diff --git a/media/codec2/hidl/1.1/utils/ComponentInterface.cpp b/media/codec2/hidl/1.1/utils/ComponentInterface.cpp
new file mode 100644
index 0000000..ccc30fe
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/ComponentInterface.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/ComponentInterface.h>
diff --git a/media/codec2/hidl/1.1/utils/ComponentStore.cpp b/media/codec2/hidl/1.1/utils/ComponentStore.cpp
new file mode 100644
index 0000000..225cd09
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/ComponentStore.cpp
@@ -0,0 +1,499 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-ComponentStore@1.1"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.1/ComponentStore.h>
+#include <codec2/hidl/1.1/InputSurface.h>
+#include <codec2/hidl/1.1/types.h>
+
+#include <android-base/file.h>
+#include <media/stagefright/bqhelper/GraphicBufferSource.h>
+#include <utils/Errors.h>
+
+#include <C2PlatformSupport.h>
+#include <util/C2InterfaceHelper.h>
+
+#include <chrono>
+#include <ctime>
+#include <iomanip>
+#include <ostream>
+#include <sstream>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using namespace ::android;
+using ::android::GraphicBufferSource;
+using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
+
+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{new CachedConfigurable(std::make_unique<StoreIntf>(store))},
+        mParameterCache{std::make_shared<StoreParameterCache>(this)},
+        mStore{store} {
+
+    std::shared_ptr<C2ComponentStore> platformStore = android::GetCodec2PlatformComponentStore();
+    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;
+}
+
+// Methods from ::android::hardware::media::c2::V1_0::IComponentStore
+Return<void> ComponentStore::createComponent(
+        const hidl_string& name,
+        const sp<IComponentListener>& listener,
+        const sp<IClientManager>& pool,
+        createComponent_cb _hidl_cb) {
+
+    sp<Component> component;
+    std::shared_ptr<C2Component> c2component;
+    Status status = static_cast<Status>(
+            mStore->createComponent(name, &c2component));
+
+    if (status == Status::OK) {
+        onInterfaceLoaded(c2component->intf());
+        component = new Component(c2component, listener, this, pool);
+        if (!component) {
+            status = Status::CORRUPTED;
+        } else {
+            reportComponentBirth(component.get());
+            if (component->status() != C2_OK) {
+                status = static_cast<Status>(component->status());
+            } else {
+                component->initListener(component);
+                if (component->status() != C2_OK) {
+                    status = static_cast<Status>(component->status());
+                }
+            }
+        }
+    }
+    _hidl_cb(status, component);
+    return Void();
+}
+
+Return<void> ComponentStore::createInterface(
+        const hidl_string& name,
+        createInterface_cb _hidl_cb) {
+    std::shared_ptr<C2ComponentInterface> c2interface;
+    c2_status_t res = mStore->createInterface(name, &c2interface);
+    sp<IComponentInterface> interface;
+    if (res == C2_OK) {
+        onInterfaceLoaded(c2interface);
+        interface = new ComponentInterface(c2interface, mParameterCache);
+    }
+    _hidl_cb(static_cast<Status>(res), interface);
+    return Void();
+}
+
+Return<void> ComponentStore::listComponents(listComponents_cb _hidl_cb) {
+    std::vector<std::shared_ptr<const C2Component::Traits>> c2traits =
+            mStore->listComponents();
+    hidl_vec<IComponentStore::ComponentTraits> traits(c2traits.size());
+    size_t ix = 0;
+    for (const std::shared_ptr<const C2Component::Traits> &c2trait : c2traits) {
+        if (c2trait) {
+            if (objcpy(&traits[ix], *c2trait)) {
+                ++ix;
+            } else {
+                break;
+            }
+        }
+    }
+    traits.resize(ix);
+    _hidl_cb(Status::OK, traits);
+    return Void();
+}
+
+Return<void> ComponentStore::createInputSurface(createInputSurface_cb _hidl_cb) {
+    sp<GraphicBufferSource> source = new GraphicBufferSource();
+    if (source->initCheck() != OK) {
+        _hidl_cb(Status::CORRUPTED, nullptr);
+        return Void();
+    }
+    using namespace std::placeholders;
+    sp<InputSurface> inputSurface = new InputSurface(
+            mParameterCache,
+            std::make_shared<C2ReflectorHelper>(),
+            source->getHGraphicBufferProducer(),
+            source);
+    _hidl_cb(inputSurface ? Status::OK : Status::NO_MEMORY,
+             inputSurface);
+    return Void();
+}
+
+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());
+    }
+}
+
+Return<void> ComponentStore::getStructDescriptors(
+        const hidl_vec<uint32_t>& indices,
+        getStructDescriptors_cb _hidl_cb) {
+    hidl_vec<StructDescriptor> descriptors(indices.size());
+    size_t dstIx = 0;
+    Status 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(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 (objcpy(&descriptors[dstIx], *structDesc)) {
+                        ++dstIx;
+                        continue;
+                    }
+                    res = Status::CORRUPTED;
+                    break;
+                }
+            }
+            res = Status::NOT_FOUND;
+        } else if (item->second) {
+            if (objcpy(&descriptors[dstIx], *item->second)) {
+                ++dstIx;
+                continue;
+            }
+            res = Status::CORRUPTED;
+            break;
+        } else {
+            res = Status::NO_MEMORY;
+            break;
+        }
+    }
+    descriptors.resize(dstIx);
+    _hidl_cb(res, descriptors);
+    return Void();
+}
+
+Return<sp<IClientManager>> ComponentStore::getPoolClientManager() {
+    return ClientManager::getInstance();
+}
+
+Return<Status> ComponentStore::copyBuffer(const Buffer& src, const Buffer& dst) {
+    // TODO implement
+    (void)src;
+    (void)dst;
+    return Status::OMITTED;
+}
+
+Return<sp<IConfigurable>> ComponentStore::getConfigurable() {
+    return mConfigurable;
+}
+
+// Methods from ::android::hardware::media::c2::V1_1::IComponentStore
+Return<void> ComponentStore::createComponent_1_1(
+        const hidl_string& name,
+        const sp<IComponentListener>& listener,
+        const sp<IClientManager>& pool,
+        createComponent_1_1_cb _hidl_cb) {
+
+    sp<Component> component;
+    std::shared_ptr<C2Component> c2component;
+    Status status = static_cast<Status>(
+            mStore->createComponent(name, &c2component));
+
+    if (status == Status::OK) {
+        onInterfaceLoaded(c2component->intf());
+        component = new Component(c2component, listener, this, pool);
+        if (!component) {
+            status = Status::CORRUPTED;
+        } else {
+            reportComponentBirth(component.get());
+            if (component->status() != C2_OK) {
+                status = static_cast<Status>(component->status());
+            } else {
+                component->initListener(component);
+                if (component->status() != C2_OK) {
+                    status = static_cast<Status>(component->status());
+                }
+            }
+        }
+    }
+    _hidl_cb(status, component);
+    return Void();
+}
+
+// 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.
+Return<void> ComponentStore::debug(
+        const hidl_handle& handle,
+        const hidl_vec<hidl_string>& /* args */) {
+    LOG(INFO) << "debug -- dumping...";
+    const native_handle_t *h = handle.getNativeHandle();
+    if (!h || h->numFds != 1) {
+       LOG(ERROR) << "debug -- dumping failed -- "
+               "invalid file descriptor to dump to";
+       return Void();
+    }
+    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(), h->data[0])) {
+        PLOG(WARNING) << "debug -- dumping failed -- write()";
+    } else {
+        LOG(INFO) << "debug -- dumping succeeded";
+    }
+    return Void();
+}
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
diff --git a/media/codec2/hidl/1.1/utils/Configurable.cpp b/media/codec2/hidl/1.1/utils/Configurable.cpp
new file mode 100644
index 0000000..1f3b2c7
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/Configurable.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/Configurable.h>
diff --git a/media/codec2/hidl/1.1/utils/InputBufferManager.cpp b/media/codec2/hidl/1.1/utils/InputBufferManager.cpp
new file mode 100644
index 0000000..45bfc86
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/InputBufferManager.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/InputBufferManager.h>
diff --git a/media/codec2/hidl/1.1/utils/InputSurface.cpp b/media/codec2/hidl/1.1/utils/InputSurface.cpp
new file mode 100644
index 0000000..ce40494
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/InputSurface.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/InputSurface.h>
diff --git a/media/codec2/hidl/1.1/utils/InputSurfaceConnection.cpp b/media/codec2/hidl/1.1/utils/InputSurfaceConnection.cpp
new file mode 100644
index 0000000..32154a7
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/InputSurfaceConnection.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/InputSurfaceConnection.h>
diff --git a/media/codec2/hidl/1.1/utils/OutputBufferQueue.cpp b/media/codec2/hidl/1.1/utils/OutputBufferQueue.cpp
new file mode 100644
index 0000000..65756e8
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/OutputBufferQueue.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/OutputBufferQueue.h>
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Component.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Component.h
new file mode 100644
index 0000000..16c81d4
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Component.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_COMPONENT_H
+#define CODEC2_HIDL_V1_1_UTILS_COMPONENT_H
+
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
+#include <android/hardware/media/c2/1.1/IComponent.h>
+#include <android/hardware/media/c2/1.0/IComponentInterface.h>
+#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <android/hardware/media/c2/1.1/IComponentStore.h>
+#include <android/hardware/media/c2/1.0/IInputSink.h>
+#include <codec2/hidl/1.1/ComponentInterface.h>
+#include <codec2/hidl/1.1/Configurable.h>
+#include <codec2/hidl/1.1/types.h>
+#include <hidl/Status.h>
+#include <hwbinder/IBinder.h>
+
+#include <C2Component.h>
+#include <C2Buffer.h>
+#include <C2.h>
+
+#include <map>
+#include <memory>
+#include <mutex>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+
+using ::android::hardware::media::c2::V1_1::IComponent;
+using ::android::hardware::media::c2::V1_0::IComponentListener;
+
+namespace utils {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::IBinder;
+using ::android::sp;
+using ::android::wp;
+
+struct ComponentStore;
+
+struct Component : public IComponent,
+                   public std::enable_shared_from_this<Component> {
+    Component(
+            const std::shared_ptr<C2Component>&,
+            const sp<IComponentListener>& listener,
+            const sp<ComponentStore>& store,
+            const sp<::android::hardware::media::bufferpool::V2_0::
+                IClientManager>& clientPoolManager);
+    c2_status_t status() const;
+
+    typedef ::android::hardware::graphics::bufferqueue::V1_0::
+            IGraphicBufferProducer HGraphicBufferProducer1;
+    typedef ::android::hardware::graphics::bufferqueue::V2_0::
+            IGraphicBufferProducer HGraphicBufferProducer2;
+
+    // Methods from IComponent follow.
+    virtual Return<Status> queue(const WorkBundle& workBundle) override;
+    virtual Return<void> flush(flush_cb _hidl_cb) override;
+    virtual Return<Status> drain(bool withEos) override;
+    virtual Return<Status> setOutputSurface(
+            uint64_t blockPoolId,
+            const sp<HGraphicBufferProducer2>& surface) override;
+    virtual Return<void> connectToInputSurface(
+            const sp<IInputSurface>& inputSurface,
+            connectToInputSurface_cb _hidl_cb) override;
+    virtual Return<void> connectToOmxInputSurface(
+            const sp<HGraphicBufferProducer1>& producer,
+            const sp<::android::hardware::media::omx::V1_0::
+            IGraphicBufferSource>& source,
+            connectToOmxInputSurface_cb _hidl_cb) override;
+    virtual Return<Status> disconnectFromInputSurface() override;
+    virtual Return<void> createBlockPool(
+            uint32_t allocatorId,
+            createBlockPool_cb _hidl_cb) override;
+    virtual Return<Status> destroyBlockPool(uint64_t blockPoolId) override;
+    virtual Return<Status> start() override;
+    virtual Return<Status> stop() override;
+    virtual Return<Status> reset() override;
+    virtual Return<Status> release() override;
+    virtual Return<sp<IComponentInterface>> getInterface() override;
+    virtual Return<sp<IInputSink>> asInputSink() override;
+    virtual Return<void> configureVideoTunnel(
+            uint32_t avSyncHwId, configureVideoTunnel_cb _hidl_cb) override;
+
+    // Returns a C2Component associated to the given sink if the sink is indeed
+    // a local component. Returns nullptr otherwise.
+    //
+    // This function is used by InputSurface::connect().
+    static std::shared_ptr<C2Component> findLocalComponent(
+            const sp<IInputSink>& sink);
+
+protected:
+    c2_status_t mInit;
+    std::shared_ptr<C2Component> mComponent;
+    sp<ComponentInterface> mInterface;
+    sp<IComponentListener> mListener;
+    sp<ComponentStore> mStore;
+    ::android::hardware::media::c2::V1_1::utils::DefaultBufferPoolSender
+            mBufferPoolSender;
+
+    struct Sink;
+    std::mutex mSinkMutex;
+    sp<Sink> mSink;
+
+    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 sp<Component>& self);
+
+    virtual ~Component() override;
+
+    friend struct ComponentStore;
+
+    struct Listener;
+};
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_COMPONENT_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentInterface.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentInterface.h
new file mode 100644
index 0000000..723c5bd
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentInterface.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_COMPONENT_INTERFACE_H
+#define CODEC2_HIDL_V1_1_UTILS_COMPONENT_INTERFACE_H
+
+#include <codec2/hidl/1.0/ComponentInterface.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::ComponentInterface;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_COMPONENT_INTERFACE_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
new file mode 100644
index 0000000..1f04391
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_COMPONENT_STORE_H
+#define CODEC2_HIDL_V1_1_UTILS_COMPONENT_STORE_H
+
+#include <codec2/hidl/1.1/Component.h>
+#include <codec2/hidl/1.1/ComponentInterface.h>
+#include <codec2/hidl/1.1/Configurable.h>
+#include <codec2/hidl/1.1/types.h>
+
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
+#include <android/hardware/media/c2/1.1/IComponentStore.h>
+#include <hidl/Status.h>
+
+#include <C2Component.h>
+#include <C2Param.h>
+#include <C2.h>
+
+#include <chrono>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::bufferpool::V2_0::IClientManager;
+
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct ComponentStore : public IComponentStore {
+    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;
+
+    // Methods from ::android::hardware::media::c2::V1_0::IComponentStore.
+    virtual Return<void> createComponent(
+            const hidl_string& name,
+            const sp<IComponentListener>& listener,
+            const sp<IClientManager>& pool,
+            createComponent_cb _hidl_cb) override;
+    virtual Return<void> createInterface(
+            const hidl_string& name,
+            createInterface_cb _hidl_cb) override;
+    virtual Return<void> listComponents(listComponents_cb _hidl_cb) override;
+    virtual Return<void> createInputSurface(
+            createInputSurface_cb _hidl_cb) override;
+    virtual Return<void> getStructDescriptors(
+            const hidl_vec<uint32_t>& indices,
+            getStructDescriptors_cb _hidl_cb) override;
+    virtual Return<sp<IClientManager>> getPoolClientManager() override;
+    virtual Return<Status> copyBuffer(
+            const Buffer& src,
+            const Buffer& dst) override;
+    virtual Return<sp<IConfigurable>> getConfigurable() override;
+
+    // Methods from ::android::hardware::media::c2::V1_1::IComponentStore.
+    virtual Return<void> createComponent_1_1(
+            const hidl_string& name,
+            const sp<IComponentListener>& listener,
+            const sp<IClientManager>& pool,
+            createComponent_1_1_cb _hidl_cb) override;
+
+    /**
+     * Dumps information when lshal is called.
+     */
+    virtual Return<void> debug(
+            const hidl_handle& handle,
+            const hidl_vec<hidl_string>& args) override;
+
+protected:
+    sp<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 V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_COMPONENT_STORE_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Configurable.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Configurable.h
new file mode 100644
index 0000000..fd9091b
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Configurable.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_CONFIGURABLE_H
+#define CODEC2_HIDL_V1_1_UTILS_CONFIGURABLE_H
+
+#include <codec2/hidl/1.0/Configurable.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::ConfigurableC2Intf;
+using ::android::hardware::media::c2::V1_0::utils::ParameterCache;
+using ::android::hardware::media::c2::V1_0::utils::CachedConfigurable;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_CONFIGURABLE_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputBufferManager.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputBufferManager.h
new file mode 100644
index 0000000..8e7a91b
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputBufferManager.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_INPUT_BUFFER_MANAGER_H
+#define CODEC2_HIDL_V1_1_UTILS_INPUT_BUFFER_MANAGER_H
+
+#include <codec2/hidl/1.0/InputBufferManager.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::InputBufferManager;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_INPUT_BUFFER_MANAGER_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurface.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurface.h
new file mode 100644
index 0000000..59223b7
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurface.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_H
+#define CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_H
+
+#include <codec2/hidl/1.0/InputSurface.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::InputSurface;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurfaceConnection.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurfaceConnection.h
new file mode 100644
index 0000000..7f695ef
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurfaceConnection.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_CONNECTION_H
+#define CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_CONNECTION_H
+
+#include <codec2/hidl/1.0/InputSurfaceConnection.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::InputSurfaceConnection;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_CONNECTION_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/OutputBufferQueue.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/OutputBufferQueue.h
new file mode 100644
index 0000000..f77852d
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/OutputBufferQueue.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_OUTPUT_BUFFER_QUEUE
+#define CODEC2_HIDL_V1_1_UTILS_OUTPUT_BUFFER_QUEUE
+
+#include <codec2/hidl/1.0/OutputBufferQueue.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::OutputBufferQueue;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_OUTPUT_BUFFER_QUEUE
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/types.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/types.h
new file mode 100644
index 0000000..d0ba93d
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/types.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_TYPES_H
+#define CODEC2_HIDL_V1_1_UTILS_TYPES_H
+
+#include <android/hardware/media/c2/1.1/IComponent.h>
+#include <android/hardware/media/c2/1.0/IComponentInterface.h>
+#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <android/hardware/media/c2/1.1/IComponentStore.h>
+#include <android/hardware/media/c2/1.0/IConfigurable.h>
+#include <android/hardware/media/c2/1.0/IInputSink.h>
+#include <android/hardware/media/c2/1.0/IInputSurface.h>
+#include <android/hardware/media/c2/1.0/IInputSurfaceConnection.h>
+
+#include <codec2/hidl/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+
+using ::android::hardware::media::c2::V1_0::BaseBlock;
+using ::android::hardware::media::c2::V1_0::Block;
+using ::android::hardware::media::c2::V1_0::Buffer;
+using ::android::hardware::media::c2::V1_0::FieldDescriptor;
+using ::android::hardware::media::c2::V1_0::FieldId;
+using ::android::hardware::media::c2::V1_0::FieldSupportedValues;
+using ::android::hardware::media::c2::V1_0::FieldSupportedValuesQuery;
+using ::android::hardware::media::c2::V1_0::FieldSupportedValuesQueryResult;
+using ::android::hardware::media::c2::V1_0::FrameData;
+using ::android::hardware::media::c2::V1_0::InfoBuffer;
+using ::android::hardware::media::c2::V1_0::ParamDescriptor;
+using ::android::hardware::media::c2::V1_0::ParamField;
+using ::android::hardware::media::c2::V1_0::ParamFieldValues;
+using ::android::hardware::media::c2::V1_0::ParamIndex;
+using ::android::hardware::media::c2::V1_0::Params;
+using ::android::hardware::media::c2::V1_0::PrimitiveValue;
+using ::android::hardware::media::c2::V1_0::SettingResult;
+using ::android::hardware::media::c2::V1_0::Status;
+using ::android::hardware::media::c2::V1_0::StructDescriptor;
+using ::android::hardware::media::c2::V1_0::ValueRange;
+using ::android::hardware::media::c2::V1_0::Work;
+using ::android::hardware::media::c2::V1_0::WorkBundle;
+using ::android::hardware::media::c2::V1_0::WorkOrdinal;
+using ::android::hardware::media::c2::V1_0::Worklet;
+
+using ::android::hardware::media::c2::V1_0::IComponentInterface;
+using ::android::hardware::media::c2::V1_0::IComponentListener;
+using ::android::hardware::media::c2::V1_0::IConfigurable;
+using ::android::hardware::media::c2::V1_0::IInputSink;
+using ::android::hardware::media::c2::V1_0::IInputSurface;
+using ::android::hardware::media::c2::V1_0::IInputSurfaceConnection;
+
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::toC2Status;
+
+using ::android::hardware::media::c2::V1_0::utils::C2Hidl_Range;
+using ::android::hardware::media::c2::V1_0::utils::C2Hidl_RangeInfo;
+using ::android::hardware::media::c2::V1_0::utils::C2Hidl_Rect;
+using ::android::hardware::media::c2::V1_0::utils::C2Hidl_RectInfo;
+
+using ::android::hardware::media::c2::V1_0::utils::objcpy;
+using ::android::hardware::media::c2::V1_0::utils::parseParamsBlob;
+using ::android::hardware::media::c2::V1_0::utils::createParamsBlob;
+using ::android::hardware::media::c2::V1_0::utils::copyParamsFromBlob;
+using ::android::hardware::media::c2::V1_0::utils::updateParamsFromBlob;
+
+using ::android::hardware::media::c2::V1_0::utils::BufferPoolSender;
+using ::android::hardware::media::c2::V1_0::utils::DefaultBufferPoolSender;
+
+using ::android::hardware::media::c2::V1_0::utils::beginTransferBufferQueueBlock;
+using ::android::hardware::media::c2::V1_0::utils::beginTransferBufferQueueBlocks;
+using ::android::hardware::media::c2::V1_0::utils::endTransferBufferQueueBlock;
+using ::android::hardware::media::c2::V1_0::utils::endTransferBufferQueueBlocks;
+using ::android::hardware::media::c2::V1_0::utils::displayBufferQueueBlock;
+
+using ::android::hardware::media::c2::V1_0::utils::operator<<;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_TYPES_H
diff --git a/media/codec2/hidl/1.1/utils/types.cpp b/media/codec2/hidl/1.1/utils/types.cpp
new file mode 100644
index 0000000..8c09023
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/types.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/types.h>
diff --git a/media/codec2/hidl/client/Android.bp b/media/codec2/hidl/client/Android.bp
index 89c1c4a..3c37990 100644
--- a/media/codec2/hidl/client/Android.bp
+++ b/media/codec2/hidl/client/Android.bp
@@ -9,10 +9,12 @@
         "android.hardware.graphics.bufferqueue@1.0",
         "android.hardware.media.bufferpool@2.0",
         "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
         "libbase",
         "libbinder",
         "libcodec2",
         "libcodec2_hidl_client@1.0",
+        "libcodec2_hidl_client@1.1",
         "libcodec2_vndk",
         "libcutils",
         "libgui",
@@ -28,8 +30,11 @@
     ],
 
     export_shared_lib_headers: [
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
         "libcodec2",
         "libcodec2_hidl_client@1.0",
+        "libcodec2_hidl_client@1.1",
         "libcodec2_vndk",
     ],
 
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index c747190..199a99c 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -19,6 +19,29 @@
 #include <android-base/logging.h>
 
 #include <codec2/hidl/client.h>
+#include <C2Debug.h>
+#include <C2BufferPriv.h>
+#include <C2PlatformSupport.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>
+#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <android/hardware/media/c2/1.0/IComponentStore.h>
+#include <android/hardware/media/c2/1.0/IConfigurable.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+
+#include <android-base/properties.h>
+#include <bufferpool/ClientManager.h>
+#include <codec2/hidl/1.0/OutputBufferQueue.h>
+#include <codec2/hidl/1.0/types.h>
+#include <codec2/hidl/1.1/OutputBufferQueue.h>
+#include <codec2/hidl/1.1/types.h>
+
+#include <cutils/native_handle.h>
+#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
+#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
+#include <hidl/HidlSupport.h>
 
 #include <deque>
 #include <iterator>
@@ -30,25 +53,6 @@
 #include <type_traits>
 #include <vector>
 
-#include <android-base/properties.h>
-#include <bufferpool/ClientManager.h>
-#include <cutils/native_handle.h>
-#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
-#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
-#include <hidl/HidlSupport.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>
-#include <android/hardware/media/c2/1.0/IComponentListener.h>
-#include <android/hardware/media/c2/1.0/IComponentStore.h>
-#include <android/hardware/media/c2/1.0/IConfigurable.h>
-#include <android/hidl/manager/1.2/IServiceManager.h>
-
-#include <C2Debug.h>
-#include <C2BufferPriv.h>
-#include <C2PlatformSupport.h>
-
 namespace android {
 
 using ::android::hardware::hidl_vec;
@@ -56,8 +60,8 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 
-using namespace ::android::hardware::media::c2::V1_0;
-using namespace ::android::hardware::media::c2::V1_0::utils;
+using namespace ::android::hardware::media::c2::V1_1;
+using namespace ::android::hardware::media::c2::V1_1::utils;
 using namespace ::android::hardware::media::bufferpool::V2_0;
 using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
 
@@ -514,8 +518,24 @@
 
 };
 
+// Codec2Client::Component::BufferPoolSender
+struct Codec2Client::Component::BufferPoolSender :
+        hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
+    BufferPoolSender()
+          : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
+    }
+};
+
+// Codec2Client::Component::OutputBufferQueue
+struct Codec2Client::Component::OutputBufferQueue :
+        hardware::media::c2::V1_1::utils::OutputBufferQueue {
+    OutputBufferQueue()
+          : hardware::media::c2::V1_1::utils::OutputBufferQueue() {
+    }
+};
+
 // Codec2Client
-Codec2Client::Codec2Client(const sp<IComponentStore>& base,
+Codec2Client::Codec2Client(sp<Base> const& base,
                            size_t serviceIndex)
       : Configurable{
             [base]() -> sp<IConfigurable> {
@@ -526,7 +546,8 @@
                         nullptr;
             }()
         },
-        mBase{base},
+        mBase1_0{base},
+        mBase1_1{Base1_1::castFrom(base)},
         mServiceIndex{serviceIndex} {
     Return<sp<IClientManager>> transResult = base->getPoolClientManager();
     if (!transResult.isOk()) {
@@ -537,7 +558,15 @@
 }
 
 sp<Codec2Client::Base> const& Codec2Client::getBase() const {
-    return mBase;
+    return mBase1_0;
+}
+
+sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
+    return mBase1_0;
+}
+
+sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
+    return mBase1_1;
 }
 
 std::string const& Codec2Client::getServiceName() const {
@@ -552,7 +581,8 @@
     c2_status_t status;
     sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
     hidlListener->base = listener;
-    Return<void> transStatus = mBase->createComponent(
+    Return<void> transStatus = mBase1_1 ?
+        mBase1_1->createComponent_1_1(
             name,
             hidlListener,
             ClientManager::getInstance(),
@@ -565,6 +595,20 @@
                 }
                 *component = std::make_shared<Codec2Client::Component>(c);
                 hidlListener->component = *component;
+            }) :
+        mBase1_0->createComponent(
+            name,
+            hidlListener,
+            ClientManager::getInstance(),
+            [&status, component, hidlListener](
+                    Status s,
+                    const sp<hardware::media::c2::V1_0::IComponent>& c) {
+                status = static_cast<c2_status_t>(s);
+                if (status != C2_OK) {
+                    return;
+                }
+                *component = std::make_shared<Codec2Client::Component>(c);
+                hidlListener->component = *component;
             });
     if (!transStatus.isOk()) {
         LOG(ERROR) << "createComponent(" << name.c_str()
@@ -587,7 +631,7 @@
                    << status << ".";
     }
 
-    (*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
+    (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
     return status;
 }
 
@@ -595,7 +639,7 @@
         const C2String& name,
         std::shared_ptr<Codec2Client::Interface>* const interface) {
     c2_status_t status;
-    Return<void> transStatus = mBase->createInterface(
+    Return<void> transStatus = mBase1_0->createInterface(
             name,
             [&status, interface](
                     Status s,
@@ -622,7 +666,7 @@
 c2_status_t Codec2Client::createInputSurface(
         std::shared_ptr<InputSurface>* const inputSurface) {
     c2_status_t status;
-    Return<void> transStatus = mBase->createInputSurface(
+    Return<void> transStatus = mBase1_0->createInputSurface(
             [&status, inputSurface](
                     Status s,
                     const sp<IInputSurface>& i) {
@@ -650,7 +694,7 @@
         bool* success) const {
     std::vector<C2Component::Traits> traits;
     std::string const& serviceName = getServiceName();
-    Return<void> transStatus = mBase->listComponents(
+    Return<void> transStatus = mBase1_0->listComponents(
             [&traits, &serviceName](Status s,
                    const hidl_vec<IComponentStore::ComponentTraits>& t) {
                 if (s != Status::OK) {
@@ -734,7 +778,7 @@
         sp<Base> mBase;
     };
 
-    return std::make_shared<SimpleParamReflector>(mBase);
+    return std::make_shared<SimpleParamReflector>(mBase1_0);
 };
 
 std::vector<std::string> const& Codec2Client::GetServiceNames() {
@@ -1053,8 +1097,32 @@
                         nullptr;
             }()
         },
-        mBase{base},
-        mBufferPoolSender{nullptr} {
+        mBase1_0{base},
+        mBase1_1{Base1_1::castFrom(base)},
+        mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+        mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
+}
+
+Codec2Client::Component::Component(const sp<Base1_1>& base)
+      : Configurable{
+            [base]() -> sp<IConfigurable> {
+                Return<sp<IComponentInterface>> transResult1 =
+                        base->getInterface();
+                if (!transResult1.isOk()) {
+                    return nullptr;
+                }
+                Return<sp<IConfigurable>> transResult2 =
+                        static_cast<sp<IComponentInterface>>(transResult1)->
+                        getConfigurable();
+                return transResult2.isOk() ?
+                        static_cast<sp<IConfigurable>>(transResult2) :
+                        nullptr;
+            }()
+        },
+        mBase1_0{base},
+        mBase1_1{base},
+        mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+        mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
 }
 
 Codec2Client::Component::~Component() {
@@ -1065,7 +1133,7 @@
         C2BlockPool::local_id_t* blockPoolId,
         std::shared_ptr<Codec2Client::Configurable>* configurable) {
     c2_status_t status;
-    Return<void> transStatus = mBase->createBlockPool(
+    Return<void> transStatus = mBase1_0->createBlockPool(
             static_cast<uint32_t>(id),
             [&status, blockPoolId, configurable](
                     Status s,
@@ -1090,7 +1158,7 @@
 
 c2_status_t Codec2Client::Component::destroyBlockPool(
         C2BlockPool::local_id_t localId) {
-    Return<Status> transResult = mBase->destroyBlockPool(
+    Return<Status> transResult = mBase1_0->destroyBlockPool(
             static_cast<uint64_t>(localId));
     if (!transResult.isOk()) {
         LOG(ERROR) << "destroyBlockPool -- transaction failed.";
@@ -1102,17 +1170,17 @@
 void Codec2Client::Component::handleOnWorkDone(
         const std::list<std::unique_ptr<C2Work>> &workItems) {
     // Output bufferqueue-based blocks' lifetime management
-    mOutputBufferQueue.holdBufferQueueBlocks(workItems);
+    mOutputBufferQueue->holdBufferQueueBlocks(workItems);
 }
 
 c2_status_t Codec2Client::Component::queue(
         std::list<std::unique_ptr<C2Work>>* const items) {
     WorkBundle workBundle;
-    if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
+    if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
         LOG(ERROR) << "queue -- bad input.";
         return C2_TRANSACTION_FAILED;
     }
-    Return<Status> transStatus = mBase->queue(workBundle);
+    Return<Status> transStatus = mBase1_0->queue(workBundle);
     if (!transStatus.isOk()) {
         LOG(ERROR) << "queue -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1130,7 +1198,7 @@
         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 = mBase->flush(
+    Return<void> transStatus = mBase1_0->flush(
             [&status, flushedWork](
                     Status s, const WorkBundle& wb) {
                 status = static_cast<c2_status_t>(s);
@@ -1165,13 +1233,13 @@
     }
 
     // Output bufferqueue-based blocks' lifetime management
-    mOutputBufferQueue.holdBufferQueueBlocks(*flushedWork);
+    mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
 
     return status;
 }
 
 c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
-    Return<Status> transStatus = mBase->drain(
+    Return<Status> transStatus = mBase1_0->drain(
             mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
     if (!transStatus.isOk()) {
         LOG(ERROR) << "drain -- transaction failed.";
@@ -1186,7 +1254,7 @@
 }
 
 c2_status_t Codec2Client::Component::start() {
-    Return<Status> transStatus = mBase->start();
+    Return<Status> transStatus = mBase1_0->start();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "start -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1200,7 +1268,7 @@
 }
 
 c2_status_t Codec2Client::Component::stop() {
-    Return<Status> transStatus = mBase->stop();
+    Return<Status> transStatus = mBase1_0->stop();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "stop -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1214,7 +1282,7 @@
 }
 
 c2_status_t Codec2Client::Component::reset() {
-    Return<Status> transStatus = mBase->reset();
+    Return<Status> transStatus = mBase1_0->reset();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "reset -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1228,7 +1296,7 @@
 }
 
 c2_status_t Codec2Client::Component::release() {
-    Return<Status> transStatus = mBase->release();
+    Return<Status> transStatus = mBase1_0->release();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "release -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1241,6 +1309,29 @@
     return status;
 }
 
+c2_status_t Codec2Client::Component::configureVideoTunnel(
+        uint32_t avSyncHwId,
+        native_handle_t** sidebandHandle) {
+    *sidebandHandle = nullptr;
+    if (!mBase1_1) {
+        return C2_OMITTED;
+    }
+    c2_status_t status{};
+    Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
+            [&status, sidebandHandle](
+                    Status s, hardware::hidl_handle const& h) {
+                status = static_cast<c2_status_t>(s);
+                if (h.getNativeHandle()) {
+                    *sidebandHandle = native_handle_clone(h.getNativeHandle());
+                }
+            });
+    if (!transStatus.isOk()) {
+        LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
+        return C2_TRANSACTION_FAILED;
+    }
+    return status;
+}
+
 c2_status_t Codec2Client::Component::setOutputSurface(
         C2BlockPool::local_id_t blockPoolId,
         const sp<IGraphicBufferProducer>& surface,
@@ -1256,18 +1347,18 @@
     }
 
     if (!surface) {
-        mOutputBufferQueue.configure(nullIgbp, generation, 0);
+        mOutputBufferQueue->configure(nullIgbp, generation, 0);
     } else if (surface->getUniqueId(&bqId) != OK) {
         LOG(ERROR) << "setOutputSurface -- "
                    "cannot obtain bufferqueue id.";
         bqId = 0;
-        mOutputBufferQueue.configure(nullIgbp, generation, 0);
+        mOutputBufferQueue->configure(nullIgbp, generation, 0);
     } else {
-        mOutputBufferQueue.configure(surface, generation, bqId);
+        mOutputBufferQueue->configure(surface, generation, bqId);
     }
     ALOGD("generation remote change %u", generation);
 
-    Return<Status> transStatus = mBase->setOutputSurface(
+    Return<Status> transStatus = mBase1_0->setOutputSurface(
             static_cast<uint64_t>(blockPoolId),
             bqId == 0 ? nullHgbp : igbp);
     if (!transStatus.isOk()) {
@@ -1286,14 +1377,14 @@
         const C2ConstGraphicBlock& block,
         const QueueBufferInput& input,
         QueueBufferOutput* output) {
-    return mOutputBufferQueue.outputBuffer(block, input, output);
+    return mOutputBufferQueue->outputBuffer(block, input, output);
 }
 
 c2_status_t Codec2Client::Component::connectToInputSurface(
         const std::shared_ptr<InputSurface>& inputSurface,
         std::shared_ptr<InputSurfaceConnection>* connection) {
     c2_status_t status;
-    Return<void> transStatus = mBase->connectToInputSurface(
+    Return<void> transStatus = mBase1_0->connectToInputSurface(
             inputSurface->mBase,
             [&status, connection](
                     Status s, const sp<IInputSurfaceConnection>& c) {
@@ -1317,7 +1408,7 @@
         const sp<HGraphicBufferSource>& source,
         std::shared_ptr<InputSurfaceConnection>* connection) {
     c2_status_t status;
-    Return<void> transStatus = mBase->connectToOmxInputSurface(
+    Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
             producer, source,
             [&status, connection](
                     Status s, const sp<IInputSurfaceConnection>& c) {
@@ -1337,7 +1428,7 @@
 }
 
 c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
-    Return<Status> transStatus = mBase->disconnectFromInputSurface();
+    Return<Status> transStatus = mBase1_0->disconnectFromInputSurface();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1376,7 +1467,7 @@
     deathRecipient->component = component;
 
     component->mDeathRecipient = deathRecipient;
-    Return<bool> transResult = component->mBase->linkToDeath(
+    Return<bool> transResult = component->mBase1_0->linkToDeath(
             component->mDeathRecipient, 0);
     if (!transResult.isOk()) {
         LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index dca28f7..649dffd 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -17,14 +17,13 @@
 #ifndef CODEC2_HIDL_CLIENT_H
 #define CODEC2_HIDL_CLIENT_H
 
-#include <gui/IGraphicBufferProducer.h>
-#include <codec2/hidl/1.0/OutputBufferQueue.h>
 #include <C2PlatformSupport.h>
 #include <C2Component.h>
 #include <C2Buffer.h>
 #include <C2Param.h>
 #include <C2.h>
 
+#include <gui/IGraphicBufferProducer.h>
 #include <hidl/HidlSupport.h>
 #include <utils/StrongPointer.h>
 
@@ -74,6 +73,11 @@
 struct IInputSurfaceConnection;
 }  // namespace android::hardware::media::c2::V1_0
 
+namespace android::hardware::media::c2::V1_1 {
+struct IComponent;
+struct IComponentStore;
+}  // namespace android::hardware::media::c2::V1_1
+
 namespace android::hardware::media::bufferpool::V2_0 {
 struct IClientManager;
 }  // namespace android::hardware::media::bufferpool::V2_0
@@ -82,6 +86,10 @@
 struct IGraphicBufferProducer;
 }  // android::hardware::graphics::bufferqueue::V1_0
 
+namespace android::hardware::graphics::bufferqueue::V2_0 {
+struct IGraphicBufferProducer;
+}  // android::hardware::graphics::bufferqueue::V2_0
+
 namespace android::hardware::media::omx::V1_0 {
 struct IGraphicBufferSource;
 }  // namespace android::hardware::media::omx::V1_0
@@ -127,7 +135,9 @@
 
 struct Codec2Client : public Codec2ConfigurableClient {
 
-    typedef ::android::hardware::media::c2::V1_0::IComponentStore Base;
+    typedef ::android::hardware::media::c2::V1_0::IComponentStore Base1_0;
+    typedef ::android::hardware::media::c2::V1_1::IComponentStore Base1_1;
+    typedef Base1_0 Base;
 
     struct Listener;
 
@@ -144,6 +154,8 @@
     typedef Codec2Client Store;
 
     sp<Base> const& getBase() const;
+    sp<Base1_0> const& getBase1_0() const;
+    sp<Base1_1> const& getBase1_1() const;
 
     std::string const& getServiceName() const;
 
@@ -206,7 +218,8 @@
     Codec2Client(sp<Base> const& base, size_t serviceIndex);
 
 protected:
-    sp<Base> mBase;
+    sp<Base1_0> mBase1_0;
+    sp<Base1_1> mBase1_1;
 
     // 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
@@ -295,7 +308,9 @@
 
 struct Codec2Client::Component : public Codec2Client::Configurable {
 
-    typedef ::android::hardware::media::c2::V1_0::IComponent Base;
+    typedef ::android::hardware::media::c2::V1_0::IComponent Base1_0;
+    typedef ::android::hardware::media::c2::V1_1::IComponent Base1_1;
+    typedef Base1_0 Base;
 
     c2_status_t createBlockPool(
             C2Allocator::id_t id,
@@ -322,6 +337,17 @@
 
     c2_status_t release();
 
+    /**
+     * Use tunneling.
+     *
+     * On success, @p sidebandHandle will be a newly allocated native handle.
+     * File descriptors in @p sidebandHandle must be closed and
+     * @p sidebandHandle itself must be deleted afterwards.
+     */
+    c2_status_t configureVideoTunnel(
+            uint32_t avSyncHwId,
+            native_handle_t** sidebandHandle);
+
     typedef ::android::
             IGraphicBufferProducer IGraphicBufferProducer;
     typedef IGraphicBufferProducer::
@@ -378,17 +404,19 @@
 
     // base cannot be null.
     Component(const sp<Base>& base);
+    Component(const sp<Base1_1>& base);
 
     ~Component();
 
 protected:
-    sp<Base> mBase;
+    sp<Base1_0> mBase1_0;
+    sp<Base1_1> mBase1_1;
 
-    ::android::hardware::media::c2::V1_0::utils::DefaultBufferPoolSender
-            mBufferPoolSender;
+    struct BufferPoolSender;
+    std::unique_ptr<BufferPoolSender> mBufferPoolSender;
 
-    ::android::hardware::media::c2::V1_0::utils::OutputBufferQueue
-            mOutputBufferQueue;
+    struct OutputBufferQueue;
+    std::unique_ptr<OutputBufferQueue> mOutputBufferQueue;
 
     static c2_status_t setDeathListener(
             const std::shared_ptr<Component>& component,
diff --git a/media/codec2/hidl/services/Android.bp b/media/codec2/hidl/services/Android.bp
index 0403a1f..46bea2e 100644
--- a/media/codec2/hidl/services/Android.bp
+++ b/media/codec2/hidl/services/Android.bp
@@ -1,37 +1,82 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This is an example of an empty Codec2.0 service.
+//
+// To use this, make a copy of this whole directory and rename modules
+// accordingly. The contents of "vendor.cpp" and files in the subdirectory
+// "seccomp_policy" may also need to be modified.
+
+// Binary file for the service.
+//
+// The init_rc file contains the absolute path to this binary on the device.
+// If the name of this module is modified, the content of the init_rc file has
+// to be modified accordingly.
+//
+// The seccomp_policy file name and its content can be modified, but note that
+// vendor.cpp also needs to be updated because it needs the absolute path to the
+// seccomp policy file on the device.
 cc_binary {
-    name: "android.hardware.media.c2@1.0-service",
-    defaults: ["hidl_defaults"],
-    soc_specific: true,
+    name: "android.hardware.media.c2@1.1-default-service",
+    vendor: true,
     relative_install_path: "hw",
+
+    init_rc: ["android.hardware.media.c2@1.1-default-service.rc"],
+
+    defaults: ["libcodec2-hidl-defaults"],
     srcs: [
         "vendor.cpp",
     ],
 
-    init_rc: ["android.hardware.media.c2@1.0-service.rc"],
-
+    // minijail is used to protect against unexpected system calls.
     shared_libs: [
-        "android.hardware.media.c2@1.0",
-        "android.hardware.media.omx@1.0",
         "libavservices_minijail_vendor",
         "libbinder",
-        "libcodec2_hidl@1.0",
-        "libcodec2_vndk",
-        "libhidlbase",
-        "liblog",
-        "libstagefright_omx",
-        "libstagefright_xmlparser",
-        "libutils",
     ],
+    required: ["android.hardware.media.c2@1.1-default-seccomp_policy"],
+}
 
+// seccomp policy file.
+//
+// This should be modified to suit the target device and architecture.
+//
+// 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.1-default-seccomp_policy",
+    vendor: true,
+    sub_dir: "seccomp_policy",
+
+    // If a specific architecture is targeted, multiple choices are not needed.
     arch: {
         arm: {
-            required: ["codec2.vendor.base.policy"],
+            src: "seccomp_policy/android.hardware.media.c2@1.1-default-arm.policy",
+        },
+        arm64: {
+            src: "seccomp_policy/android.hardware.media.c2@1.1-default-arm64.policy",
         },
         x86: {
-            required: ["codec2.vendor.base.policy"],
+            src: "seccomp_policy/android.hardware.media.c2@1.1-default-x86.policy",
+        },
+        x86_64: {
+            src: "seccomp_policy/android.hardware.media.c2@1.1-default-x86_64.policy",
         },
     },
 
-    compile_multilib: "32",
+    // This may be removed.
+    required: ["crash_dump.policy"],
 }
 
diff --git a/media/codec2/hidl/services/Android.mk b/media/codec2/hidl/services/Android.mk
deleted file mode 100644
index d9b28e7..0000000
--- a/media/codec2/hidl/services/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-# vendor service seccomp policy
-ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH), x86 x86_64 arm arm64))
-include $(CLEAR_VARS)
-LOCAL_MODULE := codec2.vendor.base.policy
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/seccomp_policy
-LOCAL_REQUIRED_MODULES := crash_dump.policy
-ifdef TARGET_2ND_ARCH
-    ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-        LOCAL_SRC_FILES := seccomp_policy/codec2.vendor.base-$(TARGET_2ND_ARCH).policy
-    else
-        LOCAL_SRC_FILES := seccomp_policy/codec2.vendor.base-$(TARGET_ARCH).policy
-    endif
-else
-    LOCAL_SRC_FILES := seccomp_policy/codec2.vendor.base-$(TARGET_ARCH).policy
-endif
-include $(BUILD_PREBUILT)
-endif
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
-
diff --git a/media/codec2/hidl/services/android.hardware.media.c2@1.0-service.rc b/media/codec2/hidl/services/android.hardware.media.c2@1.0-service.rc
deleted file mode 100644
index 8806bd1f..0000000
--- a/media/codec2/hidl/services/android.hardware.media.c2@1.0-service.rc
+++ /dev/null
@@ -1,7 +0,0 @@
-service android-hardware-media-c2-hal-1-0 /vendor/bin/hw/android.hardware.media.c2@1.0-service
-    class hal
-    user mediacodec
-    group camera mediadrm drmrpc
-    ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
-
diff --git a/media/codec2/hidl/services/android.hardware.media.c2@1.1-default-service.rc b/media/codec2/hidl/services/android.hardware.media.c2@1.1-default-service.rc
new file mode 100644
index 0000000..44f2d8e
--- /dev/null
+++ b/media/codec2/hidl/services/android.hardware.media.c2@1.1-default-service.rc
@@ -0,0 +1,7 @@
+service android-hardware-media-c2-hal-1-1 /vendor/bin/hw/android.hardware.media.c2@1.1-default-service
+    class hal
+    user mediacodec
+    group camera mediadrm drmrpc
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
+
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm.policy
similarity index 70%
copy from media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy
copy to media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm.policy
index d5871d1..9042cd7 100644
--- a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm.policy
@@ -1,4 +1,4 @@
-# Copyright (C) 2018 The Android Open Source Project
+# Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -12,21 +12,18 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Organized by frequency of systemcall - in descending order for
-# best performance.
 futex: 1
+# ioctl calls are filtered via the selinux policy.
 ioctl: 1
-write: 1
-prctl: 1
-clock_gettime: 1
-getpriority: 1
-read: 1
+sched_yield: 1
 close: 1
-writev: 1
 dup: 1
 ppoll: 1
-mmap2: 1
-getrandom: 1
+mprotect: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+mmap2: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+memfd_create: 1
+ftruncate: 1
+ftruncate64: 1
 
 # mremap: Ensure |flags| are (MREMAP_MAYMOVE | MREMAP_FIXED) TODO: Once minijail
 # parser support for '<' is in this needs to be modified to also prevent
@@ -36,38 +33,54 @@
 # for more details.
 mremap: arg3 == 3
 munmap: 1
-mprotect: 1
-madvise: 1
-openat: 1
+prctl: 1
+getuid32: 1
+writev: 1
 sigaltstack: 1
 clone: 1
-setpriority: 1
-getuid32: 1
-fstat64: 1
-fstatfs64: 1
-pread64: 1
-faccessat: 1
-readlinkat: 1
 exit: 1
-rt_sigprocmask: 1
-set_tid_address: 1
-restart_syscall: 1
-exit_group: 1
-rt_sigreturn: 1
-pipe2: 1
-gettimeofday: 1
-sched_yield: 1
-nanosleep: 1
 lseek: 1
+rt_sigprocmask: 1
+openat: 1
+open: 1
+fstat64: 1
+write: 1
+nanosleep: 1
+setpriority: 1
+set_tid_address: 1
+getdents64: 1
+readlinkat: 1
+readlink: 1
+read: 1
+pread64: 1
+fstatfs64: 1
+gettimeofday: 1
+faccessat: 1
 _llseek: 1
-sched_get_priority_max: 1
-sched_get_priority_min: 1
-statfs64: 1
-sched_setscheduler: 1
 fstatat64: 1
 ugetrlimit: 1
-getdents64: 1
+exit_group: 1
+restart_syscall: 1
+rt_sigreturn: 1
 getrandom: 1
+madvise: 1
 
-@include /system/etc/seccomp_policy/crash_dump.arm.policy
-
+# crash dump policy additions
+sigreturn: 1
+clock_gettime: 1
+futex: 1
+getpid: 1
+gettid: 1
+pipe2: 1
+recvmsg: 1
+process_vm_readv: 1
+tgkill: 1
+rt_sigaction: 1
+rt_tgsigqueueinfo: 1
+#prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
+#mprotect: arg2 in 0x1|0x2
+#mmap2: arg2 in 0x1|0x2
+geteuid32: 1
+getgid32: 1
+getegid32: 1
+getgroups32: 1
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm64.policy
similarity index 71%
rename from media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy
rename to media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm64.policy
index d5871d1..4faf8b2 100644
--- a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm64.policy
@@ -1,4 +1,4 @@
-# Copyright (C) 2018 The Android Open Source Project
+# Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -12,21 +12,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Organized by frequency of systemcall - in descending order for
-# best performance.
 futex: 1
+# ioctl calls are filtered via the selinux policy.
 ioctl: 1
-write: 1
-prctl: 1
-clock_gettime: 1
-getpriority: 1
-read: 1
+sched_yield: 1
 close: 1
-writev: 1
 dup: 1
 ppoll: 1
-mmap2: 1
-getrandom: 1
+mprotect: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+mmap: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+getuid: 1
+getrlimit: 1
+fstat: 1
+newfstatat: 1
+fstatfs: 1
+memfd_create: 1
+ftruncate: 1
 
 # mremap: Ensure |flags| are (MREMAP_MAYMOVE | MREMAP_FIXED) TODO: Once minijail
 # parser support for '<' is in this needs to be modified to also prevent
@@ -36,38 +37,45 @@
 # for more details.
 mremap: arg3 == 3
 munmap: 1
-mprotect: 1
-madvise: 1
-openat: 1
+prctl: 1
+writev: 1
 sigaltstack: 1
 clone: 1
-setpriority: 1
-getuid32: 1
-fstat64: 1
-fstatfs64: 1
-pread64: 1
-faccessat: 1
-readlinkat: 1
 exit: 1
-rt_sigprocmask: 1
-set_tid_address: 1
-restart_syscall: 1
-exit_group: 1
-rt_sigreturn: 1
-pipe2: 1
-gettimeofday: 1
-sched_yield: 1
-nanosleep: 1
 lseek: 1
-_llseek: 1
-sched_get_priority_max: 1
-sched_get_priority_min: 1
-statfs64: 1
-sched_setscheduler: 1
-fstatat64: 1
-ugetrlimit: 1
+rt_sigprocmask: 1
+openat: 1
+write: 1
+nanosleep: 1
+setpriority: 1
+set_tid_address: 1
 getdents64: 1
+readlinkat: 1
+read: 1
+pread64: 1
+gettimeofday: 1
+faccessat: 1
+exit_group: 1
+restart_syscall: 1
+rt_sigreturn: 1
 getrandom: 1
+madvise: 1
 
-@include /system/etc/seccomp_policy/crash_dump.arm.policy
+# crash dump policy additions
+clock_gettime: 1
+getpid: 1
+gettid: 1
+pipe2: 1
+recvmsg: 1
+process_vm_readv: 1
+tgkill: 1
+rt_sigaction: 1
+rt_tgsigqueueinfo: 1
+#mprotect: arg2 in 0x1|0x2
+munmap: 1
+#mmap: arg2 in 0x1|0x2
+geteuid: 1
+getgid: 1
+getegid: 1
+getgroups: 1
 
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86.policy
similarity index 81%
rename from media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy
rename to media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86.policy
index 20c7625..d9c4045 100644
--- a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86.policy
@@ -1,4 +1,4 @@
-# Copyright (C) 2018 The Android Open Source Project
+# Copyright (C) 2017 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -16,14 +16,22 @@
 mprotect: 1
 prctl: 1
 openat: 1
+open: 1
 getuid32: 1
+getuid: 1
+getrlimit: 1
 writev: 1
 ioctl: 1
 close: 1
 mmap2: 1
+mmap: 1
 fstat64: 1
+fstat: 1
+stat64: 1
+statfs64: 1
 madvise: 1
 fstatat64: 1
+newfstatat: 1
 futex: 1
 munmap: 1
 faccessat: 1
@@ -37,15 +45,22 @@
 exit_group: 1
 rt_sigreturn: 1
 ugetrlimit: 1
+readlink: 1
 readlinkat: 1
 _llseek: 1
 fstatfs64: 1
+fstatfs: 1
 pread64: 1
 mremap: 1
 dup: 1
 set_tid_address: 1
 write: 1
 nanosleep: 1
+sched_setscheduler: 1
+uname: 1
+memfd_create: 1
+ftruncate: 1
+ftruncate64: 1
 
 # Required by AddressSanitizer
 gettid: 1
@@ -54,4 +69,3 @@
 gettid: 1
 
 @include /system/etc/seccomp_policy/crash_dump.x86.policy
-
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86_64.policy
similarity index 81%
copy from media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy
copy to media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86_64.policy
index 20c7625..d9c4045 100644
--- a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86_64.policy
@@ -1,4 +1,4 @@
-# Copyright (C) 2018 The Android Open Source Project
+# Copyright (C) 2017 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -16,14 +16,22 @@
 mprotect: 1
 prctl: 1
 openat: 1
+open: 1
 getuid32: 1
+getuid: 1
+getrlimit: 1
 writev: 1
 ioctl: 1
 close: 1
 mmap2: 1
+mmap: 1
 fstat64: 1
+fstat: 1
+stat64: 1
+statfs64: 1
 madvise: 1
 fstatat64: 1
+newfstatat: 1
 futex: 1
 munmap: 1
 faccessat: 1
@@ -37,15 +45,22 @@
 exit_group: 1
 rt_sigreturn: 1
 ugetrlimit: 1
+readlink: 1
 readlinkat: 1
 _llseek: 1
 fstatfs64: 1
+fstatfs: 1
 pread64: 1
 mremap: 1
 dup: 1
 set_tid_address: 1
 write: 1
 nanosleep: 1
+sched_setscheduler: 1
+uname: 1
+memfd_create: 1
+ftruncate: 1
+ftruncate64: 1
 
 # Required by AddressSanitizer
 gettid: 1
@@ -54,4 +69,3 @@
 gettid: 1
 
 @include /system/etc/seccomp_policy/crash_dump.x86.policy
-
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-arm.policy b/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-arm.policy
deleted file mode 100644
index d5871d1..0000000
--- a/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-arm.policy
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Organized by frequency of systemcall - in descending order for
-# best performance.
-futex: 1
-ioctl: 1
-write: 1
-prctl: 1
-clock_gettime: 1
-getpriority: 1
-read: 1
-close: 1
-writev: 1
-dup: 1
-ppoll: 1
-mmap2: 1
-getrandom: 1
-
-# mremap: Ensure |flags| are (MREMAP_MAYMOVE | MREMAP_FIXED) TODO: Once minijail
-# parser support for '<' is in this needs to be modified to also prevent
-# |old_address| and |new_address| from touching the exception vector page, which
-# on ARM is statically loaded at 0xffff 0000. See
-# http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Babfeega.html
-# for more details.
-mremap: arg3 == 3
-munmap: 1
-mprotect: 1
-madvise: 1
-openat: 1
-sigaltstack: 1
-clone: 1
-setpriority: 1
-getuid32: 1
-fstat64: 1
-fstatfs64: 1
-pread64: 1
-faccessat: 1
-readlinkat: 1
-exit: 1
-rt_sigprocmask: 1
-set_tid_address: 1
-restart_syscall: 1
-exit_group: 1
-rt_sigreturn: 1
-pipe2: 1
-gettimeofday: 1
-sched_yield: 1
-nanosleep: 1
-lseek: 1
-_llseek: 1
-sched_get_priority_max: 1
-sched_get_priority_min: 1
-statfs64: 1
-sched_setscheduler: 1
-fstatat64: 1
-ugetrlimit: 1
-getdents64: 1
-getrandom: 1
-
-@include /system/etc/seccomp_policy/crash_dump.arm.policy
-
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-x86.policy b/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-x86.policy
deleted file mode 100644
index 20c7625..0000000
--- a/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-x86.policy
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-read: 1
-mprotect: 1
-prctl: 1
-openat: 1
-getuid32: 1
-writev: 1
-ioctl: 1
-close: 1
-mmap2: 1
-fstat64: 1
-madvise: 1
-fstatat64: 1
-futex: 1
-munmap: 1
-faccessat: 1
-_llseek: 1
-lseek: 1
-clone: 1
-sigaltstack: 1
-setpriority: 1
-restart_syscall: 1
-exit: 1
-exit_group: 1
-rt_sigreturn: 1
-ugetrlimit: 1
-readlinkat: 1
-_llseek: 1
-fstatfs64: 1
-pread64: 1
-mremap: 1
-dup: 1
-set_tid_address: 1
-write: 1
-nanosleep: 1
-
-# Required by AddressSanitizer
-gettid: 1
-sched_yield: 1
-getpid: 1
-gettid: 1
-
-@include /system/etc/seccomp_policy/crash_dump.x86.policy
-
diff --git a/media/codec2/hidl/services/vendor.cpp b/media/codec2/hidl/services/vendor.cpp
index ef2f98e..65bb6f7 100644
--- a/media/codec2/hidl/services/vendor.cpp
+++ b/media/codec2/hidl/services/vendor.cpp
@@ -15,25 +15,27 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "android.hardware.media.c2@1.0-service"
+#define LOG_TAG "android.hardware.media.c2@1.1-service"
 
-#include <codec2/hidl/1.0/ComponentStore.h>
-#include <hidl/HidlTransportSupport.h>
+#include <android-base/logging.h>
 #include <binder/ProcessState.h>
+#include <codec2/hidl/1.1/ComponentStore.h>
+#include <hidl/HidlTransportSupport.h>
 #include <minijail.h>
 
 #include <C2Component.h>
 
-// OmxStore is added for visibility by dumpstate.
-#include <media/stagefright/omx/1.0/OmxStore.h>
-
-// This is created by module "codec2.vendor.base.policy". This can be modified.
+// This is the absolute on-device path of the prebuild_etc module
+// "android.hardware.media.c2@1.1-default-seccomp_policy" in Android.bp.
 static constexpr char kBaseSeccompPolicyPath[] =
-        "/vendor/etc/seccomp_policy/codec2.vendor.base.policy";
+        "/vendor/etc/seccomp_policy/"
+        "android.hardware.media.c2@1.1-default-seccomp-policy";
 
-// Additional device-specific seccomp permissions can be added in this file.
+// Additional seccomp permissions can be added in this file.
+// This file does not exist by default.
 static constexpr char kExtSeccompPolicyPath[] =
-        "/vendor/etc/seccomp_policy/codec2.vendor.ext.policy";
+        "/vendor/etc/seccomp_policy/"
+        "android.hardware.media.c2@1.1-extended-seccomp-policy";
 
 class DummyC2Store : public C2ComponentStore {
 public:
@@ -97,54 +99,48 @@
 };
 
 int main(int /* argc */, char** /* argv */) {
-    ALOGD("android.hardware.media.c2@1.0-service starting...");
+    using namespace ::android;
+    LOG(DEBUG) << "android.hardware.media.c2@1.1-service starting...";
 
+    // Set up minijail to limit system calls.
     signal(SIGPIPE, SIG_IGN);
-    android::SetUpMinijail(kBaseSeccompPolicyPath, kExtSeccompPolicyPath);
+    SetUpMinijail(kBaseSeccompPolicyPath, kExtSeccompPolicyPath);
 
-    // vndbinder is needed by BufferQueue.
-    android::ProcessState::initWithDriver("/dev/vndbinder");
-    android::ProcessState::self()->startThreadPool();
+    // 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.)
-    android::hardware::configureRpcThreadpool(8, true /* callerWillJoin */);
+    hardware::configureRpcThreadpool(8, true /* callerWillJoin */);
 
     // Create IComponentStore service.
     {
-        using namespace ::android::hardware::media::c2::V1_0;
-        android::sp<IComponentStore> store;
+        using namespace ::android::hardware::media::c2::V1_1;
+        sp<IComponentStore> store;
 
-        // Vendor's TODO: Replace this with
+        // TODO: Replace this with
         // store = new utils::ComponentStore(
         //         /* implementation of C2ComponentStore */);
-        ALOGD("Instantiating Codec2's dummy IComponentStore service...");
+        LOG(DEBUG) << "Instantiating Codec2's IComponentStore service...";
         store = new utils::ComponentStore(
                 std::make_shared<DummyC2Store>());
 
         if (store == nullptr) {
-            ALOGE("Cannot create Codec2's IComponentStore service.");
+            LOG(ERROR) << "Cannot create Codec2's IComponentStore service.";
         } else {
-            if (store->registerAsService("default") != android::OK) {
-                ALOGE("Cannot register Codec2's "
-                        "IComponentStore service.");
+            constexpr char const* serviceName = "default";
+            if (store->registerAsService(serviceName) != OK) {
+                LOG(ERROR) << "Cannot register Codec2's IComponentStore service"
+                              " with instance name << \""
+                           << serviceName << "\".";
             } else {
-                ALOGI("Codec2's IComponentStore service created.");
+                LOG(DEBUG) << "Codec2's IComponentStore service registered. "
+                              "Instance name: \"" << serviceName << "\".";
             }
         }
     }
 
-    // Register IOmxStore service.
-    {
-        using namespace ::android::hardware::media::omx::V1_0;
-        android::sp<IOmxStore> omxStore = new implementation::OmxStore();
-        if (omxStore == nullptr) {
-            ALOGE("Cannot create IOmxStore HAL service.");
-        } else if (omxStore->registerAsService() != android::OK) {
-            ALOGE("Cannot register IOmxStore HAL service.");
-        }
-    }
-
-    android::hardware::joinRpcThreadpool();
+    hardware::joinRpcThreadpool();
     return 0;
 }
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 1cbbbb8..c78cdc1 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -27,6 +27,7 @@
 #include <C2PlatformSupport.h>
 
 #include <android/IOMXBufferSource.h>
+#include <android/hardware/media/c2/1.0/IInputSurface.h>
 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
 #include <android/hardware/media/omx/1.0/IOmx.h>
 #include <android-base/stringprintf.h>
diff --git a/media/extractors/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index 1d9e1e6..8638cdc 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -12,15 +12,10 @@
     ],
 
     shared_libs: [
-        "android.hardware.cas@1.0",
-        "android.hardware.cas.native@1.0",
-        "android.hidl.token@1.0-utils",
-        "android.hidl.allocator@1.0",
-        "libcrypto",
-        "libhidlmemory",
-        "libhidlbase",
-        "liblog",
-        "libmediandk",
+        "libcgrouprc#29",
+        "liblog#10000",
+        "libmediandk#29",
+        "libvndksupport#29",
     ],
 
     header_libs: [
@@ -31,11 +26,24 @@
     ],
 
     static_libs: [
+        "android.hardware.cas@1.0",
+        "android.hardware.cas.native@1.0",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "android.hidl.token@1.0",
+        "android.hidl.token@1.0-utils",
+        "libbase",
+        "libbinderthreadstate",
+        "libcutils",
+        "libhidlbase",
+        "libhidlmemory",
+        "libjsoncpp",
+        "libprocessgroup",
+        "libstagefright_esds",
         "libstagefright_foundation_without_imemory",
+        "libstagefright_mpeg2extractor",
         "libstagefright_mpeg2support",
         "libutils",
-        "libstagefright_mpeg2extractor",
-        "libstagefright_esds",
     ],
 
     name: "libmpeg2extractor",
@@ -51,11 +59,16 @@
     version_script: "exports.lds",
 
     sanitize: {
-        cfi: true,
+        // STOPSHIP: turn on cfi once b/139945549 is resolved.
+        cfi: false,
         misc_undefined: [
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
     },
 
+    apex_available: [
+        "com.android.media",
+        "test_com.android.media",
+    ],
 }
diff --git a/media/libdatasource/NuCachedSource2.cpp b/media/libdatasource/NuCachedSource2.cpp
index 7f5ae61..6d63ffb 100644
--- a/media/libdatasource/NuCachedSource2.cpp
+++ b/media/libdatasource/NuCachedSource2.cpp
@@ -689,10 +689,6 @@
     restartPrefetcherIfNecessary_l(true /* ignore low water threshold */);
 }
 
-sp<DecryptHandle> NuCachedSource2::DrmInitialization(const char* mime) {
-    return mSource->DrmInitialization(mime);
-}
-
 String8 NuCachedSource2::getUri() {
     return mSource->getUri();
 }
diff --git a/media/libdatasource/include/datasource/NuCachedSource2.h b/media/libdatasource/include/datasource/NuCachedSource2.h
index 596efb8..4c253ad 100644
--- a/media/libdatasource/include/datasource/NuCachedSource2.h
+++ b/media/libdatasource/include/datasource/NuCachedSource2.h
@@ -44,7 +44,6 @@
     virtual status_t getSize(off64_t *size);
     virtual uint32_t flags();
 
-    virtual sp<DecryptHandle> DrmInitialization(const char* mime);
     virtual String8 getUri();
 
     virtual String8 getMIMEType() const;
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index 33ea1ca..b80f4b4 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -83,9 +83,6 @@
     void close() {}
     uint32_t getFlags() override { return 0; }
     String8 toString() override { return String8("HeifDataSource"); }
-    sp<DecryptHandle> DrmInitialization(const char*) override {
-        return nullptr;
-    }
 
 private:
     enum {
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index ac88448..b064f08 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -34,7 +34,6 @@
         "aidl/android/media/MediaResourceParcel.aidl",
         "aidl/android/media/MediaResourcePolicyParcel.aidl",
     ],
-    api_dir: "api/resourcemanager",
     versions: ["1"],
 }
 
diff --git a/media/libmedia/IDataSource.cpp b/media/libmedia/IDataSource.cpp
index 31c85af..61f0a68 100644
--- a/media/libmedia/IDataSource.cpp
+++ b/media/libmedia/IDataSource.cpp
@@ -23,7 +23,6 @@
 
 #include <binder/IMemory.h>
 #include <binder/Parcel.h>
-#include <drm/drm_framework_common.h>
 #include <media/stagefright/foundation/ADebug.h>
 
 namespace android {
@@ -35,7 +34,6 @@
     CLOSE,
     GET_FLAGS,
     TO_STRING,
-    DRM_INITIALIZATION,
 };
 
 struct BpDataSource : public BpInterface<IDataSource> {
@@ -95,47 +93,6 @@
         remote()->transact(TO_STRING, data, &reply);
         return reply.readString8();
     }
-
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDataSource::getInterfaceDescriptor());
-        if (mime == NULL) {
-            data.writeInt32(0);
-        } else {
-            data.writeInt32(1);
-            data.writeCString(mime);
-        }
-        remote()->transact(DRM_INITIALIZATION, data, &reply);
-        sp<DecryptHandle> handle;
-        if (reply.dataAvail() != 0) {
-            handle = new DecryptHandle();
-            handle->decryptId = reply.readInt32();
-            handle->mimeType = reply.readString8();
-            handle->decryptApiType = reply.readInt32();
-            handle->status = reply.readInt32();
-
-            const int bufferLength = data.readInt32();
-            if (bufferLength != -1) {
-                handle->decryptInfo = new DecryptInfo();
-                handle->decryptInfo->decryptBufferLength = bufferLength;
-            }
-
-            size_t size = data.readInt32();
-            for (size_t i = 0; i < size; ++i) {
-                DrmCopyControl key = (DrmCopyControl)data.readInt32();
-                int value = data.readInt32();
-                handle->copyControlVector.add(key, value);
-            }
-
-            size = data.readInt32();
-            for (size_t i = 0; i < size; ++i) {
-                String8 key = data.readString8();
-                String8 value = data.readString8();
-                handle->extendedData.add(key, value);
-            }
-        }
-        return handle;
-    }
 };
 
 IMPLEMENT_META_INTERFACE(DataSource, "android.media.IDataSource");
@@ -178,42 +135,6 @@
             reply->writeString8(toString());
             return NO_ERROR;
         } break;
-        case DRM_INITIALIZATION: {
-            CHECK_INTERFACE(IDataSource, data, reply);
-            const char *mime = NULL;
-            const int32_t flag = data.readInt32();
-            if (flag != 0) {
-                mime = data.readCString();
-            }
-            sp<DecryptHandle> handle = DrmInitialization(mime);
-            if (handle != NULL) {
-                reply->writeInt32(handle->decryptId);
-                reply->writeString8(handle->mimeType);
-                reply->writeInt32(handle->decryptApiType);
-                reply->writeInt32(handle->status);
-
-                if (handle->decryptInfo != NULL) {
-                    reply->writeInt32(handle->decryptInfo->decryptBufferLength);
-                } else {
-                    reply->writeInt32(-1);
-                }
-
-                size_t size = handle->copyControlVector.size();
-                reply->writeInt32(size);
-                for (size_t i = 0; i < size; ++i) {
-                    reply->writeInt32(handle->copyControlVector.keyAt(i));
-                    reply->writeInt32(handle->copyControlVector.valueAt(i));
-                }
-
-                size = handle->extendedData.size();
-                reply->writeInt32(size);
-                for (size_t i = 0; i < size; ++i) {
-                    reply->writeString8(handle->extendedData.keyAt(i));
-                    reply->writeString8(handle->extendedData.valueAt(i));
-                }
-            }
-            return NO_ERROR;
-        } break;
 
         default:
             return BBinder::onTransact(code, data, reply, flags);
diff --git a/media/libmedia/api/resourcemanager/1/.hash b/media/libmedia/aidl_api/resourcemanager_aidl_interface/.hash
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/.hash
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/.hash
diff --git a/media/libmedia/api/resourcemanager/1/android/media/IResourceManagerClient.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/IResourceManagerClient.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/IResourceManagerClient.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/IResourceManagerClient.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/IResourceManagerService.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/IResourceManagerService.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/IResourceManagerService.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/IResourceManagerService.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/MediaResourceParcel.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceParcel.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/MediaResourceParcel.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceParcel.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/MediaResourcePolicyParcel.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourcePolicyParcel.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/MediaResourcePolicyParcel.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourcePolicyParcel.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/MediaResourceSubType.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceSubType.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/MediaResourceSubType.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceSubType.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/MediaResourceType.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceType.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/MediaResourceType.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceType.aidl
diff --git a/media/libmedia/include/media/IDataSource.h b/media/libmedia/include/media/IDataSource.h
index 3858f78..43e2b50 100644
--- a/media/libmedia/include/media/IDataSource.h
+++ b/media/libmedia/include/media/IDataSource.h
@@ -50,8 +50,6 @@
     virtual uint32_t getFlags() = 0;
     // get a description of the source, e.g. the url or filename it is based on
     virtual String8 toString() = 0;
-    // Initialize DRM and return a DecryptHandle.
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime) = 0;
 
 private:
     DISALLOW_EVIL_CONSTRUCTORS(IDataSource);
diff --git a/media/libmediametrics/TEST_MAPPING b/media/libmediametrics/TEST_MAPPING
new file mode 100644
index 0000000..01e9e46
--- /dev/null
+++ b/media/libmediametrics/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "presubmit": [
+    {
+       "name": "mediametrics_tests"
+    },
+    {
+       "name": "CtsNativeMediaMetricsTestCases"
+    }
+  ]
+}
diff --git a/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
index 1580891..bb4ba75 100644
--- a/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
+++ b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
@@ -31,6 +31,7 @@
       mDrmBufOffset(0),
       mDrmBufSize(0),
       mDrmBuf(NULL){
+    (void) DrmInitialization(nullptr);
 }
 
 PlayerServiceFileSource::PlayerServiceFileSource(int fd, int64_t offset, int64_t length)
@@ -40,6 +41,7 @@
       mDrmBufOffset(0),
       mDrmBufSize(0),
       mDrmBuf(NULL) {
+    (void) DrmInitialization(nullptr);
 }
 
 PlayerServiceFileSource::~PlayerServiceFileSource() {
@@ -87,7 +89,9 @@
 }
 
 sp<DecryptHandle> PlayerServiceFileSource::DrmInitialization(const char *mime) {
-    if (getuid() == AID_MEDIA_EX) return nullptr; // no DRM in media extractor
+    if (getuid() == AID_MEDIA_EX) {
+       return NULL; // no DRM in media extractor
+    }
     if (mDrmManagerClient == NULL) {
         mDrmManagerClient = new DrmManagerClient();
     }
diff --git a/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp b/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp
index 0124720..f99a861 100644
--- a/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp
+++ b/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp
@@ -32,6 +32,7 @@
 PlayerServiceMediaHTTP::PlayerServiceMediaHTTP(const sp<MediaHTTPConnection> &conn)
     : MediaHTTP(conn),
       mDrmManagerClient(NULL) {
+    (void) DrmInitialization(nullptr);
 }
 
 PlayerServiceMediaHTTP::~PlayerServiceMediaHTTP() {
@@ -40,7 +41,7 @@
 
 // DRM...
 
-sp<DecryptHandle> PlayerServiceMediaHTTP::DrmInitialization(const char* mime) {
+sp<DecryptHandle> PlayerServiceMediaHTTP::DrmInitialization(const char *mime) {
     if (mDrmManagerClient == NULL) {
         mDrmManagerClient = new DrmManagerClient();
     }
diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h
index 08a013e..7ae8dda 100644
--- a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h
+++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h
@@ -37,8 +37,6 @@
 
     virtual ssize_t readAt(off64_t offset, void *data, size_t size);
 
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime);
-
     static bool requiresDrm(int fd, int64_t offset, int64_t length, const char *mime);
 
 protected:
@@ -52,6 +50,7 @@
     ssize_t mDrmBufSize;
     unsigned char *mDrmBuf;
 
+    sp<DecryptHandle> DrmInitialization(const char *mime);
     ssize_t readAtDRM_l(off64_t offset, void *data, size_t size);
 
     PlayerServiceFileSource(const PlayerServiceFileSource &);
diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h
index 0032cd7..b5124dc 100644
--- a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h
+++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h
@@ -33,12 +33,11 @@
 protected:
     virtual ~PlayerServiceMediaHTTP();
 
-    virtual sp<DecryptHandle> DrmInitialization(const char* mime);
-
 private:
     sp<DecryptHandle> mDecryptHandle;
     DrmManagerClient *mDrmManagerClient;
 
+    sp<DecryptHandle> DrmInitialization(const char *mime);
     void clearDRMState_l();
 
     DISALLOW_EVIL_CONSTRUCTORS(PlayerServiceMediaHTTP);
diff --git a/media/libmediaplayerservice/tests/Android.bp b/media/libmediaplayerservice/tests/Android.bp
index 8357925..e845c33 100644
--- a/media/libmediaplayerservice/tests/Android.bp
+++ b/media/libmediaplayerservice/tests/Android.bp
@@ -7,6 +7,7 @@
     shared_libs: [
         "liblog",
         "libbinder",
+        "libbinder_ndk",
         "libmedia",
         "libmediaplayerservice",
         "libmediadrm",
@@ -17,6 +18,10 @@
         "android.hardware.drm@1.2",
     ],
 
+    static_libs: [
+        "resourcemanager_aidl_interface-ndk_platform",
+    ],
+
     include_dirs: [
         "frameworks/av/include",
         "frameworks/av/services/mediaresourcemanager",
diff --git a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
index 262fe32..9a8ed8d 100644
--- a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
+++ b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
@@ -16,19 +16,21 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "DrmSessionManager_test"
+#include <android/binder_auto_utils.h>
 #include <utils/Log.h>
 
 #include <gtest/gtest.h>
 
+#include <aidl/android/media/BnResourceManagerClient.h>
+#include <aidl/android/media/BnResourceManagerService.h>
 #include <android/media/BnResourceManagerClient.h>
-#include <android/media/IResourceManagerService.h>
+
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/ProcessInfoInterface.h>
-#include <mediadrm/DrmHal.h>
-#include <mediadrm/DrmSessionClientInterface.h>
 #include <mediadrm/DrmSessionManager.h>
 
 #include <algorithm>
+#include <iostream>
 #include <vector>
 
 #include "ResourceManagerService.h"
@@ -36,8 +38,109 @@
 namespace android {
 
 using ::android::binder::Status;
-using ::android::media::BnResourceManagerClient;
 using ::android::media::ResourceManagerService;
+using ::ndk::ScopedAStatus;
+
+using NdkBnResourceManagerClient = ::aidl::android::media::BnResourceManagerClient;
+using NdkBnResourceManagerService = ::aidl::android::media::BnResourceManagerService;
+using NdkMediaResource = ::aidl::android::media::MediaResourceParcel;
+using NdkResourceManagerClient = ::aidl::android::media::IResourceManagerClient;
+
+using FwkBnResourceManagerClient = ::android::media::BnResourceManagerClient;
+using FwkMediaResource = ::android::media::MediaResourceParcel;
+
+namespace {
+
+struct FwkResourceManagerClientImpl : public FwkBnResourceManagerClient {
+    FwkResourceManagerClientImpl(const std::shared_ptr<NdkResourceManagerClient> &client)
+        : mClient(client) {
+    }
+
+    Status reclaimResource(bool* _aidl_return) override {
+        mClient->reclaimResource(_aidl_return);
+        return Status::ok();
+    }
+
+    Status getName(std::string* _aidl_return) override {
+        mClient->getName(_aidl_return);
+        return Status::ok();
+    }
+
+private:
+    std::shared_ptr<NdkResourceManagerClient> mClient;
+};
+
+FwkMediaResource NdkToFwkMediaResource(const NdkMediaResource &in) {
+    FwkMediaResource out{};
+    out.type = static_cast<decltype(out.type)>(in.type);
+    out.subType = static_cast<decltype(out.subType)>(in.subType);
+    auto v(reinterpret_cast<const uint8_t *>(in.id.data()));
+    out.id.assign(v, v + in.id.size());
+    out.value = in.value;
+    return out;
+}
+
+std::vector<FwkMediaResource> NdkToFwkMediaResourceVec(const std::vector<NdkMediaResource> &in) {
+    std::vector<FwkMediaResource> out;
+    for (auto e : in) {
+        out.push_back(NdkToFwkMediaResource(e));
+    }
+    return out;
+}
+
+ScopedAStatus FwkToNdkStatus(Status err) {
+    return ScopedAStatus(AStatus_fromExceptionCode(err.serviceSpecificErrorCode()));
+}
+
+struct NdkResourceManagerServiceImpl : public NdkBnResourceManagerService {
+    using NdkMediaResourcePolicy = ::aidl::android::media::MediaResourcePolicyParcel;
+
+    NdkResourceManagerServiceImpl(const sp<ResourceManagerService> &service)
+        : mService(service) {}
+
+    ScopedAStatus config(const std::vector<NdkMediaResourcePolicy>& in_policies) override {
+        (void)in_policies;
+        return ScopedAStatus::ok();
+    }
+
+    ScopedAStatus addResource(int32_t in_pid, int32_t in_uid, int64_t in_clientId,
+            const std::shared_ptr<NdkResourceManagerClient>& in_client,
+            const std::vector<NdkMediaResource>& in_resources) override {
+        sp<FwkBnResourceManagerClient> client(new FwkResourceManagerClientImpl(in_client));
+        std::vector<FwkMediaResource> resources(NdkToFwkMediaResourceVec(in_resources));
+        auto err = mService->addResource(in_pid, in_uid, in_clientId, client, resources);
+        return FwkToNdkStatus(err);
+    }
+
+    ScopedAStatus removeResource(int32_t in_pid, int64_t in_clientId,
+            const std::vector<NdkMediaResource>& in_resources) override {
+        std::vector<FwkMediaResource> resources(NdkToFwkMediaResourceVec(in_resources));
+        auto err = mService->removeResource(in_pid, in_clientId, resources);
+        return FwkToNdkStatus(err);
+    }
+
+    ScopedAStatus removeClient(int32_t in_pid, int64_t in_clientId) override{
+        auto err = mService->removeClient(in_pid, in_clientId);
+        return FwkToNdkStatus(err);
+    }
+
+    ScopedAStatus reclaimResource(int32_t in_callingPid,
+            const std::vector<NdkMediaResource>& in_resources, bool* _aidl_return) override {
+        std::vector<FwkMediaResource> resources(NdkToFwkMediaResourceVec(in_resources));
+        auto err = mService->reclaimResource(in_callingPid, resources, _aidl_return);
+        return FwkToNdkStatus(err);
+    }
+
+private:
+    sp<ResourceManagerService> mService;
+};
+
+template <typename Impl>
+std::shared_ptr<NdkResourceManagerClient> NdkImplToIface(const Impl &impl) {
+    return std::static_pointer_cast<NdkResourceManagerClient>(impl);
+}
+
+}
 
 static Vector<uint8_t> toAndroidVector(const std::vector<uint8_t> &vec) {
     Vector<uint8_t> aVec;
@@ -66,29 +169,27 @@
     DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
 };
 
-struct FakeDrm : public BnResourceManagerClient {
+struct FakeDrm : public NdkBnResourceManagerClient {
     FakeDrm(const std::vector<uint8_t>& sessionId, const sp<DrmSessionManager>& manager)
         : mSessionId(toAndroidVector(sessionId)),
           mReclaimed(false),
           mDrmSessionManager(manager) {}
 
-    virtual ~FakeDrm() {}
-
-    Status reclaimResource(bool* _aidl_return) {
+    ScopedAStatus reclaimResource(bool* _aidl_return) {
         mReclaimed = true;
         mDrmSessionManager->removeSession(mSessionId);
         *_aidl_return = true;
-        return Status::ok();
+        return ScopedAStatus::ok();
     }
 
-    Status getName(::std::string* _aidl_return) {
+    ScopedAStatus getName(::std::string* _aidl_return) {
         String8 name("FakeDrm[");
         for (size_t i = 0; i < mSessionId.size(); ++i) {
             name.appendFormat("%02x", mSessionId[i]);
         }
         name.append("]");
         *_aidl_return = name;
-        return Status::ok();
+        return ScopedAStatus::ok();
     }
 
     bool isReclaimed() const {
@@ -137,27 +238,24 @@
 public:
     DrmSessionManagerTest()
         : mService(new ResourceManagerService(new FakeProcessInfo(), new FakeSystemCallback())),
-          mDrmSessionManager(new DrmSessionManager(mService)),
+          mDrmSessionManager(new DrmSessionManager(std::shared_ptr<NdkBnResourceManagerService>(new NdkResourceManagerServiceImpl(mService)))),
           mTestDrm1(new FakeDrm(kTestSessionId1, mDrmSessionManager)),
           mTestDrm2(new FakeDrm(kTestSessionId2, mDrmSessionManager)),
           mTestDrm3(new FakeDrm(kTestSessionId3, mDrmSessionManager)) {
-        DrmSessionManager *ptr = new DrmSessionManager(mService);
-        EXPECT_NE(ptr, nullptr);
-        /* mDrmSessionManager = ptr; */
     }
 
 protected:
     void addSession() {
-        mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mTestDrm1->mSessionId);
-        mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
-        mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
+        mDrmSessionManager->addSession(kTestPid1, NdkImplToIface(mTestDrm1), mTestDrm1->mSessionId);
+        mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm2), mTestDrm2->mSessionId);
+        mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm3), mTestDrm3->mSessionId);
     }
 
-    sp<IResourceManagerService> mService;
+    sp<ResourceManagerService> mService;
     sp<DrmSessionManager> mDrmSessionManager;
-    sp<FakeDrm> mTestDrm1;
-    sp<FakeDrm> mTestDrm2;
-    sp<FakeDrm> mTestDrm3;
+    std::shared_ptr<FakeDrm> mTestDrm1;
+    std::shared_ptr<FakeDrm> mTestDrm2;
+    std::shared_ptr<FakeDrm> mTestDrm3;
 };
 
 TEST_F(DrmSessionManagerTest, addSession) {
@@ -204,8 +302,8 @@
 
     // add a session from a higher priority process.
     const std::vector<uint8_t> sid{1, 3, 5};
-    sp<FakeDrm> drm = new FakeDrm(sid, mDrmSessionManager);
-    mDrmSessionManager->addSession(15, drm, drm->mSessionId);
+    std::shared_ptr<FakeDrm> drm(new FakeDrm(sid, mDrmSessionManager));
+    mDrmSessionManager->addSession(15, NdkImplToIface(drm), drm->mSessionId);
 
     // make sure mTestDrm2 is reclaimed next instead of mTestDrm3
     mDrmSessionManager->useSession(mTestDrm3->mSessionId);
@@ -225,9 +323,9 @@
     EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid2));
 
     // add sessions from same pid
-    mDrmSessionManager->addSession(kTestPid2, mTestDrm1, mTestDrm1->mSessionId);
-    mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
-    mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
+    mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm1), mTestDrm1->mSessionId);
+    mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm2), mTestDrm2->mSessionId);
+    mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm3), mTestDrm3->mSessionId);
 
     // use some but not all sessions
     mDrmSessionManager->useSession(mTestDrm1->mSessionId);
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index a48faca..afd5017 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -66,12 +66,14 @@
 
     shared_libs: [
         "libgui",
+        "libhidlallocatorutils",
         "liblog",
         "libmedia_codeclist",
         "libstagefright_foundation",
         "libui",
         "libutils",
         "android.hardware.cas.native@1.0",
+        "android.hardware.drm@1.0",
     ],
 
     sanitize: {
diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp
index 2f8e6af..dea83d4 100644
--- a/media/libstagefright/CallbackDataSource.cpp
+++ b/media/libstagefright/CallbackDataSource.cpp
@@ -114,10 +114,6 @@
     }
 }
 
-sp<DecryptHandle> CallbackDataSource::DrmInitialization(const char *mime) {
-    return mIDataSource->DrmInitialization(mime);
-}
-
 sp<IDataSource> CallbackDataSource::getIDataSource() const {
     return mIDataSource;
 }
@@ -191,14 +187,6 @@
     return mSource->flags();
 }
 
-sp<DecryptHandle> TinyCacheSource::DrmInitialization(const char *mime) {
-    // flush cache when DrmInitialization occurs since decrypted
-    // data may differ from what is in cache.
-    mCachedOffset = 0;
-    mCachedSize = 0;
-    return mSource->DrmInitialization(mime);
-}
-
 sp<IDataSource> TinyCacheSource::getIDataSource() const {
     return mSource->getIDataSource();
 }
diff --git a/media/libstagefright/CodecBase.cpp b/media/libstagefright/CodecBase.cpp
index 97f38f8..5765883 100644
--- a/media/libstagefright/CodecBase.cpp
+++ b/media/libstagefright/CodecBase.cpp
@@ -18,6 +18,8 @@
 #define LOG_TAG "CodecBase"
 
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <android/hardware/drm/1.0/types.h>
+#include <hidlmemory/FrameworkUtils.h>
 #include <mediadrm/ICrypto.h>
 #include <media/stagefright/CodecBase.h>
 #include <utils/Log.h>
@@ -32,4 +34,18 @@
     mDescrambler = descrambler;
 }
 
+void BufferChannelBase::IMemoryToSharedBuffer(
+        const sp<IMemory> &memory,
+        int32_t heapSeqNum,
+        hardware::drm::V1_0::SharedBuffer *buf) {
+    ssize_t offset;
+    size_t size;
+
+    sp<hardware::HidlMemory> hidlMemory;
+    hidlMemory = hardware::fromHeap(memory->getMemory(&offset, &size));
+    buf->bufferId = static_cast<uint32_t>(heapSeqNum);
+    buf->offset = offset >= 0 ? offset : 0;
+    buf->size = size;
+}
+
 } // namespace android
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 4c8be1f..120f354 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -71,9 +71,6 @@
 
     ALOGV("MediaExtractorFactory::CreateFromService %s", mime);
 
-    // initialize source decryption if needed
-    source->DrmInitialization(nullptr /* mime */);
-
     void *meta = nullptr;
     void *creator = NULL;
     FreeMetaFunc freeMeta = nullptr;
diff --git a/media/libstagefright/include/CallbackDataSource.h b/media/libstagefright/include/CallbackDataSource.h
index 9f413cd..e428494 100644
--- a/media/libstagefright/include/CallbackDataSource.h
+++ b/media/libstagefright/include/CallbackDataSource.h
@@ -41,7 +41,6 @@
     virtual String8 toString() {
         return mName;
     }
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
     virtual sp<IDataSource> getIDataSource() const;
 
 private:
@@ -70,7 +69,6 @@
     virtual String8 toString() {
         return mName;
     }
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
     virtual sp<IDataSource> getIDataSource() const;
 
 private:
diff --git a/media/libstagefright/include/ThrottledSource.h b/media/libstagefright/include/ThrottledSource.h
index 71e62f7..5ae0653 100644
--- a/media/libstagefright/include/ThrottledSource.h
+++ b/media/libstagefright/include/ThrottledSource.h
@@ -54,10 +54,6 @@
         return mSource->reconnectAtOffset(offset);
     }
 
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL) {
-        return mSource->DrmInitialization(mime);
-    }
-
     virtual String8 getMIMEType() const {
         return mSource->getMIMEType();
     }
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index ad60f46..e728c00 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -42,12 +42,20 @@
 struct RenderedFrameInfo;
 class Surface;
 struct ICrypto;
+class IMemory;
+
 namespace hardware {
 namespace cas {
 namespace native {
 namespace V1_0 {
 struct IDescrambler;
-}}}}
+}}}
+namespace drm {
+namespace V1_0 {
+struct SharedBuffer;
+}}
+}
+
 using hardware::cas::native::V1_0::IDescrambler;
 
 struct CodecBase : public AHandler, /* static */ ColorUtils {
@@ -314,6 +322,18 @@
      */
     virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) = 0;
 
+    /**
+     * Convert binder IMemory to drm SharedBuffer
+     *
+     * \param   memory      IMemory object to store encrypted content.
+     * \param   heapSeqNum  Heap sequence number from ICrypto; -1 if N/A
+     * \param   buf         SharedBuffer structure to fill.
+     */
+    static void IMemoryToSharedBuffer(
+            const sp<IMemory> &memory,
+            int32_t heapSeqNum,
+            hardware::drm::V1_0::SharedBuffer *buf);
+
 protected:
     std::unique_ptr<CodecBase::BufferCallback> mCallback;
     sp<ICrypto> mCrypto;
diff --git a/media/libstagefright/include/media/stagefright/DataSource.h b/media/libstagefright/include/media/stagefright/DataSource.h
index 1f7a473..83d3e5d 100644
--- a/media/libstagefright/include/media/stagefright/DataSource.h
+++ b/media/libstagefright/include/media/stagefright/DataSource.h
@@ -52,11 +52,6 @@
 
     ////////////////////////////////////////////////////////////////////////////
 
-    // for DRM
-    virtual sp<DecryptHandle> DrmInitialization(const char * /*mime*/ = NULL) {
-        return NULL;
-    }
-
     virtual String8 getUri() {
         return String8();
     }
diff --git a/media/libstagefright/include/media/stagefright/RemoteDataSource.h b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
index b634505..83273cb 100644
--- a/media/libstagefright/include/media/stagefright/RemoteDataSource.h
+++ b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
@@ -66,9 +66,6 @@
     virtual String8 toString()  {
         return mName;
     }
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime) {
-        return mSource->DrmInitialization(mime);
-    }
 
 private:
     enum {
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 5af7b23..657144c 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -36,6 +36,10 @@
 #include <inttypes.h>
 #include <netinet/in.h>
 
+#ifndef __ANDROID_APEX__
+#include "HlsSampleDecryptor.h"
+#endif
+
 namespace android {
 
 ElementaryStreamQueue::ElementaryStreamQueue(Mode mode, uint32_t flags)
@@ -50,7 +54,13 @@
 
     // Create the decryptor anyway since we don't know the use-case unless key is provided
     // Won't decrypt if key info not available (e.g., scanner/extractor just parsing ts files)
-    mSampleDecryptor = isSampleEncrypted() ? new HlsSampleDecryptor : NULL;
+    mSampleDecryptor = isSampleEncrypted() ?
+#ifdef __ANDROID_APEX__
+        new SampleDecryptor
+#else
+        new HlsSampleDecryptor
+#endif
+        : NULL;
 }
 
 sp<MetaData> ElementaryStreamQueue::getFormat() {
diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/ESQueue.h
index 3227f47..a06bd6a 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.h
+++ b/media/libstagefright/mpeg2ts/ESQueue.h
@@ -25,7 +25,7 @@
 #include <utils/RefBase.h>
 #include <vector>
 
-#include "HlsSampleDecryptor.h"
+#include "SampleDecryptor.h"
 
 namespace android {
 
@@ -109,7 +109,7 @@
 
     sp<MetaData> mFormat;
 
-    sp<HlsSampleDecryptor> mSampleDecryptor;
+    sp<SampleDecryptor> mSampleDecryptor;
     int mAUIndex;
 
     bool isSampleEncrypted() const {
diff --git a/media/libstagefright/mpeg2ts/HlsSampleDecryptor.h b/media/libstagefright/mpeg2ts/HlsSampleDecryptor.h
index 2c76620..63b4d7b 100644
--- a/media/libstagefright/mpeg2ts/HlsSampleDecryptor.h
+++ b/media/libstagefright/mpeg2ts/HlsSampleDecryptor.h
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef SAMPLE_AES_PROCESSOR_H_
+#ifndef HLS_SAMPLE_AES_PROCESSOR_H_
 
-#define SAMPLE_AES_PROCESSOR_H_
+#define HLS_SAMPLE_AES_PROCESSOR_H_
 
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AString.h>
@@ -28,18 +28,20 @@
 #include <utils/RefBase.h>
 #include <utils/Vector.h>
 
+#include "SampleDecryptor.h"
+
 namespace android {
 
-struct HlsSampleDecryptor : RefBase {
+struct HlsSampleDecryptor : SampleDecryptor {
 
     HlsSampleDecryptor();
     explicit HlsSampleDecryptor(const sp<AMessage> &sampleAesKeyItem);
 
-    void signalNewSampleAesKey(const sp<AMessage> &sampleAesKeyItem);
+    virtual void signalNewSampleAesKey(const sp<AMessage> &sampleAesKeyItem);
 
-    size_t processNal(uint8_t *nalData, size_t nalSize);
-    void processAAC(size_t adtsHdrSize, uint8_t *data, size_t size);
-    void processAC3(uint8_t *data, size_t size);
+    virtual size_t processNal(uint8_t *nalData, size_t nalSize);
+    virtual void processAAC(size_t adtsHdrSize, uint8_t *data, size_t size);
+    virtual void processAC3(uint8_t *data, size_t size);
 
     static AString aesBlockToStr(uint8_t block[AES_BLOCK_SIZE]);
 
@@ -60,4 +62,4 @@
 
 }  // namespace android
 
-#endif // SAMPLE_AES_PROCESSOR_H_
+#endif // HLS_SAMPLE_AES_PROCESSOR_H_
diff --git a/media/libstagefright/mpeg2ts/SampleDecryptor.h b/media/libstagefright/mpeg2ts/SampleDecryptor.h
new file mode 100644
index 0000000..6bc4ac8
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/SampleDecryptor.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SAMPLE_AES_PROCESSOR_H_
+
+#define SAMPLE_AES_PROCESSOR_H_
+
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+// Base class of HlsSampleDecryptor which has dummy default implementation.
+struct SampleDecryptor : RefBase {
+
+    SampleDecryptor() { };
+
+    virtual void signalNewSampleAesKey(const sp<AMessage> &) { };
+
+    virtual size_t processNal(uint8_t *, size_t) { return -1; };
+    virtual void processAAC(size_t, uint8_t *, size_t) { };
+    virtual void processAC3(uint8_t *, size_t) { };
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(SampleDecryptor);
+};
+
+}  // namespace android
+
+#endif // SAMPLE_AES_PROCESSOR_H_
diff --git a/media/libstagefright/tests/writer/Android.bp b/media/libstagefright/tests/writer/Android.bp
new file mode 100644
index 0000000..7e169cb
--- /dev/null
+++ b/media/libstagefright/tests/writer/Android.bp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_test {
+    name: "writerTest",
+    gtest: true,
+
+    srcs: [
+        "WriterUtility.cpp",
+        "WriterTest.cpp",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libcutils",
+        "liblog",
+        "libutils",
+    ],
+
+    static_libs: [
+        "libstagefright_webm",
+        "libdatasource",
+        "libstagefright",
+        "libstagefright_foundation",
+        "libstagefright_esds",
+        "libogg",
+    ],
+
+    include_dirs: [
+        "frameworks/av/media/libstagefright",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libstagefright/tests/writer/README.md b/media/libstagefright/tests/writer/README.md
new file mode 100644
index 0000000..52db6f0
--- /dev/null
+++ b/media/libstagefright/tests/writer/README.md
@@ -0,0 +1,30 @@
+## Media Testing ##
+---
+#### Writer :
+The Writer Test Suite validates the writers available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+mmm frameworks/av/media/libstagefright/tests/writer/
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+
+adb push ${OUT}/data/nativetest64/writerTest/writerTest /data/local/tmp/
+
+To test 32-bit binary push binaries from nativetest.
+
+adb push ${OUT}/data/nativetest/writerTest/writerTest /data/local/tmp/
+
+The resource file for the tests is taken from Codec2 VTS resource folder. Push these files into device for testing.
+```
+adb push  $ANDROID_BUILD_TOP/frameworks/av/media/codec2/hidl/1.0/vts/functional/res /sdcard/
+```
+
+usage: writerTest -P \<path_to_res_folder\>
+```
+adb shell /data/local/tmp/writerTest -P /sdcard/res/
+```
diff --git a/media/libstagefright/tests/writer/WriterTest.cpp b/media/libstagefright/tests/writer/WriterTest.cpp
new file mode 100644
index 0000000..d68438c
--- /dev/null
+++ b/media/libstagefright/tests/writer/WriterTest.cpp
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "WriterTest"
+#include <utils/Log.h>
+
+#include <fstream>
+#include <iostream>
+
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include <media/mediarecorder.h>
+
+#include <media/stagefright/AACWriter.h>
+#include <media/stagefright/AMRWriter.h>
+#include <media/stagefright/OggWriter.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/MPEG2TSWriter.h>
+#include <webm/WebmWriter.h>
+
+#include "WriterTestEnvironment.h"
+#include "WriterUtility.h"
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/writer.out"
+
+static WriterTestEnvironment *gEnv = nullptr;
+
+struct configFormat {
+    char mime[128];
+    int32_t width;
+    int32_t height;
+    int32_t sampleRate;
+    int32_t channelCount;
+};
+
+// LookUpTable of clips and metadata for component testing
+static const struct InputData {
+    const char *mime;
+    string inputFile;
+    string info;
+    int32_t firstParam;
+    int32_t secondParam;
+    bool isAudio;
+} kInputData[] = {
+        {MEDIA_MIMETYPE_AUDIO_OPUS, "bbb_opus_stereo_128kbps_48000hz.opus",
+         "bbb_opus_stereo_128kbps_48000hz.info", 48000, 2, true},
+        {MEDIA_MIMETYPE_AUDIO_AAC, "bbb_aac_stereo_128kbps_48000hz.aac",
+         "bbb_aac_stereo_128kbps_48000hz.info", 48000, 2, true},
+        {MEDIA_MIMETYPE_AUDIO_AAC_ADTS, "Mps_2_c2_fr1_Sc1_Dc2_0x03_raw.adts",
+         "Mps_2_c2_fr1_Sc1_Dc2_0x03_raw.info", 48000, 2, true},
+        {MEDIA_MIMETYPE_AUDIO_AMR_NB, "sine_amrnb_1ch_12kbps_8000hz.amrnb",
+         "sine_amrnb_1ch_12kbps_8000hz.info", 8000, 1, true},
+        {MEDIA_MIMETYPE_AUDIO_AMR_WB, "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
+         "bbb_amrwb_1ch_14kbps_16000hz.info", 16000, 1, true},
+        {MEDIA_MIMETYPE_AUDIO_VORBIS, "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
+         "bbb_vorbis_stereo_128kbps_48000hz.info", 48000, 2, true},
+        {MEDIA_MIMETYPE_AUDIO_FLAC, "bbb_flac_stereo_680kbps_48000hz.flac",
+         "bbb_flac_stereo_680kbps_48000hz.info", 48000, 2, true},
+        {MEDIA_MIMETYPE_VIDEO_VP9, "bbb_vp9_176x144_285kbps_60fps.vp9",
+         "bbb_vp9_176x144_285kbps_60fps.info", 176, 144, false},
+        {MEDIA_MIMETYPE_VIDEO_VP8, "bbb_vp8_176x144_240kbps_60fps.vp8",
+         "bbb_vp8_176x144_240kbps_60fps.info", 176, 144, false},
+        {MEDIA_MIMETYPE_VIDEO_AVC, "bbb_avc_176x144_300kbps_60fps.h264",
+         "bbb_avc_176x144_300kbps_60fps.info", 176, 144, false},
+        {MEDIA_MIMETYPE_VIDEO_HEVC, "bbb_hevc_176x144_176kbps_60fps.hevc",
+         "bbb_hevc_176x144_176kbps_60fps.info", 176, 144, false},
+        {MEDIA_MIMETYPE_VIDEO_AV1, "bbb_av1_176_144.av1", "bbb_av1_176_144.info", 176, 144, false},
+        {MEDIA_MIMETYPE_VIDEO_H263, "bbb_h263_352x288_300kbps_12fps.h263",
+         "bbb_h263_352x288_300kbps_12fps.info", 352, 288, false},
+        {MEDIA_MIMETYPE_VIDEO_MPEG4, "bbb_mpeg4_352x288_512kbps_30fps.m4v",
+         "bbb_mpeg4_352x288_512kbps_30fps.info", 352, 288, false},
+};
+
+class WriterTest : public ::testing::TestWithParam<pair<string, int32_t>> {
+  public:
+    virtual void SetUp() override {
+        mNumCsds = 0;
+        mInputFrameId = 0;
+        mWriterName = unknown_comp;
+        mDisableTest = false;
+
+        std::map<std::string, standardWriters> mapWriter = {
+                {"ogg", OGG},     {"aac", AAC},      {"aac_adts", AAC_ADTS}, {"webm", WEBM},
+                {"mpeg4", MPEG4}, {"amrnb", AMR_NB}, {"amrwb", AMR_WB},      {"mpeg2Ts", MPEG2TS}};
+        // Find the component type
+        string writerFormat = GetParam().first;
+        if (mapWriter.find(writerFormat) != mapWriter.end()) {
+            mWriterName = mapWriter[writerFormat];
+        }
+        if (mWriterName == standardWriters::unknown_comp) {
+            cout << "[   WARN   ] Test Skipped. No specific writer mentioned\n";
+            mDisableTest = true;
+        }
+    }
+
+    virtual void TearDown() override {
+        mWriter.clear();
+        mFileMeta.clear();
+        mBufferInfo.clear();
+        if (mInputStream) mInputStream.close();
+    }
+
+    void getInputBufferInfo(string inputFileName, string inputInfo);
+
+    int32_t createWriter(int32_t fd);
+
+    int32_t addWriterSource(bool isAudio, configFormat params);
+
+    enum standardWriters {
+        OGG,
+        AAC,
+        AAC_ADTS,
+        WEBM,
+        MPEG4,
+        AMR_NB,
+        AMR_WB,
+        MPEG2TS,
+        unknown_comp,
+    };
+
+    standardWriters mWriterName;
+    sp<MediaWriter> mWriter;
+    sp<MetaData> mFileMeta;
+    sp<MediaAdapter> mCurrentTrack;
+
+    bool mDisableTest;
+    int32_t mNumCsds;
+    int32_t mInputFrameId;
+    ifstream mInputStream;
+    vector<BufferInfo> mBufferInfo;
+};
+
+void WriterTest::getInputBufferInfo(string inputFileName, string inputInfo) {
+    std::ifstream eleInfo;
+    eleInfo.open(inputInfo.c_str());
+    CHECK_EQ(eleInfo.is_open(), true);
+    int32_t bytesCount = 0;
+    uint32_t flags = 0;
+    int64_t timestamp = 0;
+    while (1) {
+        if (!(eleInfo >> bytesCount)) break;
+        eleInfo >> flags;
+        eleInfo >> timestamp;
+        mBufferInfo.push_back({bytesCount, flags, timestamp});
+        if (flags == CODEC_CONFIG_FLAG) mNumCsds++;
+    }
+    eleInfo.close();
+    mInputStream.open(inputFileName.c_str(), std::ifstream::binary);
+    CHECK_EQ(mInputStream.is_open(), true);
+}
+
+int32_t WriterTest::createWriter(int32_t fd) {
+    mFileMeta = new MetaData;
+    switch (mWriterName) {
+        case OGG:
+            mWriter = new OggWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_OGG);
+            break;
+        case AAC:
+            mWriter = new AACWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADIF);
+            break;
+        case AAC_ADTS:
+            mWriter = new AACWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADTS);
+            break;
+        case WEBM:
+            mWriter = new WebmWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_WEBM);
+            break;
+        case MPEG4:
+            mWriter = new MPEG4Writer(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG_4);
+            break;
+        case AMR_NB:
+            mWriter = new AMRWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
+            break;
+        case AMR_WB:
+            mWriter = new AMRWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
+            break;
+        case MPEG2TS:
+            mWriter = new MPEG2TSWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG2TS);
+            break;
+        default:
+            return -1;
+    }
+    if (mWriter == nullptr) return -1;
+    mFileMeta->setInt32(kKeyRealTimeRecording, false);
+    return 0;
+}
+
+int32_t WriterTest::addWriterSource(bool isAudio, configFormat params) {
+    if (mInputFrameId) return -1;
+    sp<AMessage> format = new AMessage;
+    if (mInputStream.is_open()) {
+        format->setString("mime", params.mime);
+        if (isAudio) {
+            format->setInt32("channel-count", params.channelCount);
+            format->setInt32("sample-rate", params.sampleRate);
+        } else {
+            format->setInt32("width", params.width);
+            format->setInt32("height", params.height);
+        }
+
+        int32_t status =
+                writeHeaderBuffers(mInputStream, mBufferInfo, mInputFrameId, format, mNumCsds);
+        if (status != 0) return -1;
+    }
+    sp<MetaData> trackMeta = new MetaData;
+    convertMessageToMetaData(format, trackMeta);
+    mCurrentTrack = new MediaAdapter(trackMeta);
+    status_t result = mWriter->addSource(mCurrentTrack);
+    return result;
+}
+
+void getFileDetails(string &inputFilePath, string &info, configFormat &params, bool &isAudio,
+                    int32_t streamIndex = 0) {
+    if (streamIndex >= sizeof(kInputData) / sizeof(kInputData[0])) {
+        return;
+    }
+    inputFilePath += kInputData[streamIndex].inputFile;
+    info += kInputData[streamIndex].info;
+    strcpy(params.mime, kInputData[streamIndex].mime);
+    isAudio = kInputData[streamIndex].isAudio;
+    if (isAudio) {
+        params.sampleRate = kInputData[streamIndex].firstParam;
+        params.channelCount = kInputData[streamIndex].secondParam;
+    } else {
+        params.width = kInputData[streamIndex].firstParam;
+        params.height = kInputData[streamIndex].secondParam;
+    }
+    return;
+}
+
+TEST_P(WriterTest, CreateWriterTest) {
+    if (mDisableTest) return;
+    ALOGV("Tests the creation of writers");
+
+    string outputFile = OUTPUT_FILE_NAME;
+    int32_t fd =
+            open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+    if (fd < 0) return;
+
+    // Creating writer within a test scope. Destructor should be called when the test ends
+    int32_t status = createWriter(fd);
+    if (status) {
+        cout << "Failed to create writer for output format:" << GetParam().first << "\n";
+        ASSERT_TRUE(false);
+    }
+}
+
+TEST_P(WriterTest, WriterTest) {
+    if (mDisableTest) return;
+    ALOGV("Checks if for a given input, a valid muxed file has been created or not");
+
+    string writerFormat = GetParam().first;
+    string outputFile = OUTPUT_FILE_NAME;
+    int32_t fd =
+            open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+    if (fd < 0) return;
+    int32_t status = createWriter(fd);
+    if (status) {
+        cout << "Failed to create writer for output format:" << writerFormat << "\n";
+        ASSERT_TRUE(false);
+    }
+    string inputFile = gEnv->getRes();
+    string inputInfo = gEnv->getRes();
+    configFormat param;
+    bool isAudio;
+    int32_t inputFileIdx = GetParam().second;
+    getFileDetails(inputFile, inputInfo, param, isAudio, inputFileIdx);
+    if (!inputFile.compare(gEnv->getRes())) {
+        ALOGV("No input file specified");
+        return;
+    }
+    getInputBufferInfo(inputFile, inputInfo);
+    status = addWriterSource(isAudio, param);
+    if (status) {
+        cout << "Failed to add source for " << writerFormat << "Writer \n";
+        ASSERT_TRUE(false);
+    }
+    CHECK_EQ((status_t)OK, mWriter->start(mFileMeta.get()));
+    status = sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack, 0,
+                                 mBufferInfo.size());
+    mCurrentTrack->stop();
+    if (status) {
+        cout << writerFormat << " writer failed \n";
+        mWriter->stop();
+        ASSERT_TRUE(false);
+    }
+    CHECK_EQ((status_t)OK, mWriter->stop());
+    close(fd);
+}
+
+TEST_P(WriterTest, PauseWriterTest) {
+    if (mDisableTest) return;
+    ALOGV("Validates the pause() api of writers");
+
+    string writerFormat = GetParam().first;
+    string outputFile = OUTPUT_FILE_NAME;
+    int32_t fd =
+            open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+    if (fd < 0) return;
+    int32_t status = createWriter(fd);
+    if (status) {
+        cout << "Failed to create writer for output format:" << writerFormat << "\n";
+        ASSERT_TRUE(false);
+    }
+    string inputFile = gEnv->getRes();
+    string inputInfo = gEnv->getRes();
+    configFormat param;
+    bool isAudio;
+    int32_t inputFileIdx = GetParam().second;
+    getFileDetails(inputFile, inputInfo, param, isAudio, inputFileIdx);
+    if (!inputFile.compare(gEnv->getRes())) {
+        ALOGV("No input file specified");
+        return;
+    }
+    getInputBufferInfo(inputFile, inputInfo);
+    status = addWriterSource(isAudio, param);
+    if (status) {
+        cout << "Failed to add source for " << writerFormat << "Writer \n";
+        ASSERT_TRUE(false);
+    }
+    CHECK_EQ((status_t)OK, mWriter->start(mFileMeta.get()));
+    status = sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack, 0,
+                                 mBufferInfo.size() / 4);
+    if (status) {
+        cout << writerFormat << " writer failed \n";
+        mCurrentTrack->stop();
+        mWriter->stop();
+        ASSERT_TRUE(false);
+    }
+
+    bool isPaused = false;
+    if ((mWriterName != standardWriters::MPEG2TS) && (mWriterName != standardWriters::MPEG4)) {
+        CHECK_EQ((status_t)OK, mWriter->pause());
+        isPaused = true;
+    }
+    // In the pause state, writers shouldn't write anything. Testing the writers for the same
+    int32_t numFramesPaused = mBufferInfo.size() / 4;
+    status |= sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack,
+                                  mInputFrameId, numFramesPaused, isPaused);
+    if (isPaused) {
+        CHECK_EQ((status_t)OK, mWriter->start(mFileMeta.get()));
+    }
+    status |= sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack,
+                                  mInputFrameId, mBufferInfo.size());
+    mCurrentTrack->stop();
+    if (status) {
+        cout << writerFormat << " writer failed \n";
+        mWriter->stop();
+        ASSERT_TRUE(false);
+    }
+    CHECK_EQ((status_t)OK, mWriter->stop());
+    close(fd);
+}
+
+// TODO: (b/144476164)
+// Add AAC_ADTS, FLAC, AV1 input
+INSTANTIATE_TEST_SUITE_P(WriterTestAll, WriterTest,
+                         ::testing::Values(make_pair("ogg", 0), make_pair("webm", 0),
+                                           make_pair("aac", 1), make_pair("mpeg4", 1),
+                                           make_pair("amrnb", 3), make_pair("amrwb", 4),
+                                           make_pair("webm", 5), make_pair("webm", 7),
+                                           make_pair("webm", 8), make_pair("mpeg4", 9),
+                                           make_pair("mpeg4", 10), make_pair("mpeg4", 12),
+                                           make_pair("mpeg4", 13), make_pair("mpeg2Ts", 1),
+                                           make_pair("mpeg2Ts", 9)));
+
+int main(int argc, char **argv) {
+    gEnv = new WriterTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/tests/writer/WriterTestEnvironment.h b/media/libstagefright/tests/writer/WriterTestEnvironment.h
new file mode 100644
index 0000000..34c2baa
--- /dev/null
+++ b/media/libstagefright/tests/writer/WriterTestEnvironment.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __WRITER_TEST_ENVIRONMENT_H__
+#define __WRITER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class WriterTestEnvironment : public ::testing::Environment {
+  public:
+    WriterTestEnvironment() : res("/sdcard/media/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int WriterTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"res", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P':
+                setRes(optarg);
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __WRITER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/tests/writer/WriterUtility.cpp b/media/libstagefright/tests/writer/WriterUtility.cpp
new file mode 100644
index 0000000..2ba90a0
--- /dev/null
+++ b/media/libstagefright/tests/writer/WriterUtility.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "WriterUtility"
+#include <utils/Log.h>
+
+#include <media/stagefright/MediaBuffer.h>
+
+#include "WriterUtility.h"
+
+int32_t sendBuffersToWriter(ifstream &inputStream, vector<BufferInfo> &bufferInfo,
+                            int32_t &inputFrameId, sp<MediaAdapter> &currentTrack, int32_t offset,
+                            int32_t range, bool isPaused) {
+    while (1) {
+        if (inputFrameId == (int)bufferInfo.size() || inputFrameId >= (offset + range)) break;
+        int32_t size = bufferInfo[inputFrameId].size;
+        char *data = (char *)malloc(size);
+        if (!data) {
+            ALOGE("Insufficient memeory to read input");
+            return -1;
+        }
+
+        inputStream.read(data, size);
+        CHECK_EQ(inputStream.gcount(), size);
+
+        sp<ABuffer> buffer = new ABuffer((void *)data, size);
+        if (buffer.get() == nullptr) {
+            ALOGE("sendBuffersToWriter() got a nullptr buffer.");
+            return -1;
+        }
+        MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
+
+        // Released in MediaAdapter::signalBufferReturned().
+        mediaBuffer->add_ref();
+        mediaBuffer->set_range(buffer->offset(), buffer->size());
+
+        MetaDataBase &sampleMetaData = mediaBuffer->meta_data();
+        sampleMetaData.setInt64(kKeyTime, bufferInfo[inputFrameId].timeUs);
+        // Just set the kKeyDecodingTime as the presentation time for now.
+        sampleMetaData.setInt64(kKeyDecodingTime, bufferInfo[inputFrameId].timeUs);
+
+        if (bufferInfo[inputFrameId].flags == 1) {
+            sampleMetaData.setInt32(kKeyIsSyncFrame, true);
+        }
+
+        // This pushBuffer will wait until the mediaBuffer is consumed.
+        int status = currentTrack->pushBuffer(mediaBuffer);
+        free(data);
+        inputFrameId++;
+
+        if (OK != status) {
+            if (!isPaused) return status;
+            else {
+                ALOGD("Writer is in paused state. Input buffers won't get consumed");
+                return 0;
+            }
+        }
+    }
+    return 0;
+}
+
+int32_t writeHeaderBuffers(ifstream &inputStream, vector<BufferInfo> &bufferInfo,
+                           int32_t &inputFrameId, sp<AMessage> &format, int32_t numCsds) {
+    char csdName[kMaxCSDStrlen];
+    for (int csdId = 0; csdId < numCsds; csdId++) {
+        int32_t flags = bufferInfo[inputFrameId].flags;
+        if (flags == CODEC_CONFIG_FLAG) {
+            int32_t size = bufferInfo[inputFrameId].size;
+            char *data = (char *)malloc(size);
+            if (!data) {
+                ALOGE("Insufficient memeory to read input");
+                return -1;
+            }
+            inputStream.read(data, size);
+            CHECK_EQ(inputStream.gcount(), size);
+
+            sp<ABuffer> csdBuffer = ABuffer::CreateAsCopy((void *)data, size);
+            if (csdBuffer.get() == nullptr || csdBuffer->base() == nullptr) {
+                return -1;
+            }
+            snprintf(csdName, sizeof(csdName), "csd-%d", csdId);
+            format->setBuffer(csdName, csdBuffer);
+            inputFrameId++;
+            free(data);
+        }
+    }
+    return 0;
+}
diff --git a/media/libstagefright/tests/writer/WriterUtility.h b/media/libstagefright/tests/writer/WriterUtility.h
new file mode 100644
index 0000000..d402798
--- /dev/null
+++ b/media/libstagefright/tests/writer/WriterUtility.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WRITER_UTILITY_H_
+#define WRITER_UTILITY_H_
+
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <media/stagefright/MediaAdapter.h>
+
+using namespace android;
+using namespace std;
+
+#define CODEC_CONFIG_FLAG 32
+
+constexpr uint32_t kMaxCSDStrlen = 16;
+
+struct BufferInfo {
+    int32_t size;
+    uint32_t flags;
+    int64_t timeUs;
+};
+
+int32_t sendBuffersToWriter(ifstream &inputStream, vector<BufferInfo> &bufferInfo,
+                            int32_t &inputFrameId, sp<MediaAdapter> &currentTrack, int32_t offset,
+                            int32_t range, bool isPaused = false);
+
+int32_t writeHeaderBuffers(ifstream &inputStream, vector<BufferInfo> &bufferInfo,
+                           int32_t &inputFrameId, sp<AMessage> &format, int32_t numCsds);
+
+#endif  // WRITER_UTILITY_H_
diff --git a/media/mediaserver/manifest_media_c2_software.xml b/media/mediaserver/manifest_media_c2_software.xml
index 5196336..f23ed44 100644
--- a/media/mediaserver/manifest_media_c2_software.xml
+++ b/media/mediaserver/manifest_media_c2_software.xml
@@ -2,7 +2,7 @@
     <hal>
         <name>android.hardware.media.c2</name>
         <transport>hwbinder</transport>
-        <version>1.0</version>
+        <version>1.1</version>
         <interface>
             <name>IComponentStore</name>
             <instance>software</instance>
diff --git a/media/mediaserver/mediaserver.rc b/media/mediaserver/mediaserver.rc
index f6c325c..ecb75a9 100644
--- a/media/mediaserver/mediaserver.rc
+++ b/media/mediaserver/mediaserver.rc
@@ -1,3 +1,6 @@
+on property:init.svc.media=*
+    setprop init.svc.mediadrm ${init.svc.media}
+
 service media /system/bin/mediaserver
     class main
     user media
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index b78373d..8a95982 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -35,14 +35,13 @@
 #include <media/stagefright/MediaErrors.h>
 #include <binder/IServiceManager.h>
 #include <media/NdkMediaCrypto.h>
-#include <mediadrm/IMediaDrmService.h>
 
 
 using namespace android;
 
 typedef Vector<uint8_t> idvec_t;
 
-struct DrmListener: virtual public BnDrmClient
+struct DrmListener: virtual public IDrmClient
 {
 private:
     AMediaDrm *mObj;
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index f666ad0..7531578 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -4,7 +4,7 @@
     AImageReader_acquireLatestImageAsync; # introduced=26
     AImageReader_acquireNextImage; # introduced=24
     AImageReader_acquireNextImageAsync; # introduced=26
-    AImageReader_getWindowNativeHandle; #vndk
+    AImageReader_getWindowNativeHandle; # llndk
     AImageReader_delete; # introduced=24
     AImageReader_getFormat; # introduced=24
     AImageReader_getHeight; # introduced=24
diff --git a/media/tests/benchmark/README.md b/media/tests/benchmark/README.md
index 487ddb8..520a2cf 100644
--- a/media/tests/benchmark/README.md
+++ b/media/tests/benchmark/README.md
@@ -118,5 +118,30 @@
 The test encodes input stream and benchmarks the encoders available in SDK.
 ```
 adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.EncoderTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+```
 
+# Codec2
+To run the test suite for measuring performance of the codec2 layer, follow the following steps:
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+adb push $(OUT)/data/nativetest64/* /data/local/tmp/
+Eg. adb push $(OUT)/data/nativetest64/C2DecoderTest/C2DecoderTest /data/local/tmp/
+
+To test 32-bit binary push binaries from nativetest.
+adb push $(OUT)/data/nativetest/* /data/local/tmp/
+Eg. adb push $(OUT)/data/nativetest/C2DecoderTest/C2DecoderTest /data/local/tmp/
+
+To get the resource files for the test follow instructions given in [NDK](#NDK)
+
+## C2 Decoder
+
+The test decodes input stream and benchmarks the codec2 decoders available in device.
+
+Setup steps are same as [extractor](#extractor).
+
+```
+adb shell /data/local/tmp/C2DecoderTest -P /data/local/tmp/MediaBenchmark/res/
 ```
diff --git a/media/tests/benchmark/src/native/common/Android.bp b/media/tests/benchmark/src/native/common/Android.bp
index 1da0102..babc329 100644
--- a/media/tests/benchmark/src/native/common/Android.bp
+++ b/media/tests/benchmark/src/native/common/Android.bp
@@ -24,6 +24,7 @@
     srcs: [
         "BenchmarkCommon.cpp",
         "Stats.cpp",
+        "utils/Timers.cpp",
     ],
 
     export_include_dirs: ["."],
@@ -49,7 +50,6 @@
     shared_libs: [
         "libmediandk",
         "liblog",
-        "libutils",
     ],
 
     cflags: [
@@ -58,6 +58,39 @@
     ]
 }
 
+cc_library_static {
+    name: "libmediabenchmark_codec2_common",
+    defaults: [
+        "libmediabenchmark_codec2_common-defaults",
+    ],
+
+    srcs: [
+        "BenchmarkC2Common.cpp",
+    ],
+
+    export_include_dirs: ["."],
+
+    ldflags: ["-Wl,-Bsymbolic"]
+}
+
+cc_defaults {
+    name: "libmediabenchmark_codec2_common-defaults",
+
+    defaults: [
+        "libmediabenchmark_common-defaults",
+        "libcodec2-hidl-client-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    include_dirs: [
+        "frameworks/av/media/codec2/hidl/client/include",
+    ],
+
+    shared_libs: [
+        "libcodec2_client",
+    ]
+}
+
 // public dependency for native implementation
 // to be used by code under media/benchmark/* only
 cc_defaults {
diff --git a/media/tests/benchmark/src/native/common/BenchmarkC2Common.cpp b/media/tests/benchmark/src/native/common/BenchmarkC2Common.cpp
new file mode 100644
index 0000000..622a0e1
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/BenchmarkC2Common.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "BenchmarkC2Common"
+
+#include "BenchmarkC2Common.h"
+
+int32_t BenchmarkC2Common::setupCodec2() {
+    ALOGV("In %s", __func__);
+    mClient = android::Codec2Client::CreateFromService("default");
+    if (!mClient) return -1;
+
+    std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
+    if (!store) return -1;
+
+    c2_status_t status = store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator);
+    if (status != C2_OK) return status;
+
+    mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
+    if (!mLinearPool) return -1;
+
+    status = store->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &mGraphicAllocator);
+    if (status != C2_OK) return status;
+
+    mGraphicPool = std::make_shared<C2PooledBlockPool>(mGraphicAllocator, mBlockPoolId++);
+    if (!mGraphicPool) return -1;
+
+    for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
+        mWorkQueue.emplace_back(new C2Work);
+    }
+    if (!mStats) mStats = new Stats();
+
+    return status;
+}
+
+vector<string> BenchmarkC2Common::getSupportedComponentList(bool isEncoder) {
+    // Get List of components from all known services
+    vector<string> codecList;
+    const std::vector<C2Component::Traits> listTraits = mClient->ListComponents();
+    if (listTraits.size() == 0)
+        ALOGE("ComponentInfo list empty.");
+    else {
+        for (size_t i = 0; i < listTraits.size(); i++) {
+            if (isEncoder && C2Component::KIND_ENCODER == listTraits[i].kind) {
+                codecList.push_back(listTraits[i].name);
+            } else if (!isEncoder && C2Component::KIND_DECODER == listTraits[i].kind) {
+                codecList.push_back(listTraits[i].name);
+            }
+        }
+    }
+    return codecList;
+}
+
+void BenchmarkC2Common::waitOnInputConsumption() {
+    typedef std::unique_lock<std::mutex> ULock;
+    uint32_t queueSize;
+    uint32_t maxRetry = 0;
+    {
+        ULock l(mQueueLock);
+        queueSize = mWorkQueue.size();
+    }
+    while ((maxRetry < MAX_RETRY) && (queueSize < MAX_INPUT_BUFFERS)) {
+        ULock l(mQueueLock);
+        if (queueSize != mWorkQueue.size()) {
+            queueSize = mWorkQueue.size();
+            maxRetry = 0;
+        } else {
+            mQueueCondition.wait_for(l, TIME_OUT);
+            maxRetry++;
+        }
+    }
+}
+
+void BenchmarkC2Common::handleWorkDone(std::list<std::unique_ptr<C2Work>> &workItems) {
+    ALOGV("In %s", __func__);
+    mStats->addOutputTime();
+    for (std::unique_ptr<C2Work> &work : workItems) {
+        if (!work->worklets.empty()) {
+            if (work->worklets.front()->output.flags != C2FrameData::FLAG_INCOMPLETE) {
+                mEos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) !=
+                       0;
+                ALOGV("WorkDone: frameID received %d , mEos : %d",
+                      (int)work->worklets.front()->output.ordinal.frameIndex.peeku(), mEos);
+                work->input.buffers.clear();
+                work->worklets.clear();
+                {
+                    typedef std::unique_lock<std::mutex> ULock;
+                    ULock l(mQueueLock);
+                    mWorkQueue.push_back(std::move(work));
+                    mQueueCondition.notify_all();
+                }
+            }
+        }
+    }
+}
+
diff --git a/media/tests/benchmark/src/native/common/BenchmarkC2Common.h b/media/tests/benchmark/src/native/common/BenchmarkC2Common.h
new file mode 100644
index 0000000..d67758a
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/BenchmarkC2Common.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BENCHMARK_C2_COMMON_H__
+#define __BENCHMARK_C2_COMMON_H__
+
+#include "codec2/hidl/client.h"
+
+#include <C2Component.h>
+#include <C2Config.h>
+
+#include <hidl/HidlSupport.h>
+
+#include <C2AllocatorIon.h>
+#include <C2Buffer.h>
+#include <C2BufferPriv.h>
+
+#include "BenchmarkCommon.h"
+
+#define MAX_RETRY 20
+#define TIME_OUT 400ms
+#define MAX_INPUT_BUFFERS 8
+
+using android::C2AllocatorIon;
+
+class LinearBuffer : public C2Buffer {
+  public:
+    explicit LinearBuffer(const std::shared_ptr<C2LinearBlock> &block)
+        : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
+
+    explicit LinearBuffer(const std::shared_ptr<C2LinearBlock> &block, size_t size)
+        : C2Buffer({block->share(block->offset(), size, ::C2Fence())}) {}
+};
+
+class GraphicBuffer : public C2Buffer {
+  public:
+    explicit GraphicBuffer(const std::shared_ptr<C2GraphicBlock> &block)
+        : C2Buffer({block->share(C2Rect(block->width(), block->height()), ::C2Fence())}) {}
+};
+
+/**
+ * Handle Callback functions onWorkDone(), onTripped(),
+ * onError(), onDeath(), onFramesRendered() for C2 Components
+ */
+struct CodecListener : public android::Codec2Client::Listener {
+  public:
+    CodecListener(
+            const std::function<void(std::list<std::unique_ptr<C2Work>> &workItems)> fn = nullptr)
+        : callBack(fn) {}
+    virtual void onWorkDone(const std::weak_ptr<android::Codec2Client::Component> &comp,
+                            std::list<std::unique_ptr<C2Work>> &workItems) override {
+        ALOGV("onWorkDone called");
+        (void)comp;
+        if (callBack) callBack(workItems);
+    }
+
+    virtual void onTripped(
+            const std::weak_ptr<android::Codec2Client::Component> &comp,
+            const std::vector<std::shared_ptr<C2SettingResult>> &settingResults) override {
+        (void)comp;
+        (void)settingResults;
+    }
+
+    virtual void onError(const std::weak_ptr<android::Codec2Client::Component> &comp,
+                         uint32_t errorCode) override {
+        (void)comp;
+        ALOGV("onError called");
+        if (errorCode != 0) ALOGE("Error : %u", errorCode);
+    }
+
+    virtual void onDeath(const std::weak_ptr<android::Codec2Client::Component> &comp) override {
+        (void)comp;
+    }
+
+    virtual void onInputBufferDone(uint64_t frameIndex, size_t arrayIndex) override {
+        (void)frameIndex;
+        (void)arrayIndex;
+    }
+
+    virtual void onFrameRendered(uint64_t bufferQueueId, int32_t slotId,
+                                 int64_t timestampNs) override {
+        (void)bufferQueueId;
+        (void)slotId;
+        (void)timestampNs;
+    }
+
+    std::function<void(std::list<std::unique_ptr<C2Work>> &workItems)> callBack;
+};
+
+class BenchmarkC2Common {
+  public:
+    BenchmarkC2Common()
+        : mEos(false),
+          mStats(nullptr),
+          mClient(nullptr),
+          mBlockPoolId(0),
+          mLinearPool(nullptr),
+          mGraphicPool(nullptr),
+          mLinearAllocator(nullptr),
+          mGraphicAllocator(nullptr) {}
+
+    int32_t setupCodec2();
+
+    vector<string> getSupportedComponentList(bool isEncoder);
+
+    void waitOnInputConsumption();
+
+    // callback function to process onWorkDone received by Listener
+    void handleWorkDone(std::list<std::unique_ptr<C2Work>> &workItems);
+
+    bool mEos;
+  protected:
+    Stats *mStats;
+
+    std::shared_ptr<android::Codec2Client> mClient;
+
+    C2BlockPool::local_id_t mBlockPoolId;
+    std::shared_ptr<C2BlockPool> mLinearPool;
+    std::shared_ptr<C2BlockPool> mGraphicPool;
+    std::shared_ptr<C2Allocator> mLinearAllocator;
+    std::shared_ptr<C2Allocator> mGraphicAllocator;
+
+    std::mutex mQueueLock;
+    std::condition_variable mQueueCondition;
+    std::list<std::unique_ptr<C2Work>> mWorkQueue;
+};
+
+#endif  // __BENCHMARK_C2_COMMON_H__
diff --git a/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp b/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp
index 5bdb48a..ab74508 100644
--- a/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp
+++ b/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp
@@ -56,10 +56,10 @@
 
 void OnErrorCB(AMediaCodec *codec, void *userdata, media_status_t err, int32_t actionCode,
                const char *detail) {
-    (void)codec;
-    ALOGV("OnErrorCB: err(%d), actionCode(%d), detail(%s)", err, actionCode, detail);
+    ALOGE("OnErrorCB: err(%d), actionCode(%d), detail(%s)", err, actionCode, detail);
     CallBackHandle *self = (CallBackHandle *)userdata;
     self->mSawError = true;
+    self->mIOQueue.push([self, codec, err]() { self->onError(codec, err); });
 }
 
 AMediaCodec *createMediaCodec(AMediaFormat *format, const char *mime, string codecName,
diff --git a/media/tests/benchmark/src/native/common/BenchmarkCommon.h b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
index df16baf..8153a86 100644
--- a/media/tests/benchmark/src/native/common/BenchmarkCommon.h
+++ b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
@@ -17,8 +17,6 @@
 #ifndef __BENCHMARK_COMMON_H__
 #define __BENCHMARK_COMMON_H__
 
-#include <utils/Log.h>
-
 #include <inttypes.h>
 #include <mutex>
 #include <queue>
@@ -89,6 +87,10 @@
         (void)codec;
         (void)format;
     }
+    virtual void onError(AMediaCodec *codec, media_status_t err) {
+        (void)codec;
+        (void)err;
+    }
     virtual void onOutputAvailable(AMediaCodec *codec, int32_t index,
                                    AMediaCodecBufferInfo *bufferInfo) {
         (void)codec;
diff --git a/media/tests/benchmark/src/native/common/Stats.cpp b/media/tests/benchmark/src/native/common/Stats.cpp
index 6bcd3ce..2d9bb31 100644
--- a/media/tests/benchmark/src/native/common/Stats.cpp
+++ b/media/tests/benchmark/src/native/common/Stats.cpp
@@ -19,7 +19,6 @@
 
 #include <iostream>
 #include <stdint.h>
-#include <utils/Log.h>
 
 #include "Stats.h"
 
diff --git a/media/tests/benchmark/src/native/common/Stats.h b/media/tests/benchmark/src/native/common/Stats.h
index 024319a..2f556ee 100644
--- a/media/tests/benchmark/src/native/common/Stats.h
+++ b/media/tests/benchmark/src/native/common/Stats.h
@@ -17,11 +17,28 @@
 #ifndef __STATS_H__
 #define __STATS_H__
 
+#include <android/log.h>
+
+#ifndef ALOG
+#define ALOG(priority, tag, ...) ((void)__android_log_print(ANDROID_##priority, tag, __VA_ARGS__))
+
+#define ALOGI(...) ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define ALOGE(...) ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#define ALOGD(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+#if LOG_NDEBUG
+#define ALOGV(cond, ...)   ((void)0)
+#else
+#define ALOGV(...) ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
+#endif
+#endif  // ALOG
+
 #include <sys/time.h>
 #include <algorithm>
 #include <numeric>
 #include <vector>
-#include <utils/Timers.h>
+
+// Include local copy of Timers taken from system/core/libutils
+#include "utils/Timers.h"
 
 using namespace std;
 
diff --git a/media/tests/benchmark/src/native/common/utils/Timers.cpp b/media/tests/benchmark/src/native/common/utils/Timers.cpp
new file mode 100644
index 0000000..1acbdb3
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/utils/Timers.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Timer functions.
+//
+
+#define LOG_TAG "Timers"
+
+#include <limits.h>
+#include <time.h>
+
+#include "Timers.h"
+
+#if defined(__ANDROID__)
+nsecs_t systemTime(int clock) {
+    static const clockid_t clocks[] = {CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID,
+                                       CLOCK_THREAD_CPUTIME_ID, CLOCK_BOOTTIME};
+    struct timespec t;
+    t.tv_sec = t.tv_nsec = 0;
+    clock_gettime(clocks[clock], &t);
+    return nsecs_t(t.tv_sec) * 1000000000LL + t.tv_nsec;
+}
+#else
+nsecs_t systemTime(int /*clock*/) {
+    // Clock support varies widely across hosts. Mac OS doesn't support
+    // posix clocks, older glibcs don't support CLOCK_BOOTTIME and Windows
+    // is windows.
+    struct timeval t;
+    t.tv_sec = t.tv_usec = 0;
+    gettimeofday(&t, NULL);
+    return nsecs_t(t.tv_sec) * 1000000000LL + nsecs_t(t.tv_usec) * 1000LL;
+}
+#endif
+
+int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime) {
+    nsecs_t timeoutDelayMillis;
+    if (timeoutTime > referenceTime) {
+        uint64_t timeoutDelay = uint64_t(timeoutTime - referenceTime);
+        if (timeoutDelay > uint64_t((INT_MAX - 1) * 1000000LL)) {
+            timeoutDelayMillis = -1;
+        } else {
+            timeoutDelayMillis = (timeoutDelay + 999999LL) / 1000000LL;
+        }
+    } else {
+        timeoutDelayMillis = 0;
+    }
+    return (int)timeoutDelayMillis;
+}
diff --git a/media/tests/benchmark/src/native/common/utils/Timers.h b/media/tests/benchmark/src/native/common/utils/Timers.h
new file mode 100644
index 0000000..d643dcd
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/utils/Timers.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Timer functions.
+//
+
+#ifndef _LIBS_UTILS_TIMERS_H
+#define _LIBS_UTILS_TIMERS_H
+
+#include <stdint.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+// ------------------------------------------------------------------
+// C API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int64_t nsecs_t;  // nano-seconds
+
+static inline nsecs_t seconds_to_nanoseconds(nsecs_t secs) {
+    return secs * 1000000000;
+}
+
+static inline nsecs_t milliseconds_to_nanoseconds(nsecs_t secs) {
+    return secs * 1000000;
+}
+
+static inline nsecs_t microseconds_to_nanoseconds(nsecs_t secs) {
+    return secs * 1000;
+}
+
+static inline nsecs_t nanoseconds_to_seconds(nsecs_t secs) {
+    return secs / 1000000000;
+}
+
+static inline nsecs_t nanoseconds_to_milliseconds(nsecs_t secs) {
+    return secs / 1000000;
+}
+
+static inline nsecs_t nanoseconds_to_microseconds(nsecs_t secs) {
+    return secs / 1000;
+}
+
+static inline nsecs_t s2ns(nsecs_t v) {
+    return seconds_to_nanoseconds(v);
+}
+static inline nsecs_t ms2ns(nsecs_t v) {
+    return milliseconds_to_nanoseconds(v);
+}
+static inline nsecs_t us2ns(nsecs_t v) {
+    return microseconds_to_nanoseconds(v);
+}
+static inline nsecs_t ns2s(nsecs_t v) {
+    return nanoseconds_to_seconds(v);
+}
+static inline nsecs_t ns2ms(nsecs_t v) {
+    return nanoseconds_to_milliseconds(v);
+}
+static inline nsecs_t ns2us(nsecs_t v) {
+    return nanoseconds_to_microseconds(v);
+}
+
+static inline nsecs_t seconds(nsecs_t v) {
+    return s2ns(v);
+}
+static inline nsecs_t milliseconds(nsecs_t v) {
+    return ms2ns(v);
+}
+static inline nsecs_t microseconds(nsecs_t v) {
+    return us2ns(v);
+}
+
+enum {
+    SYSTEM_TIME_REALTIME = 0,   // system-wide realtime clock
+    SYSTEM_TIME_MONOTONIC = 1,  // monotonic time since unspecified starting point
+    SYSTEM_TIME_PROCESS = 2,    // high-resolution per-process clock
+    SYSTEM_TIME_THREAD = 3,     // high-resolution per-thread clock
+    SYSTEM_TIME_BOOTTIME = 4    // same as SYSTEM_TIME_MONOTONIC, but including CPU suspend time
+};
+
+// return the system-time according to the specified clock
+#ifdef __cplusplus
+nsecs_t systemTime(int clock = SYSTEM_TIME_MONOTONIC);
+#else
+nsecs_t systemTime(int clock);
+#endif  // def __cplusplus
+
+/**
+ * Returns the number of milliseconds to wait between the reference time and the timeout time.
+ * If the timeout is in the past relative to the reference time, returns 0.
+ * If the timeout is more than INT_MAX milliseconds in the future relative to the reference time,
+ * such as when timeoutTime == LLONG_MAX, returns -1 to indicate an infinite timeout delay.
+ * Otherwise, returns the difference between the reference time and timeout time
+ * rounded up to the next millisecond.
+ */
+int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // _LIBS_UTILS_TIMERS_H
diff --git a/media/tests/benchmark/src/native/decoder/Android.bp b/media/tests/benchmark/src/native/decoder/Android.bp
index b6286d4..b5072ab 100644
--- a/media/tests/benchmark/src/native/decoder/Android.bp
+++ b/media/tests/benchmark/src/native/decoder/Android.bp
@@ -29,3 +29,22 @@
 
     ldflags: ["-Wl,-Bsymbolic"]
 }
+
+cc_library_static {
+    name: "libmediabenchmark_codec2_decoder",
+    defaults: [
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_codec2_common-defaults",
+    ],
+
+    srcs: ["C2Decoder.cpp"],
+
+    static_libs: [
+        "libmediabenchmark_codec2_common",
+        "libmediabenchmark_extractor",
+    ],
+
+    export_include_dirs: ["."],
+
+    ldflags: ["-Wl,-Bsymbolic"]
+}
diff --git a/media/tests/benchmark/src/native/decoder/C2Decoder.cpp b/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
new file mode 100644
index 0000000..20a1468
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "C2Decoder"
+#include <log/log.h>
+
+#include "C2Decoder.h"
+#include <iostream>
+
+int32_t C2Decoder::createCodec2Component(string compName, AMediaFormat *format) {
+    ALOGV("In %s", __func__);
+    mListener.reset(new CodecListener(
+            [this](std::list<std::unique_ptr<C2Work>> &workItems) { handleWorkDone(workItems); }));
+    if (!mListener) return -1;
+
+    const char *mime = nullptr;
+    AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
+    if (!mime) {
+        ALOGE("Error in AMediaFormat_getString");
+        return -1;
+    }
+    // Configure the plugin with Input properties
+    std::vector<C2Param *> configParam;
+    if (!strncmp(mime, "audio/", 6)) {
+        int32_t sampleRate, numChannels;
+        AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sampleRate);
+        AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &numChannels);
+        C2StreamSampleRateInfo::output sampleRateInfo(0u, sampleRate);
+        C2StreamChannelCountInfo::output channelCountInfo(0u, numChannels);
+        configParam.push_back(&sampleRateInfo);
+        configParam.push_back(&channelCountInfo);
+
+    } else {
+        int32_t width, height;
+        AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &width);
+        AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &height);
+        C2StreamPictureSizeInfo::input inputSize(0u, width, height);
+        configParam.push_back(&inputSize);
+    }
+
+    int64_t sTime = mStats->getCurTime();
+    mComponent = mClient->CreateComponentByName(compName.c_str(), mListener, &mClient);
+    if (mComponent == nullptr) {
+        ALOGE("Create component failed for %s", compName.c_str());
+        return -1;
+    }
+    std::vector<std::unique_ptr<C2SettingResult>> failures;
+    int32_t status = mComponent->config(configParam, C2_DONT_BLOCK, &failures);
+    if (failures.size() != 0) {
+        ALOGE("Invalid Configuration");
+        return -1;
+    }
+
+    status |= mComponent->start();
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setInitTime(timeTaken);
+    return status;
+}
+
+int32_t C2Decoder::decodeFrames(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo) {
+    ALOGV("In %s", __func__);
+    typedef std::unique_lock<std::mutex> ULock;
+    c2_status_t status = C2_OK;
+    mStats->setStartTime();
+    while (1) {
+        if (mNumInputFrame == frameInfo.size()) break;
+        std::unique_ptr<C2Work> work;
+        // Prepare C2Work
+        {
+            ULock l(mQueueLock);
+            if (mWorkQueue.empty()) mQueueCondition.wait_for(l, MAX_RETRY * TIME_OUT);
+            if (!mWorkQueue.empty()) {
+                mStats->addInputTime();
+                work.swap(mWorkQueue.front());
+                mWorkQueue.pop_front();
+            } else {
+                std::cout << "Wait for generating C2Work exceeded timeout" << std::endl;
+                return -1;
+            }
+        }
+
+        uint32_t flags = frameInfo[mNumInputFrame].flags;
+        if (flags == AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG) {
+            flags = C2FrameData::FLAG_CODEC_CONFIG;
+        }
+        if (mNumInputFrame == (frameInfo.size() - 1)) {
+            flags |= C2FrameData::FLAG_END_OF_STREAM;
+        }
+        work->input.flags = (C2FrameData::flags_t)flags;
+        work->input.ordinal.timestamp = frameInfo[mNumInputFrame].presentationTimeUs;
+        work->input.ordinal.frameIndex = mNumInputFrame;
+        work->input.buffers.clear();
+        int size = frameInfo[mNumInputFrame].size;
+        int alignedSize = ALIGN(size, PAGE_SIZE);
+        if (size) {
+            std::shared_ptr<C2LinearBlock> block;
+            status = mLinearPool->fetchLinearBlock(
+                    alignedSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+            if (status != C2_OK || block == nullptr) {
+                std::cout << "C2LinearBlock::map() failed : " << status << std::endl;
+                return status;
+            }
+
+            C2WriteView view = block->map().get();
+            if (view.error() != C2_OK) {
+                std::cout << "C2LinearBlock::map() failed : " << view.error() << std::endl;
+                return view.error();
+            }
+            memcpy(view.base(), inputBuffer + mOffset, size);
+            work->input.buffers.emplace_back(new LinearBuffer(block, size));
+            mStats->addFrameSize(size);
+        }
+        work->worklets.clear();
+        work->worklets.emplace_back(new C2Worklet);
+
+        std::list<std::unique_ptr<C2Work>> items;
+        items.push_back(std::move(work));
+        // queue() invokes process() function of C2 Plugin.
+        status = mComponent->queue(&items);
+        if (status != C2_OK) {
+            ALOGE("queue failed");
+            return status;
+        }
+        ALOGV("Frame #%d size = %d queued", mNumInputFrame, size);
+        mNumInputFrame++;
+        mOffset += size;
+    }
+    return status;
+}
+
+void C2Decoder::deInitCodec() {
+    ALOGV("In %s", __func__);
+    if (!mComponent) return;
+
+    int64_t sTime = mStats->getCurTime();
+    mComponent->stop();
+    mComponent->release();
+    mComponent = nullptr;
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setDeInitTime(timeTaken);
+}
+
+void C2Decoder::dumpStatistics(string inputReference, int64_t durationUs) {
+    string operation = "c2decode";
+    mStats->dumpStatistics(operation, inputReference, durationUs);
+}
+
+void C2Decoder::resetDecoder() {
+    mOffset = 0;
+    mNumInputFrame = 0;
+    if (mStats) mStats->reset();
+}
diff --git a/media/tests/benchmark/src/native/decoder/C2Decoder.h b/media/tests/benchmark/src/native/decoder/C2Decoder.h
new file mode 100644
index 0000000..4a3eb96
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/C2Decoder.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __C2_DECODER_H__
+#define __C2_DECODER_H__
+
+#include "BenchmarkC2Common.h"
+
+#define ALIGN(_sz, _align) (((_sz) + ((_align) - 1)) & ~((_align) - 1))
+
+class C2Decoder : public BenchmarkC2Common {
+  public:
+    C2Decoder() : mOffset(0), mNumInputFrame(0), mComponent(nullptr) {}
+
+    int32_t createCodec2Component(string codecName, AMediaFormat *format);
+
+    int32_t decodeFrames(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo);
+
+    void deInitCodec();
+
+    void dumpStatistics(string inputReference, int64_t durationUs);
+
+    void resetDecoder();
+
+  private:
+    int32_t mOffset;
+    int32_t mNumInputFrame;
+    vector<AMediaCodecBufferInfo> mFrameMetaData;
+
+    std::shared_ptr<android::Codec2Client::Listener> mListener;
+    std::shared_ptr<android::Codec2Client::Component> mComponent;
+};
+
+#endif  // __C2_DECODER_H__
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.cpp b/media/tests/benchmark/src/native/decoder/Decoder.cpp
index ef84537..ac0d525 100644
--- a/media/tests/benchmark/src/native/decoder/Decoder.cpp
+++ b/media/tests/benchmark/src/native/decoder/Decoder.cpp
@@ -32,8 +32,8 @@
     int64_t timestamp = frameInfo[frameID].presentationTimeUs;
     ssize_t bytesCount = frameInfo[frameID].size;
     if (bufSize < bytesCount) {
-        ALOGE("Error : insufficient resource");
-        return make_tuple(0, AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE, 0);
+        ALOGE("Error : Buffer size is insufficient to read sample");
+        return make_tuple(0, AMEDIA_ERROR_MALFORMED, 0);
     }
 
     memcpy(buf, inputBuffer + offset, bytesCount);
@@ -54,6 +54,7 @@
         size_t bufSize;
         uint8_t *buf = AMediaCodec_getInputBuffer(mCodec, bufIdx, &bufSize);
         if (!buf) {
+            mErrorCode = AMEDIA_ERROR_IO;
             mSignalledError = true;
             mDecoderDoneCondition.notify_one();
             return;
@@ -64,7 +65,8 @@
         int64_t presentationTimeUs = 0;
         tie(bytesRead, flag, presentationTimeUs) = readSampleData(
                 mInputBuffer, mOffset, mFrameMetaData, buf, mNumInputFrame, bufSize);
-        if (flag == AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE) {
+        if (flag == AMEDIA_ERROR_MALFORMED) {
+            mErrorCode = (media_status_t)flag;
             mSignalledError = true;
             mDecoderDoneCondition.notify_one();
             return;
@@ -74,9 +76,10 @@
         ALOGV("%s bytesRead : %zd presentationTimeUs : %" PRId64 " mSawInputEOS : %s", __FUNCTION__,
               bytesRead, presentationTimeUs, mSawInputEOS ? "TRUE" : "FALSE");
 
-        int status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */, bytesRead,
-                                                  presentationTimeUs, flag);
+        media_status_t status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */,
+                                                             bytesRead, presentationTimeUs, flag);
         if (AMEDIA_OK != status) {
+            mErrorCode = status;
             mSignalledError = true;
             mDecoderDoneCondition.notify_one();
             return;
@@ -127,6 +130,16 @@
     }
 }
 
+void Decoder::onError(AMediaCodec *mediaCodec, media_status_t err) {
+    ALOGV("In %s", __func__);
+    if (mediaCodec == mCodec && mediaCodec) {
+        ALOGE("Received Error %d", err);
+        mErrorCode = err;
+        mSignalledError = true;
+        mDecoderDoneCondition.notify_one();
+    }
+}
+
 void Decoder::setupDecoder() {
     if (!mFormat) mFormat = mExtractor->getFormat();
 }
@@ -168,7 +181,8 @@
                 ssize_t inIdx = AMediaCodec_dequeueInputBuffer(mCodec, kQueueDequeueTimeoutUs);
                 if (inIdx < 0 && inIdx != AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
                     ALOGE("AMediaCodec_dequeueInputBuffer returned invalid index %zd\n", inIdx);
-                    return AMEDIA_ERROR_IO;
+                    mErrorCode = (media_status_t)inIdx;
+                    return mErrorCode;
                 } else if (inIdx >= 0) {
                     mStats->addInputTime();
                     onInputAvailable(mCodec, inIdx);
@@ -188,13 +202,18 @@
             } else if (!(outIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER ||
                          outIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)) {
                 ALOGE("AMediaCodec_dequeueOutputBuffer returned invalid index %zd\n", outIdx);
-                return AMEDIA_ERROR_IO;
+                mErrorCode = (media_status_t)outIdx;
+                return mErrorCode;
             }
         }
     } else {
         unique_lock<mutex> lock(mMutex);
         mDecoderDoneCondition.wait(lock, [this]() { return (mSawOutputEOS || mSignalledError); });
     }
+    if (mSignalledError) {
+        ALOGE("Received Error while Decoding");
+        return mErrorCode;
+    }
 
     if (codecName.empty()) {
         char *decName;
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.h b/media/tests/benchmark/src/native/decoder/Decoder.h
index 7630e7b..aeda080 100644
--- a/media/tests/benchmark/src/native/decoder/Decoder.h
+++ b/media/tests/benchmark/src/native/decoder/Decoder.h
@@ -38,6 +38,7 @@
           mSawInputEOS(false),
           mSawOutputEOS(false),
           mSignalledError(false),
+          mErrorCode(AMEDIA_OK),
           mInputBuffer(nullptr),
           mOutFp(nullptr) {
         mExtractor = new Extractor();
@@ -61,6 +62,8 @@
 
     void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) override;
 
+    void onError(AMediaCodec *mediaCodec, media_status_t err) override;
+
     void onOutputAvailable(AMediaCodec *codec, int32_t index,
                            AMediaCodecBufferInfo *bufferInfo) override;
 
@@ -82,6 +85,7 @@
     bool mSawInputEOS;
     bool mSawOutputEOS;
     bool mSignalledError;
+    media_status_t mErrorCode;
 
     int32_t mOffset;
     uint8_t *mInputBuffer;
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.cpp b/media/tests/benchmark/src/native/encoder/Encoder.cpp
index 5fdf9e3..a5605de 100644
--- a/media/tests/benchmark/src/native/encoder/Encoder.cpp
+++ b/media/tests/benchmark/src/native/encoder/Encoder.cpp
@@ -34,6 +34,7 @@
         size_t bufSize = 0;
         char *buf = (char *)AMediaCodec_getInputBuffer(mCodec, bufIdx, &bufSize);
         if (!buf) {
+            mErrorCode = AMEDIA_ERROR_IO;
             mSignalledError = true;
             mEncoderDoneCondition.notify_one();
             return;
@@ -41,6 +42,7 @@
 
         if (mInputBufferSize < mOffset) {
             ALOGE("Out of bound access of input buffer\n");
+            mErrorCode = AMEDIA_ERROR_MALFORMED;
             mSignalledError = true;
             mEncoderDoneCondition.notify_one();
             return;
@@ -51,6 +53,7 @@
         }
         if (bufSize < bytesRead) {
             ALOGE("bytes to read %zu bufSize %zu \n", bytesRead, bufSize);
+            mErrorCode = AMEDIA_ERROR_MALFORMED;
             mSignalledError = true;
             mEncoderDoneCondition.notify_one();
             return;
@@ -58,6 +61,7 @@
         if (bytesRead < mParams.frameSize && mNumInputFrame < mParams.numFrames - 1) {
             ALOGE("Partial frame at frameID %d bytesRead %zu frameSize %d total numFrames %d\n",
                   mNumInputFrame, bytesRead, mParams.frameSize, mParams.numFrames);
+            mErrorCode = AMEDIA_ERROR_MALFORMED;
             mSignalledError = true;
             mEncoderDoneCondition.notify_one();
             return;
@@ -66,6 +70,7 @@
         size_t bytesgcount = mEleStream->gcount();
         if (bytesgcount != bytesRead) {
             ALOGE("bytes to read %zu actual bytes read %zu \n", bytesRead, bytesgcount);
+            mErrorCode = AMEDIA_ERROR_MALFORMED;
             mSignalledError = true;
             mEncoderDoneCondition.notify_one();
             return;
@@ -89,9 +94,10 @@
         ALOGV("%s bytesRead : %zd presentationTimeUs : %" PRIu64 " mSawInputEOS : %s", __FUNCTION__,
               bytesRead, presentationTimeUs, mSawInputEOS ? "TRUE" : "FALSE");
 
-        int status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */, bytesRead,
-                                                  presentationTimeUs, flag);
+        media_status_t status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */,
+                                                             bytesRead, presentationTimeUs, flag);
         if (AMEDIA_OK != status) {
+            mErrorCode = status;
             mSignalledError = true;
             mEncoderDoneCondition.notify_one();
             return;
@@ -133,6 +139,16 @@
     }
 }
 
+void Encoder::onError(AMediaCodec *mediaCodec, media_status_t err) {
+    ALOGV("In %s", __func__);
+    if (mediaCodec == mCodec && mediaCodec) {
+        ALOGE("Received Error %d", err);
+        mErrorCode = err;
+        mSignalledError = true;
+        mEncoderDoneCondition.notify_one();
+    }
+}
+
 void Encoder::setupEncoder() {
     if (!mFormat) mFormat = AMediaFormat_new();
 }
@@ -235,7 +251,8 @@
                 ssize_t inIdx = AMediaCodec_dequeueInputBuffer(mCodec, kQueueDequeueTimeoutUs);
                 if (inIdx < 0 && inIdx != AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
                     ALOGE("AMediaCodec_dequeueInputBuffer returned invalid index %zd\n", inIdx);
-                    return AMEDIA_ERROR_IO;
+                    mErrorCode = (media_status_t)inIdx;
+                    return mErrorCode;
                 } else if (inIdx >= 0) {
                     mStats->addInputTime();
                     onInputAvailable(mCodec, inIdx);
@@ -255,13 +272,18 @@
             } else if (!(outIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER ||
                          outIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)) {
                 ALOGE("AMediaCodec_dequeueOutputBuffer returned invalid index %zd\n", outIdx);
-                return AMEDIA_ERROR_IO;
+                mErrorCode = (media_status_t)outIdx;
+                return mErrorCode;
             }
         }
     } else {
         unique_lock<mutex> lock(mMutex);
         mEncoderDoneCondition.wait(lock, [this]() { return (mSawOutputEOS || mSignalledError); });
     }
+    if (mSignalledError) {
+        ALOGE("Received Error while Encoding");
+        return mErrorCode;
+    }
 
     if (codecName.empty()) {
         char *encName;
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.h b/media/tests/benchmark/src/native/encoder/Encoder.h
index 75d9941..6059c4a 100644
--- a/media/tests/benchmark/src/native/encoder/Encoder.h
+++ b/media/tests/benchmark/src/native/encoder/Encoder.h
@@ -49,7 +49,8 @@
           mNumOutputFrame(0),
           mSawInputEOS(false),
           mSawOutputEOS(false),
-          mSignalledError(false) {}
+          mSignalledError(false),
+          mErrorCode(AMEDIA_OK) {}
 
     virtual ~Encoder() {}
 
@@ -65,6 +66,8 @@
 
     void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) override;
 
+    void onError(AMediaCodec *mediaCodec, media_status_t err) override;
+
     void onOutputAvailable(AMediaCodec *codec, int32_t index,
                            AMediaCodecBufferInfo *bufferInfo) override;
 
@@ -83,6 +86,7 @@
     bool mSawInputEOS;
     bool mSawOutputEOS;
     bool mSignalledError;
+    media_status_t mErrorCode;
 
     char *mMime;
     int32_t mOffset;
diff --git a/media/tests/benchmark/tests/Android.bp b/media/tests/benchmark/tests/Android.bp
index 24fd68c..128d055 100644
--- a/media/tests/benchmark/tests/Android.bp
+++ b/media/tests/benchmark/tests/Android.bp
@@ -75,3 +75,20 @@
         "libmediabenchmark_encoder",
     ],
 }
+
+cc_test {
+    name: "C2DecoderTest",
+    gtest: true,
+    defaults: [
+        "libmediabenchmark_codec2_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    srcs: ["C2DecoderTest.cpp"],
+
+    static_libs: [
+        "libmediabenchmark_extractor",
+        "libmediabenchmark_codec2_common",
+        "libmediabenchmark_codec2_decoder",
+    ],
+}
diff --git a/media/tests/benchmark/tests/C2DecoderTest.cpp b/media/tests/benchmark/tests/C2DecoderTest.cpp
new file mode 100644
index 0000000..3531d8a
--- /dev/null
+++ b/media/tests/benchmark/tests/C2DecoderTest.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "C2DecoderTest"
+
+#include <fstream>
+#include <iostream>
+#include <limits>
+
+#include "BenchmarkTestEnvironment.h"
+#include "C2Decoder.h"
+#include "Extractor.h"
+
+static BenchmarkTestEnvironment *gEnv = nullptr;
+
+class C2DecoderTest : public ::testing::TestWithParam<pair<string, string>> {
+  public:
+    C2DecoderTest() : mDecoder(nullptr), disableTest(false) { setupC2DecoderTest(); }
+
+    void setupC2DecoderTest();
+
+    vector<string> mCodecList;
+    C2Decoder *mDecoder;
+    bool disableTest;
+};
+
+void C2DecoderTest::setupC2DecoderTest() {
+    mDecoder = new C2Decoder();
+    if (!mDecoder) {
+        cout << "[   WARN   ] Test Skipped. C2Decoder creation failed\n";
+        disableTest = true;
+        return;
+    }
+    int32_t status = mDecoder->setupCodec2();
+    if (status != 0) {
+        cout << "[   WARN   ] Test Skipped. Codec2 setup failed \n";
+        disableTest = true;
+        return;
+    }
+    mCodecList = mDecoder->getSupportedComponentList(false /* isEncoder*/);
+    if (!mCodecList.size()) {
+        cout << "[   WARN   ] Test Skipped. Codec2 client didn't recognise any component \n";
+        disableTest = true;
+        return;
+    }
+}
+
+TEST_P(C2DecoderTest, Codec2Decode) {
+    if (disableTest) return;
+
+    ALOGV("Decode the samples given by extractor using codec2");
+    string inputFile = gEnv->getRes() + GetParam().first;
+    FILE *inputFp = fopen(inputFile.c_str(), "rb");
+    if (!inputFp) {
+        cout << "[   WARN   ] Test Skipped. Unable to open input file" << inputFile
+             << " for reading \n";
+        return;
+    }
+
+    Extractor *extractor = new Extractor();
+    if (!extractor) {
+        cout << "[   WARN   ] Test Skipped. Extractor creation failed \n";
+        return;
+    }
+
+    // Read file properties
+    fseek(inputFp, 0, SEEK_END);
+    size_t fileSize = ftell(inputFp);
+    fseek(inputFp, 0, SEEK_SET);
+    int32_t fd = fileno(inputFp);
+
+    if (fileSize > kMaxBufferSize) {
+        cout << "[   WARN   ] Test Skipped. Input file size is greater than the threshold memory "
+                "dedicated to the test \n";
+    }
+
+    int32_t trackCount = extractor->initExtractor(fd, fileSize);
+    if (trackCount <= 0) {
+        cout << "[   WARN   ] Test Skipped. initExtractor failed\n";
+        return;
+    }
+    for (int32_t curTrack = 0; curTrack < trackCount; curTrack++) {
+        int32_t status = extractor->setupTrackFormat(curTrack);
+        if (status != 0) {
+            cout << "[   WARN   ] Test Skipped. Track Format invalid \n";
+            return;
+        }
+
+        uint8_t *inputBuffer = (uint8_t *)malloc(fileSize);
+        if (!inputBuffer) {
+            cout << "[   WARN   ] Test Skipped. Insufficient memory \n";
+            return;
+        }
+
+        vector<AMediaCodecBufferInfo> frameInfo;
+        AMediaCodecBufferInfo info;
+        uint32_t inputBufferOffset = 0;
+        int32_t idx = 0;
+
+        // Get CSD data
+        while (1) {
+            void *csdBuffer = extractor->getCSDSample(info, idx);
+            if (!csdBuffer || !info.size) break;
+            // copy the meta data and buffer to be passed to decoder
+            if (inputBufferOffset + info.size > fileSize) {
+                cout << "[   WARN   ] Test Skipped. Memory allocated not sufficient\n";
+                free(inputBuffer);
+                return;
+            }
+            memcpy(inputBuffer + inputBufferOffset, csdBuffer, info.size);
+            frameInfo.push_back(info);
+            inputBufferOffset += info.size;
+            idx++;
+        }
+
+        // Get frame data
+        while (1) {
+            status = extractor->getFrameSample(info);
+            if (status || !info.size) break;
+            // copy the meta data and buffer to be passed to decoder
+            if (inputBufferOffset + info.size > fileSize) {
+                cout << "[   WARN   ] Test Skipped. Memory allocated not sufficient\n";
+                free(inputBuffer);
+                return;
+            }
+            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+            frameInfo.push_back(info);
+            inputBufferOffset += info.size;
+        }
+
+        AMediaFormat *format = extractor->getFormat();
+        // Decode the given input stream for all C2 codecs supported by device
+        for (string codecName : mCodecList) {
+            if (codecName.find(GetParam().second) != string::npos &&
+                codecName.find("secure") == string::npos) {
+                status = mDecoder->createCodec2Component(codecName, format);
+                if (status != 0) {
+                    cout << "[   WARN   ] Test Skipped. Create component failed for " << codecName
+                         << "\n";
+                    continue;
+                }
+
+                // Send the inputs to C2 Decoder and wait till all buffers are returned.
+                mDecoder->decodeFrames(inputBuffer, frameInfo);
+                mDecoder->waitOnInputConsumption();
+                if (!mDecoder->mEos) {
+                    cout << "[   WARN   ] Test Failed. Didn't receive EOS \n";
+                }
+                mDecoder->deInitCodec();
+                int64_t durationUs = extractor->getClipDuration();
+                cout << "codec: " << codecName << endl;
+                mDecoder->dumpStatistics(GetParam().first, durationUs);
+                mDecoder->resetDecoder();
+            }
+        }
+        free(inputBuffer);
+        fclose(inputFp);
+        extractor->deInitExtractor();
+        delete extractor;
+        delete mDecoder;
+    }
+}
+
+// TODO: (b/140549596)
+// Add wav files
+INSTANTIATE_TEST_SUITE_P(
+        AudioDecoderTest, C2DecoderTest,
+        ::testing::Values(
+                make_pair("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "aac"),
+                make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", "mp3"),
+                make_pair("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "amrnb"),
+                make_pair("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "amrnb"),
+                make_pair("bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", "vorbis"),
+                make_pair("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "flac"),
+                make_pair("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "opus")));
+
+INSTANTIATE_TEST_SUITE_P(
+        VideoDecoderTest, C2DecoderTest,
+        ::testing::Values(
+                make_pair("crowd_1920x1080_25fps_4000kbps_vp9.webm", "vp9"),
+                make_pair("crowd_1920x1080_25fps_4000kbps_vp8.webm", "vp8"),
+                make_pair("crowd_1920x1080_25fps_4000kbps_av1.webm", "av1"),
+                make_pair("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", "mpeg2"),
+                make_pair("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "mpeg4"),
+                make_pair("crowd_352x288_25fps_6000kbps_h263.3gp", "h263"),
+                make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", "avc"),
+                make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "hevc")));
+
+int main(int argc, char **argv) {
+    gEnv = new BenchmarkTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("C2 Decoder Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/tests/benchmark/tests/DecoderTest.cpp b/media/tests/benchmark/tests/DecoderTest.cpp
index 242178f..fa37435 100644
--- a/media/tests/benchmark/tests/DecoderTest.cpp
+++ b/media/tests/benchmark/tests/DecoderTest.cpp
@@ -93,7 +93,7 @@
         decoder->setupDecoder();
         status = decoder->decode(inputBuffer, frameInfo, codecName, asyncMode);
         if (status != AMEDIA_OK) {
-            cout << "[   WARN   ] Test Skipped. Decode returned error \n";
+            cout << "[   WARN   ] Test Failed. Decode returned error " << status << endl;
             free(inputBuffer);
             return;
         }
diff --git a/media/tests/benchmark/tests/EncoderTest.cpp b/media/tests/benchmark/tests/EncoderTest.cpp
index 9f42c64..c3963f8 100644
--- a/media/tests/benchmark/tests/EncoderTest.cpp
+++ b/media/tests/benchmark/tests/EncoderTest.cpp
@@ -143,7 +143,11 @@
         string codecName = get<1>(params);
         bool asyncMode = get<2>(params);
         status = encoder->encode(codecName, eleStream, eleSize, asyncMode, encParams, (char *)mime);
-        ASSERT_EQ(status, 0);
+        if (status != AMEDIA_OK) {
+            cout << "[   WARN   ] Test Failed. Encode returned error " << status << endl;
+            free(inputBuffer);
+            return;
+        }
         encoder->deInitCodec();
         cout << "codec : " << codecName << endl;
         string inputReference = get<0>(params);
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index c10adbb..b704573 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -732,9 +732,10 @@
 }
 
 Status CameraService::makeClient(const sp<CameraService>& cameraService,
-        const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
-        int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
-        int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
+        const sp<IInterface>& cameraCb, const String16& packageName,
+        const std::unique_ptr<String16>& featureId, const String8& cameraId, int api1CameraId,
+        int facing, int clientPid, uid_t clientUid, int servicePid, int halVersion,
+        int deviceVersion, apiLevel effectiveApiLevel,
         /*out*/sp<BasicClient>* client) {
 
     if (halVersion < 0 || halVersion == deviceVersion) {
@@ -744,7 +745,7 @@
           case CAMERA_DEVICE_API_VERSION_1_0:
             if (effectiveApiLevel == API_1) {  // Camera1 API route
                 sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
-                *client = new CameraClient(cameraService, tmp, packageName,
+                *client = new CameraClient(cameraService, tmp, packageName, featureId,
                         api1CameraId, facing, clientPid, clientUid,
                         getpid());
             } else { // Camera2 API route
@@ -762,15 +763,15 @@
           case CAMERA_DEVICE_API_VERSION_3_5:
             if (effectiveApiLevel == API_1) { // Camera1 API route
                 sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
-                *client = new Camera2Client(cameraService, tmp, packageName,
+                *client = new Camera2Client(cameraService, tmp, packageName, featureId,
                         cameraId, api1CameraId,
                         facing, clientPid, clientUid,
                         servicePid);
             } else { // Camera2 API route
                 sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
                         static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
-                *client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
-                        facing, clientPid, clientUid, servicePid);
+                *client = new CameraDeviceClient(cameraService, tmp, packageName, featureId,
+                        cameraId, facing, clientPid, clientUid, servicePid);
             }
             break;
           default:
@@ -787,7 +788,7 @@
             halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
             // Only support higher HAL version device opened as HAL1.0 device.
             sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
-            *client = new CameraClient(cameraService, tmp, packageName,
+            *client = new CameraClient(cameraService, tmp, packageName, featureId,
                     api1CameraId, facing, clientPid, clientUid,
                     servicePid);
         } else {
@@ -887,7 +888,7 @@
     if (!(ret = connectHelper<ICameraClient,Client>(
             sp<ICameraClient>{nullptr}, id, cameraId,
             static_cast<int>(CAMERA_HAL_API_VERSION_UNSPECIFIED),
-            internalPackageName, uid, USE_CALLING_PID,
+            internalPackageName, std::unique_ptr<String16>(), uid, USE_CALLING_PID,
             API_1, /*shimUpdateOnly*/ true, /*out*/ tmp)
             ).isOk()) {
         ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().string());
@@ -1400,8 +1401,8 @@
     String8 id = cameraIdIntToStr(api1CameraId);
     sp<Client> client = nullptr;
     ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId,
-            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, clientPid, API_1,
-            /*shimUpdateOnly*/ false, /*out*/client);
+            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, std::unique_ptr<String16>(),
+            clientUid, clientPid, API_1, /*shimUpdateOnly*/ false, /*out*/client);
 
     if(!ret.isOk()) {
         logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageName),
@@ -1427,8 +1428,8 @@
     Status ret = Status::ok();
     sp<Client> client = nullptr;
     ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId, halVersion,
-            clientPackageName, clientUid, USE_CALLING_PID, API_1, /*shimUpdateOnly*/ false,
-            /*out*/client);
+            clientPackageName, std::unique_ptr<String16>(), clientUid, USE_CALLING_PID, API_1,
+            /*shimUpdateOnly*/ false, /*out*/client);
 
     if(!ret.isOk()) {
         logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageName),
@@ -1502,6 +1503,7 @@
         const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
         const String16& cameraId,
         const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId,
         int clientUid,
         /*out*/
         sp<hardware::camera2::ICameraDeviceUser>* device) {
@@ -1511,6 +1513,7 @@
     String8 id = String8(cameraId);
     sp<CameraDeviceClient> client = nullptr;
     String16 clientPackageNameAdj = clientPackageName;
+
     if (hardware::IPCThreadState::self()->isServingCall()) {
         std::string vendorClient =
                 StringPrintf("vendor.client.pid<%d>", CameraThreadState::getCallingPid());
@@ -1518,7 +1521,7 @@
     }
     ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
             /*api1CameraId*/-1,
-            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageNameAdj,
+            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageNameAdj, clientFeatureId,
             clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, /*out*/client);
 
     if(!ret.isOk()) {
@@ -1533,8 +1536,9 @@
 
 template<class CALLBACK, class CLIENT>
 Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
-        int api1CameraId, int halVersion, const String16& clientPackageName, int clientUid,
-        int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly,
+        int api1CameraId, int halVersion, const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId, int clientUid, int clientPid,
+        apiLevel effectiveApiLevel, bool shimUpdateOnly,
         /*out*/sp<CLIENT>& device) {
     binder::Status ret = binder::Status::ok();
 
@@ -1617,7 +1621,7 @@
         }
 
         sp<BasicClient> tmp = nullptr;
-        if(!(ret = makeClient(this, cameraCb, clientPackageName,
+        if(!(ret = makeClient(this, cameraCb, clientPackageName, clientFeatureId,
                 cameraId, api1CameraId, facing,
                 clientPid, clientUid, getpid(),
                 halVersion, deviceVersion, effectiveApiLevel,
@@ -2459,13 +2463,14 @@
 CameraService::Client::Client(const sp<CameraService>& cameraService,
         const sp<ICameraClient>& cameraClient,
         const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId,
         const String8& cameraIdStr,
         int api1CameraId, int cameraFacing,
         int clientPid, uid_t clientUid,
         int servicePid) :
         CameraService::BasicClient(cameraService,
                 IInterface::asBinder(cameraClient),
-                clientPackageName,
+                clientPackageName, clientFeatureId,
                 cameraIdStr, cameraFacing,
                 clientPid, clientUid,
                 servicePid),
@@ -2495,17 +2500,24 @@
 
 CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
         const sp<IBinder>& remoteCallback,
-        const String16& clientPackageName,
+        const String16& clientPackageName, const std::unique_ptr<String16>& clientFeatureId,
         const String8& cameraIdStr, int cameraFacing,
         int clientPid, uid_t clientUid,
         int servicePid):
         mCameraIdStr(cameraIdStr), mCameraFacing(cameraFacing),
-        mClientPackageName(clientPackageName), mClientPid(clientPid), mClientUid(clientUid),
+        mClientPackageName(clientPackageName),
+        mClientPid(clientPid), mClientUid(clientUid),
         mServicePid(servicePid),
         mDisconnected(false),
         mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE),
         mRemoteBinder(remoteCallback)
 {
+    if (clientFeatureId) {
+        mClientFeatureId = std::unique_ptr<String16>(new String16(*clientFeatureId));
+    } else {
+        mClientFeatureId = std::unique_ptr<String16>();
+    }
+
     if (sCameraService == nullptr) {
         sCameraService = cameraService;
     }
@@ -2649,8 +2661,9 @@
         int32_t res;
         mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
                 mClientPackageName, mOpsCallback);
-        res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA,
-                mClientUid, mClientPackageName, /*startIfModeDefault*/ false);
+        res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA, mClientUid,
+                mClientPackageName, /*startIfModeDefault*/ false, mClientFeatureId,
+                String16("start camera ") + String16(mCameraIdStr));
 
         if (res == AppOpsManager::MODE_ERRORED) {
             ALOGI("Camera %s: Access for \"%s\" has been revoked",
@@ -2692,7 +2705,7 @@
         // Notify app ops that the camera is available again
         if (mAppOpsManager != nullptr) {
             mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
-                    mClientPackageName);
+                    mClientPackageName, mClientFeatureId);
             mOpsActive = false;
         }
         // This function is called when a client disconnects. This should
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 829a3ee..1f40fc3 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -134,7 +134,8 @@
 
     virtual binder::Status     connectDevice(
             const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb, const String16& cameraId,
-            const String16& clientPackageName, int32_t clientUid,
+            const String16& clientPackageName, const std::unique_ptr<String16>& clientFeatureId,
+            int32_t clientUid,
             /*out*/
             sp<hardware::camera2::ICameraDeviceUser>* device);
 
@@ -275,6 +276,7 @@
         BasicClient(const sp<CameraService>& cameraService,
                 const sp<IBinder>& remoteCallback,
                 const String16& clientPackageName,
+                const std::unique_ptr<String16>& clientFeatureId,
                 const String8& cameraIdStr,
                 int cameraFacing,
                 int clientPid,
@@ -294,6 +296,7 @@
         const String8                   mCameraIdStr;
         const int                       mCameraFacing;
         String16                        mClientPackageName;
+        std::unique_ptr<String16>       mClientFeatureId;
         pid_t                           mClientPid;
         const uid_t                     mClientUid;
         const pid_t                     mServicePid;
@@ -365,6 +368,7 @@
         Client(const sp<CameraService>& cameraService,
                 const sp<hardware::ICameraClient>& cameraClient,
                 const String16& clientPackageName,
+                const std::unique_ptr<String16>& clientFeatureId,
                 const String8& cameraIdStr,
                 int api1CameraId,
                 int cameraFacing,
@@ -688,8 +692,8 @@
     template<class CALLBACK, class CLIENT>
     binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
             int api1CameraId, int halVersion, const String16& clientPackageName,
-            int clientUid, int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly,
-            /*out*/sp<CLIENT>& device);
+            const std::unique_ptr<String16>& clientFeatureId, int clientUid, int clientPid,
+            apiLevel effectiveApiLevel, bool shimUpdateOnly, /*out*/sp<CLIENT>& device);
 
     // Lock guarding camera service state
     Mutex               mServiceLock;
@@ -985,9 +989,10 @@
     static String8 getFormattedCurrentTime();
 
     static binder::Status makeClient(const sp<CameraService>& cameraService,
-            const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
-            int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
-            int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
+            const sp<IInterface>& cameraCb, const String16& packageName,
+            const std::unique_ptr<String16>& featureId, const String8& cameraId, int api1CameraId,
+            int facing, int clientPid, uid_t clientUid, int servicePid, int halVersion,
+            int deviceVersion, apiLevel effectiveApiLevel,
             /*out*/sp<BasicClient>* client);
 
     status_t checkCameraAccess(const String16& opPackageName);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index c273881..5dbbc0b 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -50,13 +50,14 @@
 Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
         const sp<hardware::ICameraClient>& cameraClient,
         const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId,
         const String8& cameraDeviceId,
         int api1CameraId,
         int cameraFacing,
         int clientPid,
         uid_t clientUid,
         int servicePid):
-        Camera2ClientBase(cameraService, cameraClient, clientPackageName,
+        Camera2ClientBase(cameraService, cameraClient, clientPackageName, clientFeatureId,
                 cameraDeviceId, api1CameraId, cameraFacing,
                 clientPid, clientUid, servicePid),
         mParameters(api1CameraId, cameraFacing)
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index 8a17b17..8034ab4 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -93,6 +93,7 @@
     Camera2Client(const sp<CameraService>& cameraService,
             const sp<hardware::ICameraClient>& cameraClient,
             const String16& clientPackageName,
+            const std::unique_ptr<String16>& clientFeatureId,
             const String8& cameraDeviceId,
             int api1CameraId,
             int cameraFacing,
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 388a5dc..83da880 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -34,11 +34,11 @@
 
 CameraClient::CameraClient(const sp<CameraService>& cameraService,
         const sp<hardware::ICameraClient>& cameraClient,
-        const String16& clientPackageName,
+        const String16& clientPackageName, const std::unique_ptr<String16>& clientFeatureId,
         int cameraId, int cameraFacing,
         int clientPid, int clientUid,
         int servicePid):
-        Client(cameraService, cameraClient, clientPackageName,
+        Client(cameraService, cameraClient, clientPackageName, clientFeatureId,
                 String8::format("%d", cameraId), cameraId, cameraFacing, clientPid,
                 clientUid, servicePid)
 {
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index b26b612..501ad18 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -66,6 +66,7 @@
     CameraClient(const sp<CameraService>& cameraService,
             const sp<hardware::ICameraClient>& cameraClient,
             const String16& clientPackageName,
+            const std::unique_ptr<String16>& clientFeatureId,
             int cameraId,
             int cameraFacing,
             int clientPid,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 08fb153..27bebde 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -54,6 +54,7 @@
         const sp<CameraService>& cameraService,
         const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
         const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId,
         const String8& cameraId,
         int api1CameraId,
         int cameraFacing,
@@ -63,6 +64,7 @@
     BasicClient(cameraService,
             IInterface::asBinder(remoteCallback),
             clientPackageName,
+            clientFeatureId,
             cameraId,
             cameraFacing,
             clientPid,
@@ -78,12 +80,13 @@
 CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
         const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
         const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId,
         const String8& cameraId,
         int cameraFacing,
         int clientPid,
         uid_t clientUid,
         int servicePid) :
-    Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
+    Camera2ClientBase(cameraService, remoteCallback, clientPackageName, clientFeatureId,
                 cameraId, /*API1 camera ID*/ -1,
                 cameraFacing, clientPid, clientUid, servicePid),
     mInputStream(),
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index fe25010..7efc5ab 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -47,6 +47,7 @@
     CameraDeviceClientBase(const sp<CameraService>& cameraService,
             const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
             const String16& clientPackageName,
+            const std::unique_ptr<String16>& clientFeatureId,
             const String8& cameraId,
             int api1CameraId,
             int cameraFacing,
@@ -163,6 +164,7 @@
     CameraDeviceClient(const sp<CameraService>& cameraService,
             const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
             const String16& clientPackageName,
+            const std::unique_ptr<String16>& clientFeatureId,
             const String8& cameraId,
             int cameraFacing,
             int clientPid,
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 78feb3e..8792f9a 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -44,13 +44,14 @@
         const sp<CameraService>& cameraService,
         const sp<TCamCallbacks>& remoteCallback,
         const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId,
         const String8& cameraId,
         int api1CameraId,
         int cameraFacing,
         int clientPid,
         uid_t clientUid,
         int servicePid):
-        TClientBase(cameraService, remoteCallback, clientPackageName,
+        TClientBase(cameraService, remoteCallback, clientPackageName, clientFeatureId,
                 cameraId, api1CameraId, cameraFacing, clientPid, clientUid, servicePid),
         mSharedCameraCallbacks(remoteCallback),
         mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index 6693847..12cba0b 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -48,6 +48,7 @@
     Camera2ClientBase(const sp<CameraService>& cameraService,
                       const sp<TCamCallbacks>& remoteCallback,
                       const String16& clientPackageName,
+                      const std::unique_ptr<String16>& clientFeatureId,
                       const String8& cameraId,
                       int api1CameraId,
                       int cameraFacing,
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index 80df7db..5c6c518 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -139,7 +139,9 @@
     mOutputSlots.clear();
     mConsumerBufferCount.clear();
 
-    mConsumer->consumerDisconnect();
+    if (mConsumer.get() != nullptr) {
+        mConsumer->consumerDisconnect();
+    }
 
     if (mBuffers.size() > 0) {
         SP_LOGW("%zu buffers still being tracked", mBuffers.size());
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index 1daa035..97ba9c4 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -103,7 +103,7 @@
     }
     sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = hybridCallbacks;
     binder::Status serviceRet = mAidlICameraService->connectDevice(
-            callbacks, String16(cameraId.c_str()), String16(""),
+            callbacks, String16(cameraId.c_str()), String16(""), std::unique_ptr<String16>(),
             hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
     HStatus status = HStatus::NO_ERROR;
     if (!serviceRet.isOk()) {
diff --git a/services/mediaanalytics/TEST_MAPPING b/services/mediaanalytics/TEST_MAPPING
new file mode 100644
index 0000000..01e9e46
--- /dev/null
+++ b/services/mediaanalytics/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "presubmit": [
+    {
+       "name": "mediametrics_tests"
+    },
+    {
+       "name": "CtsNativeMediaMetricsTestCases"
+    }
+  ]
+}
diff --git a/services/mediaanalytics/tests/Android.bp b/services/mediaanalytics/tests/Android.bp
index 7bca1c4..a8a330c 100644
--- a/services/mediaanalytics/tests/Android.bp
+++ b/services/mediaanalytics/tests/Android.bp
@@ -1,5 +1,6 @@
 cc_test {
     name: "mediametrics_tests",
+    test_suites: ["device-tests"],
 
     cflags: [
         "-Wall",
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
index fa5bc4a..ad03e68 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/services/mediacodec/registrant/Android.bp
@@ -9,12 +9,11 @@
         "libmedia_headers",
     ],
 
+    defaults: [
+        "libcodec2-hidl-defaults",
+    ],
     shared_libs: [
-        "android.hardware.media.c2@1.0",
         "libbase",
-        "libcodec2_hidl@1.0",
-        "libcodec2_vndk",
-        "libutils",
     ],
 
     // Codecs
diff --git a/services/mediacodec/registrant/CodecServiceRegistrant.cpp b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
index 706ebee..58db801e 100644
--- a/services/mediacodec/registrant/CodecServiceRegistrant.cpp
+++ b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
@@ -20,11 +20,11 @@
 #include <android-base/logging.h>
 
 #include <C2PlatformSupport.h>
-#include <codec2/hidl/1.0/ComponentStore.h>
+#include <codec2/hidl/1.1/ComponentStore.h>
 #include <media/CodecServiceRegistrant.h>
 
 extern "C" void RegisterCodecServices() {
-    using namespace ::android::hardware::media::c2::V1_0;
+    using namespace ::android::hardware::media::c2::V1_1;
     LOG(INFO) << "Creating software Codec2 service...";
     android::sp<IComponentStore> store =
         new utils::ComponentStore(
diff --git a/services/mediadrm/Android.mk b/services/mediadrm/Android.mk
index 72d42ae..e8c82b1 100644
--- a/services/mediadrm/Android.mk
+++ b/services/mediadrm/Android.mk
@@ -17,7 +17,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    MediaDrmService.cpp \
     main_mediadrmserver.cpp
 
 LOCAL_HEADER_LIBRARIES:= \
diff --git a/services/mediadrm/MediaDrmService.cpp b/services/mediadrm/MediaDrmService.cpp
deleted file mode 100644
index 4715bc2..0000000
--- a/services/mediadrm/MediaDrmService.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-**
-** Copyright 2008, 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.
-*/
-
-// Proxy for media player implementations
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaDrmService"
-
-#include "MediaDrmService.h"
-#include <binder/IServiceManager.h>
-#include <utils/Log.h>
-
-#include <mediadrm/CryptoHal.h>
-#include <mediadrm/DrmHal.h>
-
-namespace android {
-
-void MediaDrmService::instantiate() {
-    defaultServiceManager()->addService(
-            String16("media.drm"), new MediaDrmService());
-}
-
-sp<IDrm> MediaDrmService::makeDrm() {
-    return new DrmHal;
-}
-
-} // namespace android
diff --git a/services/mediadrm/MediaDrmService.h b/services/mediadrm/MediaDrmService.h
deleted file mode 100644
index 87bdb53..0000000
--- a/services/mediadrm/MediaDrmService.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-**
-** Copyright 2008, 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 ANDROID_MEDIADRMSERVICE_H
-#define ANDROID_MEDIADRMSERVICE_H
-
-#include <arpa/inet.h>
-
-#include <utils/threads.h>
-
-#include <media/Metadata.h>
-#include <media/stagefright/foundation/ABase.h>
-#include <mediadrm/IMediaDrmService.h>
-
-namespace android {
-
-class MediaDrmService : public BnMediaDrmService
-{
-public:
-    static void instantiate();
-
-    // IMediaDrmService interface
-    virtual sp<IDrm> makeDrm();
-private:
-    MediaDrmService() {}
-    virtual ~MediaDrmService() {}
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_MEDIADRMSERVICE_H
diff --git a/services/mediadrm/main_mediadrmserver.cpp b/services/mediadrm/main_mediadrmserver.cpp
index b767b8c..5939701 100644
--- a/services/mediadrm/main_mediadrmserver.cpp
+++ b/services/mediadrm/main_mediadrmserver.cpp
@@ -15,29 +15,22 @@
 ** limitations under the License.
 */
 
-#define LOG_TAG "mediaserver"
+#define LOG_TAG "mediadrmserver"
 //#define LOG_NDEBUG 0
 
-#include <fcntl.h>
-#include <sys/prctl.h>
-#include <sys/wait.h>
+#include <signal.h>
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <cutils/properties.h>
-#include <utils/Log.h>
-#include "MediaDrmService.h"
 
 using namespace android;
 
+/*
+ * Keep mediadrmserver in case it is referenced by build files we don't know of.
+ * todo(robertshih): remove after verifying with `build_test.bash --dist --incremental`
+ */
 int main()
 {
     signal(SIGPIPE, SIG_IGN);
-
-    sp<ProcessState> proc(ProcessState::self());
-    sp<IServiceManager> sm = defaultServiceManager();
-    ALOGI("ServiceManager: %p", sm.get());
-    MediaDrmService::instantiate();
     ProcessState::self()->startThreadPool();
     IPCThreadState::self()->joinThreadPool();
 }