Reorganize drm hal modules

Previously the drm and crypto plugins were separate hals.
This implied a separation of implementation libraries which
causes problems for some drm schemes. The reorganization
combines the hals into a single interface under drm.

Tests: basic gtests passing

Change-Id: I5cde6ff9f60625a0219731c4dbfcaefbd9f27f88
related-to-bug: 32815560
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
index 87a0019..ac5b90a 100644
--- a/drm/1.0/default/Android.mk
+++ b/drm/1.0/default/Android.mk
@@ -14,6 +14,8 @@
 # limitations under the License.
 
 
+############# Build legacy drm service ############
+
 LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
@@ -24,16 +26,14 @@
   service.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
+  android.hardware.drm@1.0 \
+  android.hidl.memory@1.0 \
   libhidlbase \
   libhidltransport \
-  liblog \
-  libhwbinder \
-  libutils \
   libhardware \
-  android.hardware.drm.drm@1.0 \
-  android.hardware.drm.crypto@1.0 \
-  android.hidl.memory@1.0 \
-
+  libhwbinder \
+  liblog \
+  libutils \
 
 LOCAL_C_INCLUDES := \
   hardware/interfaces/drm
@@ -43,3 +43,37 @@
 LOCAL_32_BIT_ONLY := true
 
 include $(BUILD_EXECUTABLE)
+
+############# Build legacy drm impl library ############
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.drm@1.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    DrmFactory.cpp \
+    DrmPlugin.cpp \
+    CryptoFactory.cpp \
+    CryptoPlugin.cpp \
+    TypeConvert.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    android.hardware.drm@1.0 \
+    android.hidl.memory@1.0 \
+    libhidlbase \
+    libhidlmemory \
+    libhidltransport \
+    libhwbinder \
+    liblog \
+    libmediadrm \
+    libstagefright_foundation \
+    libutils \
+
+LOCAL_C_INCLUDES := \
+    frameworks/native/include \
+    frameworks/av/include
+
+# TODO: The legacy DRM plugins only support 32-bit. They need
+# to be migrated to 64-bit (b/18948909)
+LOCAL_32_BIT_ONLY := true
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/1.0/default/CryptoFactory.cpp b/drm/1.0/default/CryptoFactory.cpp
new file mode 100644
index 0000000..02084e7
--- /dev/null
+++ b/drm/1.0/default/CryptoFactory.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CryptoFactory.h"
+#include "CryptoPlugin.h"
+#include "TypeConvert.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    CryptoFactory::CryptoFactory() :
+        loader("/vendor/lib/mediadrm", "createCryptoFactory") {
+    }
+
+    // Methods from ::android::hardware::drm::V1_0::ICryptoFactory follow.
+    Return<bool> CryptoFactory::isCryptoSchemeSupported(
+            const hidl_array<uint8_t, 16>& uuid) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    Return<void> CryptoFactory::createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            const hidl_vec<uint8_t>& initData, createPlugin_cb _hidl_cb) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                android::CryptoPlugin *legacyPlugin = NULL;
+                status_t status = loader.getFactory(i)->createPlugin(uuid.data(),
+                        initData.data(), initData.size(), &legacyPlugin);
+                CryptoPlugin *newPlugin = NULL;
+                if (legacyPlugin == NULL) {
+                    ALOGE("Crypto legacy HAL: failed to create crypto plugin");
+                } else {
+                    newPlugin = new CryptoPlugin(legacyPlugin);
+                }
+                _hidl_cb(toStatus(status), newPlugin);
+                return Void();
+            }
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, NULL);
+        return Void();
+    }
+
+    ICryptoFactory* HIDL_FETCH_ICryptoFactory(const char* /* name */) {
+        return new CryptoFactory();
+    }
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/CryptoFactory.h b/drm/1.0/default/CryptoFactory.h
new file mode 100644
index 0000000..412b557
--- /dev/null
+++ b/drm/1.0/default/CryptoFactory.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_DRM_V1_0__CRYPTOFACTORY_H
+#define ANDROID_HARDWARE_DRM_V1_0__CRYPTOFACTORY_H
+
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <hidl/Status.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/PluginLoader.h>
+#include <media/SharedLibrary.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::V1_0::ICryptoFactory;
+using ::android::hardware::drm::V1_0::ICryptoPlugin;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct CryptoFactory : public ICryptoFactory {
+    CryptoFactory();
+    virtual ~CryptoFactory() {}
+
+    // Methods from ::android::hardware::drm::V1_0::ICryptoFactory follow.
+
+    Return<bool> isCryptoSchemeSupported(const hidl_array<uint8_t, 16>& uuid)
+            override;
+
+    Return<void> createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            const hidl_vec<uint8_t>& initData, createPlugin_cb _hidl_cb)
+            override;
+
+private:
+    android::PluginLoader<android::CryptoFactory> loader;
+
+    CryptoFactory(const CryptoFactory &) = delete;
+    void operator=(const CryptoFactory &) = delete;
+};
+
+extern "C" ICryptoFactory* HIDL_FETCH_ICryptoFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_V1_0__CRYPTOFACTORY_H
diff --git a/drm/1.0/default/CryptoPlugin.cpp b/drm/1.0/default/CryptoPlugin.cpp
new file mode 100644
index 0000000..073f030
--- /dev/null
+++ b/drm/1.0/default/CryptoPlugin.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CryptoPlugin.h"
+#include "TypeConvert.h"
+
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+#include <media/stagefright/foundation/AString.h>
+#include <utils/Log.h>
+
+using android::hardware::hidl_memory;
+using android::hidl::memory::V1_0::IMemory;
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    // Methods from ::android::hardware::drm::V1_0::ICryptoPlugin follow
+    Return<bool> CryptoPlugin::requiresSecureDecoderComponent(
+            const hidl_string& mime) {
+        return mLegacyPlugin->requiresSecureDecoderComponent(mime);
+    }
+
+    Return<void> CryptoPlugin::notifyResolution(uint32_t width,
+            uint32_t height) {
+        mLegacyPlugin->notifyResolution(width, height);
+        return Void();
+    }
+
+    Return<Status> CryptoPlugin::setMediaDrmSession(
+            const hidl_vec<uint8_t>& sessionId) {
+        return toStatus(mLegacyPlugin->setMediaDrmSession(toVector(sessionId)));
+    }
+
+    Return<void> CryptoPlugin::setSharedBufferBase(const hidl_memory& base) {
+        mSharedBufferBase = mapMemory(base);
+        return Void();
+    }
+
+    Return<void> CryptoPlugin::decrypt(bool secure,
+            const hidl_array<uint8_t, 16>& keyId,
+            const hidl_array<uint8_t, 16>& iv, Mode mode,
+            const Pattern& pattern, const hidl_vec<SubSample>& subSamples,
+            const SharedBuffer& source, uint64_t offset,
+            const DestinationBuffer& destination,
+            decrypt_cb _hidl_cb) {
+
+        android::CryptoPlugin::Mode legacyMode;
+        switch(mode) {
+        case Mode::UNENCRYPTED:
+            legacyMode = android::CryptoPlugin::kMode_Unencrypted;
+            break;
+        case Mode::AES_CTR:
+            legacyMode = android::CryptoPlugin::kMode_AES_CTR;
+            break;
+        case Mode::AES_CBC_CTS:
+            legacyMode = android::CryptoPlugin::kMode_AES_WV;
+            break;
+        case Mode::AES_CBC:
+            legacyMode = android::CryptoPlugin::kMode_AES_CBC;
+            break;
+        }
+        android::CryptoPlugin::Pattern legacyPattern;
+        legacyPattern.mEncryptBlocks = pattern.encryptBlocks;
+        legacyPattern.mSkipBlocks = pattern.skipBlocks;
+
+        android::CryptoPlugin::SubSample *legacySubSamples =
+            new android::CryptoPlugin::SubSample[subSamples.size()];
+
+        for (size_t i = 0; i < subSamples.size(); i++) {
+            legacySubSamples[i].mNumBytesOfClearData
+                = subSamples[i].numBytesOfClearData;
+            legacySubSamples[i].mNumBytesOfEncryptedData
+                = subSamples[i].numBytesOfEncryptedData;
+        }
+
+        AString detailMessage;
+
+        if (source.offset + offset + source.size > mSharedBufferBase->getSize()) {
+            _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
+            return Void();
+        }
+
+        uint8_t *base = static_cast<uint8_t *>
+                (static_cast<void *>(mSharedBufferBase->getPointer()));
+        void *srcPtr = static_cast<void *>(base + source.offset + offset);
+
+        void *destPtr = NULL;
+        if (destination.type == BufferType::SHARED_MEMORY) {
+            const SharedBuffer& destBuffer = destination.nonsecureMemory;
+            if (destBuffer.offset + destBuffer.size > mSharedBufferBase->getSize()) {
+                _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
+                return Void();
+            }
+            destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
+        } else if (destination.type == BufferType::NATIVE_HANDLE) {
+            native_handle_t *handle = const_cast<native_handle_t *>(
+                    destination.secureMemory.getNativeHandle());
+            destPtr = static_cast<void *>(handle);
+        }
+        ssize_t result = mLegacyPlugin->decrypt(secure, keyId.data(), iv.data(),
+                legacyMode, legacyPattern, srcPtr, legacySubSamples,
+                subSamples.size(), destPtr, &detailMessage);
+
+        delete[] legacySubSamples;
+
+        uint32_t status;
+        uint32_t bytesWritten;
+
+        if (result >= 0) {
+            status = android::OK;
+            bytesWritten = result;
+        } else {
+            status = -result;
+            bytesWritten = 0;
+        }
+
+        _hidl_cb(toStatus(status), bytesWritten, detailMessage.c_str());
+        return Void();
+    }
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/CryptoPlugin.h b/drm/1.0/default/CryptoPlugin.h
new file mode 100644
index 0000000..f805f09
--- /dev/null
+++ b/drm/1.0/default/CryptoPlugin.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
+#define ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
+
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <hidl/Status.h>
+#include <media/hardware/CryptoAPI.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::V1_0::DestinationBuffer;
+using ::android::hardware::drm::V1_0::ICryptoPlugin;
+using ::android::hardware::drm::V1_0::Mode;
+using ::android::hardware::drm::V1_0::Pattern;
+using ::android::hardware::drm::V1_0::SubSample;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
+struct CryptoPlugin : public ICryptoPlugin {
+    CryptoPlugin(android::CryptoPlugin *plugin) : mLegacyPlugin(plugin) {}
+
+    ~CryptoPlugin() {delete mLegacyPlugin;}
+
+    // Methods from ::android::hardware::drm::V1_0::ICryptoPlugin
+    // follow.
+
+    Return<bool> requiresSecureDecoderComponent(const hidl_string& mime)
+            override;
+
+    Return<void> notifyResolution(uint32_t width, uint32_t height) override;
+
+    Return<Status> setMediaDrmSession(const hidl_vec<uint8_t>& sessionId)
+            override;
+
+    Return<void> setSharedBufferBase(const ::android::hardware::hidl_memory& base)
+            override;
+
+    Return<void> decrypt(bool secure, const hidl_array<uint8_t, 16>& keyId,
+            const hidl_array<uint8_t, 16>& iv, Mode mode, const Pattern& pattern,
+            const hidl_vec<SubSample>& subSamples, const SharedBuffer& source,
+            uint64_t offset, const DestinationBuffer& destination,
+            decrypt_cb _hidl_cb) override;
+
+private:
+    android::CryptoPlugin *mLegacyPlugin;
+    sp<IMemory> mSharedBufferBase;
+
+    CryptoPlugin() = delete;
+    CryptoPlugin(const CryptoPlugin &) = delete;
+    void operator=(const CryptoPlugin &) = delete;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
diff --git a/drm/1.0/default/DrmFactory.cpp b/drm/1.0/default/DrmFactory.cpp
new file mode 100644
index 0000000..cba2c99
--- /dev/null
+++ b/drm/1.0/default/DrmFactory.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DrmFactory.h"
+#include "DrmPlugin.h"
+#include "TypeConvert.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    DrmFactory::DrmFactory() :
+        loader("/vendor/lib/mediadrm", "createDrmFactory") {
+    }
+
+    // Methods from ::android::hardware::drm::V1_0::IDrmFactory follow.
+    Return<bool> DrmFactory::isCryptoSchemeSupported (
+            const hidl_array<uint8_t, 16>& uuid) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    Return<bool> DrmFactory::isContentTypeSupported (
+            const hidl_string& mimeType) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isContentTypeSupported(String8(mimeType.c_str()))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    Return<void> DrmFactory::createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            createPlugin_cb _hidl_cb) {
+
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                android::DrmPlugin *legacyPlugin = NULL;
+                status_t status = loader.getFactory(i)->createDrmPlugin(
+                        uuid.data(), &legacyPlugin);
+                DrmPlugin *newPlugin = NULL;
+                if (legacyPlugin == NULL) {
+                    ALOGE("Drm legacy HAL: failed to create drm plugin");
+                } else {
+                    newPlugin = new DrmPlugin(legacyPlugin);
+                }
+                _hidl_cb(toStatus(status), newPlugin);
+                return Void();
+            }
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, NULL);
+        return Void();
+    }
+
+    IDrmFactory* HIDL_FETCH_IDrmFactory(const char* /* name */) {
+        return new DrmFactory();
+    }
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/DrmFactory.h b/drm/1.0/default/DrmFactory.h
new file mode 100644
index 0000000..78b7f6e
--- /dev/null
+++ b/drm/1.0/default/DrmFactory.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_DRM_V1_0__DRMFACTORY_H
+#define ANDROID_HARDWARE_DRM_V1_0__DRMFACTORY_H
+
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <hidl/Status.h>
+#include <media/drm/DrmAPI.h>
+#include <media/PluginLoader.h>
+#include <media/SharedLibrary.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::V1_0::IDrmFactory;
+using ::android::hardware::drm::V1_0::IDrmPlugin;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct DrmFactory : public IDrmFactory {
+    DrmFactory();
+    virtual ~DrmFactory() {}
+
+    // Methods from ::android::hardware::drm::V1_0::IDrmFactory follow.
+
+    Return<bool> isCryptoSchemeSupported(const hidl_array<uint8_t, 16>& uuid)
+            override;
+
+    Return<bool> isContentTypeSupported(const hidl_string &mimeType)
+            override;
+
+    Return<void> createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            createPlugin_cb _hidl_cb) override;
+
+private:
+    android::PluginLoader<android::DrmFactory> loader;
+
+    DrmFactory(const DrmFactory &) = delete;
+    void operator=(const DrmFactory &) = delete;
+};
+
+extern "C" IDrmFactory* HIDL_FETCH_IDrmFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_V1_0__DRMFACTORY_H
diff --git a/drm/1.0/default/DrmPlugin.cpp b/drm/1.0/default/DrmPlugin.cpp
new file mode 100644
index 0000000..9204fc5
--- /dev/null
+++ b/drm/1.0/default/DrmPlugin.cpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+#include "DrmPlugin.h"
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    // Methods from ::android::hardware::drm::V1_0::IDrmPlugin follow.
+
+    Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) {
+        Vector<uint8_t> legacySessionId;
+        status_t status = mLegacyPlugin->openSession(legacySessionId);
+        _hidl_cb(toStatus(status), toHidlVec(legacySessionId));
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) {
+        return toStatus(mLegacyPlugin->closeSession(toVector(sessionId)));
+    }
+
+    Return<void> DrmPlugin::getKeyRequest(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& initData, const hidl_string& mimeType,
+            KeyType keyType, const hidl_vec<KeyValue>& optionalParameters,
+            getKeyRequest_cb _hidl_cb) {
+
+        status_t status = android::OK;
+
+        android::DrmPlugin::KeyType legacyKeyType;
+        switch(keyType) {
+        case KeyType::OFFLINE:
+            legacyKeyType = android::DrmPlugin::kKeyType_Offline;
+            break;
+        case KeyType::STREAMING:
+            legacyKeyType = android::DrmPlugin::kKeyType_Streaming;
+            break;
+        case KeyType::RELEASE:
+            legacyKeyType = android::DrmPlugin::kKeyType_Release;
+            break;
+        default:
+            status = android::BAD_VALUE;
+            break;
+        }
+
+        Vector<uint8_t> legacyRequest;
+        KeyRequestType requestType = KeyRequestType::UNKNOWN;
+        String8 defaultUrl;
+
+        if (status == android::OK) {
+            android::KeyedVector<String8, String8> legacyOptionalParameters;
+            for (size_t i = 0; i < optionalParameters.size(); i++) {
+                legacyOptionalParameters.add(String8(optionalParameters[i].key),
+                        String8(optionalParameters[i].value));
+            }
+
+            android::DrmPlugin::KeyRequestType legacyRequestType =
+                    android::DrmPlugin::kKeyRequestType_Unknown;
+
+            status_t status = mLegacyPlugin->getKeyRequest(toVector(scope),
+                    toVector(initData), String8(mimeType), legacyKeyType,
+                    legacyOptionalParameters, legacyRequest, defaultUrl,
+                    &legacyRequestType);
+
+            switch(legacyRequestType) {
+            case android::DrmPlugin::kKeyRequestType_Initial:
+                requestType = KeyRequestType::INITIAL;
+                break;
+            case android::DrmPlugin::kKeyRequestType_Renewal:
+                requestType = KeyRequestType::RENEWAL;
+                break;
+            case android::DrmPlugin::kKeyRequestType_Release:
+                requestType = KeyRequestType::RELEASE;
+                break;
+            case android::DrmPlugin::kKeyRequestType_Unknown:
+                status = android::BAD_VALUE;
+                break;
+            }
+        }
+        _hidl_cb(toStatus(status), toHidlVec(legacyRequest), requestType,
+                 defaultUrl.string());
+        return Void();
+    }
+
+    Return<void> DrmPlugin::provideKeyResponse(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& response, provideKeyResponse_cb _hidl_cb) {
+
+        Vector<uint8_t> keySetId;
+        status_t status = mLegacyPlugin->provideKeyResponse(toVector(scope),
+                toVector(response), keySetId);
+        _hidl_cb(toStatus(status), toHidlVec(keySetId));
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::removeKeys(const hidl_vec<uint8_t>& sessionId) {
+        return toStatus(mLegacyPlugin->removeKeys(toVector(sessionId)));
+    }
+
+    Return<Status> DrmPlugin::restoreKeys(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keySetId) {
+        status_t legacyStatus = mLegacyPlugin->restoreKeys(toVector(sessionId),
+                toVector(keySetId));
+        return toStatus(legacyStatus);
+    }
+
+    Return<void> DrmPlugin::queryKeyStatus(const hidl_vec<uint8_t>& sessionId,
+            queryKeyStatus_cb _hidl_cb) {
+
+        android::KeyedVector<String8, String8> legacyInfoMap;
+        status_t status = mLegacyPlugin->queryKeyStatus(toVector(sessionId),
+                legacyInfoMap);
+
+        Vector<KeyValue> infoMapVec;
+        for (size_t i = 0; i < legacyInfoMap.size(); i++) {
+            KeyValue keyValuePair;
+            keyValuePair.key = String8(legacyInfoMap.keyAt(i));
+            keyValuePair.value = String8(legacyInfoMap.valueAt(i));
+            infoMapVec.push_back(keyValuePair);
+        }
+        _hidl_cb(toStatus(status), toHidlVec(infoMapVec));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getProvisionRequest(
+            const hidl_string& certificateType,
+            const hidl_string& certificateAuthority,
+            getProvisionRequest_cb _hidl_cb) {
+
+        Vector<uint8_t> legacyRequest;
+        String8 legacyDefaultUrl;
+        status_t status = mLegacyPlugin->getProvisionRequest(
+                String8(certificateType), String8(certificateAuthority),
+                legacyRequest, legacyDefaultUrl);
+
+        _hidl_cb(toStatus(status), toHidlVec(legacyRequest),
+                hidl_string(legacyDefaultUrl));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::provideProvisionResponse(
+            const hidl_vec<uint8_t>& response,
+            provideProvisionResponse_cb _hidl_cb) {
+
+        Vector<uint8_t> certificate;
+        Vector<uint8_t> wrappedKey;
+
+        status_t legacyStatus = mLegacyPlugin->provideProvisionResponse(
+                toVector(response), certificate, wrappedKey);
+
+        _hidl_cb(toStatus(legacyStatus), toHidlVec(certificate),
+                toHidlVec(wrappedKey));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) {
+        List<Vector<uint8_t> > legacySecureStops;
+        status_t status = mLegacyPlugin->getSecureStops(legacySecureStops);
+
+        Vector<SecureStop> secureStopsVec;
+        List<Vector<uint8_t> >::iterator iter = legacySecureStops.begin();
+
+        while (iter != legacySecureStops.end()) {
+            SecureStop secureStop;
+            secureStop.opaqueData = toHidlVec(*iter++);
+            secureStopsVec.push_back(secureStop);
+        }
+
+        _hidl_cb(toStatus(status), toHidlVec(secureStopsVec));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getSecureStop(const hidl_vec<uint8_t>& secureStopId,
+            getSecureStop_cb _hidl_cb) {
+
+        Vector<uint8_t> legacySecureStop;
+        status_t status = mLegacyPlugin->getSecureStop(toVector(secureStopId),
+                legacySecureStop);
+
+        SecureStop secureStop;
+        secureStop.opaqueData = toHidlVec(legacySecureStop);
+        _hidl_cb(toStatus(status), secureStop);
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::releaseAllSecureStops() {
+        return toStatus(mLegacyPlugin->releaseAllSecureStops());
+    }
+
+    Return<Status> DrmPlugin::releaseSecureStop(
+            const hidl_vec<uint8_t>& secureStopId) {
+        status_t legacyStatus =
+            mLegacyPlugin->releaseSecureStops(toVector(secureStopId));
+        return toStatus(legacyStatus);
+    }
+
+    Return<void> DrmPlugin::getPropertyString(const hidl_string& propertyName,
+            getPropertyString_cb _hidl_cb) {
+        String8 legacyValue;
+        status_t status = mLegacyPlugin->getPropertyString(
+                String8(propertyName), legacyValue);
+        _hidl_cb(toStatus(status), legacyValue.string());
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getPropertyByteArray(const hidl_string& propertyName,
+            getPropertyByteArray_cb _hidl_cb) {
+        Vector<uint8_t> legacyValue;
+        status_t status = mLegacyPlugin->getPropertyByteArray(
+                String8(propertyName), legacyValue);
+        _hidl_cb(toStatus(status), toHidlVec(legacyValue));
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::setPropertyString(const hidl_string& propertyName,
+            const hidl_string& value) {
+        status_t legacyStatus =
+            mLegacyPlugin->setPropertyString(String8(propertyName),
+                    String8(value));
+        return toStatus(legacyStatus);
+    }
+
+    Return<Status> DrmPlugin::setPropertyByteArray(
+            const hidl_string& propertyName, const hidl_vec<uint8_t>& value) {
+        status_t legacyStatus =
+            mLegacyPlugin->setPropertyByteArray(String8(propertyName),
+                    toVector(value));
+        return toStatus(legacyStatus);
+    }
+
+    Return<Status> DrmPlugin::setCipherAlgorithm(
+            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
+        status_t legacyStatus =
+            mLegacyPlugin->setCipherAlgorithm(toVector(sessionId),
+                String8(algorithm));
+        return toStatus(legacyStatus);
+    }
+
+    Return<Status> DrmPlugin::setMacAlgorithm(
+            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
+        status_t legacyStatus =
+            mLegacyPlugin->setMacAlgorithm(toVector(sessionId),
+                String8(algorithm));
+        return toStatus(legacyStatus);
+    }
+
+    Return<void> DrmPlugin::encrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, encrypt_cb _hidl_cb) {
+
+        Vector<uint8_t> legacyOutput;
+        status_t status = mLegacyPlugin->encrypt(toVector(sessionId),
+                toVector(keyId), toVector(input), toVector(iv), legacyOutput);
+        _hidl_cb(toStatus(status), toHidlVec(legacyOutput));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::decrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, decrypt_cb _hidl_cb) {
+
+        Vector<uint8_t> legacyOutput;
+        status_t status = mLegacyPlugin->decrypt(toVector(sessionId),
+                toVector(keyId), toVector(input), toVector(iv), legacyOutput);
+        _hidl_cb(toStatus(status), toHidlVec(legacyOutput));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sign(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            sign_cb _hidl_cb) {
+        Vector<uint8_t> legacySignature;
+        status_t status = mLegacyPlugin->sign(toVector(sessionId),
+                toVector(keyId), toVector(message), legacySignature);
+        _hidl_cb(toStatus(status), toHidlVec(legacySignature));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::verify(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& signature, verify_cb _hidl_cb) {
+
+        bool match;
+        status_t status = mLegacyPlugin->verify(toVector(sessionId),
+                toVector(keyId), toVector(message), toVector(signature),
+                match);
+        _hidl_cb(toStatus(status), match);
+        return Void();
+    }
+
+    Return<void> DrmPlugin::signRSA(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& wrappedKey, signRSA_cb _hidl_cb) {
+
+        Vector<uint8_t> legacySignature;
+        status_t status = mLegacyPlugin->signRSA(toVector(sessionId),
+                String8(algorithm), toVector(message), toVector(wrappedKey),
+                legacySignature);
+        _hidl_cb(toStatus(status), toHidlVec(legacySignature));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::setListener(const sp<IDrmPluginListener>& listener) {
+        mListener = listener;
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sendEvent(EventType eventType,
+            const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
+        mListener->sendEvent(eventType, sessionId, data);
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sendExpirationUpdate(
+            const hidl_vec<uint8_t>& sessionId, int64_t expiryTimeInMS) {
+        mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
+        mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
+        return Void();
+    }
+
+
+    // Methods from android::DrmPluginListener
+
+    void DrmPlugin::sendEvent(android::DrmPlugin::EventType legacyEventType,
+            int /*unused*/, Vector<uint8_t> const *sessionId,
+            Vector<uint8_t> const *data) {
+
+        EventType eventType;
+        bool sendEvent = true;
+        switch(legacyEventType) {
+        case android::DrmPlugin::kDrmPluginEventProvisionRequired:
+            eventType = EventType::PROVISION_REQUIRED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventKeyNeeded:
+            eventType = EventType::KEY_NEEDED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventKeyExpired:
+            eventType = EventType::KEY_EXPIRED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventVendorDefined:
+            eventType = EventType::VENDOR_DEFINED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventSessionReclaimed:
+            eventType = EventType::SESSION_RECLAIMED;
+            break;
+        default:
+            sendEvent = false;
+            break;
+        }
+        if (sendEvent) {
+            mListener->sendEvent(eventType, toHidlVec(*sessionId),
+                    toHidlVec(*data));
+        }
+    }
+
+    void DrmPlugin::sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+            int64_t expiryTimeInMS) {
+        mListener->sendExpirationUpdate(toHidlVec(*sessionId), expiryTimeInMS);
+    }
+
+    void DrmPlugin::sendKeysChange(Vector<uint8_t> const *sessionId,
+            Vector<android::DrmPlugin::KeyStatus> const *legacyKeyStatusList,
+            bool hasNewUsableKey) {
+
+        Vector<KeyStatus> keyStatusVec;
+        for (size_t i = 0; i < legacyKeyStatusList->size(); i++) {
+            const android::DrmPlugin::KeyStatus &legacyKeyStatus =
+                legacyKeyStatusList->itemAt(i);
+
+            KeyStatus keyStatus;
+
+            switch(legacyKeyStatus.mType) {
+            case android::DrmPlugin::kKeyStatusType_Usable:
+                keyStatus.type = KeyStatusType::USABLE;
+                break;
+            case android::DrmPlugin::kKeyStatusType_Expired:
+                keyStatus.type = KeyStatusType::EXPIRED;
+                break;
+            case android::DrmPlugin::kKeyStatusType_OutputNotAllowed:
+                keyStatus.type = KeyStatusType::OUTPUTNOTALLOWED;
+                break;
+            case android::DrmPlugin::kKeyStatusType_StatusPending:
+                keyStatus.type = KeyStatusType::STATUSPENDING;
+                break;
+            case android::DrmPlugin::kKeyStatusType_InternalError:
+            default:
+                keyStatus.type = KeyStatusType::INTERNALERROR;
+                break;
+            }
+
+            keyStatus.keyId = toHidlVec(legacyKeyStatus.mKeyId);
+            keyStatusVec.push_back(keyStatus);
+        }
+        mListener->sendKeysChange(toHidlVec(*sessionId),
+                toHidlVec(keyStatusVec), hasNewUsableKey);
+    }
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/DrmPlugin.h b/drm/1.0/default/DrmPlugin.h
new file mode 100644
index 0000000..dce6c0c
--- /dev/null
+++ b/drm/1.0/default/DrmPlugin.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_DRM_V1_0__DRMPLUGIN_H
+#define ANDROID_HARDWARE_DRM_V1_0__DRMPLUGIN_H
+
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.0/IDrmPluginListener.h>
+#include <hidl/Status.h>
+#include <media/drm/DrmAPI.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::V1_0::EventType;
+using ::android::hardware::drm::V1_0::IDrmPlugin;
+using ::android::hardware::drm::V1_0::IDrmPluginListener;
+using ::android::hardware::drm::V1_0::KeyRequestType;
+using ::android::hardware::drm::V1_0::KeyStatus;
+using ::android::hardware::drm::V1_0::KeyType;
+using ::android::hardware::drm::V1_0::KeyValue;
+using ::android::hardware::drm::V1_0::SecureStop;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct DrmPlugin : public IDrmPlugin, android::DrmPluginListener {
+
+    DrmPlugin(android::DrmPlugin *plugin) : mLegacyPlugin(plugin) {}
+    ~DrmPlugin() {delete mLegacyPlugin;}
+
+    // Methods from ::android::hardware::drm::V1_0::IDrmPlugin follow.
+
+    Return<void> openSession(openSession_cb _hidl_cb) override;
+
+    Return<Status> closeSession(const hidl_vec<uint8_t>& sessionId) override;
+
+    Return<void> getKeyRequest(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& initData, const hidl_string& mimeType,
+            KeyType keyType, const hidl_vec<KeyValue>& optionalParameters,
+            getKeyRequest_cb _hidl_cb) override;
+
+    Return<void> provideKeyResponse(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& response, provideKeyResponse_cb _hidl_cb)
+            override;
+
+    Return<Status> removeKeys(const hidl_vec<uint8_t>& sessionId) override;
+
+    Return<Status> restoreKeys(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keySetId) override;
+
+    Return<void> queryKeyStatus(const hidl_vec<uint8_t>& sessionId,
+            queryKeyStatus_cb _hidl_cb) override;
+
+    Return<void> getProvisionRequest(const hidl_string& certificateType,
+            const hidl_string& certificateAuthority,
+            getProvisionRequest_cb _hidl_cb) override;
+
+    Return<void> provideProvisionResponse(const hidl_vec<uint8_t>& response,
+            provideProvisionResponse_cb _hidl_cb) override;
+
+    Return<void> getSecureStops(getSecureStops_cb _hidl_cb) override;
+
+    Return<void> getSecureStop(const hidl_vec<uint8_t>& secureStopId,
+            getSecureStop_cb _hidl_cb) override;
+
+    Return<Status> releaseAllSecureStops() override;
+
+    Return<Status> releaseSecureStop(const hidl_vec<uint8_t>& secureStopId)
+            override;
+
+    Return<void> getPropertyString(const hidl_string& propertyName,
+            getPropertyString_cb _hidl_cb) override;
+
+    Return<void> getPropertyByteArray(const hidl_string& propertyName,
+            getPropertyByteArray_cb _hidl_cb) override;
+
+    Return<Status> setPropertyString(const hidl_string& propertyName,
+            const hidl_string& value) override;
+
+    Return<Status> setPropertyByteArray(const hidl_string& propertyName,
+            const hidl_vec<uint8_t>& value) override;
+
+    Return<Status> setCipherAlgorithm(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm) override;
+
+    Return<Status> setMacAlgorithm(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm) override;
+
+    Return<void> encrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, encrypt_cb _hidl_cb) override;
+
+    Return<void> decrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, decrypt_cb _hidl_cb) override;
+
+    Return<void> sign(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            sign_cb _hidl_cb) override;
+
+    Return<void> verify(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& signature, verify_cb _hidl_cb) override;
+
+    Return<void> signRSA(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& wrappedkey, signRSA_cb _hidl_cb) override;
+
+    Return<void> setListener(const sp<IDrmPluginListener>& listener) override;
+
+    Return<void> sendEvent(EventType eventType,
+            const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data)
+            override;
+
+    Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+            int64_t expiryTimeInMS) override;
+
+    Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey)
+            override;
+
+    // Methods from android::DrmPluginListener follow
+
+    virtual void sendEvent(android::DrmPlugin::EventType eventType, int extra,
+            Vector<uint8_t> const *sessionId, Vector<uint8_t> const *data);
+
+    virtual void sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+            int64_t expiryTimeInMS);
+
+    virtual void sendKeysChange(Vector<uint8_t> const *sessionId,
+            Vector<android::DrmPlugin::KeyStatus> const *keyStatusList,
+            bool hasNewUsableKey);
+
+private:
+    android::DrmPlugin *mLegacyPlugin;
+    sp<IDrmPluginListener> mListener;
+
+    DrmPlugin() = delete;
+    DrmPlugin(const DrmPlugin &) = delete;
+    void operator=(const DrmPlugin &) = delete;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_V1_0__DRMPLUGIN_H
diff --git a/drm/1.0/default/TypeConvert.cpp b/drm/1.0/default/TypeConvert.cpp
new file mode 100644
index 0000000..52cc503
--- /dev/null
+++ b/drm/1.0/default/TypeConvert.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+Status toStatus(status_t legacyStatus) {
+    Status status;
+    switch(legacyStatus) {
+    case android::OK:
+        status = Status::OK;
+        break;
+    case android::ERROR_DRM_NO_LICENSE:
+        status = Status::ERROR_DRM_NO_LICENSE;
+        break;
+    case android::ERROR_DRM_LICENSE_EXPIRED:
+        status = Status::ERROR_DRM_LICENSE_EXPIRED;
+        break;
+    case android::ERROR_DRM_SESSION_NOT_OPENED:
+        status = Status::ERROR_DRM_SESSION_NOT_OPENED;
+        break;
+    case android::ERROR_DRM_CANNOT_HANDLE:
+        status = Status::ERROR_DRM_CANNOT_HANDLE;
+        break;
+    case android::ERROR_DRM_TAMPER_DETECTED:
+        status = Status::ERROR_DRM_INVALID_STATE;
+        break;
+    case android::BAD_VALUE:
+        status = Status::BAD_VALUE;
+        break;
+    case android::ERROR_DRM_NOT_PROVISIONED:
+        status = Status::ERROR_DRM_NOT_PROVISIONED;
+        break;
+    case android::ERROR_DRM_RESOURCE_BUSY:
+        status = Status::ERROR_DRM_RESOURCE_BUSY;
+        break;
+    case android::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+        status = Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+        break;
+    case android::ERROR_DRM_DEVICE_REVOKED:
+        status = Status::ERROR_DRM_DEVICE_REVOKED;
+        break;
+    default:
+        ALOGW("Unable to convert legacy status: %d, defaulting to UNKNOWN",
+            legacyStatus);
+        status = Status::ERROR_DRM_UNKNOWN;
+        break;
+    }
+    return status;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/TypeConvert.h b/drm/1.0/default/TypeConvert.h
new file mode 100644
index 0000000..107fda5
--- /dev/null
+++ b/drm/1.0/default/TypeConvert.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_DRM_V1_0_TYPECONVERT
+#define ANDROID_HARDWARE_DRM_V1_0_TYPECONVERT
+
+#include <android/hardware/drm/1.0/types.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/Vector.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+
+template<typename T> const hidl_vec<T> toHidlVec(const Vector<T> &Vector) {
+    hidl_vec<T> vec;
+    vec.setToExternal(const_cast<T *>(Vector.array()), Vector.size());
+    return vec;
+}
+
+template<typename T> hidl_vec<T> toHidlVec(Vector<T> &Vector) {
+    hidl_vec<T> vec;
+    vec.setToExternal(Vector.editArray(), Vector.size());
+    return vec;
+}
+
+template<typename T> const Vector<T> toVector(const hidl_vec<T> &vec) {
+    Vector<T> vector;
+    vector.appendArray(vec.data(), vec.size());
+    return *const_cast<const Vector<T> *>(&vector);
+}
+
+template<typename T> Vector<T> toVector(hidl_vec<T> &vec) {
+    Vector<T> vector;
+    vector.appendArray(vec.data(), vec.size());
+    return vector;
+}
+
+template<typename T, size_t SIZE> const Vector<T> toVector(
+        const hidl_array<T, SIZE> &array) {
+    Vector<T> vector;
+    vector.appendArray(array.data(), array.size());
+    return vector;
+}
+
+template<typename T, size_t SIZE> Vector<T> toVector(
+        hidl_array<T, SIZE> &array) {
+    Vector<T> vector;
+    vector.appendArray(array.data(), array.size());
+    return vector;
+}
+
+Status toStatus(status_t legacyStatus);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif // ANDROID_HARDWARE_DRM_V1_0_TYPECONVERT
diff --git a/drm/1.0/default/service.cpp b/drm/1.0/default/service.cpp
index 3531e03..fba56ec 100644
--- a/drm/1.0/default/service.cpp
+++ b/drm/1.0/default/service.cpp
@@ -16,8 +16,8 @@
 
 #define LOG_TAG "android.hardware.drm@1.0-service"
 
-#include <crypto/1.0/default/CryptoFactory.h>
-#include <drm/1.0/default/DrmFactory.h>
+#include <1.0/default/CryptoFactory.h>
+#include <1.0/default/DrmFactory.h>
 
 #include <hidl/HidlTransportSupport.h>
 #include <hidl/LegacySupport.h>
@@ -26,8 +26,8 @@
 using android::hardware::joinRpcThreadpool;
 using android::hardware::registerPassthroughServiceImplementation;
 
-using android::hardware::drm::crypto::V1_0::ICryptoFactory;
-using android::hardware::drm::drm::V1_0::IDrmFactory;
+using android::hardware::drm::V1_0::ICryptoFactory;
+using android::hardware::drm::V1_0::IDrmFactory;
 
 int main() {
     ALOGD("android.hardware.drm@1.0-service starting...");