Merge "Pipe through featureId from context to Camera code"
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index b3fd7e9..26e147b 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -17,9 +17,6 @@
     srcs: [
         "DrmPluginPath.cpp",
         "DrmSessionManager.cpp",
-        "ICrypto.cpp",
-        "IDrm.cpp",
-        "IDrmClient.cpp",
         "IMediaDrmService.cpp",
         "SharedLibrary.cpp",
         "DrmHal.cpp",
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 40077f9..53a7446 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -479,12 +479,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;
 }
@@ -1567,11 +1561,6 @@
     return hResult.isOk() ? err : DEAD_OBJECT;
 }
 
-void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
-{
-    cleanup();
-}
-
 void DrmHal::reportFrameworkMetrics() const
 {
     std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("mediadrm"));
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index 5cfd7c0..3a76591 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -17,9 +17,16 @@
 //#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.1/ICryptoFactory.h>
+#include <android/hardware/drm/1.2/ICryptoFactory.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 +34,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 +58,56 @@
     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 MakeCryptoFactories(const uint8_t uuid[16], V &cryptoFactories) {
+    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)) {
+                    cryptoFactories.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::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,11 +115,28 @@
 }
 
 sp<IDrm> MakeDrm(status_t *pstatus) {
-    return MakeObject<IDrm, DrmHal>(pstatus);
+    return MakeObject<DrmHal>(pstatus);
 }
 
 sp<ICrypto> MakeCrypto(status_t *pstatus) {
-    return MakeObject<ICrypto, CryptoHal>(pstatus);
+    return MakeObject<CryptoHal>(pstatus);
+}
+
+std::vector<sp<::V1_0::ICryptoFactory>> MakeCryptoFactories(const uint8_t uuid[16]) {
+    std::vector<sp<::V1_0::ICryptoFactory>> cryptoFactories;
+    MakeCryptoFactories<::V1_0::ICryptoFactory>(uuid, cryptoFactories);
+    MakeCryptoFactories<::V1_1::ICryptoFactory>(uuid, cryptoFactories);
+    MakeCryptoFactories<::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
index 0b650f2..db67c23 100644
--- a/drm/libmediadrm/IMediaDrmService.cpp
+++ b/drm/libmediadrm/IMediaDrmService.cpp
@@ -29,11 +29,6 @@
 
 namespace android {
 
-enum {
-    MAKE_CRYPTO = IBinder::FIRST_CALL_TRANSACTION,
-    MAKE_DRM,
-};
-
 class BpMediaDrmService: public BpInterface<IMediaDrmService>
 {
 public:
@@ -42,20 +37,6 @@
     {
     }
 
-    virtual sp<ICrypto> makeCrypto() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaDrmService::getInterfaceDescriptor());
-        remote()->transact(MAKE_CRYPTO, data, &reply);
-        return interface_cast<ICrypto>(reply.readStrongBinder());
-    }
-
-    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");
@@ -66,18 +47,6 @@
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch (code) {
-        case MAKE_CRYPTO: {
-            CHECK_INTERFACE(IMediaDrmService, data, reply);
-            sp<ICrypto> crypto = makeCrypto();
-            reply->writeStrongBinder(IInterface::asBinder(crypto));
-            return NO_ERROR;
-        } break;
-        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);
     }
@@ -85,14 +54,4 @@
 
 // ----------------------------------------------------------------------------
 
-template<>
-sp<IDrm> IMediaDrmService::makeObject<IDrm>() {
-    return makeDrm();
-}
-
-template<>
-sp<ICrypto> IMediaDrmService::makeObject<ICrypto>() {
-    return makeCrypto();
-}
-
 } // 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 0431c93..97dd920 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHal.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -57,8 +57,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;
@@ -192,8 +191,6 @@
 
     Return<void> sendSessionLostState(const hidl_vec<uint8_t>& sessionId);
 
-    virtual void binderDied(const wp<IBinder> &the_late_who);
-
 private:
     static Mutex mLock;
 
diff --git a/drm/libmediadrm/include/mediadrm/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
index fbe80c6..db79008 100644
--- a/drm/libmediadrm/include/mediadrm/IDrm.h
+++ b/drm/libmediadrm/include/mediadrm/IDrm.h
@@ -29,8 +29,9 @@
 
 struct AString;
 
-struct IDrm : public IInterface {
-    DECLARE_META_INTERFACE(Drm);
+struct IDrm : public virtual RefBase {
+
+    virtual ~IDrm() {}
 
     virtual status_t initCheck() const = 0;
 
@@ -146,19 +147,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
index 7dcce94..715e0e4 100644
--- a/drm/libmediadrm/include/mediadrm/IMediaDrmService.h
+++ b/drm/libmediadrm/include/mediadrm/IMediaDrmService.h
@@ -25,7 +25,6 @@
 
 namespace android {
 
-struct ICrypto;
 struct IDrm;
 
 class IMediaDrmService: public IInterface
@@ -33,12 +32,6 @@
 public:
     DECLARE_META_INTERFACE(MediaDrmService);
 
-
-    virtual sp<ICrypto>         makeCrypto() = 0;
-    virtual sp<IDrm>            makeDrm() = 0;
-
-    template<typename I> sp<I>  makeObject();
-
 };
 
 // ----------------------------------------------------------------------------
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
index a5bc09b..ab6f645 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -17,9 +17,13 @@
 #ifndef ANDROID_DRMUTILS_H
 #define ANDROID_DRMUTILS_H
 
+#include <android/hardware/drm/1.0/ICryptoFactory.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 +81,11 @@
     obj.writeInt32(hasNewUsableKey);
 }
 
+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/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/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/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/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/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/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.h b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
index df16baf..15749f0 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>
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..e88d011
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
@@ -0,0 +1,166 @@
+/*
+ * 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 "C2Decoder.h"
+
+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 {
+                cout << "Wait for generating C2Work exceeded timeout" << 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) {
+                cout << "C2LinearBlock::map() failed : " << status << endl;
+                return status;
+            }
+
+            C2WriteView view = block->map().get();
+            if (view.error() != C2_OK) {
+                cout << "C2LinearBlock::map() failed : " << view.error() << 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..0e79d51
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/C2Decoder.h
@@ -0,0 +1,51 @@
+/*
+ * 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 <stdio.h>
+#include <algorithm>
+#include <fstream>
+
+#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/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/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index d54ab42..1355b1b 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -29,7 +29,9 @@
 #include <system/audio_effects/effect_visualizer.h>
 #include <audio_utils/channels.h>
 #include <audio_utils/primitives.h>
+#include <media/AudioContainers.h>
 #include <media/AudioEffect.h>
+#include <media/AudioDeviceTypeAddr.h>
 #include <media/audiohal/EffectHalInterface.h>
 #include <media/audiohal/EffectsFactoryHalInterface.h>
 #include <mediautils/ServiceUtilities.h>
@@ -1229,9 +1231,11 @@
     }
 }
 
-status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device)
+status_t AudioFlinger::EffectModule::sendSetAudioDevicesCommand(
+        const AudioDeviceTypeAddrVector &devices, uint32_t cmdCode)
 {
-    if (device == AUDIO_DEVICE_NONE) {
+    audio_devices_t deviceType = deviceTypesToBitMask(getAudioDeviceTypes(devices));
+    if (deviceType == AUDIO_DEVICE_NONE) {
         return NO_ERROR;
     }
 
@@ -1243,17 +1247,26 @@
     if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
         status_t cmdStatus;
         uint32_t size = sizeof(status_t);
-        uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE :
-                            EFFECT_CMD_SET_INPUT_DEVICE;
-        status = mEffectInterface->command(cmd,
+        // FIXME: use audio device types and addresses when the hal interface is ready.
+        status = mEffectInterface->command(cmdCode,
                                            sizeof(uint32_t),
-                                           &device,
+                                           &deviceType,
                                            &size,
                                            &cmdStatus);
     }
     return status;
 }
 
+status_t AudioFlinger::EffectModule::setDevices(const AudioDeviceTypeAddrVector &devices)
+{
+    return sendSetAudioDevicesCommand(devices, EFFECT_CMD_SET_DEVICE);
+}
+
+status_t AudioFlinger::EffectModule::setInputDevice(const AudioDeviceTypeAddr &device)
+{
+    return sendSetAudioDevicesCommand({device}, EFFECT_CMD_SET_INPUT_DEVICE);
+}
+
 status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
 {
     Mutex::Autolock _l(mLock);
@@ -2288,12 +2301,21 @@
     return mEffects.size();
 }
 
-// setDevice_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setDevice_l(audio_devices_t device)
+// setDevices_l() must be called with ThreadBase::mLock held
+void AudioFlinger::EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
 {
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
-        mEffects[i]->setDevice(device);
+        mEffects[i]->setDevices(devices);
+    }
+}
+
+// setInputDevice_l() must be called with ThreadBase::mLock held
+void AudioFlinger::EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
+{
+    size_t size = mEffects.size();
+    for (size_t i = 0; i < size; i++) {
+        mEffects[i]->setInputDevice(device);
     }
 }
 
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 220874d..dbf63c8 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -109,7 +109,8 @@
     const effect_descriptor_t& desc() const { return mDescriptor; }
     wp<EffectChain>&     chain() { return mChain; }
 
-    status_t         setDevice(audio_devices_t device);
+    status_t         setDevices(const AudioDeviceTypeAddrVector &devices);
+    status_t         setInputDevice(const AudioDeviceTypeAddr &device);
     status_t         setVolume(uint32_t *left, uint32_t *right, bool controller);
     status_t         setMode(audio_mode_t mode);
     status_t         setAudioSource(audio_source_t source);
@@ -158,6 +159,7 @@
     status_t start_l();
     status_t stop_l();
     status_t remove_effect_from_hal_l();
+    status_t sendSetAudioDevicesCommand(const AudioDeviceTypeAddrVector &devices, uint32_t cmdCode);
 
 mutable Mutex               mLock;      // mutex for process, commands and handles list protection
     wp<ThreadBase>      mThread;    // parent thread
@@ -350,7 +352,8 @@
     // FIXME use float to improve the dynamic range
     bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false);
     void resetVolume_l();
-    void setDevice_l(audio_devices_t device);
+    void setDevices_l(const AudioDeviceTypeAddrVector &devices);
+    void setInputDevice_l(const AudioDeviceTypeAddr &device);
     void setMode_l(audio_mode_t mode);
     void setAudioSource_l(audio_source_t source);
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index bd031ea..4be21b1 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1378,8 +1378,8 @@
             effectCreated = true;
 
             // FIXME: use vector of device and address when effect interface is ready.
-            effect->setDevice(deviceTypesToBitMask(outDeviceTypes()));
-            effect->setDevice(inDeviceType());
+            effect->setDevices(outDeviceTypeAddrs());
+            effect->setInputDevice(inDeviceTypeAddr());
             effect->setMode(mAudioFlinger->getMode());
             effect->setAudioSource(mAudioSource);
         }
@@ -1495,8 +1495,8 @@
         return status;
     }
 
-    effect->setDevice(deviceTypesToBitMask(outDeviceTypes()));
-    effect->setDevice(inDeviceType());
+    effect->setDevices(outDeviceTypeAddrs());
+    effect->setInputDevice(inDeviceTypeAddr());
     effect->setMode(mAudioFlinger->getMode());
     effect->setAudioSource(mAudioSource);
 
@@ -4070,7 +4070,7 @@
 #endif
 
     for (size_t i = 0; i < mEffectChains.size(); i++) {
-        mEffectChains[i]->setDevice_l(type);
+        mEffectChains[i]->setDevices_l(deviceTypeAddrs);
     }
 
     // mPatch.num_sinks is not set when the thread is created so that
@@ -8321,7 +8321,7 @@
     mInDeviceTypeAddr.mAddress = patch->sources[0].ext.device.address;
     audio_port_handle_t deviceId = patch->sources[0].id;
     for (size_t i = 0; i < mEffectChains.size(); i++) {
-        mEffectChains[i]->setDevice_l(mInDeviceTypeAddr.mType);
+        mEffectChains[i]->setInputDevice_l(inDeviceTypeAddr());
     }
 
     checkBtNrec_l();
@@ -8391,7 +8391,7 @@
     mOutDevices = outDevices;
     mOutDeviceTypeAddrs = deviceTypeAddrsFromDescriptors(mOutDevices);
     for (size_t i = 0; i < mEffectChains.size(); i++) {
-        mEffectChains[i]->setDevice_l(deviceTypesToBitMask(outDeviceTypes()));
+        mEffectChains[i]->setDevices_l(outDeviceTypeAddrs());
     }
 }
 
@@ -8922,7 +8922,11 @@
     }
 
     for (size_t i = 0; i < mEffectChains.size(); i++) {
-        mEffectChains[i]->setDevice_l(type);
+        if (isOutput()) {
+            mEffectChains[i]->setDevices_l(sinkDeviceTypeAddrs);
+        } else {
+            mEffectChains[i]->setInputDevice_l(sourceDeviceTypeAddr);
+        }
     }
 
     if (!isOutput()) {
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index a70b7ae..ef7eb6e 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -321,6 +321,13 @@
                     return isOutput() ? outDeviceTypes() : DeviceTypeSet({inDeviceType()});
                 }
 
+                const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const {
+                    return mOutDeviceTypeAddrs;
+                }
+                const AudioDeviceTypeAddr& inDeviceTypeAddr() const {
+                    return mInDeviceTypeAddr;
+                }
+
     virtual     bool        isOutput() const = 0;
 
     virtual     sp<StreamHalInterface> stream() const = 0;
diff --git a/services/mediadrm/MediaDrmService.cpp b/services/mediadrm/MediaDrmService.cpp
index 5afd079..3cee88b 100644
--- a/services/mediadrm/MediaDrmService.cpp
+++ b/services/mediadrm/MediaDrmService.cpp
@@ -34,12 +34,4 @@
             String16("media.drm"), new MediaDrmService());
 }
 
-sp<ICrypto> MediaDrmService::makeCrypto() {
-    return new CryptoHal;
-}
-
-sp<IDrm> MediaDrmService::makeDrm() {
-    return new DrmHal;
-}
-
 } // namespace android
diff --git a/services/mediadrm/MediaDrmService.h b/services/mediadrm/MediaDrmService.h
index 3607201..8a11e36 100644
--- a/services/mediadrm/MediaDrmService.h
+++ b/services/mediadrm/MediaDrmService.h
@@ -33,9 +33,6 @@
 public:
     static void instantiate();
 
-    // IMediaDrmService interface
-    virtual sp<ICrypto> makeCrypto();
-    virtual sp<IDrm> makeDrm();
 private:
     MediaDrmService() {}
     virtual ~MediaDrmService() {}