Merge "rename some files related to MediaPlayer2."
diff --git a/drm/mediadrm/plugins/clearkey/common/Android.bp b/drm/mediadrm/plugins/clearkey/common/Android.bp
new file mode 100644
index 0000000..2c674e1
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/Android.bp
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+    name: "libclearkeycommon",
+    vendor: true,
+
+    srcs: [
+        "ClearKeyUUID.cpp",
+        "Utils.cpp",
+    ],
+
+    cflags: ["-Wall", "-Werror"],
+
+    include_dirs: ["frameworks/av/include"],
+
+    shared_libs: ["libutils"],
+
+    export_include_dirs: ["include"],
+
+    sanitize: {
+        integer_overflow: true,
+    },
+}
+
diff --git a/drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp b/drm/mediadrm/plugins/clearkey/common/ClearKeyUUID.cpp
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp
rename to drm/mediadrm/plugins/clearkey/common/ClearKeyUUID.cpp
diff --git a/drm/mediadrm/plugins/clearkey/Utils.cpp b/drm/mediadrm/plugins/clearkey/common/Utils.cpp
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/Utils.cpp
rename to drm/mediadrm/plugins/clearkey/common/Utils.cpp
diff --git a/drm/mediadrm/plugins/clearkey/ClearKeyUUID.h b/drm/mediadrm/plugins/clearkey/common/include/ClearKeyUUID.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/ClearKeyUUID.h
rename to drm/mediadrm/plugins/clearkey/common/include/ClearKeyUUID.h
diff --git a/drm/mediadrm/plugins/clearkey/MimeType.h b/drm/mediadrm/plugins/clearkey/common/include/MimeType.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/MimeType.h
rename to drm/mediadrm/plugins/clearkey/common/include/MimeType.h
diff --git a/drm/mediadrm/plugins/clearkey/Utils.h b/drm/mediadrm/plugins/clearkey/common/include/Utils.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/Utils.h
rename to drm/mediadrm/plugins/clearkey/common/include/Utils.h
diff --git a/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.cpp b/drm/mediadrm/plugins/clearkey/default/AesCtrDecryptor.cpp
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/AesCtrDecryptor.cpp
rename to drm/mediadrm/plugins/clearkey/default/AesCtrDecryptor.cpp
diff --git a/drm/mediadrm/plugins/clearkey/Android.bp b/drm/mediadrm/plugins/clearkey/default/Android.bp
similarity index 90%
rename from drm/mediadrm/plugins/clearkey/Android.bp
rename to drm/mediadrm/plugins/clearkey/default/Android.bp
index 4b7a63c..7ba5708 100644
--- a/drm/mediadrm/plugins/clearkey/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/default/Android.bp
@@ -16,10 +16,10 @@
 
 cc_library_shared {
     name: "libdrmclearkeyplugin",
+    vendor: true,
 
     srcs: [
         "AesCtrDecryptor.cpp",
-        "ClearKeyUUID.cpp",
         "CreatePluginFactories.cpp",
         "CryptoFactory.cpp",
         "CryptoPlugin.cpp",
@@ -29,10 +29,8 @@
         "JsonWebKey.cpp",
         "Session.cpp",
         "SessionLibrary.cpp",
-        "Utils.cpp",
     ],
 
-    vendor: true,
     relative_install_path: "mediadrm",
 
     cflags: ["-Wall", "-Werror"],
@@ -44,16 +42,20 @@
         "libutils",
     ],
 
-    static_libs: ["libjsmn"],
+    static_libs: [
+        "libclearkeycommon",
+        "libjsmn"
+    ],
+
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    export_static_lib_headers: ["libjsmn"],
 
     include_dirs: [
         "frameworks/native/include",
         "frameworks/av/include",
     ],
 
-    export_include_dirs: ["."],
-    export_static_lib_headers: ["libjsmn"],
-
     sanitize: {
         integer_overflow: true,
     },
diff --git a/drm/mediadrm/plugins/clearkey/CreatePluginFactories.cpp b/drm/mediadrm/plugins/clearkey/default/CreatePluginFactories.cpp
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/CreatePluginFactories.cpp
rename to drm/mediadrm/plugins/clearkey/default/CreatePluginFactories.cpp
diff --git a/drm/mediadrm/plugins/clearkey/CryptoFactory.cpp b/drm/mediadrm/plugins/clearkey/default/CryptoFactory.cpp
similarity index 97%
rename from drm/mediadrm/plugins/clearkey/CryptoFactory.cpp
rename to drm/mediadrm/plugins/clearkey/default/CryptoFactory.cpp
index eeb64c3..f15f92b 100644
--- a/drm/mediadrm/plugins/clearkey/CryptoFactory.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/CryptoFactory.cpp
@@ -15,7 +15,7 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "ClearKeyCryptoPlugin"
+#define LOG_TAG "ClearKeyCryptoFactory"
 #include <utils/Log.h>
 
 #include <utils/Errors.h>
diff --git a/drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/default/CryptoPlugin.cpp
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp
rename to drm/mediadrm/plugins/clearkey/default/CryptoPlugin.cpp
diff --git a/drm/mediadrm/plugins/clearkey/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/default/DrmFactory.cpp
similarity index 97%
rename from drm/mediadrm/plugins/clearkey/DrmFactory.cpp
rename to drm/mediadrm/plugins/clearkey/default/DrmFactory.cpp
index c83321b..8301e40 100644
--- a/drm/mediadrm/plugins/clearkey/DrmFactory.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/DrmFactory.cpp
@@ -15,7 +15,7 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "ClearKeyCryptoPlugin"
+#define LOG_TAG "ClearKeyDrmFactory"
 #include <utils/Log.h>
 
 #include <utils/Errors.h>
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp
similarity index 99%
rename from drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
rename to drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp
index 944002d..1b8b8c1 100644
--- a/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp
@@ -15,7 +15,7 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "ClearKeyCryptoPlugin"
+#define LOG_TAG "ClearKeyDrmPlugin"
 #include <utils/Log.h>
 
 #include <media/stagefright/MediaErrors.h>
diff --git a/drm/mediadrm/plugins/clearkey/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/InitDataParser.cpp
rename to drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp
diff --git a/drm/mediadrm/plugins/clearkey/JsonWebKey.cpp b/drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/JsonWebKey.cpp
rename to drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp
diff --git a/drm/mediadrm/plugins/clearkey/Session.cpp b/drm/mediadrm/plugins/clearkey/default/Session.cpp
similarity index 98%
rename from drm/mediadrm/plugins/clearkey/Session.cpp
rename to drm/mediadrm/plugins/clearkey/default/Session.cpp
index d210f5e..b3ceaec 100644
--- a/drm/mediadrm/plugins/clearkey/Session.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/Session.cpp
@@ -15,7 +15,7 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "ClearKeyCryptoPlugin"
+#define LOG_TAG "ClearKeySession"
 #include <utils/Log.h>
 
 #include <media/stagefright/MediaErrors.h>
diff --git a/drm/mediadrm/plugins/clearkey/SessionLibrary.cpp b/drm/mediadrm/plugins/clearkey/default/SessionLibrary.cpp
similarity index 97%
rename from drm/mediadrm/plugins/clearkey/SessionLibrary.cpp
rename to drm/mediadrm/plugins/clearkey/default/SessionLibrary.cpp
index 0419f97..529230e 100644
--- a/drm/mediadrm/plugins/clearkey/SessionLibrary.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/SessionLibrary.cpp
@@ -15,7 +15,7 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "ClearKeyCryptoPlugin"
+#define LOG_TAG "ClearKeySessionLibrary"
 #include <utils/Log.h>
 
 #include <utils/String8.h>
diff --git a/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.h b/drm/mediadrm/plugins/clearkey/default/include/AesCtrDecryptor.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/AesCtrDecryptor.h
rename to drm/mediadrm/plugins/clearkey/default/include/AesCtrDecryptor.h
diff --git a/drm/mediadrm/plugins/clearkey/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/default/include/ClearKeyDrmProperties.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/ClearKeyDrmProperties.h
rename to drm/mediadrm/plugins/clearkey/default/include/ClearKeyDrmProperties.h
diff --git a/drm/mediadrm/plugins/clearkey/ClearKeyTypes.h b/drm/mediadrm/plugins/clearkey/default/include/ClearKeyTypes.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/ClearKeyTypes.h
rename to drm/mediadrm/plugins/clearkey/default/include/ClearKeyTypes.h
diff --git a/drm/mediadrm/plugins/clearkey/CreatePluginFactories.h b/drm/mediadrm/plugins/clearkey/default/include/CreatePluginFactories.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/CreatePluginFactories.h
rename to drm/mediadrm/plugins/clearkey/default/include/CreatePluginFactories.h
diff --git a/drm/mediadrm/plugins/clearkey/CryptoFactory.h b/drm/mediadrm/plugins/clearkey/default/include/CryptoFactory.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/CryptoFactory.h
rename to drm/mediadrm/plugins/clearkey/default/include/CryptoFactory.h
diff --git a/drm/mediadrm/plugins/clearkey/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/default/include/CryptoPlugin.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/CryptoPlugin.h
rename to drm/mediadrm/plugins/clearkey/default/include/CryptoPlugin.h
diff --git a/drm/mediadrm/plugins/clearkey/DrmFactory.h b/drm/mediadrm/plugins/clearkey/default/include/DrmFactory.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/DrmFactory.h
rename to drm/mediadrm/plugins/clearkey/default/include/DrmFactory.h
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/default/include/DrmPlugin.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/DrmPlugin.h
rename to drm/mediadrm/plugins/clearkey/default/include/DrmPlugin.h
diff --git a/drm/mediadrm/plugins/clearkey/InitDataParser.h b/drm/mediadrm/plugins/clearkey/default/include/InitDataParser.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/InitDataParser.h
rename to drm/mediadrm/plugins/clearkey/default/include/InitDataParser.h
diff --git a/drm/mediadrm/plugins/clearkey/JsonWebKey.h b/drm/mediadrm/plugins/clearkey/default/include/JsonWebKey.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/JsonWebKey.h
rename to drm/mediadrm/plugins/clearkey/default/include/JsonWebKey.h
diff --git a/drm/mediadrm/plugins/clearkey/Session.h b/drm/mediadrm/plugins/clearkey/default/include/Session.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/Session.h
rename to drm/mediadrm/plugins/clearkey/default/include/Session.h
diff --git a/drm/mediadrm/plugins/clearkey/SessionLibrary.h b/drm/mediadrm/plugins/clearkey/default/include/SessionLibrary.h
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/SessionLibrary.h
rename to drm/mediadrm/plugins/clearkey/default/include/SessionLibrary.h
diff --git a/drm/mediadrm/plugins/clearkey/tests/AesCtrDecryptorUnittest.cpp b/drm/mediadrm/plugins/clearkey/default/tests/AesCtrDecryptorUnittest.cpp
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/tests/AesCtrDecryptorUnittest.cpp
rename to drm/mediadrm/plugins/clearkey/default/tests/AesCtrDecryptorUnittest.cpp
diff --git a/drm/mediadrm/plugins/clearkey/tests/Android.bp b/drm/mediadrm/plugins/clearkey/default/tests/Android.bp
similarity index 96%
rename from drm/mediadrm/plugins/clearkey/tests/Android.bp
rename to drm/mediadrm/plugins/clearkey/default/tests/Android.bp
index ea17bbb..4419865 100644
--- a/drm/mediadrm/plugins/clearkey/tests/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/default/tests/Android.bp
@@ -29,6 +29,8 @@
         "JsonWebKeyUnittest.cpp",
     ],
 
+    static_libs: ["libclearkeycommon"],
+
     shared_libs: [
         "libcrypto",
         "libdrmclearkeyplugin",
diff --git a/drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp b/drm/mediadrm/plugins/clearkey/default/tests/InitDataParserUnittest.cpp
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp
rename to drm/mediadrm/plugins/clearkey/default/tests/InitDataParserUnittest.cpp
diff --git a/drm/mediadrm/plugins/clearkey/tests/JsonWebKeyUnittest.cpp b/drm/mediadrm/plugins/clearkey/default/tests/JsonWebKeyUnittest.cpp
similarity index 100%
rename from drm/mediadrm/plugins/clearkey/tests/JsonWebKeyUnittest.cpp
rename to drm/mediadrm/plugins/clearkey/default/tests/JsonWebKeyUnittest.cpp
diff --git a/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp b/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp
new file mode 100644
index 0000000..2fce0790
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "hidl_ClearkeyDecryptor"
+#include <utils/Log.h>
+
+#include <openssl/aes.h>
+
+#include "AesCtrDecryptor.h"
+#include "ClearKeyTypes.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::drm::V1_0::SubSample;
+using ::android::hardware::drm::V1_0::Status;
+
+static const size_t kBlockBitCount = kBlockSize * 8;
+
+Status AesCtrDecryptor::decrypt(
+        const std::vector<uint8_t>& key,
+        const Iv iv, const uint8_t* source,
+        uint8_t* destination,
+        const std::vector<SubSample> subSamples,
+        size_t numSubSamples,
+        size_t* bytesDecryptedOut) {
+    uint32_t blockOffset = 0;
+    uint8_t previousEncryptedCounter[kBlockSize];
+    memset(previousEncryptedCounter, 0, kBlockSize);
+
+    if (key.size() != kBlockSize || (sizeof(Iv) / sizeof(uint8_t)) != kBlockSize) {
+        android_errorWriteLog(0x534e4554, "63982768");
+        return Status::ERROR_DRM_DECRYPT;
+    }
+
+    size_t offset = 0;
+    AES_KEY opensslKey;
+    AES_set_encrypt_key(key.data(), kBlockBitCount, &opensslKey);
+    Iv opensslIv;
+    memcpy(opensslIv, iv, sizeof(opensslIv));
+
+    for (size_t i = 0; i < numSubSamples; ++i) {
+        const SubSample& subSample = subSamples[i];
+
+        if (subSample.numBytesOfClearData > 0) {
+            memcpy(destination + offset, source + offset,
+                    subSample.numBytesOfClearData);
+            offset += subSample.numBytesOfClearData;
+        }
+
+        if (subSample.numBytesOfEncryptedData > 0) {
+            AES_ctr128_encrypt(source + offset, destination + offset,
+                    subSample.numBytesOfEncryptedData, &opensslKey,
+                    opensslIv, previousEncryptedCounter,
+                    &blockOffset);
+            offset += subSample.numBytesOfEncryptedData;
+        }
+    }
+
+    *bytesDecryptedOut = offset;
+    return Status::OK;
+}
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
diff --git a/drm/mediadrm/plugins/clearkey/Android.bp b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
similarity index 66%
copy from drm/mediadrm/plugins/clearkey/Android.bp
copy to drm/mediadrm/plugins/clearkey/hidl/Android.bp
index 4b7a63c..341d4f6 100644
--- a/drm/mediadrm/plugins/clearkey/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
@@ -1,5 +1,5 @@
 //
-// Copyright (C) 2014 The Android Open Source Project
+// Copyright (C) 2018 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -14,12 +14,14 @@
 // limitations under the License.
 //
 
-cc_library_shared {
-    name: "libdrmclearkeyplugin",
+cc_binary {
+    name: "android.hardware.drm@1.1-service.clearkey",
+    vendor: true,
 
     srcs: [
         "AesCtrDecryptor.cpp",
-        "ClearKeyUUID.cpp",
+        "Base64.cpp",
+        "Buffer.cpp",
         "CreatePluginFactories.cpp",
         "CryptoFactory.cpp",
         "CryptoPlugin.cpp",
@@ -29,29 +31,34 @@
         "JsonWebKey.cpp",
         "Session.cpp",
         "SessionLibrary.cpp",
-        "Utils.cpp",
+        "service.cpp",
     ],
 
-    vendor: true,
-    relative_install_path: "mediadrm",
+    relative_install_path: "hw",
 
     cflags: ["-Wall", "-Werror"],
+    init_rc: ["android.hardware.drm@1.1-service.clearkey.rc"],
 
     shared_libs: [
+        "android.hardware.drm@1.0",
+        "android.hardware.drm@1.1",
+        "libbase",
+        "libbinder",
         "libcrypto",
+        "libhidlbase",
+        "libhidlmemory",
+        "libhidltransport",
         "liblog",
-        "libstagefright_foundation",
         "libutils",
     ],
 
-    static_libs: ["libjsmn"],
-
-    include_dirs: [
-        "frameworks/native/include",
-        "frameworks/av/include",
+    static_libs: [
+        "libclearkeycommon",
+        "libjsmn",
     ],
 
-    export_include_dirs: ["."],
+    local_include_dirs: ["include"],
+
     export_static_lib_headers: ["libjsmn"],
 
     sanitize: {
@@ -59,7 +66,3 @@
     },
 }
 
-//########################################################################
-// Build unit tests
-
-subdirs = ["tests"]
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp b/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp
new file mode 100644
index 0000000..c2ed751
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Base64.h"
+
+#include <string>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+sp<Buffer> decodeBase64(const std::string &s) {
+    size_t n = s.size();
+
+    if ((n % 4) != 0) {
+        return nullptr;
+    }
+
+    size_t padding = 0;
+    if (n >= 1 && s.c_str()[n - 1] == '=') {
+        padding = 1;
+
+        if (n >= 2 && s.c_str()[n - 2] == '=') {
+            padding = 2;
+
+            if (n >= 3 && s.c_str()[n - 3] == '=') {
+                padding = 3;
+            }
+        }
+    }
+
+    // We divide first to avoid overflow. It's OK to do this because we
+    // already made sure that n % 4 == 0.
+    size_t outLen = (n / 4) * 3 - padding;
+
+    sp<Buffer> buffer = new Buffer(outLen);
+    uint8_t *out = buffer->data();
+    if (out == nullptr || buffer->size() < outLen) {
+        return nullptr;
+    }
+
+    size_t j = 0;
+    uint32_t accum = 0;
+    for (size_t i = 0; i < n; ++i) {
+        char c = s.c_str()[i];
+        unsigned value;
+        if (c >= 'A' && c <= 'Z') {
+            value = c - 'A';
+        } else if (c >= 'a' && c <= 'z') {
+            value = 26 + c - 'a';
+        } else if (c >= '0' && c <= '9') {
+            value = 52 + c - '0';
+        } else if (c == '+' || c == '-') {
+            value = 62;
+        } else if (c == '/' || c == '_') {
+            value = 63;
+        } else if (c != '=') {
+            return nullptr;
+        } else {
+            if (i < n - padding) {
+                return nullptr;
+            }
+
+            value = 0;
+        }
+
+        accum = (accum << 6) | value;
+
+        if (((i + 1) % 4) == 0) {
+            if (j < outLen) { out[j++] = (accum >> 16); }
+            if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
+            if (j < outLen) { out[j++] = accum & 0xff; }
+
+            accum = 0;
+        }
+    }
+
+    return buffer;
+}
+
+static char encode6Bit(unsigned x) {
+    if (x <= 25) {
+        return 'A' + x;
+    } else if (x <= 51) {
+        return 'a' + x - 26;
+    } else if (x <= 61) {
+        return '0' + x - 52;
+    } else if (x == 62) {
+        return '+';
+    } else {
+        return '/';
+    }
+}
+
+void encodeBase64(const void *_data, size_t size, std::string *out) {
+    out->clear();
+
+    const uint8_t *data = (const uint8_t *)_data;
+
+    size_t i;
+    for (i = 0; i < (size / 3) * 3; i += 3) {
+        uint8_t x1 = data[i];
+        uint8_t x2 = data[i + 1];
+        uint8_t x3 = data[i + 2];
+
+        out->push_back(encode6Bit(x1 >> 2));
+        out->push_back(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
+        out->push_back(encode6Bit((x2 << 2 | x3 >> 6) & 0x3f));
+        out->push_back(encode6Bit(x3 & 0x3f));
+    }
+    switch (size % 3) {
+        case 0:
+            break;
+        case 2:
+        {
+            uint8_t x1 = data[i];
+            uint8_t x2 = data[i + 1];
+            out->push_back(encode6Bit(x1 >> 2));
+            out->push_back(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
+            out->push_back(encode6Bit((x2 << 2) & 0x3f));
+            out->push_back('=');
+            break;
+        }
+        default:
+        {
+            uint8_t x1 = data[i];
+            out->push_back(encode6Bit(x1 >> 2));
+            out->push_back(encode6Bit((x1 << 4) & 0x3f));
+            out->append("==");
+            break;
+        }
+    }
+}
+
+void encodeBase64Url(const void *_data, size_t size, std::string *out) {
+    encodeBase64(_data, size, out);
+
+    if ((std::string::npos != out->find("+")) ||
+            (std::string::npos != out->find("/"))) {
+        size_t outLen = out->size();
+        char *base64url = new char[outLen];
+        for (size_t i = 0; i < outLen; ++i) {
+            if (out->c_str()[i] == '+')
+                base64url[i] = '-';
+            else if (out->c_str()[i] == '/')
+                base64url[i] = '_';
+            else
+                base64url[i] = out->c_str()[i];
+        }
+
+        out->assign(base64url, outLen);
+        delete[] base64url;
+    }
+}
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp b/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp
new file mode 100644
index 0000000..e58f58a
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Buffer.h"
+
+#include <android/hardware/drm/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+Buffer::Buffer(size_t capacity)
+      : mRangeOffset(0),
+      mOwnsData(true) {
+    mData = malloc(capacity);
+    if (mData == nullptr) {
+        mCapacity = 0;
+        mRangeLength = 0;
+    } else {
+        mCapacity = capacity;
+        mRangeLength = capacity;
+    }
+}
+
+Buffer::~Buffer() {
+    if (mOwnsData) {
+        if (mData != nullptr) {
+            free(mData);
+            mData = nullptr;
+        }
+    }
+}
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp b/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
new file mode 100644
index 0000000..1ba5c6a
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CreatePluginFactories.h"
+
+#include "CryptoFactory.h"
+#include "DrmFactory.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+extern "C" {
+
+IDrmFactory* createDrmFactory() {
+    return new DrmFactory();
+}
+
+ICryptoFactory* createCryptoFactory() {
+    return new CryptoFactory();
+}
+
+} // extern "C"
+
+}  // namespace clearkey
+}  // namespace V1_1
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
new file mode 100644
index 0000000..0848cef
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "hidl_ClearKeyCryptoFactory"
+#include <utils/Log.h>
+
+#include "CryptoFactory.h"
+
+#include "ClearKeyUUID.h"
+#include "CryptoPlugin.h"
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+Return<bool> CryptoFactory::isCryptoSchemeSupported(
+    const hidl_array<uint8_t, 16> &uuid)
+{
+    return clearkeydrm::isClearKeyUUID(uuid.data());
+}
+
+Return<void> CryptoFactory::createPlugin(
+    const hidl_array<uint8_t, 16> &uuid,
+    const hidl_vec<uint8_t> &initData,
+    createPlugin_cb _hidl_cb) {
+
+    if (!isCryptoSchemeSupported(uuid.data())) {
+        ALOGE("Clearkey Drm HAL: failed to create clearkey plugin, " \
+                "invalid crypto scheme");
+        _hidl_cb(Status::BAD_VALUE, nullptr);
+        return Void();
+    }
+
+    CryptoPlugin *cryptoPlugin = new CryptoPlugin(initData);
+    Status status = cryptoPlugin->getInitStatus();
+    if (status == Status::OK) {
+        _hidl_cb(Status::OK, cryptoPlugin);
+    } else {
+        delete cryptoPlugin;
+        _hidl_cb(status, nullptr);
+    }
+    return Void();
+}
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
new file mode 100644
index 0000000..f33f94e
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "hidl_ClearKeyCryptoPlugin"
+#include <utils/Log.h>
+
+#include "CryptoPlugin.h"
+#include "SessionLibrary.h"
+#include "TypeConvert.h"
+
+#include <hidlmemory/mapping.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::drm::V1_0::BufferType;
+
+Return<void> CryptoPlugin::setSharedBufferBase(
+        const hidl_memory& base, uint32_t bufferId) {
+    sp<IMemory> hidlMemory = mapMemory(base);
+    ALOGE_IF(hidlMemory == nullptr, "mapMemory returns nullptr");
+
+    // allow mapMemory to return nullptr
+    mSharedBufferMap[bufferId] = hidlMemory;
+    return Void();
+}
+
+// Returns negative values for error code and positive values for the size of
+// decrypted data.  In theory, the output size can be larger than the input
+// size, but in practice this will never happen for AES-CTR.
+Return<void> CryptoPlugin::decrypt(
+        bool secure,
+        const hidl_array<uint8_t, KEY_ID_SIZE>& keyId,
+        const hidl_array<uint8_t, KEY_IV_SIZE>& iv,
+        Mode mode,
+        const Pattern& pattern,
+        const hidl_vec<SubSample>& subSamples,
+        const SharedBuffer& source,
+        uint64_t offset,
+        const DestinationBuffer& destination,
+        decrypt_cb _hidl_cb) {
+    UNUSED(pattern);
+
+    if (secure) {
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+            "Secure decryption is not supported with ClearKey.");
+        return Void();
+    }
+
+    if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
+      _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+               "source decrypt buffer base not set");
+      return Void();
+    }
+
+    if (destination.type == BufferType::SHARED_MEMORY) {
+      const SharedBuffer& dest = destination.nonsecureMemory;
+      if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) {
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+                 "destination decrypt buffer base not set");
+        return Void();
+      }
+    }
+
+    sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
+    if (sourceBase == nullptr) {
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr");
+        return Void();
+    }
+
+    if (source.offset + offset + source.size > sourceBase->getSize()) {
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
+        return Void();
+    }
+
+    uint8_t *base = static_cast<uint8_t *>
+            (static_cast<void *>(sourceBase->getPointer()));
+    uint8_t* srcPtr = static_cast<uint8_t *>(base + source.offset + offset);
+    void* destPtr = NULL;
+    if (destination.type == BufferType::SHARED_MEMORY) {
+        const SharedBuffer& destBuffer = destination.nonsecureMemory;
+        sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
+        if (destBase == nullptr) {
+            _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
+            return Void();
+        }
+
+        if (destBuffer.offset + destBuffer.size > destBase->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);
+    }
+
+    // Calculate the output buffer size and determine if any subsamples are
+    // encrypted.
+    size_t destSize = 0;
+    bool haveEncryptedSubsamples = false;
+    for (size_t i = 0; i < subSamples.size(); i++) {
+        const SubSample &subSample = subSamples[i];
+        destSize += subSample.numBytesOfClearData;
+        destSize += subSample.numBytesOfEncryptedData;
+        if (subSample.numBytesOfEncryptedData > 0) {
+        haveEncryptedSubsamples = true;
+        }
+    }
+
+    if (mode == Mode::UNENCRYPTED) {
+        if (haveEncryptedSubsamples) {
+            _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+                    "Encrypted subsamples found in allegedly unencrypted data.");
+            return Void();
+        }
+
+        size_t offset = 0;
+        for (size_t i = 0; i < subSamples.size(); ++i) {
+            const SubSample& subSample = subSamples[i];
+            if (subSample.numBytesOfClearData != 0) {
+                memcpy(reinterpret_cast<uint8_t*>(destPtr) + offset,
+                       reinterpret_cast<const uint8_t*>(srcPtr) + offset,
+                       subSample.numBytesOfClearData);
+                offset += subSample.numBytesOfClearData;
+            }
+        }
+
+        _hidl_cb(Status::OK, static_cast<ssize_t>(offset), "");
+        return Void();
+    } else if (mode == Mode::AES_CTR) {
+        size_t bytesDecrypted;
+        Status res = mSession->decrypt(keyId.data(), iv.data(), srcPtr,
+                static_cast<uint8_t*>(destPtr), toVector(subSamples), &bytesDecrypted);
+        if (res == Status::OK) {
+            _hidl_cb(Status::OK, static_cast<ssize_t>(bytesDecrypted), "");
+            return Void();
+        } else {
+            _hidl_cb(Status::ERROR_DRM_DECRYPT, static_cast<ssize_t>(res),
+                    "Decryption Error");
+            return Void();
+        }
+    } else {
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+                "Selected encryption mode is not supported by the ClearKey DRM Plugin.");
+        return Void();
+    }
+}
+
+Return<Status> CryptoPlugin::setMediaDrmSession(
+        const hidl_vec<uint8_t>& sessionId) {
+    if (!sessionId.size()) {
+        mSession = nullptr;
+    } else {
+        mSession = SessionLibrary::get()->findSession(sessionId);
+        if (!mSession.get()) {
+            return Status::ERROR_DRM_SESSION_NOT_OPENED;
+        }
+    }
+    return Status::OK;
+}
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
new file mode 100644
index 0000000..77557f9
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "hidl_ClearKeyDrmFactory"
+#include <utils/Log.h>
+
+#include <utils/Errors.h>
+
+#include "DrmFactory.h"
+
+#include "DrmPlugin.h"
+#include "ClearKeyUUID.h"
+#include "MimeType.h"
+#include "SessionLibrary.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::drm::V1_0::Status;
+using ::android::hardware::Void;
+
+Return<bool> DrmFactory::isCryptoSchemeSupported(
+        const hidl_array<uint8_t, 16>& uuid) {
+    return clearkeydrm::isClearKeyUUID(uuid.data());
+}
+
+Return<bool> DrmFactory::isContentTypeSupported(const hidl_string &mimeType) {
+    // This should match the mimeTypes handed by InitDataParser.
+    return mimeType == kIsoBmffVideoMimeType ||
+            mimeType == kIsoBmffAudioMimeType ||
+            mimeType == kCencInitDataFormat ||
+            mimeType == kWebmVideoMimeType ||
+            mimeType == kWebmAudioMimeType ||
+            mimeType == kWebmInitDataFormat;
+}
+
+Return<void> DrmFactory::createPlugin(
+    const hidl_array<uint8_t, 16>& uuid,
+    const hidl_string& appPackageName,
+    createPlugin_cb _hidl_cb) {
+    UNUSED(appPackageName);
+
+    DrmPlugin *plugin = NULL;
+    if (!isCryptoSchemeSupported(uuid.data())) {
+        ALOGE("Clear key Drm HAL: failed to create drm plugin, " \
+                "invalid crypto scheme");
+        _hidl_cb(Status::BAD_VALUE, plugin);
+        return Void();
+    }
+
+    plugin = new DrmPlugin(SessionLibrary::get());
+    _hidl_cb(Status::OK, plugin);
+    return Void();
+}
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
new file mode 100644
index 0000000..9506cd1
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "hidl_ClearKeyPlugin"
+#include <utils/Log.h>
+
+#include <stdio.h>
+
+#include "DrmPlugin.h"
+#include "ClearKeyDrmProperties.h"
+#include "Session.h"
+#include "TypeConvert.h"
+
+namespace {
+const std::string kStreaming("Streaming");
+const std::string kOffline("Offline");
+const std::string kTrue("True");
+
+const std::string kQueryKeyLicenseType("LicenseType");
+    // Value: "Streaming" or "Offline"
+const std::string kQueryKeyPlayAllowed("PlayAllowed");
+    // Value: "True" or "False"
+const std::string kQueryKeyRenewAllowed("RenewAllowed");
+    // Value: "True" or "False"
+};
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
+        : mSessionLibrary(sessionLibrary) {
+    mPlayPolicy.clear();
+    initProperties();
+
+}
+
+void DrmPlugin::initProperties() {
+    mStringProperties.clear();
+    mStringProperties[kVendorKey] = kVendorValue;
+    mStringProperties[kVersionKey] = kVersionValue;
+    mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue;
+    mStringProperties[kAlgorithmsKey] = kAlgorithmsValue;
+    mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue;
+
+    std::vector<uint8_t> valueVector;
+    valueVector.clear();
+    valueVector.insert(valueVector.end(),
+            kTestDeviceIdData, kTestDeviceIdData + sizeof(kTestDeviceIdData) / sizeof(uint8_t));
+    mByteArrayProperties[kDeviceIdKey] = valueVector;
+
+    valueVector.clear();
+    valueVector.insert(valueVector.end(),
+            kMetricsData, kMetricsData + sizeof(kMetricsData) / sizeof(uint8_t));
+    mByteArrayProperties[kMetricsKey] = valueVector;
+}
+
+Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) {
+    sp<Session> session = mSessionLibrary->createSession();
+    std::vector<uint8_t> sessionId = session->sessionId();
+
+    setSecurityLevel(sessionId, SecurityLevel::SW_SECURE_CRYPTO);
+    _hidl_cb(Status::OK, toHidlVec(sessionId));
+    return Void();
+}
+
+Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) {
+    if (sessionId.size() == 0) {
+        return Status::BAD_VALUE;
+    }
+
+    sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
+    if (session.get()) {
+        mSessionLibrary->destroySession(session);
+        return Status::OK;
+    }
+    return Status::ERROR_DRM_SESSION_NOT_OPENED;
+}
+
+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) {
+    UNUSED(optionalParameters);
+
+    if (scope.size() == 0) {
+        // Returns empty keyRequest, unknown keyType and empty defaultUrl
+        _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>(),
+                KeyRequestType::UNKNOWN, "");
+        return Void();
+    }
+
+    if (keyType != KeyType::STREAMING) {
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(),
+                KeyRequestType::UNKNOWN, "");
+        return Void();
+    }
+
+    sp<Session> session = mSessionLibrary->findSession(toVector(scope));
+    if (!session.get()) {
+        _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, hidl_vec<uint8_t>(),
+                KeyRequestType::UNKNOWN, "");
+        return Void();
+    }
+
+    std::vector<uint8_t> request;
+    Status status = session->getKeyRequest(initData, mimeType, &request);
+    _hidl_cb(status, toHidlVec(request), KeyRequestType::INITIAL, "");
+    return Void();
+}
+
+Return<void> DrmPlugin::getKeyRequest_1_1(
+        const hidl_vec<uint8_t>& scope,
+        const hidl_vec<uint8_t>& initData,
+        const hidl_string& mimeType,
+        KeyType keyType,
+        const hidl_vec<KeyValue>& optionalParameters,
+        getKeyRequest_1_1_cb _hidl_cb) {
+    hidl_string defaultUrl;
+    hidl_vec<uint8_t> request;
+    ::android::hardware::drm::V1_1::KeyRequestType requestType =
+            static_cast<::android::hardware::drm::V1_1::KeyRequestType>(KeyRequestType::UNKNOWN);
+    Status status = Status::OK;
+
+    defaultUrl.clear();
+    getKeyRequest(scope, initData, mimeType, keyType, optionalParameters,
+            [&](Status statusCode, const hidl_vec<uint8_t>& hResult,
+            KeyRequestType hKeyRequestType,
+            const hidl_string& hDefaultUrl) {
+        defaultUrl = hDefaultUrl;
+        request = hResult;
+        requestType = static_cast<::android::hardware::drm::V1_1::KeyRequestType>(hKeyRequestType);
+        status = statusCode;
+    });
+    _hidl_cb(status, request, requestType, defaultUrl);
+    return Void();
+}
+
+void DrmPlugin::setPlayPolicy() {
+    mPlayPolicy.clear();
+
+    KeyValue policy;
+    policy.key = kQueryKeyLicenseType;
+    policy.value = kStreaming;
+    mPlayPolicy.push_back(policy);
+
+    policy.key = kQueryKeyPlayAllowed;
+    policy.value = kTrue;
+    mPlayPolicy.push_back(policy);
+
+    policy.key = kQueryKeyRenewAllowed;
+    mPlayPolicy.push_back(policy);
+}
+
+Return<void> DrmPlugin::provideKeyResponse(
+        const hidl_vec<uint8_t>& scope,
+        const hidl_vec<uint8_t>& response,
+        provideKeyResponse_cb _hidl_cb) {
+    if (scope.size() == 0 || response.size() == 0) {
+        // Returns empty keySetId
+        _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
+        return Void();
+    }
+    sp<Session> session = mSessionLibrary->findSession(toVector(scope));
+    if (!session.get()) {
+        _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, hidl_vec<uint8_t>());
+        return Void();
+    }
+
+    setPlayPolicy();
+    std::vector<uint8_t> keySetId;
+    Status status = session->provideKeyResponse(response);
+    if (status == Status::OK) {
+        // This is for testing AMediaDrm_setOnEventListener only.
+        sendEvent(EventType::VENDOR_DEFINED, 0, scope);
+        keySetId.clear();
+    }
+
+    // Returns status and empty keySetId
+    _hidl_cb(status, toHidlVec(keySetId));
+    return Void();
+}
+
+Return<void> DrmPlugin::getPropertyString(
+        const hidl_string& propertyName, getPropertyString_cb _hidl_cb) {
+    std::string name(propertyName.c_str());
+    std::string value;
+
+    if (name == "vendor") {
+        value = "Google";
+    } else if (name == "version") {
+        value = "1.1";
+    } else if (name == "description") {
+        value = "ClearKey CDM";
+    } else if (name == "algorithms") {
+        value = "";
+    } else if (name == "listenerTestSupport") {
+        value = mStringProperties[name];
+    } else {
+        ALOGE("App requested unknown string property %s", name.c_str());
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, "");
+        return Void();
+    }
+    _hidl_cb(Status::OK, value.c_str());
+    return Void();
+}
+
+Return<void> DrmPlugin::getPropertyByteArray(
+        const hidl_string& propertyName, getPropertyByteArray_cb _hidl_cb) {
+    std::map<std::string, std::vector<uint8_t> >::iterator itr =
+            mByteArrayProperties.find(std::string(propertyName.c_str()));
+    if (itr == mByteArrayProperties.end()) {
+        ALOGE("App requested unknown property: %s", propertyName.c_str());
+        _hidl_cb(Status::BAD_VALUE, std::vector<uint8_t>());
+        return Void();
+    }
+    _hidl_cb(Status::OK, itr->second);
+    return Void();
+
+}
+
+Return<Status> DrmPlugin::setPropertyString(
+    const hidl_string& name, const hidl_string& value) {
+    std::string immutableKeys;
+    immutableKeys.append(kAlgorithmsKey + ",");
+    immutableKeys.append(kPluginDescriptionKey + ",");
+    immutableKeys.append(kVendorKey + ",");
+    immutableKeys.append(kVersionKey + ",");
+
+    std::string key = std::string(name.c_str());
+    if (immutableKeys.find(key) != std::string::npos) {
+        ALOGD("Cannot set immutable property: %s", key.c_str());
+        return Status::BAD_VALUE;
+    }
+
+    std::map<std::string, std::string>::iterator itr =
+            mStringProperties.find(key);
+    if (itr == mStringProperties.end()) {
+        ALOGE("Cannot set undefined property string, key=%s", key.c_str());
+        return Status::BAD_VALUE;
+    }
+
+    mStringProperties[key] = std::string(value.c_str());
+    return Status::OK;
+}
+
+Return<Status> DrmPlugin::setPropertyByteArray(
+    const hidl_string& name, const hidl_vec<uint8_t>& value) {
+   UNUSED(value);
+   if (name == kDeviceIdKey) {
+      ALOGD("Cannot set immutable property: %s", name.c_str());
+      return Status::BAD_VALUE;
+   }
+
+   // Setting of undefined properties is not supported
+   ALOGE("Failed to set property byte array, key=%s", name.c_str());
+   return Status::ERROR_DRM_CANNOT_HANDLE;
+}
+
+Return<void> DrmPlugin::queryKeyStatus(
+        const hidl_vec<uint8_t>& sessionId,
+        queryKeyStatus_cb _hidl_cb) {
+
+    if (sessionId.size() == 0) {
+        // Returns empty key status KeyValue pair
+        _hidl_cb(Status::BAD_VALUE, hidl_vec<KeyValue>());
+        return Void();
+    }
+
+    std::vector<KeyValue> infoMapVec;
+    infoMapVec.clear();
+
+    KeyValue keyValuePair;
+    for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
+        keyValuePair.key = mPlayPolicy[i].key;
+        keyValuePair.value = mPlayPolicy[i].value;
+        infoMapVec.push_back(keyValuePair);
+    }
+    _hidl_cb(Status::OK, toHidlVec(infoMapVec));
+    return Void();
+}
+
+Return<void> DrmPlugin::getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) {
+        uint32_t currentSessions = mSessionLibrary->numOpenSessions();
+        uint32_t maxSessions = 10;
+        _hidl_cb(Status::OK, currentSessions, maxSessions);
+        return Void();
+}
+
+Return<void> DrmPlugin::getSecurityLevel(const hidl_vec<uint8_t>& sessionId,
+            getSecurityLevel_cb _hidl_cb) {
+    if (sessionId.size() == 0) {
+        _hidl_cb(Status::BAD_VALUE, SecurityLevel::UNKNOWN);
+        return Void();
+    }
+
+    std::vector<uint8_t> sid = toVector(sessionId);
+    sp<Session> session = mSessionLibrary->findSession(sid);
+    if (!session.get()) {
+        _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, SecurityLevel::UNKNOWN);
+        return Void();
+    }
+
+    std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
+            mSecurityLevel.find(sid);
+    if (itr == mSecurityLevel.end()) {
+        ALOGE("Session id not found");
+        _hidl_cb(Status::ERROR_DRM_INVALID_STATE, SecurityLevel::UNKNOWN);
+        return Void();
+    }
+
+    _hidl_cb(Status::OK, itr->second);
+    return Void();
+}
+
+Return<Status> DrmPlugin::setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
+            SecurityLevel level) {
+    if (sessionId.size() == 0) {
+        ALOGE("Invalid empty session id");
+        return Status::BAD_VALUE;
+    }
+
+    if (level > SecurityLevel::HW_SECURE_ALL) {
+        ALOGE("Cannot set invalid security level");
+        return Status::BAD_VALUE;
+    }
+
+    std::vector<uint8_t> sid = toVector(sessionId);
+    sp<Session> session = mSessionLibrary->findSession(sid);
+    if (!session.get()) {
+        return Status::ERROR_DRM_SESSION_NOT_OPENED;
+    }
+
+    std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
+            mSecurityLevel.find(sid);
+    if (itr != mSecurityLevel.end()) {
+        mSecurityLevel[sid] = level;
+    } else {
+        if (!mSecurityLevel.insert(
+                std::pair<std::vector<uint8_t>, SecurityLevel>(sid, level)).second) {
+            ALOGE("Failed to set security level");
+            return Status::ERROR_DRM_INVALID_STATE;
+        }
+    }
+    return Status::OK;
+}
+
+}  // namespace clearkey
+}  // namespace V1_1
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
new file mode 100644
index 0000000..e2bb651
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "hidl_InitDataParser"
+
+#include <algorithm>
+#include <utils/Log.h>
+
+#include "InitDataParser.h"
+
+#include "Base64.h"
+
+#include "ClearKeyUUID.h"
+#include "MimeType.h"
+#include "Utils.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+namespace {
+    const size_t kKeyIdSize = 16;
+    const size_t kSystemIdSize = 16;
+}
+
+std::vector<uint8_t> StrToVector(const std::string& str) {
+    std::vector<uint8_t> vec(str.begin(), str.end());
+    return vec;
+}
+
+Status InitDataParser::parse(const std::vector<uint8_t>& initData,
+        const std::string& type,
+        std::vector<uint8_t>* licenseRequest) {
+    // Build a list of the key IDs
+    std::vector<const uint8_t*> keyIds;
+
+    if (type == kIsoBmffVideoMimeType ||
+        type == kIsoBmffAudioMimeType ||
+        type == kCencInitDataFormat) {
+        Status res = parsePssh(initData, &keyIds);
+        if (res != Status::OK) {
+            return res;
+        }
+    } else if (type == kWebmVideoMimeType ||
+        type == kWebmAudioMimeType ||
+        type == kWebmInitDataFormat) {
+        // WebM "init data" is just a single key ID
+        if (initData.size() != kKeyIdSize) {
+            return Status::ERROR_DRM_CANNOT_HANDLE;
+        }
+        keyIds.push_back(initData.data());
+    } else {
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    // Build the request
+    std::string requestJson = generateRequest(keyIds);
+    std::vector<uint8_t> requestJsonVec = StrToVector(requestJson);
+
+    licenseRequest->clear();
+    licenseRequest->insert(licenseRequest->end(), requestJsonVec.begin(), requestJsonVec.end());
+    return Status::OK;
+}
+
+Status InitDataParser::parsePssh(const std::vector<uint8_t>& initData,
+        std::vector<const uint8_t*>* keyIds) {
+    size_t readPosition = 0;
+
+    // Validate size field
+    uint32_t expectedSize = initData.size();
+    expectedSize = htonl(expectedSize);
+    if (memcmp(&initData[readPosition], &expectedSize,
+               sizeof(expectedSize)) != 0) {
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+    readPosition += sizeof(expectedSize);
+
+    // Validate PSSH box identifier
+    const char psshIdentifier[4] = {'p', 's', 's', 'h'};
+    if (memcmp(&initData[readPosition], psshIdentifier,
+               sizeof(psshIdentifier)) != 0) {
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+    readPosition += sizeof(psshIdentifier);
+
+    // Validate EME version number
+    const uint8_t psshVersion1[4] = {1, 0, 0, 0};
+    if (memcmp(&initData[readPosition], psshVersion1,
+               sizeof(psshVersion1)) != 0) {
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+    readPosition += sizeof(psshVersion1);
+
+    // Validate system ID
+    if (!clearkeydrm::isClearKeyUUID(&initData[readPosition])) {
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+    readPosition += kSystemIdSize;
+
+    // Read key ID count
+    uint32_t keyIdCount;
+    memcpy(&keyIdCount, &initData[readPosition], sizeof(keyIdCount));
+    keyIdCount = ntohl(keyIdCount);
+    readPosition += sizeof(keyIdCount);
+    if (readPosition + ((uint64_t)keyIdCount * kKeyIdSize) !=
+            initData.size() - sizeof(uint32_t)) {
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    // Calculate the key ID offsets
+    for (uint32_t i = 0; i < keyIdCount; ++i) {
+        size_t keyIdPosition = readPosition + (i * kKeyIdSize);
+        keyIds->push_back(&initData[keyIdPosition]);
+    }
+    return Status::OK;
+}
+
+std::string InitDataParser::generateRequest(const std::vector<const uint8_t*>& keyIds) {
+    const std::string kRequestPrefix("{\"kids\":[");
+    const std::string kRequestSuffix("],\"type\":\"temporary\"}");
+
+    std::string request(kRequestPrefix);
+    std::string encodedId;
+    for (size_t i = 0; i < keyIds.size(); ++i) {
+        encodedId.clear();
+        encodeBase64Url(keyIds[i], kKeyIdSize, &encodedId);
+        if (i != 0) {
+            request.append(",");
+        }
+        request.push_back('\"');
+        request.append(encodedId);
+        request.push_back('\"');
+    }
+    request.append(kRequestSuffix);
+
+    // Android's Base64 encoder produces padding. EME forbids padding.
+    const char kBase64Padding = '=';
+    request.erase(std::remove(request.begin(), request.end(), kBase64Padding), request.end());
+
+    return request;
+}
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp b/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp
new file mode 100644
index 0000000..cccb41e
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "hidl_JsonWebKey"
+
+#include <utils/Log.h>
+
+#include "JsonWebKey.h"
+
+#include "Base64.h"
+
+namespace {
+const std::string kKeysTag("keys");
+const std::string kKeyTypeTag("kty");
+const std::string kSymmetricKeyValue("oct");
+const std::string kKeyTag("k");
+const std::string kKeyIdTag("kid");
+const std::string kBase64Padding("=");
+}
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+JsonWebKey::JsonWebKey() {
+}
+
+JsonWebKey::~JsonWebKey() {
+}
+
+/*
+ * Parses a JSON Web Key Set string, initializes a KeyMap with key id:key
+ * pairs from the JSON Web Key Set. Both key ids and keys are base64url
+ * encoded. The KeyMap contains base64url decoded key id:key pairs.
+ *
+ * @return Returns false for errors, true for success.
+ */
+bool JsonWebKey::extractKeysFromJsonWebKeySet(const std::string& jsonWebKeySet,
+        KeyMap* keys) {
+
+    keys->clear();
+
+    if (!parseJsonWebKeySet(jsonWebKeySet, &mJsonObjects)) {
+        return false;
+    }
+
+    // mJsonObjects[0] contains the entire JSON Web Key Set, including
+    // all the base64 encoded keys. Each key is also stored separately as
+    // a JSON object in mJsonObjects[1..n] where n is the total
+    // number of keys in the set.
+    if (!isJsonWebKeySet(mJsonObjects[0])) {
+        return false;
+    }
+
+    std::string encodedKey, encodedKeyId;
+    std::vector<uint8_t> decodedKey, decodedKeyId;
+
+    // mJsonObjects[1] contains the first JSON Web Key in the set
+    for (size_t i = 1; i < mJsonObjects.size(); ++i) {
+        encodedKeyId.clear();
+        encodedKey.clear();
+
+        if (!parseJsonObject(mJsonObjects[i], &mTokens))
+            return false;
+
+        if (findKey(mJsonObjects[i], &encodedKeyId, &encodedKey)) {
+            if (encodedKeyId.empty() || encodedKey.empty()) {
+                ALOGE("Must have both key id and key in the JsonWebKey set.");
+                continue;
+            }
+
+            if (!decodeBase64String(encodedKeyId, &decodedKeyId)) {
+                ALOGE("Failed to decode key id(%s)", encodedKeyId.c_str());
+                continue;
+            }
+
+            if (!decodeBase64String(encodedKey, &decodedKey)) {
+                ALOGE("Failed to decode key(%s)", encodedKey.c_str());
+                continue;
+            }
+
+            keys->insert(std::pair<std::vector<uint8_t>,
+                    std::vector<uint8_t> >(decodedKeyId, decodedKey));
+        }
+    }
+    return true;
+}
+
+bool JsonWebKey::decodeBase64String(const std::string& encodedText,
+        std::vector<uint8_t>* decodedText) {
+
+    decodedText->clear();
+
+    // encodedText should not contain padding characters as per EME spec.
+    if (encodedText.find(kBase64Padding) != std::string::npos) {
+        return false;
+    }
+
+    // Since decodeBase64() requires padding characters,
+    // add them so length of encodedText is exactly a multiple of 4.
+    int remainder = encodedText.length() % 4;
+    std::string paddedText(encodedText);
+    if (remainder > 0) {
+        for (int i = 0; i < 4 - remainder; ++i) {
+            paddedText.append(kBase64Padding);
+        }
+    }
+
+    sp<Buffer> buffer = decodeBase64(paddedText);
+    if (buffer == nullptr) {
+        ALOGE("Malformed base64 encoded content found.");
+        return false;
+    }
+
+    decodedText->insert(decodedText->end(), buffer->base(), buffer->base() + buffer->size());
+    return true;
+}
+
+bool JsonWebKey::findKey(const std::string& jsonObject, std::string* keyId,
+        std::string* encodedKey) {
+
+    std::string key, value;
+
+    // Only allow symmetric key, i.e. "kty":"oct" pair.
+    if (jsonObject.find(kKeyTypeTag) != std::string::npos) {
+        findValue(kKeyTypeTag, &value);
+        if (0 != value.compare(kSymmetricKeyValue))
+            return false;
+    }
+
+    if (jsonObject.find(kKeyIdTag) != std::string::npos) {
+        findValue(kKeyIdTag, keyId);
+    }
+
+    if (jsonObject.find(kKeyTag) != std::string::npos) {
+        findValue(kKeyTag, encodedKey);
+    }
+    return true;
+}
+
+void JsonWebKey::findValue(const std::string &key, std::string* value) {
+    value->clear();
+    const char* valueToken;
+    for (std::vector<std::string>::const_iterator nextToken = mTokens.begin();
+        nextToken != mTokens.end(); ++nextToken) {
+        if (0 == (*nextToken).compare(key)) {
+            if (nextToken + 1 == mTokens.end())
+                break;
+            valueToken = (*(nextToken + 1)).c_str();
+            value->assign(valueToken);
+            nextToken++;
+            break;
+        }
+    }
+}
+
+bool JsonWebKey::isJsonWebKeySet(const std::string& jsonObject) const {
+    if (jsonObject.find(kKeysTag) == std::string::npos) {
+        ALOGE("JSON Web Key does not contain keys.");
+        return false;
+    }
+    return true;
+}
+
+/*
+ * Parses a JSON objects string and initializes a vector of tokens.
+ *
+ * @return Returns false for errors, true for success.
+ */
+bool JsonWebKey::parseJsonObject(const std::string& jsonObject,
+        std::vector<std::string>* tokens) {
+    jsmn_parser parser;
+
+    jsmn_init(&parser);
+    int numTokens = jsmn_parse(&parser,
+        jsonObject.c_str(), jsonObject.size(), nullptr, 0);
+    if (numTokens < 0) {
+        ALOGE("Parser returns error code=%d", numTokens);
+        return false;
+    }
+
+    unsigned int jsmnTokensSize = numTokens * sizeof(jsmntok_t);
+    mJsmnTokens.clear();
+    mJsmnTokens.resize(jsmnTokensSize);
+
+    jsmn_init(&parser);
+    int status = jsmn_parse(&parser, jsonObject.c_str(),
+        jsonObject.size(), mJsmnTokens.data(), numTokens);
+    if (status < 0) {
+        ALOGE("Parser returns error code=%d", status);
+        return false;
+    }
+
+    tokens->clear();
+    std::string token;
+    const char *pjs;
+    for (int j = 0; j < numTokens; ++j) {
+        pjs = jsonObject.c_str() + mJsmnTokens[j].start;
+        if (mJsmnTokens[j].type == JSMN_STRING ||
+                mJsmnTokens[j].type == JSMN_PRIMITIVE) {
+            token.assign(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start);
+            tokens->push_back(token);
+        }
+    }
+    return true;
+}
+
+/*
+ * Parses JSON Web Key Set string and initializes a vector of JSON objects.
+ *
+ * @return Returns false for errors, true for success.
+ */
+bool JsonWebKey::parseJsonWebKeySet(const std::string& jsonWebKeySet,
+        std::vector<std::string>* jsonObjects) {
+    if (jsonWebKeySet.empty()) {
+        ALOGE("Empty JSON Web Key");
+        return false;
+    }
+
+    // The jsmn parser only supports unicode encoding.
+    jsmn_parser parser;
+
+    // Computes number of tokens. A token marks the type, offset in
+    // the original string.
+    jsmn_init(&parser);
+    int numTokens = jsmn_parse(&parser,
+            jsonWebKeySet.c_str(), jsonWebKeySet.size(), nullptr, 0);
+    if (numTokens < 0) {
+        ALOGE("Parser returns error code=%d", numTokens);
+        return false;
+    }
+
+    unsigned int jsmnTokensSize = numTokens * sizeof(jsmntok_t);
+    mJsmnTokens.resize(jsmnTokensSize);
+
+    jsmn_init(&parser);
+    int status = jsmn_parse(&parser, jsonWebKeySet.c_str(),
+            jsonWebKeySet.size(), mJsmnTokens.data(), numTokens);
+    if (status < 0) {
+        ALOGE("Parser returns error code=%d", status);
+        return false;
+    }
+
+    std::string token;
+    const char *pjs;
+    for (int i = 0; i < numTokens; ++i) {
+        pjs = jsonWebKeySet.c_str() + mJsmnTokens[i].start;
+        if (mJsmnTokens[i].type == JSMN_OBJECT) {
+            token.assign(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start);
+            jsonObjects->push_back(token);
+        }
+    }
+    return true;
+}
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
new file mode 100644
index 0000000..07c9269
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "hidl_ClearKeySession"
+#include <utils/Log.h>
+
+#include "Session.h"
+#include "Utils.h"
+
+#include "AesCtrDecryptor.h"
+#include "InitDataParser.h"
+#include "JsonWebKey.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::drm::V1_0::KeyValue;
+using ::android::hardware::drm::V1_0::Status;
+using ::android::hardware::drm::V1_0::SubSample;
+using ::android::hardware::Return;
+using ::android::sp;
+
+using android::Mutex;
+
+Status Session::getKeyRequest(
+        const std::vector<uint8_t>& initData,
+        const std::string& mimeType,
+        std::vector<uint8_t>* keyRequest) const {
+    InitDataParser parser;
+    return parser.parse(initData, mimeType, keyRequest);
+}
+
+Status Session::provideKeyResponse(const std::vector<uint8_t>& response) {
+    std::string responseString(
+            reinterpret_cast<const char*>(response.data()), response.size());
+    KeyMap keys;
+
+    Mutex::Autolock lock(mMapLock);
+    JsonWebKey parser;
+    if (parser.extractKeysFromJsonWebKeySet(responseString, &keys)) {
+        for (auto &key : keys) {
+            std::string first(key.first.begin(), key.first.end());
+            std::string second(key.second.begin(), key.second.end());
+            mKeyMap.insert(std::pair<std::vector<uint8_t>,
+                    std::vector<uint8_t> >(key.first, key.second));
+        }
+        return Status::OK;
+    } else {
+        return Status::ERROR_DRM_UNKNOWN;
+    }
+}
+
+Status Session::decrypt(
+        const KeyId keyId, const Iv iv, const uint8_t* srcPtr,
+        uint8_t* destPtr, const std::vector<SubSample> subSamples,
+        size_t* bytesDecryptedOut) {
+    Mutex::Autolock lock(mMapLock);
+
+    std::vector<uint8_t> keyIdVector;
+    keyIdVector.clear();
+    keyIdVector.insert(keyIdVector.end(), keyId, keyId + kBlockSize);
+    std::map<std::vector<uint8_t>, std::vector<uint8_t> >::iterator itr;
+    itr = mKeyMap.find(keyIdVector);
+    if (itr == mKeyMap.end()) {
+        return Status::ERROR_DRM_NO_LICENSE;
+    }
+
+    AesCtrDecryptor decryptor;
+    return decryptor.decrypt(
+            itr->second /*key*/, iv, srcPtr, destPtr, subSamples,
+            subSamples.size(), bytesDecryptedOut);
+}
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp b/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp
new file mode 100644
index 0000000..b4319e6
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "hidl_ClearKeySessionLibrary"
+#include <utils/Log.h>
+
+#include "SessionLibrary.h"
+#include "Utils.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::sp;
+
+Mutex SessionLibrary::sSingletonLock;
+SessionLibrary* SessionLibrary::sSingleton = NULL;
+
+SessionLibrary* SessionLibrary::get() {
+    Mutex::Autolock lock(sSingletonLock);
+
+    if (sSingleton == NULL) {
+        ALOGD("Instantiating Session Library Singleton.");
+        sSingleton = new SessionLibrary();
+    }
+
+    return sSingleton;
+}
+
+sp<Session> SessionLibrary::createSession() {
+    Mutex::Autolock lock(mSessionsLock);
+
+    char sessionIdRaw[16];
+    snprintf(sessionIdRaw, sizeof(sessionIdRaw), "%u", mNextSessionId);
+
+    mNextSessionId += 1;
+
+    std::vector<uint8_t> sessionId;
+    sessionId.insert(sessionId.end(), sessionIdRaw,
+            sessionIdRaw + sizeof(sessionIdRaw) / sizeof(uint8_t));
+
+    mSessions.insert(std::pair<std::vector<uint8_t>,
+            sp<Session> >(sessionId, new Session(sessionId)));
+    std::map<std::vector<uint8_t>, sp<Session> >::iterator itr = mSessions.find(sessionId);
+    if (itr != mSessions.end()) {
+        return itr->second;
+    } else {
+        return nullptr;
+    }
+}
+
+sp<Session> SessionLibrary::findSession(
+        const std::vector<uint8_t>& sessionId) {
+    Mutex::Autolock lock(mSessionsLock);
+    std::map<std::vector<uint8_t>, sp<Session> >::iterator itr = mSessions.find(sessionId);
+    if (itr != mSessions.end()) {
+        return itr->second;
+    } else {
+        return nullptr;
+    }
+}
+
+void SessionLibrary::destroySession(const sp<Session>& session) {
+    Mutex::Autolock lock(mSessionsLock);
+    mSessions.erase(session->sessionId());
+}
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.1-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.1-service.clearkey.rc
new file mode 100644
index 0000000..ffe856a
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.1-service.clearkey.rc
@@ -0,0 +1,6 @@
+service vendor.drm-clearkey-hal-1-1 /vendor/bin/hw/android.hardware.drm@1.1-service.clearkey
+    class hal
+    user media
+    group media mediadrm
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h b/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h
new file mode 100644
index 0000000..0c7ef20
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_AES_CTR_DECRYPTOR_H_
+#define CLEARKEY_AES_CTR_DECRYPTOR_H_
+
+#include "ClearKeyTypes.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::drm::V1_0::Status;
+using ::android::hardware::drm::V1_0::SubSample;
+
+class AesCtrDecryptor {
+public:
+    AesCtrDecryptor() {}
+
+    Status decrypt(const std::vector<uint8_t>& key, const Iv iv,
+            const uint8_t* source, uint8_t* destination,
+            const std::vector<SubSample> subSamples, size_t numSubSamples,
+            size_t* bytesDecryptedOut);
+
+private:
+    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(AesCtrDecryptor);
+};
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif // CLEARKEY_AES_CTR_DECRYPTOR_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h b/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h
new file mode 100644
index 0000000..4a385bd
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BASE_64_H_
+
+#define BASE_64_H_
+
+#include <android/hardware/drm/1.0/types.h>
+
+#include "Buffer.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::sp;
+
+struct Buffer;
+
+sp<Buffer> decodeBase64(const std::string &s);
+void encodeBase64(const void *data, size_t size, std::string *out);
+
+void encodeBase64Url(const void *data, size_t size, std::string *out);
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif  // BASE_64_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h b/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h
new file mode 100644
index 0000000..5bbb28a
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BUFFER_H_
+#define BUFFER_H_
+
+#include <android/hardware/drm/1.0/types.h>
+#include <utils/RefBase.h>
+
+#include "ClearKeyTypes.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::sp;
+
+struct Buffer : public RefBase {
+    explicit Buffer(size_t capacity);
+
+    uint8_t *base() { return reinterpret_cast<uint8_t *>(mData); }
+    uint8_t *data() { return reinterpret_cast<uint8_t *>(mData) + mRangeOffset; }
+    size_t capacity() const { return mCapacity; }
+    size_t size() const { return mRangeLength; }
+    size_t offset() const { return mRangeOffset; }
+
+protected:
+    virtual ~Buffer();
+
+private:
+    void *mData;
+    size_t mCapacity;
+    size_t mRangeOffset;
+    size_t mRangeLength;
+
+    bool mOwnsData;
+
+    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(Buffer);
+};
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif  // BUFFER_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
new file mode 100644
index 0000000..7731b14
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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 CLEARKEY_DRM_PROPERTIES_H_
+#define CLEARKEY_DRM_PROPERTIES_H_
+
+#include <string.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+static const std::string kVendorKey("vendor");
+static const std::string kVendorValue("Google");
+static const std::string kVersionKey("version");
+static const std::string kVersionValue("1.0");
+static const std::string kPluginDescriptionKey("description");
+static const std::string kPluginDescriptionValue("ClearKey CDM");
+static const std::string kAlgorithmsKey("algorithms");
+static const std::string kAlgorithmsValue("");
+static const std::string kListenerTestSupportKey("listenerTestSupport");
+static const std::string kListenerTestSupportValue("true");
+
+static const std::string kDeviceIdKey("deviceId");
+static const uint8_t kTestDeviceIdData[] =
+        {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+         0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
+// TODO stub out metrics for nw
+static const std::string kMetricsKey("metrics");
+static const uint8_t kMetricsData[] = { 0 };
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif // CLEARKEY_DRM_PROPERTIES_H_
+
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
new file mode 100644
index 0000000..46cb5e4
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_MACROS_H_
+#define CLEARKEY_MACROS_H_
+
+#include <android/hardware/drm/1.0/types.h>
+
+#include <map>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::drm::V1_0::KeyValue;
+using ::android::hardware::hidl_vec;
+
+const uint8_t kBlockSize = 16; //AES_BLOCK_SIZE;
+typedef uint8_t KeyId[kBlockSize];
+typedef uint8_t Iv[kBlockSize];
+
+typedef ::android::hardware::drm::V1_0::SubSample SubSample;
+typedef std::map<std::vector<uint8_t>, std::vector<uint8_t> > KeyMap;
+
+#define CLEARKEY_DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&) = delete;      \
+  void operator=(const TypeName&) = delete;
+
+#define CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(TypeName) \
+  TypeName() = delete;                     \
+  TypeName(const TypeName&) = delete;      \
+  void operator=(const TypeName&) = delete;
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif // CLEARKEY_MACROS_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h b/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
new file mode 100644
index 0000000..9952027
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
+#define CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
+
+#include <android/hardware/drm/1.1/ICryptoFactory.h>
+#include <android/hardware/drm/1.1/IDrmFactory.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::drm::V1_1::ICryptoFactory;
+using ::android::hardware::drm::V1_1::IDrmFactory;
+
+extern "C" {
+    IDrmFactory* createDrmFactory();
+    ICryptoFactory* createCryptoFactory();
+}
+
+}  // namespace clearkey
+}  // namespace V1_1
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+#endif // CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
new file mode 100644
index 0000000..175ab76
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_CRYPTO_FACTORY_H_
+#define CLEARKEY_CRYPTO_FACTORY_H_
+
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <android/hardware/drm/1.1/ICryptoFactory.h>
+
+#include "ClearKeyTypes.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::drm::V1_1::ICryptoFactory;
+using ::android::hardware::drm::V1_0::ICryptoPlugin;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+
+struct CryptoFactory : public ICryptoFactory {
+    CryptoFactory() {}
+    virtual ~CryptoFactory() {}
+
+    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:
+    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(CryptoFactory);
+
+};
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif // CLEARKEY_CRYPTO_FACTORY_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
new file mode 100644
index 0000000..6a73806
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_CRYPTO_PLUGIN_H_
+#define CLEARKEY_CRYPTO_PLUGIN_H_
+
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+
+#include "ClearKeyTypes.h"
+#include "Session.h"
+#include "Utils.h"
+
+namespace {
+    static const size_t KEY_ID_SIZE = 16;
+    static const size_t KEY_IV_SIZE = 16;
+}
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+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::SharedBuffer;
+using ::android::hardware::drm::V1_0::Status;
+using ::android::hardware::drm::V1_0::SubSample;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
+struct CryptoPlugin : public ICryptoPlugin {
+    explicit CryptoPlugin(const hidl_vec<uint8_t>& sessionId) {
+        mInitStatus = setMediaDrmSession(sessionId);
+    }
+    virtual ~CryptoPlugin() {}
+
+    Return<bool> requiresSecureDecoderComponent(const hidl_string& mime) {
+        UNUSED(mime);
+        return false;
+    }
+
+    Return<void> notifyResolution(uint32_t width, uint32_t height) {
+        UNUSED(width);
+        UNUSED(height);
+        return Void();
+    }
+
+    Return<void> decrypt(
+            bool secure,
+            const hidl_array<uint8_t, KEY_ID_SIZE>& keyId,
+            const hidl_array<uint8_t, KEY_IV_SIZE>& iv,
+            Mode mode,
+            const Pattern& pattern,
+            const hidl_vec<SubSample>& subSamples,
+            const SharedBuffer& source,
+            uint64_t offset,
+            const DestinationBuffer& destination,
+            decrypt_cb _hidl_cb);
+
+    Return<void> setSharedBufferBase(const hidl_memory& base,
+            uint32_t bufferId);
+
+    Return<Status> setMediaDrmSession(const hidl_vec<uint8_t>& sessionId);
+
+    Return<Status> getInitStatus() const { return mInitStatus; }
+
+private:
+    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(CryptoPlugin);
+
+    std::map<uint32_t, sp<IMemory> > mSharedBufferMap;
+    sp<Session> mSession;
+    Status mInitStatus;
+};
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif // CLEARKEY_CRYPTO_PLUGIN_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
new file mode 100644
index 0000000..6f58195
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_DRM_FACTORY_H_
+#define CLEARKEY_DRM_FACTORY_H_
+
+#include <android/hardware/drm/1.1/IDrmPlugin.h>
+#include <android/hardware/drm/1.1/IDrmFactory.h>
+
+#include "ClearKeyTypes.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+
+struct DrmFactory : public IDrmFactory {
+    DrmFactory() {}
+    virtual ~DrmFactory() {}
+
+    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,
+            const hidl_string& appPackageName,
+            createPlugin_cb _hidl_cb) override;
+
+private:
+    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(DrmFactory);
+};
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif // CLEARKEY_DRM_FACTORY_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
new file mode 100644
index 0000000..5ae9833
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_DRM_PLUGIN_H_
+#define CLEARKEY_DRM_PLUGIN_H_
+
+
+#include <android/hardware/drm/1.1/IDrmPlugin.h>
+
+#include "SessionLibrary.h"
+#include "Utils.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::drm::V1_0::EventType;
+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::drm::V1_0::SecureStopId;
+using ::android::hardware::drm::V1_0::Status;
+
+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 {
+    explicit DrmPlugin(SessionLibrary* sessionLibrary);
+
+    virtual ~DrmPlugin() {}
+
+    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> getKeyRequest_1_1(
+        const hidl_vec<uint8_t>& scope,
+        const hidl_vec<uint8_t>& initData,
+        const hidl_string& mimeType,
+        KeyType keyType,
+        const hidl_vec<KeyValue>& optionalParameters,
+        getKeyRequest_1_1_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) {
+        if (sessionId.size() == 0) {
+            return Status::BAD_VALUE;
+        }
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    Return<Status> restoreKeys(
+        const hidl_vec<uint8_t>& sessionId,
+        const hidl_vec<uint8_t>& keySetId) {
+
+        if (sessionId.size() == 0 || keySetId.size() == 0) {
+            return Status::BAD_VALUE;
+        }
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    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) {
+        UNUSED(certificateType);
+        UNUSED(certificateAuthority);
+
+        hidl_string defaultUrl;
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(), defaultUrl);
+        return Void();
+    }
+
+    Return<void> provideProvisionResponse(
+        const hidl_vec<uint8_t>& response,
+        provideProvisionResponse_cb _hidl_cb) {
+
+        if (response.size() == 0) {
+            _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>(), hidl_vec<uint8_t>());
+            return Void();
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(), hidl_vec<uint8_t>());
+        return Void();
+    }
+
+    Return<void> getSecureStops(getSecureStops_cb _hidl_cb) {
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<SecureStop>());
+        return Void();
+    }
+
+    Return<void> getSecureStop(
+        const hidl_vec<uint8_t>& secureStopId,
+        getSecureStop_cb _hidl_cb) {
+
+        if (secureStopId.size() == 0) {
+            _hidl_cb(Status::BAD_VALUE, SecureStop());
+            return Void();
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, SecureStop());
+        return Void();
+    }
+
+    Return<Status> releaseSecureStop(const hidl_vec<uint8_t>& ssRelease) {
+        if (ssRelease.size() == 0) {
+            return Status::BAD_VALUE;
+        }
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    Return<Status> releaseAllSecureStops() {
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    Return<void> getHdcpLevels(getHdcpLevels_cb _hidl_cb) {
+        HdcpLevel connectedLevel = HdcpLevel::HDCP_NONE;
+        HdcpLevel maxLevel = HdcpLevel::HDCP_NO_OUTPUT;
+        _hidl_cb(Status::OK, connectedLevel, maxLevel);
+        return Void();
+    }
+
+    Return<void> getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) override;
+
+    Return<void> getSecurityLevel(const hidl_vec<uint8_t>& sessionId,
+            getSecurityLevel_cb _hidl_cb) override;
+
+    Return<Status> setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
+            SecurityLevel level) override;
+
+    Return<void> getPropertyString(
+        const hidl_string& name,
+        getPropertyString_cb _hidl_cb) override;
+
+    Return<void> getPropertyByteArray(
+        const hidl_string& name,
+        getPropertyByteArray_cb _hidl_cb) override;
+
+    Return<Status> setPropertyString(
+            const hidl_string& name, const hidl_string& value) override;
+
+    Return<Status> setPropertyByteArray(
+            const hidl_string& name, const hidl_vec<uint8_t>& value) override;
+
+    Return<Status> setCipherAlgorithm(
+            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
+        if (sessionId.size() == 0 || algorithm.size() == 0) {
+            return Status::BAD_VALUE;
+        }
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    Return<Status> setMacAlgorithm(
+            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
+        if (sessionId.size() == 0 || algorithm.size() == 0) {
+            return Status::BAD_VALUE;
+        }
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    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) {
+        if (sessionId.size() == 0 || keyId.size() == 0 ||
+                input.size() == 0 || iv.size() == 0) {
+            _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
+            return Void();
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
+        return Void();
+    }
+
+    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) {
+        if (sessionId.size() == 0 || keyId.size() == 0 ||
+                input.size() == 0 || iv.size() == 0) {
+            _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
+            return Void();
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
+        return Void();
+    }
+
+    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) {
+        if (sessionId.size() == 0 || keyId.size() == 0 ||
+                message.size() == 0) {
+            _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
+            return Void();
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
+        return Void();
+    }
+
+    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) {
+
+        if (sessionId.size() == 0 || keyId.size() == 0 ||
+                message.size() == 0 || signature.size() == 0) {
+            _hidl_cb(Status::BAD_VALUE, false);
+            return Void();
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, false);
+        return Void();
+    }
+
+    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) {
+        if (sessionId.size() == 0 || algorithm.size() == 0 ||
+                message.size() == 0 || wrappedKey.size() == 0) {
+             _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
+             return Void();
+         }
+         _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
+         return Void();
+    }
+
+    Return<void> setListener(const sp<IDrmPluginListener>& listener) {
+        mListener = listener;
+        return Void();
+    };
+
+    Return<void> sendEvent(EventType eventType, const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& data) {
+        if (mListener != NULL) {
+            mListener->sendEvent(eventType, sessionId, data);
+        } else {
+            ALOGE("Null event listener, event not sent");
+        }
+        return Void();
+    }
+
+    Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId, int64_t expiryTimeInMS) {
+        if (mListener != NULL) {
+            mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
+        } else {
+            ALOGE("Null event listener, event not sent");
+        }
+        return Void();
+    }
+
+    Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
+        if (mListener != NULL) {
+            mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
+        } else {
+            ALOGE("Null event listener, event not sent");
+        }
+        return Void();
+    }
+
+    Return<void> getMetrics(getMetrics_cb _hidl_cb) {
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<DrmMetricGroup>());
+        return Void();
+    }
+
+    Return<void> getSecureStopIds(getSecureStopIds_cb _hidl_cb) {
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<SecureStopId>());
+        return Void();
+    }
+
+    Return<Status> releaseSecureStops(const SecureStopRelease& ssRelease) {
+        if (ssRelease.opaqueData.size() == 0) {
+            return Status::BAD_VALUE;
+        }
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    Return<Status> removeSecureStop(const hidl_vec<uint8_t>& secureStopId) {
+        if (secureStopId.size() == 0) {
+            return Status::BAD_VALUE;
+        }
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    Return<Status> removeAllSecureStops() {
+        return Status::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+private:
+    void initProperties();
+    void setPlayPolicy();
+
+    std::vector<KeyValue> mPlayPolicy;
+    std::map<std::string, std::string> mStringProperties;
+    std::map<std::string, std::vector<uint8_t> > mByteArrayProperties;
+    std::map<std::vector<uint8_t>, SecurityLevel> mSecurityLevel;
+    sp<IDrmPluginListener> mListener;
+    SessionLibrary *mSessionLibrary;
+
+    CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin);
+};
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif // CLEARKEY_DRM_PLUGIN_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h b/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h
new file mode 100644
index 0000000..3189c4a
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *            http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_INIT_DATA_PARSER_H_
+#define CLEARKEY_INIT_DATA_PARSER_H_
+
+#include <android/hardware/drm/1.0/types.h>
+
+#include "ClearKeyTypes.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::drm::V1_0::Status;
+
+class InitDataParser {
+public:
+    InitDataParser() {}
+
+    Status parse(const std::vector<uint8_t>& initData,
+            const std::string& type,
+            std::vector<uint8_t>* licenseRequest);
+
+private:
+    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(InitDataParser);
+
+    Status parsePssh(const std::vector<uint8_t>& initData,
+            std::vector<const uint8_t*>* keyIds);
+
+    std::string generateRequest(
+            const std::vector<const uint8_t*>& keyIds);
+};
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif // CLEARKEY_INIT_DATA_PARSER_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h b/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h
new file mode 100644
index 0000000..4ab034c
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef CLEARKEY_JSON_WEB_KEY_H_
+#define CLEARKEY_JSON_WEB_KEY_H_
+
+#include "jsmn.h"
+#include "Utils.h"
+#include "ClearKeyTypes.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+class JsonWebKey {
+ public:
+    JsonWebKey();
+    virtual ~JsonWebKey();
+
+    bool extractKeysFromJsonWebKeySet(const std::string& jsonWebKeySet,
+            KeyMap* keys);
+
+ private:
+    std::vector<jsmntok_t> mJsmnTokens;
+    std::vector<std::string> mJsonObjects;
+    std::vector<std::string> mTokens;
+
+    bool decodeBase64String(const std::string& encodedText,
+            std::vector<uint8_t>* decodedText);
+    bool findKey(const std::string& jsonObject, std::string* keyId,
+            std::string* encodedKey);
+    void findValue(const std::string &key, std::string* value);
+    bool isJsonWebKeySet(const std::string& jsonObject) const;
+    bool parseJsonObject(const std::string& jsonObject,
+            std::vector<std::string>* tokens);
+    bool parseJsonWebKeySet(const std::string& jsonWebKeySet,
+            std::vector<std::string>* jsonObjects);
+
+    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(JsonWebKey);
+};
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif  // CLEARKEY_JSON_WEB_KEY_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
new file mode 100644
index 0000000..cddfca5
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_SESSION_H_
+#define CLEARKEY_SESSION_H_
+
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+#include <vector>
+
+#include "ClearKeyTypes.h"
+
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::drm::V1_0::Status;
+using ::android::hardware::drm::V1_0::SubSample;
+
+class Session : public RefBase {
+public:
+    explicit Session(const std::vector<uint8_t>& sessionId)
+            : mSessionId(sessionId) {}
+    virtual ~Session() {}
+
+    const std::vector<uint8_t>& sessionId() const { return mSessionId; }
+
+    Status getKeyRequest(
+            const std::vector<uint8_t>& mimeType,
+            const std::string& initDataType,
+            std::vector<uint8_t>* keyRequest) const;
+
+    Status provideKeyResponse(
+            const std::vector<uint8_t>& response);
+
+    Status decrypt(
+            const KeyId keyId, const Iv iv, const uint8_t* srcPtr,
+            uint8_t* dstPtr, const std::vector<SubSample> subSamples,
+            size_t* bytesDecryptedOut);
+
+private:
+    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(Session);
+
+    const std::vector<uint8_t> mSessionId;
+    KeyMap mKeyMap;
+    Mutex mMapLock;
+};
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif // CLEARKEY_SESSION_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h b/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h
new file mode 100644
index 0000000..326a0c1
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_SESSION_LIBRARY_H_
+#define CLEARKEY_SESSION_LIBRARY_H_
+
+#include <utils/RefBase.h>
+#include <utils/Mutex.h>
+
+#include "ClearKeyTypes.h"
+#include "Session.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::sp;
+
+class SessionLibrary : public RefBase {
+public:
+    static SessionLibrary* get();
+
+    sp<Session> createSession();
+
+    sp<Session> findSession(
+            const std::vector<uint8_t>& sessionId);
+
+    void destroySession(const sp<Session>& session);
+
+    size_t numOpenSessions() const { return mSessions.size(); }
+
+private:
+    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(SessionLibrary);
+
+    SessionLibrary() : mNextSessionId(1) {}
+
+    static Mutex sSingletonLock;
+    static SessionLibrary* sSingleton;
+
+    Mutex mSessionsLock;
+    uint32_t mNextSessionId;
+    std::map<std::vector<uint8_t>, sp<Session> > mSessions;
+};
+
+} // namespace clearkey
+} // namespace V1_1
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif // CLEARKEY_SESSION_LIBRARY_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
new file mode 100644
index 0000000..cc06329
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_ANDROID_HARDWARE_DRM_V1_1_TYPECONVERT
+#define CLEARKEY_ANDROID_HARDWARE_DRM_V1_1_TYPECONVERT
+
+#include <vector>
+
+#include <android/hardware/drm/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_1 {
+namespace clearkey {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_vec;
+
+template<typename T> const hidl_vec<T> toHidlVec(const std::vector<T> &vec) {
+    hidl_vec<T> hVec;
+    hVec.setToExternal(const_cast<T *>(vec.data()), vec.size());
+    return hVec;
+}
+
+template<typename T> hidl_vec<T> toHidlVec(std::vector<T> &vec) {
+    hidl_vec<T> hVec;
+    hVec.setToExternal(vec.data(), vec.size());
+    return hVec;
+}
+
+template<typename T> const std::vector<T> toVector(const hidl_vec<T> &hVec) {
+    std::vector<T> vec;
+    vec.assign(hVec.data(), hVec.data() + hVec.size());
+    return *const_cast<const std::vector<T> *>(&vec);
+}
+
+template<typename T> std::vector<T> toVector(hidl_vec<T> &hVec) {
+    std::vector<T> vec;
+    vec.assign(hVec.data(), hVec.data() + hVec.size());
+    return vec;
+}
+
+template<typename T, size_t SIZE> const std::vector<T> toVector(
+        const hidl_array<T, SIZE> &hArray) {
+    std::vector<T> vec;
+    vec.assign(hArray.data(), hArray.data() + hArray.size());
+    return vec;
+}
+
+template<typename T, size_t SIZE> std::vector<T> toVector(
+        hidl_array<T, SIZE> &hArray) {
+    std::vector<T> vec;
+    vec.assign(hArray.data(), hArray.data() + hArray.size());
+    return vec;
+}
+
+}  // namespace clearkey
+}  // namespace V1_1
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif // CLEARKEY_ANDROID_HARDWARE_DRM_V1_1_TYPECONVERT
diff --git a/drm/mediadrm/plugins/clearkey/hidl/service.cpp b/drm/mediadrm/plugins/clearkey/hidl/service.cpp
new file mode 100644
index 0000000..6a97b72
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/service.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.drm@1.1-service.clearkey"
+
+#include <CryptoFactory.h>
+#include <DrmFactory.h>
+
+#include <android-base/logging.h>
+#include <binder/ProcessState.h>
+#include <hidl/HidlTransportSupport.h>
+
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+using ::android::sp;
+
+using android::hardware::drm::V1_1::ICryptoFactory;
+using android::hardware::drm::V1_1::IDrmFactory;
+using android::hardware::drm::V1_1::clearkey::CryptoFactory;
+using android::hardware::drm::V1_1::clearkey::DrmFactory;
+
+
+int main(int /* argc */, char** /* argv */) {
+    ALOGD("android.hardware.drm@1.1-service.clearkey starting...");
+
+    // The DRM HAL may communicate to other vendor components via
+    // /dev/vndbinder
+    android::ProcessState::initWithDriver("/dev/vndbinder");
+
+    sp<IDrmFactory> drmFactory = new DrmFactory;
+    sp<ICryptoFactory> cryptoFactory = new CryptoFactory;
+
+    configureRpcThreadpool(8, true /* callerWillJoin */);
+
+    // Setup hwbinder service
+    CHECK_EQ(drmFactory->registerAsService("clearkey"), android::NO_ERROR)
+        << "Failed to register Clearkey Factory HAL";
+    CHECK_EQ(cryptoFactory->registerAsService("clearkey"), android::NO_ERROR)
+        << "Failed to register Clearkey Crypto  HAL";
+
+    joinRpcThreadpool();
+}
diff --git a/include/media/DataSourceBase.h b/include/media/DataSourceBase.h
new file mode 120000
index 0000000..54c8047
--- /dev/null
+++ b/include/media/DataSourceBase.h
@@ -0,0 +1 @@
+../../media/libmediaextractor/include/media/DataSourceBase.h
\ No newline at end of file
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index 6f28374..1614ca4 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -19,7 +19,7 @@
 #include <utils/Log.h>
 
 #include "AACExtractor.h"
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -35,7 +35,7 @@
 
 class AACSource : public MediaSourceBase {
 public:
-    AACSource(const sp<DataSource> &source,
+    AACSource(DataSourceBase *source,
               const sp<MetaData> &meta,
               const Vector<uint64_t> &offset_vector,
               int64_t frame_duration_us);
@@ -53,7 +53,7 @@
 
 private:
     static const size_t kMaxFrameSize;
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     sp<MetaData> mMeta;
 
     off64_t mOffset;
@@ -91,7 +91,7 @@
 // The returned value is the AAC frame size with the ADTS header length (regardless of
 //     the presence of the CRC).
 // If headerSize is non-NULL, it will be used to return the size of the header of this ADTS frame.
-static size_t getAdtsFrameLength(const sp<DataSource> &source, off64_t offset, size_t* headerSize) {
+static size_t getAdtsFrameLength(DataSourceBase *source, off64_t offset, size_t* headerSize) {
 
     const size_t kAdtsHeaderLengthNoCrc = 7;
     const size_t kAdtsHeaderLengthWithCrc = 9;
@@ -132,7 +132,7 @@
 }
 
 AACExtractor::AACExtractor(
-        const sp<DataSource> &source, const sp<AMessage> &_meta)
+        DataSourceBase *source, const sp<AMessage> &_meta)
     : mDataSource(source),
       mInitCheck(NO_INIT),
       mFrameDurationUs(0) {
@@ -229,7 +229,7 @@
 const size_t AACSource::kMaxFrameSize = 8192;
 
 AACSource::AACSource(
-        const sp<DataSource> &source, const sp<MetaData> &meta,
+        DataSourceBase *source, const sp<MetaData> &meta,
         const Vector<uint64_t> &offset_vector,
         int64_t frame_duration_us)
     : mDataSource(source),
@@ -332,13 +332,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 static MediaExtractor* CreateExtractor(
-        const sp<DataSource> &source,
+        DataSourceBase *source,
         const sp<AMessage>& meta) {
     return new AACExtractor(source, meta);
 }
 
 static MediaExtractor::CreatorFunc Sniff(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *meta) {
     off64_t pos = 0;
 
diff --git a/media/extractors/aac/AACExtractor.h b/media/extractors/aac/AACExtractor.h
index 33fbba7..e99699c 100644
--- a/media/extractors/aac/AACExtractor.h
+++ b/media/extractors/aac/AACExtractor.h
@@ -29,7 +29,7 @@
 
 class AACExtractor : public MediaExtractor {
 public:
-    AACExtractor(const sp<DataSource> &source, const sp<AMessage> &meta);
+    AACExtractor(DataSourceBase *source, const sp<AMessage> &meta);
 
     virtual size_t countTracks();
     virtual MediaSourceBase *getTrack(size_t index);
@@ -42,7 +42,7 @@
     virtual ~AACExtractor();
 
 private:
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     sp<MetaData> mMeta;
     status_t mInitCheck;
 
@@ -54,7 +54,7 @@
 };
 
 bool SniffAAC(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *);
 
 }  // namespace android
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index 10be50c..547e3f5 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -20,7 +20,7 @@
 
 #include "AMRExtractor.h"
 
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaBufferGroup.h>
@@ -33,7 +33,7 @@
 
 class AMRSource : public MediaSourceBase {
 public:
-    AMRSource(const sp<DataSource> &source,
+    AMRSource(DataSourceBase *source,
               const sp<MetaData> &meta,
               bool isWide,
               const off64_t *offset_table,
@@ -51,7 +51,7 @@
     virtual ~AMRSource();
 
 private:
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     sp<MetaData> mMeta;
     bool mIsWide;
 
@@ -97,7 +97,7 @@
     return frameSize;
 }
 
-static status_t getFrameSizeByOffset(const sp<DataSource> &source,
+static status_t getFrameSizeByOffset(DataSourceBase *source,
         off64_t offset, bool isWide, size_t *frameSize) {
     uint8_t header;
     ssize_t count = source->readAt(offset, &header, 1);
@@ -116,7 +116,7 @@
     return OK;
 }
 
-AMRExtractor::AMRExtractor(const sp<DataSource> &source)
+AMRExtractor::AMRExtractor(DataSourceBase *source)
     : mDataSource(source),
       mInitCheck(NO_INIT),
       mOffsetTableLength(0) {
@@ -206,7 +206,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 AMRSource::AMRSource(
-        const sp<DataSource> &source, const sp<MetaData> &meta,
+        DataSourceBase *source, const sp<MetaData> &meta,
         bool isWide, const off64_t *offset_table, size_t offset_table_length)
     : mDataSource(source),
       mMeta(meta),
@@ -339,7 +339,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 bool SniffAMR(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *) {
     char header[9];
 
@@ -372,13 +372,13 @@
         1,
         "AMR Extractor",
         [](
-                const sp<DataSource> &source,
+                DataSourceBase *source,
                 String8 *mimeType,
                 float *confidence,
                 sp<AMessage> *meta __unused) -> MediaExtractor::CreatorFunc {
             if (SniffAMR(source, mimeType, confidence, meta)) {
                 return [](
-                        const sp<DataSource> &source,
+                        DataSourceBase *source,
                         const sp<AMessage>& meta __unused) -> MediaExtractor* {
                     return new AMRExtractor(source);};
             }
diff --git a/media/extractors/amr/AMRExtractor.h b/media/extractors/amr/AMRExtractor.h
index 56883e3..d6d49f2 100644
--- a/media/extractors/amr/AMRExtractor.h
+++ b/media/extractors/amr/AMRExtractor.h
@@ -29,7 +29,7 @@
 
 class AMRExtractor : public MediaExtractor {
 public:
-    explicit AMRExtractor(const sp<DataSource> &source);
+    explicit AMRExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
     virtual MediaSourceBase *getTrack(size_t index);
@@ -42,7 +42,7 @@
     virtual ~AMRExtractor();
 
 private:
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     sp<MetaData> mMeta;
     status_t mInitCheck;
     bool mIsWide;
@@ -55,7 +55,7 @@
 };
 
 bool SniffAMR(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *);
 
 }  // namespace android
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index ba28e86..8dbb5a1 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -22,7 +22,7 @@
 // libFLAC parser
 #include "FLAC/stream_decoder.h"
 
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -165,7 +165,7 @@
 
 public:
     FLACSource(
-            const sp<DataSource> &dataSource,
+            DataSourceBase *dataSource,
             const sp<MetaData> &trackMetadata);
 
     virtual status_t start(MetaData *params);
@@ -179,7 +179,7 @@
     virtual ~FLACSource();
 
 private:
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     sp<MetaData> mTrackMetadata;
     sp<FLACParser> mParser;
     bool mInitCheck;
@@ -203,7 +203,7 @@
     };
 
     explicit FLACParser(
-        const sp<DataSource> &dataSource,
+        DataSourceBase *dataSource,
         // If metadata pointers aren't provided, we don't fill them
         const sp<MetaData> &fileMetadata = 0,
         const sp<MetaData> &trackMetadata = 0);
@@ -243,7 +243,7 @@
     virtual ~FLACParser();
 
 private:
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     sp<MetaData> mFileMetadata;
     sp<MetaData> mTrackMetadata;
     bool mInitCheck;
@@ -612,7 +612,7 @@
 // FLACParser
 
 FLACParser::FLACParser(
-        const sp<DataSource> &dataSource,
+        DataSourceBase *dataSource,
         const sp<MetaData> &fileMetadata,
         const sp<MetaData> &trackMetadata)
     : mDataSource(dataSource),
@@ -833,7 +833,7 @@
 // FLACsource
 
 FLACSource::FLACSource(
-        const sp<DataSource> &dataSource,
+        DataSourceBase *dataSource,
         const sp<MetaData> &trackMetadata)
     : mDataSource(dataSource),
       mTrackMetadata(trackMetadata),
@@ -918,7 +918,7 @@
 // FLACExtractor
 
 FLACExtractor::FLACExtractor(
-        const sp<DataSource> &dataSource)
+        DataSourceBase *dataSource)
     : mDataSource(dataSource),
       mInitCheck(false)
 {
@@ -969,7 +969,7 @@
 // Sniffer
 
 bool SniffFLAC(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *)
 {
     // first 4 is the signature word
@@ -1000,13 +1000,13 @@
             1,
             "FLAC Extractor",
             [](
-                    const sp<DataSource> &source,
+                    DataSourceBase *source,
                     String8 *mimeType,
                     float *confidence,
                     sp<AMessage> *meta __unused) -> MediaExtractor::CreatorFunc {
                 if (SniffFLAC(source, mimeType, confidence, meta)) {
                     return [](
-                            const sp<DataSource> &source,
+                            DataSourceBase *source,
                             const sp<AMessage>& meta __unused) -> MediaExtractor* {
                         return new FLACExtractor(source);};
                 }
diff --git a/media/extractors/flac/FLACExtractor.h b/media/extractors/flac/FLACExtractor.h
index 2e7ee3b..ef07212 100644
--- a/media/extractors/flac/FLACExtractor.h
+++ b/media/extractors/flac/FLACExtractor.h
@@ -17,7 +17,7 @@
 #ifndef FLAC_EXTRACTOR_H_
 #define FLAC_EXTRACTOR_H_
 
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/MediaExtractor.h>
 #include <utils/String8.h>
 
@@ -28,8 +28,7 @@
 class FLACExtractor : public MediaExtractor {
 
 public:
-    // Extractor assumes ownership of source
-    explicit FLACExtractor(const sp<DataSource> &source);
+    explicit FLACExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
     virtual MediaSourceBase *getTrack(size_t index);
@@ -42,7 +41,7 @@
     virtual ~FLACExtractor();
 
 private:
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     sp<FLACParser> mParser;
     status_t mInitCheck;
     sp<MetaData> mFileMetadata;
@@ -57,7 +56,7 @@
 
 };
 
-bool SniffFLAC(const sp<DataSource> &source, String8 *mimeType,
+bool SniffFLAC(DataSourceBase *source, String8 *mimeType,
         float *confidence, sp<AMessage> *);
 
 }  // namespace android
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp
index 18b1d23..711c6a5 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/extractors/midi/MidiExtractor.cpp
@@ -141,7 +141,7 @@
 
 // MidiEngine
 
-MidiEngine::MidiEngine(const sp<DataSource> &dataSource,
+MidiEngine::MidiEngine(DataSourceBase *dataSource,
         const sp<MetaData> &fileMetadata,
         const sp<MetaData> &trackMetadata) :
             mGroup(NULL),
@@ -261,7 +261,7 @@
 // MidiExtractor
 
 MidiExtractor::MidiExtractor(
-        const sp<DataSource> &dataSource)
+        DataSourceBase *dataSource)
     : mDataSource(dataSource),
       mInitCheck(false)
 {
@@ -308,7 +308,7 @@
 // Sniffer
 
 bool SniffMidi(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *)
 {
     sp<MidiEngine> p = new MidiEngine(source, NULL, NULL);
@@ -333,13 +333,13 @@
         1,
         "MIDI Extractor",
         [](
-                const sp<DataSource> &source,
+                DataSourceBase *source,
                 String8 *mimeType,
                 float *confidence,
                 sp<AMessage> *meta __unused) -> MediaExtractor::CreatorFunc {
             if (SniffMidi(source, mimeType, confidence, meta)) {
                 return [](
-                        const sp<DataSource> &source,
+                        DataSourceBase *source,
                         const sp<AMessage>& meta __unused) -> MediaExtractor* {
                     return new MidiExtractor(source);};
             }
diff --git a/media/extractors/midi/MidiExtractor.h b/media/extractors/midi/MidiExtractor.h
index 87e4654..91efd06 100644
--- a/media/extractors/midi/MidiExtractor.h
+++ b/media/extractors/midi/MidiExtractor.h
@@ -17,7 +17,7 @@
 #ifndef MIDI_EXTRACTOR_H_
 #define MIDI_EXTRACTOR_H_
 
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/MediaExtractor.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaBufferGroup.h>
@@ -29,7 +29,7 @@
 
 class MidiEngine : public RefBase {
 public:
-    MidiEngine(const sp<DataSource> &dataSource,
+    MidiEngine(DataSourceBase *dataSource,
             const sp<MetaData> &fileMetadata,
             const sp<MetaData> &trackMetadata);
     ~MidiEngine();
@@ -52,8 +52,7 @@
 class MidiExtractor : public MediaExtractor {
 
 public:
-    // Extractor assumes ownership of source
-    explicit MidiExtractor(const sp<DataSource> &source);
+    explicit MidiExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
     virtual MediaSourceBase *getTrack(size_t index);
@@ -66,7 +65,7 @@
     virtual ~MidiExtractor();
 
 private:
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     status_t mInitCheck;
     sp<MetaData> mFileMetadata;
 
@@ -88,7 +87,7 @@
 
 };
 
-bool SniffMidi(const sp<DataSource> &source, String8 *mimeType,
+bool SniffMidi(DataSourceBase *source, String8 *mimeType,
         float *confidence, sp<AMessage> *);
 
 }  // namespace android
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 6df0012..f61f7c7 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -21,7 +21,7 @@
 #include "FLACDecoder.h"
 #include "MatroskaExtractor.h"
 
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AUtils.h>
@@ -40,8 +40,8 @@
 
 namespace android {
 
-struct DataSourceReader : public mkvparser::IMkvReader {
-    explicit DataSourceReader(const sp<DataSource> &source)
+struct DataSourceBaseReader : public mkvparser::IMkvReader {
+    explicit DataSourceBaseReader(DataSourceBase *source)
         : mSource(source) {
     }
 
@@ -83,10 +83,10 @@
     }
 
 private:
-    sp<DataSource> mSource;
+    DataSourceBase *mSource;
 
-    DataSourceReader(const DataSourceReader &);
-    DataSourceReader &operator=(const DataSourceReader &);
+    DataSourceBaseReader(const DataSourceBaseReader &);
+    DataSourceBaseReader &operator=(const DataSourceBaseReader &);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -852,9 +852,9 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
+MatroskaExtractor::MatroskaExtractor(DataSourceBase *source)
     : mDataSource(source),
-      mReader(new DataSourceReader(mDataSource)),
+      mReader(new DataSourceBaseReader(mDataSource)),
       mSegment(NULL),
       mExtractedThumbnails(false),
       mIsWebm(false),
@@ -862,8 +862,8 @@
     off64_t size;
     mIsLiveStreaming =
         (mDataSource->flags()
-            & (DataSource::kWantsPrefetching
-                | DataSource::kIsCachingDataSource))
+            & (DataSourceBase::kWantsPrefetching
+                | DataSourceBase::kIsCachingDataSource))
         && mDataSource->getSize(&size) != OK;
 
     mkvparser::EBMLHeader ebmlHeader;
@@ -1548,9 +1548,9 @@
 }
 
 bool SniffMatroska(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *) {
-    DataSourceReader reader(source);
+    DataSourceBaseReader reader(source);
     mkvparser::EBMLHeader ebmlHeader;
     long long pos;
     if (ebmlHeader.Parse(&reader, pos) < 0) {
@@ -1574,13 +1574,13 @@
         1,
         "Matroska Extractor",
         [](
-                const sp<DataSource> &source,
+                DataSourceBase *source,
                 String8 *mimeType,
                 float *confidence,
                 sp<AMessage> *meta __unused) -> MediaExtractor::CreatorFunc {
             if (SniffMatroska(source, mimeType, confidence, meta)) {
                 return [](
-                        const sp<DataSource> &source,
+                        DataSourceBase *source,
                         const sp<AMessage>& meta __unused) -> MediaExtractor* {
                     return new MatroskaExtractor(source);};
             }
diff --git a/media/extractors/mkv/MatroskaExtractor.h b/media/extractors/mkv/MatroskaExtractor.h
index 54419bf..095452b 100644
--- a/media/extractors/mkv/MatroskaExtractor.h
+++ b/media/extractors/mkv/MatroskaExtractor.h
@@ -30,11 +30,11 @@
 class String8;
 
 class MetaData;
-struct DataSourceReader;
+struct DataSourceBaseReader;
 struct MatroskaSource;
 
 struct MatroskaExtractor : public MediaExtractor {
-    explicit MatroskaExtractor(const sp<DataSource> &source);
+    explicit MatroskaExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
 
@@ -76,8 +76,8 @@
     Mutex mLock;
     Vector<TrackInfo> mTracks;
 
-    sp<DataSource> mDataSource;
-    DataSourceReader *mReader;
+    DataSourceBase *mDataSource;
+    DataSourceBaseReader *mReader;
     mkvparser::Segment *mSegment;
     bool mExtractedThumbnails;
     bool mIsLiveStreaming;
@@ -96,7 +96,7 @@
 };
 
 bool SniffMatroska(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *);
 
 }  // namespace android
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 7e27fd8..25d4deb 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -24,7 +24,7 @@
 #include "VBRISeeker.h"
 #include "XINGSeeker.h"
 
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -46,7 +46,7 @@
 static const uint32_t kMask = 0xfffe0c00;
 
 static bool Resync(
-        const sp<DataSource> &source, uint32_t match_header,
+        DataSourceBase *source, uint32_t match_header,
         off64_t *inout_pos, off64_t *post_id3_pos, uint32_t *out_header) {
     if (post_id3_pos != NULL) {
         *post_id3_pos = 0;
@@ -212,7 +212,7 @@
 class MP3Source : public MediaSourceBase {
 public:
     MP3Source(
-            const sp<MetaData> &meta, const sp<DataSource> &source,
+            const sp<MetaData> &meta, DataSourceBase *source,
             off64_t first_frame_pos, uint32_t fixed_header,
             const sp<MP3Seeker> &seeker);
 
@@ -230,7 +230,7 @@
 private:
     static const size_t kMaxFrameSize;
     sp<MetaData> mMeta;
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     off64_t mFirstFramePos;
     uint32_t mFixedHeader;
     off64_t mCurrentPos;
@@ -247,7 +247,7 @@
 };
 
 MP3Extractor::MP3Extractor(
-        const sp<DataSource> &source, const sp<AMessage> &meta)
+        DataSourceBase *source, const sp<AMessage> &meta)
     : mInitCheck(NO_INIT),
       mDataSource(source),
       mFirstFramePos(-1),
@@ -436,7 +436,7 @@
 // Set our max frame size to the nearest power of 2 above this size (aka, 4kB)
 const size_t MP3Source::kMaxFrameSize = (1 << 12); /* 4096 bytes */
 MP3Source::MP3Source(
-        const sp<MetaData> &meta, const sp<DataSource> &source,
+        const sp<MetaData> &meta, DataSourceBase *source,
         off64_t first_frame_pos, uint32_t fixed_header,
         const sp<MP3Seeker> &seeker)
     : mMeta(meta),
@@ -667,13 +667,13 @@
 }
 
 static MediaExtractor* CreateExtractor(
-        const sp<DataSource> &source,
+        DataSourceBase *source,
         const sp<AMessage>& meta) {
     return new MP3Extractor(source, meta);
 }
 
 static MediaExtractor::CreatorFunc Sniff(
-        const sp<DataSource> &source, String8 *mimeType,
+        DataSourceBase *source, String8 *mimeType,
         float *confidence, sp<AMessage> *meta) {
     off64_t pos = 0;
     off64_t post_id3_pos;
diff --git a/media/extractors/mp3/MP3Extractor.h b/media/extractors/mp3/MP3Extractor.h
index 3b3387d..6257112 100644
--- a/media/extractors/mp3/MP3Extractor.h
+++ b/media/extractors/mp3/MP3Extractor.h
@@ -24,14 +24,13 @@
 namespace android {
 
 struct AMessage;
-class DataSource;
+class DataSourceBase;
 struct MP3Seeker;
 class String8;
 
 class MP3Extractor : public MediaExtractor {
 public:
-    // Extractor assumes ownership of "source".
-    MP3Extractor(const sp<DataSource> &source, const sp<AMessage> &meta);
+    MP3Extractor(DataSourceBase *source, const sp<AMessage> &meta);
 
     virtual size_t countTracks();
     virtual MediaSourceBase *getTrack(size_t index);
@@ -43,7 +42,7 @@
 private:
     status_t mInitCheck;
 
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     off64_t mFirstFramePos;
     sp<MetaData> mMeta;
     uint32_t mFixedHeader;
@@ -54,7 +53,7 @@
 };
 
 bool SniffMP3(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *meta);
 
 }  // namespace android
diff --git a/media/extractors/mp3/VBRISeeker.cpp b/media/extractors/mp3/VBRISeeker.cpp
index e7db6fd..51c5d1f 100644
--- a/media/extractors/mp3/VBRISeeker.cpp
+++ b/media/extractors/mp3/VBRISeeker.cpp
@@ -27,7 +27,7 @@
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ByteUtils.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 
 namespace android {
 
@@ -37,7 +37,7 @@
 
 // static
 sp<VBRISeeker> VBRISeeker::CreateFromSource(
-        const sp<DataSource> &source, off64_t post_id3_pos) {
+        DataSourceBase *source, off64_t post_id3_pos) {
     off64_t pos = post_id3_pos;
 
     uint8_t header[4];
diff --git a/media/extractors/mp3/VBRISeeker.h b/media/extractors/mp3/VBRISeeker.h
index 87258b0..e46af36 100644
--- a/media/extractors/mp3/VBRISeeker.h
+++ b/media/extractors/mp3/VBRISeeker.h
@@ -24,11 +24,11 @@
 
 namespace android {
 
-class DataSource;
+class DataSourceBase;
 
 struct VBRISeeker : public MP3Seeker {
     static sp<VBRISeeker> CreateFromSource(
-            const sp<DataSource> &source, off64_t post_id3_pos);
+            DataSourceBase *source, off64_t post_id3_pos);
 
     virtual bool getDuration(int64_t *durationUs);
     virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos);
diff --git a/media/extractors/mp3/XINGSeeker.cpp b/media/extractors/mp3/XINGSeeker.cpp
index fa59701..adfa8d2 100644
--- a/media/extractors/mp3/XINGSeeker.cpp
+++ b/media/extractors/mp3/XINGSeeker.cpp
@@ -21,7 +21,7 @@
 #include <media/stagefright/foundation/avc_utils.h>
 
 #include <media/stagefright/foundation/ByteUtils.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 
 namespace android {
 
@@ -77,7 +77,7 @@
 
 // static
 sp<XINGSeeker> XINGSeeker::CreateFromSource(
-        const sp<DataSource> &source, off64_t first_frame_pos) {
+        DataSourceBase *source, off64_t first_frame_pos) {
     sp<XINGSeeker> seeker = new XINGSeeker;
 
     seeker->mFirstFramePos = first_frame_pos;
diff --git a/media/extractors/mp3/XINGSeeker.h b/media/extractors/mp3/XINGSeeker.h
index 37077c4..db847bc 100644
--- a/media/extractors/mp3/XINGSeeker.h
+++ b/media/extractors/mp3/XINGSeeker.h
@@ -22,11 +22,11 @@
 
 namespace android {
 
-class DataSource;
+class DataSourceBase;
 
 struct XINGSeeker : public MP3Seeker {
     static sp<XINGSeeker> CreateFromSource(
-            const sp<DataSource> &source, off64_t first_frame_pos);
+            DataSourceBase *source, off64_t first_frame_pos);
 
     virtual bool getDuration(int64_t *durationUs);
     virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos);
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index 85c66b2..cef5f4a 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -18,7 +18,7 @@
 #define LOG_TAG "ItemTable"
 
 #include <ItemTable.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -87,7 +87,7 @@
 
 struct Box {
 protected:
-    Box(const sp<DataSource> source, uint32_t type) :
+    Box(DataSourceBase *source, uint32_t type) :
         mDataSource(source), mType(type) {}
 
     virtual ~Box() {}
@@ -99,14 +99,14 @@
 
     inline uint32_t type() const { return mType; }
 
-    inline sp<DataSource> source() const { return mDataSource; }
+    inline DataSourceBase *source() const { return mDataSource; }
 
     status_t parseChunk(off64_t *offset);
 
     status_t parseChunks(off64_t offset, size_t size);
 
 private:
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     uint32_t mType;
 };
 
@@ -181,7 +181,7 @@
 
 struct FullBox : public Box {
 protected:
-    FullBox(const sp<DataSource> source, uint32_t type) :
+    FullBox(DataSourceBase *source, uint32_t type) :
         Box(source, type), mVersion(0), mFlags(0) {}
 
     inline uint8_t version() const { return mVersion; }
@@ -216,7 +216,7 @@
 //
 
 struct PitmBox : public FullBox {
-    PitmBox(const sp<DataSource> source) :
+    PitmBox(DataSourceBase *source) :
         FullBox(source, FOURCC('p', 'i', 't', 'm')) {}
 
     status_t parse(off64_t offset, size_t size, uint32_t *primaryItemId);
@@ -296,7 +296,7 @@
 };
 
 struct IlocBox : public FullBox {
-    IlocBox(const sp<DataSource> source, KeyedVector<uint32_t, ItemLoc> *itemLocs) :
+    IlocBox(DataSourceBase *source, KeyedVector<uint32_t, ItemLoc> *itemLocs) :
         FullBox(source, FOURCC('i', 'l', 'o', 'c')),
         mItemLocs(itemLocs), mHasConstructMethod1(false) {}
 
@@ -466,7 +466,7 @@
 //
 
 struct ItemReference : public Box, public RefBase {
-    ItemReference(const sp<DataSource> source, uint32_t type, uint32_t itemIdSize) :
+    ItemReference(DataSourceBase *source, uint32_t type, uint32_t itemIdSize) :
         Box(source, type), mItemId(0), mRefIdSize(itemIdSize) {}
 
     status_t parse(off64_t offset, size_t size);
@@ -575,7 +575,7 @@
 }
 
 struct IrefBox : public FullBox {
-    IrefBox(const sp<DataSource> source, Vector<sp<ItemReference> > *itemRefs) :
+    IrefBox(DataSourceBase *source, Vector<sp<ItemReference> > *itemRefs) :
         FullBox(source, FOURCC('i', 'r', 'e', 'f')), mRefIdSize(0), mItemRefs(itemRefs) {}
 
     status_t parse(off64_t offset, size_t size);
@@ -637,7 +637,7 @@
 };
 
 struct IspeBox : public FullBox, public ItemProperty {
-    IspeBox(const sp<DataSource> source) :
+    IspeBox(DataSourceBase *source) :
         FullBox(source, FOURCC('i', 's', 'p', 'e')), mWidth(0), mHeight(0) {}
 
     status_t parse(off64_t offset, size_t size) override;
@@ -673,7 +673,7 @@
 }
 
 struct HvccBox : public Box, public ItemProperty {
-    HvccBox(const sp<DataSource> source) :
+    HvccBox(DataSourceBase *source) :
         Box(source, FOURCC('h', 'v', 'c', 'C')) {}
 
     status_t parse(off64_t offset, size_t size) override;
@@ -706,7 +706,7 @@
 }
 
 struct IrotBox : public Box, public ItemProperty {
-    IrotBox(const sp<DataSource> source) :
+    IrotBox(DataSourceBase *source) :
         Box(source, FOURCC('i', 'r', 'o', 't')), mAngle(0) {}
 
     status_t parse(off64_t offset, size_t size) override;
@@ -735,7 +735,7 @@
 }
 
 struct ColrBox : public Box, public ItemProperty {
-    ColrBox(const sp<DataSource> source) :
+    ColrBox(DataSourceBase *source) :
         Box(source, FOURCC('c', 'o', 'l', 'r')) {}
 
     status_t parse(off64_t offset, size_t size) override;
@@ -783,7 +783,7 @@
 }
 
 struct IpmaBox : public FullBox {
-    IpmaBox(const sp<DataSource> source, Vector<AssociationEntry> *associations) :
+    IpmaBox(DataSourceBase *source, Vector<AssociationEntry> *associations) :
         FullBox(source, FOURCC('i', 'p', 'm', 'a')), mAssociations(associations) {}
 
     status_t parse(off64_t offset, size_t size);
@@ -857,7 +857,7 @@
 }
 
 struct IpcoBox : public Box {
-    IpcoBox(const sp<DataSource> source, Vector<sp<ItemProperty> > *properties) :
+    IpcoBox(DataSourceBase *source, Vector<sp<ItemProperty> > *properties) :
         Box(source, FOURCC('i', 'p', 'c', 'o')), mItemProperties(properties) {}
 
     status_t parse(off64_t offset, size_t size);
@@ -914,7 +914,7 @@
 }
 
 struct IprpBox : public Box {
-    IprpBox(const sp<DataSource> source,
+    IprpBox(DataSourceBase *source,
             Vector<sp<ItemProperty> > *properties,
             Vector<AssociationEntry> *associations) :
         Box(source, FOURCC('i', 'p', 'r', 'p')),
@@ -971,7 +971,7 @@
 };
 
 struct InfeBox : public FullBox {
-    InfeBox(const sp<DataSource> source) :
+    InfeBox(DataSourceBase *source) :
         FullBox(source, FOURCC('i', 'n', 'f', 'e')) {}
 
     status_t parse(off64_t offset, size_t size, ItemInfo *itemInfo);
@@ -1075,7 +1075,7 @@
 }
 
 struct IinfBox : public FullBox {
-    IinfBox(const sp<DataSource> source, Vector<ItemInfo> *itemInfos) :
+    IinfBox(DataSourceBase *source, Vector<ItemInfo> *itemInfos) :
         FullBox(source, FOURCC('i', 'i', 'n', 'f')),
         mItemInfos(itemInfos), mHasGrids(false) {}
 
@@ -1144,7 +1144,7 @@
 
 //////////////////////////////////////////////////////////////////
 
-ItemTable::ItemTable(const sp<DataSource> &source)
+ItemTable::ItemTable(DataSourceBase *source)
     : mDataSource(source),
       mPrimaryItemId(0),
       mIdatOffset(0),
diff --git a/media/extractors/mp4/ItemTable.h b/media/extractors/mp4/ItemTable.h
index 3d2e2ae..f4a69cc 100644
--- a/media/extractors/mp4/ItemTable.h
+++ b/media/extractors/mp4/ItemTable.h
@@ -25,7 +25,7 @@
 
 namespace android {
 
-class DataSource;
+class DataSourceBase;
 class MetaData;
 
 namespace heif {
@@ -44,7 +44,7 @@
 
 class ItemTable : public RefBase {
 public:
-    explicit ItemTable(const sp<DataSource> &source);
+    explicit ItemTable(DataSourceBase *source);
 
     status_t parse(uint32_t type, off64_t offset, size_t size);
 
@@ -60,7 +60,7 @@
     ~ItemTable();
 
 private:
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
 
     KeyedVector<uint32_t, ItemLoc> mItemLocs;
     Vector<ItemInfo> mItemInfos;
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 9f21db6..30dda13 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -69,7 +69,7 @@
 public:
     // Caller retains ownership of both "dataSource" and "sampleTable".
     MPEG4Source(const sp<MetaData> &format,
-                const sp<DataSource> &dataSource,
+                DataSourceBase *dataSource,
                 int32_t timeScale,
                 const sp<SampleTable> &sampleTable,
                 Vector<SidxEntry> &sidx,
@@ -93,7 +93,7 @@
     Mutex mLock;
 
     sp<MetaData> mFormat;
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     int32_t mTimescale;
     sp<SampleTable> mSampleTable;
     uint32_t mCurrentSampleIndex;
@@ -186,47 +186,51 @@
 // all remaining requests to the wrapped datasource.
 // This is used to cache the full sampletable metadata for a single track,
 // possibly wrapping multiple times to cover all tracks, i.e.
-// Each MPEG4DataSource caches the sampletable metadata for a single track.
+// Each CachedRangedDataSource caches the sampletable metadata for a single track.
 
-struct MPEG4DataSource : public DataSource {
-    explicit MPEG4DataSource(const sp<DataSource> &source);
+struct CachedRangedDataSource : public DataSourceBase {
+    explicit CachedRangedDataSource(DataSourceBase *source);
+    virtual ~CachedRangedDataSource();
 
     virtual status_t initCheck() const;
     virtual ssize_t readAt(off64_t offset, void *data, size_t size);
     virtual status_t getSize(off64_t *size);
     virtual uint32_t flags();
 
-    status_t setCachedRange(off64_t offset, size_t size);
+    status_t setCachedRange(off64_t offset, size_t size, bool assumeSourceOwnershipOnSuccess);
 
-protected:
-    virtual ~MPEG4DataSource();
 
 private:
     Mutex mLock;
 
-    sp<DataSource> mSource;
+    DataSourceBase *mSource;
+    bool mOwnsDataSource;
     off64_t mCachedOffset;
     size_t mCachedSize;
     uint8_t *mCache;
 
     void clearCache();
 
-    MPEG4DataSource(const MPEG4DataSource &);
-    MPEG4DataSource &operator=(const MPEG4DataSource &);
+    CachedRangedDataSource(const CachedRangedDataSource &);
+    CachedRangedDataSource &operator=(const CachedRangedDataSource &);
 };
 
-MPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
+CachedRangedDataSource::CachedRangedDataSource(DataSourceBase *source)
     : mSource(source),
+      mOwnsDataSource(false),
       mCachedOffset(0),
       mCachedSize(0),
       mCache(NULL) {
 }
 
-MPEG4DataSource::~MPEG4DataSource() {
+CachedRangedDataSource::~CachedRangedDataSource() {
     clearCache();
+    if (mOwnsDataSource) {
+        delete (CachedRangedDataSource*)mSource;
+    }
 }
 
-void MPEG4DataSource::clearCache() {
+void CachedRangedDataSource::clearCache() {
     if (mCache) {
         free(mCache);
         mCache = NULL;
@@ -236,11 +240,11 @@
     mCachedSize = 0;
 }
 
-status_t MPEG4DataSource::initCheck() const {
+status_t CachedRangedDataSource::initCheck() const {
     return mSource->initCheck();
 }
 
-ssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
+ssize_t CachedRangedDataSource::readAt(off64_t offset, void *data, size_t size) {
     Mutex::Autolock autoLock(mLock);
 
     if (isInRange(mCachedOffset, mCachedSize, offset, size)) {
@@ -251,15 +255,17 @@
     return mSource->readAt(offset, data, size);
 }
 
-status_t MPEG4DataSource::getSize(off64_t *size) {
+status_t CachedRangedDataSource::getSize(off64_t *size) {
     return mSource->getSize(size);
 }
 
-uint32_t MPEG4DataSource::flags() {
+uint32_t CachedRangedDataSource::flags() {
     return mSource->flags();
 }
 
-status_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
+status_t CachedRangedDataSource::setCachedRange(off64_t offset,
+        size_t size,
+        bool assumeSourceOwnershipOnSuccess) {
     Mutex::Autolock autoLock(mLock);
 
     clearCache();
@@ -280,7 +286,7 @@
 
         return ERROR_IO;
     }
-
+    mOwnsDataSource = assumeSourceOwnershipOnSuccess;
     return OK;
 }
 
@@ -334,11 +340,12 @@
     return false;
 }
 
-MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source, const char *mime)
+MPEG4Extractor::MPEG4Extractor(DataSourceBase *source, const char *mime)
     : mMoofOffset(0),
       mMoofFound(false),
       mMdatFound(false),
       mDataSource(source),
+      mCachedSource(NULL),
       mInitCheck(NO_INIT),
       mHeaderTimescale(0),
       mIsQT(false),
@@ -354,10 +361,6 @@
 }
 
 MPEG4Extractor::~MPEG4Extractor() {
-    release();
-}
-
-void MPEG4Extractor::release() {
     Track *track = mFirstTrack;
     while (track) {
         Track *next = track->next;
@@ -381,10 +384,7 @@
     }
     mPssh.clear();
 
-    if (mDataSource != NULL) {
-        mDataSource->close();
-        mDataSource.clear();
-    }
+    delete mCachedSource;
 }
 
 uint32_t MPEG4Extractor::flags() const {
@@ -692,14 +692,14 @@
 
 // Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
 static int32_t readSize(off64_t offset,
-        const sp<DataSource> &DataSource, uint8_t *numOfBytes) {
+        DataSourceBase *DataSourceBase, uint8_t *numOfBytes) {
     uint32_t size = 0;
     uint8_t data;
     bool moreData = true;
     *numOfBytes = 0;
 
     while (moreData) {
-        if (DataSource->readAt(offset, &data, 1) < 1) {
+        if (DataSourceBase->readAt(offset, &data, 1) < 1) {
             return -1;
         }
         offset ++;
@@ -1045,13 +1045,17 @@
                 ALOGV("sampleTable chunk is %" PRIu64 " bytes long.", chunk_size);
 
                 if (mDataSource->flags()
-                        & (DataSource::kWantsPrefetching
-                            | DataSource::kIsCachingDataSource)) {
-                    sp<MPEG4DataSource> cachedSource =
-                        new MPEG4DataSource(mDataSource);
+                        & (DataSourceBase::kWantsPrefetching
+                            | DataSourceBase::kIsCachingDataSource)) {
+                    CachedRangedDataSource *cachedSource =
+                        new CachedRangedDataSource(mDataSource);
 
-                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
-                        mDataSource = cachedSource;
+                    if (cachedSource->setCachedRange(
+                            *offset, chunk_size,
+                            mCachedSource != NULL /* assume ownership on success */) == OK) {
+                        mDataSource = mCachedSource = cachedSource;
+                    } else {
+                        delete cachedSource;
                     }
                 }
 
@@ -3890,7 +3894,7 @@
 
 MPEG4Source::MPEG4Source(
         const sp<MetaData> &format,
-        const sp<DataSource> &dataSource,
+        DataSourceBase *dataSource,
         int32_t timeScale,
         const sp<SampleTable> &sampleTable,
         Vector<SidxEntry> &sidx,
@@ -5379,7 +5383,7 @@
 }
 
 static bool LegacySniffMPEG4(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+        DataSourceBase *source, String8 *mimeType, float *confidence) {
     uint8_t header[8];
 
     ssize_t n = source->readAt(4, header, sizeof(header));
@@ -5446,7 +5450,7 @@
 // (end of the 'moov' atom) and report it to the caller as part of
 // the metadata.
 static bool BetterSniffMPEG4(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *meta) {
     // We scan up to 128 bytes to identify this file as an MP4.
     static const off64_t kMaxScanOffset = 128ll;
@@ -5563,13 +5567,13 @@
 }
 
 static MediaExtractor* CreateExtractor(
-        const sp<DataSource> &source,
+        DataSourceBase *source,
         const sp<AMessage>& meta __unused) {
     return new MPEG4Extractor(source);
 }
 
 static MediaExtractor::CreatorFunc Sniff(
-        const sp<DataSource> &source,
+        DataSourceBase *source,
         String8 *mimeType,
         float *confidence,
         sp<AMessage> *meta) {
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index e947b87..644c430 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -20,7 +20,7 @@
 
 #include <arpa/inet.h>
 
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/MediaExtractor.h>
 #include <media/stagefright/foundation/AString.h>
 #include <utils/List.h>
@@ -29,7 +29,8 @@
 
 namespace android {
 struct AMessage;
-class DataSource;
+class DataSourceBase;
+struct CachedRangedDataSource;
 class SampleTable;
 class String8;
 namespace heif {
@@ -52,8 +53,7 @@
 
 class MPEG4Extractor : public MediaExtractor {
 public:
-    // Extractor assumes ownership of "source".
-    explicit MPEG4Extractor(const sp<DataSource> &source, const char *mime = NULL);
+    explicit MPEG4Extractor(DataSourceBase *source, const char *mime = NULL);
 
     virtual size_t countTracks();
     virtual MediaSourceBase *getTrack(size_t index);
@@ -62,7 +62,6 @@
     virtual sp<MetaData> getMetaData();
     virtual uint32_t flags() const;
     virtual const char * name() { return "MPEG4Extractor"; }
-    virtual void release();
 
     // for DRM
     virtual char* getDrmTrackInfo(size_t trackID, int *len);
@@ -98,7 +97,8 @@
 
     Vector<Trex> mTrex;
 
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
+    CachedRangedDataSource *mCachedSource;
     status_t mInitCheck;
     uint32_t mHeaderTimescale;
     bool mIsQT;
@@ -160,7 +160,7 @@
 };
 
 bool SniffMPEG4(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *);
 
 }  // namespace android
diff --git a/media/extractors/mp4/SampleIterator.cpp b/media/extractors/mp4/SampleIterator.cpp
index c194397..93ee7c6 100644
--- a/media/extractors/mp4/SampleIterator.cpp
+++ b/media/extractors/mp4/SampleIterator.cpp
@@ -22,7 +22,7 @@
 
 #include <arpa/inet.h>
 
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ByteUtils.h>
 
diff --git a/media/extractors/mp4/SampleTable.cpp b/media/extractors/mp4/SampleTable.cpp
index 378d63a..81c353e 100644
--- a/media/extractors/mp4/SampleTable.cpp
+++ b/media/extractors/mp4/SampleTable.cpp
@@ -25,7 +25,7 @@
 
 #include <arpa/inet.h>
 
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ByteUtils.h>
 
@@ -114,7 +114,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-SampleTable::SampleTable(const sp<DataSource> &source)
+SampleTable::SampleTable(DataSourceBase *source)
     : mDataSource(source),
       mChunkOffsetOffset(-1),
       mChunkOffsetType(0),
diff --git a/media/extractors/mp4/SampleTable.h b/media/extractors/mp4/SampleTable.h
index 466e26b..e4e974b 100644
--- a/media/extractors/mp4/SampleTable.h
+++ b/media/extractors/mp4/SampleTable.h
@@ -27,12 +27,12 @@
 
 namespace android {
 
-class DataSource;
+class DataSourceBase;
 struct SampleIterator;
 
 class SampleTable : public RefBase {
 public:
-    explicit SampleTable(const sp<DataSource> &source);
+    explicit SampleTable(DataSourceBase *source);
 
     bool isValid() const;
 
@@ -99,7 +99,7 @@
     // Limit the total size of all internal tables to 200MiB.
     static const size_t kMaxTotalSize = 200 * (1 << 20);
 
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     Mutex mLock;
 
     off64_t mChunkOffsetOffset;
diff --git a/media/extractors/mpeg2/ExtractorBundle.cpp b/media/extractors/mpeg2/ExtractorBundle.cpp
index d5682e9..443d685 100644
--- a/media/extractors/mpeg2/ExtractorBundle.cpp
+++ b/media/extractors/mpeg2/ExtractorBundle.cpp
@@ -34,18 +34,18 @@
         1,
         "MPEG2-PS/TS Extractor",
         [](
-                const sp<DataSource> &source,
+                DataSourceBase *source,
                 String8 *mimeType,
                 float *confidence,
                 sp<AMessage> *meta __unused) -> MediaExtractor::CreatorFunc {
             if (SniffMPEG2TS(source, mimeType, confidence, meta)) {
                 return [](
-                        const sp<DataSource> &source,
+                        DataSourceBase *source,
                         const sp<AMessage>& meta __unused) -> MediaExtractor* {
                     return new MPEG2TSExtractor(source);};
             } else if (SniffMPEG2PS(source, mimeType, confidence, meta)) {
                         return [](
-                                const sp<DataSource> &source,
+                                DataSourceBase *source,
                                 const sp<AMessage>& meta __unused) -> MediaExtractor* {
                             return new MPEG2PSExtractor(source);};
             }
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index 0978387..697e44f 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -23,7 +23,7 @@
 #include "mpeg2ts/AnotherPacketSource.h"
 #include "mpeg2ts/ESQueue.h"
 
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -94,7 +94,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-MPEG2PSExtractor::MPEG2PSExtractor(const sp<DataSource> &source)
+MPEG2PSExtractor::MPEG2PSExtractor(DataSourceBase *source)
     : mDataSource(source),
       mOffset(0),
       mFinalResult(OK),
@@ -751,7 +751,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 bool SniffMPEG2PS(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *) {
     uint8_t header[5];
     if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.h b/media/extractors/mpeg2/MPEG2PSExtractor.h
index f8a97ef..adf719a 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.h
@@ -31,7 +31,7 @@
 class String8;
 
 struct MPEG2PSExtractor : public MediaExtractor {
-    explicit MPEG2PSExtractor(const sp<DataSource> &source);
+    explicit MPEG2PSExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
     virtual MediaSourceBase *getTrack(size_t index);
@@ -50,7 +50,7 @@
     struct WrappedTrack;
 
     mutable Mutex mLock;
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
 
     off64_t mOffset;
     status_t mFinalResult;
@@ -72,7 +72,7 @@
 };
 
 bool SniffMPEG2PS(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *);
 
 }  // namespace android
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index b24e8db..6d0b1cc 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -22,7 +22,7 @@
 
 #include "MPEG2TSExtractor.h"
 
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/IStreamSource.h>
 #include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -121,7 +121,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-MPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source)
+MPEG2TSExtractor::MPEG2TSExtractor(DataSourceBase *source)
     : mDataSource(source),
       mParser(new ATSParser),
       mLastSyncEvent(0),
@@ -367,7 +367,7 @@
 }
 
 status_t MPEG2TSExtractor::estimateDurationsFromTimesUsAtEnd()  {
-    if (!(mDataSource->flags() & DataSource::kIsLocalFileSource)) {
+    if (!(mDataSource->flags() & DataSourceBase::kIsLocalFileSource)) {
         return ERROR_UNSUPPORTED;
     }
 
@@ -646,7 +646,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 bool SniffMPEG2TS(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *) {
     for (int i = 0; i < 5; ++i) {
         char header;
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.h b/media/extractors/mpeg2/MPEG2TSExtractor.h
index 362f016..57cb675 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.h
@@ -32,12 +32,12 @@
 struct AMessage;
 struct AnotherPacketSource;
 struct ATSParser;
-class DataSource;
+class DataSourceBase;
 struct MPEG2TSSource;
 class String8;
 
 struct MPEG2TSExtractor : public MediaExtractor {
-    explicit MPEG2TSExtractor(const sp<DataSource> &source);
+    explicit MPEG2TSExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
     virtual MediaSourceBase *getTrack(size_t index);
@@ -55,7 +55,7 @@
 
     mutable Mutex mLock;
 
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
 
     sp<ATSParser> mParser;
 
@@ -79,9 +79,9 @@
     // Try to feed more data from source to parser.
     // |isInit| means this function is called inside init(). This is a signal to
     // save SyncEvent so that init() can add SyncPoint after it updates |mSourceImpls|.
-    // This function returns OK if expected amount of data is fed from DataSource to
+    // This function returns OK if expected amount of data is fed from DataSourceBase to
     // parser and is successfully parsed. Otherwise, various error codes could be
-    // returned, e.g., ERROR_END_OF_STREAM, or no data availalbe from DataSource, or
+    // returned, e.g., ERROR_END_OF_STREAM, or no data availalbe from DataSourceBase, or
     // the data has syntax error during parsing, etc.
     status_t feedMore(bool isInit = false);
     status_t seek(int64_t seekTimeUs,
@@ -100,7 +100,7 @@
 };
 
 bool SniffMPEG2TS(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *);
 
 }  // namespace android
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index f62ec47..1d04bed 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -21,7 +21,7 @@
 #include "OggExtractor.h"
 
 #include <cutils/properties.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -69,7 +69,7 @@
 
 struct MyOggExtractor {
     MyOggExtractor(
-            const sp<DataSource> &source,
+            DataSourceBase *source,
             const char *mimeType,
             size_t numHeaders,
             int64_t seekPreRollUs);
@@ -105,7 +105,7 @@
         int64_t mTimeUs;
     };
 
-    sp<DataSource> mSource;
+    DataSourceBase *mSource;
     off64_t mOffset;
     Page mCurrentPage;
     uint64_t mCurGranulePosition;
@@ -164,7 +164,7 @@
 };
 
 struct MyVorbisExtractor : public MyOggExtractor {
-    explicit MyVorbisExtractor(const sp<DataSource> &source)
+    explicit MyVorbisExtractor(DataSourceBase *source)
         : MyOggExtractor(source,
                 MEDIA_MIMETYPE_AUDIO_VORBIS,
                 /* numHeaders */ 3,
@@ -192,7 +192,7 @@
     static const int32_t kOpusSampleRate = 48000;
     static const int64_t kOpusSeekPreRollUs = 80000; // 80 ms
 
-    explicit MyOpusExtractor(const sp<DataSource> &source)
+    explicit MyOpusExtractor(DataSourceBase *source)
         : MyOggExtractor(source, MEDIA_MIMETYPE_AUDIO_OPUS, /*numHeaders*/ 2, kOpusSeekPreRollUs),
           mChannelCount(0),
           mCodecDelay(0),
@@ -294,7 +294,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 MyOggExtractor::MyOggExtractor(
-        const sp<DataSource> &source,
+        DataSourceBase *source,
         const char *mimeType,
         size_t numHeaders,
         int64_t seekPreRollUs)
@@ -852,7 +852,7 @@
 
     off64_t size;
     uint64_t lastGranulePosition;
-    if (!(mSource->flags() & DataSource::kIsCachingDataSource)
+    if (!(mSource->flags() & DataSourceBase::kIsCachingDataSource)
             && mSource->getSize(&size) == OK
             && findPrevGranulePosition(size, &lastGranulePosition) == OK) {
         // Let's assume it's cheap to seek to the end.
@@ -1315,7 +1315,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-OggExtractor::OggExtractor(const sp<DataSource> &source)
+OggExtractor::OggExtractor(DataSourceBase *source)
     : mDataSource(source),
       mInitCheck(NO_INIT),
       mImpl(NULL) {
@@ -1370,13 +1370,13 @@
 }
 
 static MediaExtractor* CreateExtractor(
-        const sp<DataSource> &source,
+        DataSourceBase *source,
         const sp<AMessage>& meta __unused) {
     return new OggExtractor(source);
 }
 
 static MediaExtractor::CreatorFunc Sniff(
-        const sp<DataSource> &source,
+        DataSourceBase *source,
         String8 *mimeType,
         float *confidence,
         sp<AMessage> *) {
diff --git a/media/extractors/ogg/OggExtractor.h b/media/extractors/ogg/OggExtractor.h
index 126428c..c9c37eb 100644
--- a/media/extractors/ogg/OggExtractor.h
+++ b/media/extractors/ogg/OggExtractor.h
@@ -24,14 +24,14 @@
 namespace android {
 
 struct AMessage;
-class DataSource;
+class DataSourceBase;
 class String8;
 
 struct MyOggExtractor;
 struct OggSource;
 
 struct OggExtractor : public MediaExtractor {
-    explicit OggExtractor(const sp<DataSource> &source);
+    explicit OggExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
     virtual MediaSourceBase *getTrack(size_t index);
@@ -46,7 +46,7 @@
 private:
     friend struct OggSource;
 
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     status_t mInitCheck;
 
     MyOggExtractor *mImpl;
@@ -56,7 +56,7 @@
 };
 
 bool SniffOgg(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        DataSourceBase *source, String8 *mimeType, float *confidence,
         sp<AMessage> *);
 
 }  // namespace android
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index cf22c66..105a37f 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -21,7 +21,7 @@
 #include "WAVExtractor.h"
 
 #include <audio_utils/primitives.h>
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaBufferGroup.h>
@@ -57,7 +57,7 @@
 
 struct WAVSource : public MediaSourceBase {
     WAVSource(
-            const sp<DataSource> &dataSource,
+            DataSourceBase *dataSource,
             const sp<MetaData> &meta,
             uint16_t waveFormat,
             int32_t bitsPerSample,
@@ -78,7 +78,7 @@
 private:
     static const size_t kMaxFrameSize;
 
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     sp<MetaData> mMeta;
     uint16_t mWaveFormat;
     int32_t mSampleRate;
@@ -94,7 +94,7 @@
     WAVSource &operator=(const WAVSource &);
 };
 
-WAVExtractor::WAVExtractor(const sp<DataSource> &source)
+WAVExtractor::WAVExtractor(DataSourceBase *source)
     : mDataSource(source),
       mValidFormat(false),
       mChannelMask(CHANNEL_MASK_USE_CHANNEL_ORDER) {
@@ -348,7 +348,7 @@
 const size_t WAVSource::kMaxFrameSize = 32768;
 
 WAVSource::WAVSource(
-        const sp<DataSource> &dataSource,
+        DataSourceBase *dataSource,
         const sp<MetaData> &meta,
         uint16_t waveFormat,
         int32_t bitsPerSample,
@@ -545,13 +545,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 static MediaExtractor* CreateExtractor(
-        const sp<DataSource> &source,
+        DataSourceBase *source,
         const sp<AMessage>& meta __unused) {
     return new WAVExtractor(source);
 }
 
 static MediaExtractor::CreatorFunc Sniff(
-        const sp<DataSource> &source,
+        DataSourceBase *source,
         String8 *mimeType,
         float *confidence,
         sp<AMessage> *) {
diff --git a/media/extractors/wav/WAVExtractor.h b/media/extractors/wav/WAVExtractor.h
index 47c3c40..67661ed 100644
--- a/media/extractors/wav/WAVExtractor.h
+++ b/media/extractors/wav/WAVExtractor.h
@@ -24,13 +24,12 @@
 namespace android {
 
 struct AMessage;
-class DataSource;
+class DataSourceBase;
 class String8;
 
 class WAVExtractor : public MediaExtractor {
 public:
-    // Extractor assumes ownership of "source".
-    explicit WAVExtractor(const sp<DataSource> &source);
+    explicit WAVExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
     virtual MediaSourceBase *getTrack(size_t index);
@@ -42,7 +41,7 @@
     virtual ~WAVExtractor();
 
 private:
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     status_t mInitCheck;
     bool mValidFormat;
     uint16_t mWaveFormat;
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index a8a7b82..51ccb5a 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -39,8 +39,7 @@
     SETMEDIACAS,
     SETUID,
     NAME,
-    GETMETRICS,
-    RELEASE,
+    GETMETRICS
 };
 
 class BpMediaExtractor : public BpInterface<IMediaExtractor> {
@@ -140,13 +139,6 @@
         ALOGV("name NOT IMPLEMENTED");
         return NULL;
     }
-
-    virtual void release() {
-        ALOGV("release");
-        Parcel data, reply;
-        data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
-        remote()->transact(RELEASE, data, &reply);
-    }
 };
 
 IMPLEMENT_META_INTERFACE(MediaExtractor, "android.media.IMediaExtractor");
@@ -224,12 +216,6 @@
             reply->writeInt32(setMediaCas(casToken));
             return OK;
         }
-        case RELEASE: {
-            ALOGV("release");
-            CHECK_INTERFACE(IMediaExtractor, data, reply);
-            release();
-            return OK;
-        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index 4e5d67f..0896e75 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -47,7 +47,7 @@
     mLength = size;
 }
 
-MidiIoWrapper::MidiIoWrapper(const sp<DataSource> &source) {
+MidiIoWrapper::MidiIoWrapper(DataSourceBase *source) {
     ALOGV("MidiIoWrapper(DataSource)");
     mFd = -1;
     mDataSource = source;
diff --git a/media/libmedia/include/media/IMediaExtractor.h b/media/libmedia/include/media/IMediaExtractor.h
index 44f8c1d..9899429 100644
--- a/media/libmedia/include/media/IMediaExtractor.h
+++ b/media/libmedia/include/media/IMediaExtractor.h
@@ -68,8 +68,6 @@
     virtual void setUID(uid_t uid)  = 0;
 
     virtual const char * name() = 0;
-
-    virtual void release() = 0;
 };
 
 
diff --git a/media/libmedia/include/media/MidiIoWrapper.h b/media/libmedia/include/media/MidiIoWrapper.h
index 2754b2c..a27b410 100644
--- a/media/libmedia/include/media/MidiIoWrapper.h
+++ b/media/libmedia/include/media/MidiIoWrapper.h
@@ -19,7 +19,7 @@
 
 #include <libsonivox/eas_types.h>
 
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 
 namespace android {
 
@@ -27,7 +27,7 @@
 public:
     MidiIoWrapper(const char *path);
     MidiIoWrapper(int fd, off64_t offset, int64_t size);
-    MidiIoWrapper(const sp<DataSource> &source);
+    MidiIoWrapper(DataSourceBase *source);
 
     ~MidiIoWrapper();
 
@@ -40,7 +40,7 @@
     int mFd;
     off64_t mBase;
     int64_t  mLength;
-    sp<DataSource> mDataSource;
+    DataSourceBase *mDataSource;
     EAS_FILE mEasFile;
 };
 
diff --git a/media/libmediaextractor/Android.bp b/media/libmediaextractor/Android.bp
index 4071fba..8f4ba70 100644
--- a/media/libmediaextractor/Android.bp
+++ b/media/libmediaextractor/Android.bp
@@ -23,7 +23,7 @@
     ],
 
     srcs: [
-        "DataSource.cpp",
+        "DataSourceBase.cpp",
         "MediaBuffer.cpp",
         "MediaBufferGroup.cpp",
         "MediaSourceBase.cpp",
diff --git a/media/libmediaextractor/DataSource.cpp b/media/libmediaextractor/DataSourceBase.cpp
similarity index 77%
rename from media/libmediaextractor/DataSource.cpp
rename to media/libmediaextractor/DataSourceBase.cpp
index 72959c6..d3af4eb 100644
--- a/media/libmediaextractor/DataSource.cpp
+++ b/media/libmediaextractor/DataSourceBase.cpp
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 //#define LOG_NDEBUG 0
-#define LOG_TAG "DataSource"
+#define LOG_TAG "DataSourceBase"
 
-#include <media/DataSource.h>
+#include <media/DataSourceBase.h>
 #include <media/stagefright/foundation/ByteUtils.h>
 #include <media/stagefright/MediaErrors.h>
 #include <utils/String8.h>
 
 namespace android {
 
-bool DataSource::getUInt16(off64_t offset, uint16_t *x) {
+bool DataSourceBase::getUInt16(off64_t offset, uint16_t *x) {
     *x = 0;
 
     uint8_t byte[2];
@@ -36,7 +36,7 @@
     return true;
 }
 
-bool DataSource::getUInt24(off64_t offset, uint32_t *x) {
+bool DataSourceBase::getUInt24(off64_t offset, uint32_t *x) {
     *x = 0;
 
     uint8_t byte[3];
@@ -49,7 +49,7 @@
     return true;
 }
 
-bool DataSource::getUInt32(off64_t offset, uint32_t *x) {
+bool DataSourceBase::getUInt32(off64_t offset, uint32_t *x) {
     *x = 0;
 
     uint32_t tmp;
@@ -62,7 +62,7 @@
     return true;
 }
 
-bool DataSource::getUInt64(off64_t offset, uint64_t *x) {
+bool DataSourceBase::getUInt64(off64_t offset, uint64_t *x) {
     *x = 0;
 
     uint64_t tmp;
@@ -75,7 +75,7 @@
     return true;
 }
 
-bool DataSource::getUInt16Var(off64_t offset, uint16_t *x, size_t size) {
+bool DataSourceBase::getUInt16Var(off64_t offset, uint16_t *x, size_t size) {
     if (size == 2) {
         return getUInt16(offset, x);
     }
@@ -89,7 +89,7 @@
     return false;
 }
 
-bool DataSource::getUInt32Var(off64_t offset, uint32_t *x, size_t size) {
+bool DataSourceBase::getUInt32Var(off64_t offset, uint32_t *x, size_t size) {
     if (size == 4) {
         return getUInt32(offset, x);
     }
@@ -103,7 +103,7 @@
     return false;
 }
 
-bool DataSource::getUInt64Var(off64_t offset, uint64_t *x, size_t size) {
+bool DataSourceBase::getUInt64Var(off64_t offset, uint64_t *x, size_t size) {
     if (size == 8) {
         return getUInt64(offset, x);
     }
@@ -117,13 +117,13 @@
     return false;
 }
 
-status_t DataSource::getSize(off64_t *size) {
+status_t DataSourceBase::getSize(off64_t *size) {
     *size = 0;
 
     return ERROR_UNSUPPORTED;
 }
 
-String8 DataSource::getMIMEType() const {
+String8 DataSourceBase::getMIMEType() const {
     return String8("application/octet-stream");
 }
 
diff --git a/media/libmediaextractor/include/media/DataSource.h b/media/libmediaextractor/include/media/DataSource.h
index 9f00e0a..a066183 100644
--- a/media/libmediaextractor/include/media/DataSource.h
+++ b/media/libmediaextractor/include/media/DataSource.h
@@ -20,75 +20,21 @@
 
 #include <sys/types.h>
 #include <media/stagefright/MediaErrors.h>
+#include <media/DataSourceBase.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
 #include <drm/DrmManagerClient.h>
 
+
 namespace android {
 
 class String8;
 
-class DataSource : public RefBase {
+class DataSource : public DataSourceBase, public virtual RefBase {
 public:
-    enum Flags {
-        kWantsPrefetching      = 1,
-        kStreamedFromLocalHost = 2,
-        kIsCachingDataSource   = 4,
-        kIsHTTPBasedSource     = 8,
-        kIsLocalFileSource     = 16,
-    };
-
     DataSource() {}
 
-    virtual status_t initCheck() const = 0;
-
-    // Returns the number of bytes read, or -1 on failure. It's not an error if
-    // this returns zero; it just means the given offset is equal to, or
-    // beyond, the end of the source.
-    virtual ssize_t readAt(off64_t offset, void *data, size_t size) = 0;
-
-    // Convenience methods:
-    bool getUInt16(off64_t offset, uint16_t *x);
-    bool getUInt24(off64_t offset, uint32_t *x); // 3 byte int, returned as a 32-bit int
-    bool getUInt32(off64_t offset, uint32_t *x);
-    bool getUInt64(off64_t offset, uint64_t *x);
-
-    // read either int<N> or int<2N> into a uint<2N>_t, size is the int size in bytes.
-    bool getUInt16Var(off64_t offset, uint16_t *x, size_t size);
-    bool getUInt32Var(off64_t offset, uint32_t *x, size_t size);
-    bool getUInt64Var(off64_t offset, uint64_t *x, size_t size);
-
-    // May return ERROR_UNSUPPORTED.
-    virtual status_t getSize(off64_t *size);
-
-    virtual uint32_t flags() {
-        return 0;
-    }
-
-    virtual String8 toString() {
-        return String8("<unspecified>");
-    }
-
-    virtual status_t reconnectAtOffset(off64_t /*offset*/) {
-        return ERROR_UNSUPPORTED;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-
-    // for DRM
-    virtual sp<DecryptHandle> DrmInitialization(const char * /*mime*/ = NULL) {
-        return NULL;
-    }
-
-    virtual String8 getUri() {
-        return String8();
-    }
-
-    virtual String8 getMIMEType() const;
-
-    virtual void close() {};
-
 protected:
     virtual ~DataSource() {}
 
diff --git a/media/libmediaextractor/include/media/DataSourceBase.h b/media/libmediaextractor/include/media/DataSourceBase.h
new file mode 100644
index 0000000..f964137
--- /dev/null
+++ b/media/libmediaextractor/include/media/DataSourceBase.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2009 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 DATA_SOURCE_BASE_H_
+
+#define DATA_SOURCE_BASE_H_
+
+#include <sys/types.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
+
+namespace android {
+
+class String8;
+
+class DataSourceBase {
+public:
+    enum Flags {
+        kWantsPrefetching      = 1,
+        kStreamedFromLocalHost = 2,
+        kIsCachingDataSource   = 4,
+        kIsHTTPBasedSource     = 8,
+        kIsLocalFileSource     = 16,
+    };
+
+    DataSourceBase() {}
+
+    virtual status_t initCheck() const = 0;
+
+    // Returns the number of bytes read, or -1 on failure. It's not an error if
+    // this returns zero; it just means the given offset is equal to, or
+    // beyond, the end of the source.
+    virtual ssize_t readAt(off64_t offset, void *data, size_t size) = 0;
+
+    // Convenience methods:
+    bool getUInt16(off64_t offset, uint16_t *x);
+    bool getUInt24(off64_t offset, uint32_t *x); // 3 byte int, returned as a 32-bit int
+    bool getUInt32(off64_t offset, uint32_t *x);
+    bool getUInt64(off64_t offset, uint64_t *x);
+
+    // read either int<N> or int<2N> into a uint<2N>_t, size is the int size in bytes.
+    bool getUInt16Var(off64_t offset, uint16_t *x, size_t size);
+    bool getUInt32Var(off64_t offset, uint32_t *x, size_t size);
+    bool getUInt64Var(off64_t offset, uint64_t *x, size_t size);
+
+    // Reads in "count" entries of type T into vector *x.
+    // Returns true if "count" entries can be read.
+    // If fewer than "count" entries can be read, return false. In this case,
+    // the output vector *x will still have those entries that were read. Call
+    // x->size() to obtain the number of entries read.
+    // The optional parameter chunkSize specifies how many entries should be
+    // read from the data source at one time into a temporary buffer. Increasing
+    // chunkSize can improve the performance at the cost of extra memory usage.
+    // The default value for chunkSize is set to read at least 4k bytes at a
+    // time, depending on sizeof(T).
+    template <typename T>
+    bool getVector(off64_t offset, Vector<T>* x, size_t count,
+                   size_t chunkSize = (4095 / sizeof(T)) + 1);
+
+    // May return ERROR_UNSUPPORTED.
+    virtual status_t getSize(off64_t *size);
+
+    virtual uint32_t flags() {
+        return 0;
+    }
+
+    virtual String8 toString() {
+        return String8("<unspecified>");
+    }
+
+    virtual status_t reconnectAtOffset(off64_t /*offset*/) {
+        return ERROR_UNSUPPORTED;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    // for DRM
+    virtual sp<DecryptHandle> DrmInitialization(const char * /*mime*/ = NULL) {
+        return NULL;
+    }
+
+    virtual String8 getUri() {
+        return String8();
+    }
+
+    virtual String8 getMIMEType() const;
+
+    virtual void close() {};
+
+protected:
+    virtual ~DataSourceBase() {}
+
+private:
+    DataSourceBase(const DataSourceBase &);
+    DataSourceBase &operator=(const DataSourceBase &);
+};
+
+template <typename T>
+bool DataSourceBase::getVector(off64_t offset, Vector<T>* x, size_t count,
+                           size_t chunkSize)
+{
+    x->clear();
+    if (chunkSize == 0) {
+        return false;
+    }
+    if (count == 0) {
+        return true;
+    }
+
+    T tmp[chunkSize];
+    ssize_t numBytesRead;
+    size_t numBytesPerChunk = chunkSize * sizeof(T);
+    size_t i;
+
+    for (i = 0; i + chunkSize < count; i += chunkSize) {
+        // This loops is executed when more than chunkSize records need to be
+        // read.
+        numBytesRead = this->readAt(offset, (void*)&tmp, numBytesPerChunk);
+        if (numBytesRead == -1) { // If readAt() returns -1, there is an error.
+            return false;
+        }
+        if (static_cast<size_t>(numBytesRead) < numBytesPerChunk) {
+            // This case is triggered when the stream ends before the whole
+            // chunk is read.
+            x->appendArray(tmp, (size_t)numBytesRead / sizeof(T));
+            return false;
+        }
+        x->appendArray(tmp, chunkSize);
+        offset += numBytesPerChunk;
+    }
+
+    // There are (count - i) more records to read.
+    // Right now, (count - i) <= chunkSize.
+    // We do the same thing as above, but with chunkSize replaced by count - i.
+    numBytesRead = this->readAt(offset, (void*)&tmp, (count - i) * sizeof(T));
+    if (numBytesRead == -1) {
+        return false;
+    }
+    x->appendArray(tmp, (size_t)numBytesRead / sizeof(T));
+    return x->size() == count;
+}
+
+}  // namespace android
+
+#endif  // DATA_SOURCE_BASE_H_
diff --git a/media/libmediaextractor/include/media/MediaExtractor.h b/media/libmediaextractor/include/media/MediaExtractor.h
index 27581f3..60495ec 100644
--- a/media/libmediaextractor/include/media/MediaExtractor.h
+++ b/media/libmediaextractor/include/media/MediaExtractor.h
@@ -27,7 +27,7 @@
 
 namespace android {
 
-class DataSource;
+class DataSourceBase;
 class MetaData;
 class String8;
 struct AMessage;
@@ -87,15 +87,14 @@
 
     virtual const char * name() { return "<unspecified>"; }
 
-    virtual void release() {}
     typedef MediaExtractor* (*CreatorFunc)(
-            const sp<DataSource> &source, const sp<AMessage> &meta);
+            DataSourceBase *source, const sp<AMessage> &meta);
 
     // The sniffer can optionally fill in "meta" with an AMessage containing
     // a dictionary of values that helps the corresponding extractor initialize
     // its state without duplicating effort already exerted by the sniffer.
     typedef CreatorFunc (*SnifferFunc)(
-            const sp<DataSource> &source, String8 *mimeType,
+            DataSourceBase *source, String8 *mimeType,
             float *confidence, sp<AMessage> *meta);
 
     typedef struct {
diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp
index f479644..71b737b 100644
--- a/media/libstagefright/CallbackDataSource.cpp
+++ b/media/libstagefright/CallbackDataSource.cpp
@@ -21,6 +21,7 @@
 #include "include/CallbackDataSource.h"
 
 #include <binder/IMemory.h>
+#include <binder/IPCThreadState.h>
 #include <media/IDataSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 
@@ -34,7 +35,10 @@
       mIsClosed(false) {
     // Set up the buffer to read into.
     mMemory = mIDataSource->getIMemory();
-    mName = String8::format("CallbackDataSource(%s)", mIDataSource->toString().string());
+    mName = String8::format("CallbackDataSource(%d->%d, %s)",
+            getpid(),
+            IPCThreadState::self()->getCallingPid(),
+            mIDataSource->toString().string());
 
 }
 
diff --git a/media/libstagefright/InterfaceUtils.cpp b/media/libstagefright/InterfaceUtils.cpp
index 284e63b..70fbbd7 100644
--- a/media/libstagefright/InterfaceUtils.cpp
+++ b/media/libstagefright/InterfaceUtils.cpp
@@ -38,11 +38,13 @@
 }
 
 sp<IMediaExtractor> CreateIMediaExtractorFromMediaExtractor(
-        MediaExtractor *extractor, const sp<RefBase> &plugin) {
+        MediaExtractor *extractor,
+        const sp<DataSource> &source,
+        const sp<RefBase> &plugin) {
     if (extractor == nullptr) {
         return nullptr;
     }
-    return RemoteMediaExtractor::wrap(extractor, plugin);
+    return RemoteMediaExtractor::wrap(extractor, source, plugin);
 }
 
 sp<MediaSource> CreateMediaSourceFromIMediaSource(const sp<IMediaSource> &source) {
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index e79696c..bb72167 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -118,7 +118,7 @@
     String8 tmp;
     float confidence;
     sp<ExtractorPlugin> plugin;
-    creator = sniff(source, &tmp, &confidence, &meta, plugin);
+    creator = sniff(source.get(), &tmp, &confidence, &meta, plugin);
     if (!creator) {
         ALOGV("FAILED to autodetect media content.");
         return NULL;
@@ -128,8 +128,8 @@
     ALOGV("Autodetected media content as '%s' with confidence %.2f",
          mime, confidence);
 
-    MediaExtractor *ret = creator(source, meta);
-    return CreateIMediaExtractorFromMediaExtractor(ret, plugin);
+    MediaExtractor *ret = creator(source.get(), meta);
+    return CreateIMediaExtractorFromMediaExtractor(ret, source, plugin);
 }
 
 //static
@@ -165,7 +165,7 @@
 
 // static
 MediaExtractor::CreatorFunc MediaExtractorFactory::sniff(
-        const sp<DataSource> &source, String8 *mimeType, float *confidence, sp<AMessage> *meta,
+        DataSourceBase *source, String8 *mimeType, float *confidence, sp<AMessage> *meta,
         sp<ExtractorPlugin> &plugin) {
     *mimeType = "";
     *confidence = 0.0f;
diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp
index 3ebee51..601c9fa 100644
--- a/media/libstagefright/RemoteMediaExtractor.cpp
+++ b/media/libstagefright/RemoteMediaExtractor.cpp
@@ -37,9 +37,12 @@
 static const char *kExtractorFormat = "android.media.mediaextractor.fmt";
 
 RemoteMediaExtractor::RemoteMediaExtractor(
-        MediaExtractor *extractor, const sp<RefBase> &plugin)
+        MediaExtractor *extractor,
+        const sp<DataSource> &source,
+        const sp<RefBase> &plugin)
     :mExtractor(extractor),
-    mExtractorPlugin(plugin) {
+     mSource(source),
+     mExtractorPlugin(plugin) {
 
     mAnalyticsItem = nullptr;
     if (MEDIA_LOG) {
@@ -67,6 +70,8 @@
 
 RemoteMediaExtractor::~RemoteMediaExtractor() {
     delete mExtractor;
+    mSource->close();
+    mSource.clear();
     mExtractorPlugin = nullptr;
     // log the current record, provided it has some information worth recording
     if (MEDIA_LOG) {
@@ -129,19 +134,17 @@
     return mExtractor->name();
 }
 
-void RemoteMediaExtractor::release() {
-    return mExtractor->release();
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 
 // static
 sp<IMediaExtractor> RemoteMediaExtractor::wrap(
-        MediaExtractor *extractor, const sp<RefBase> &plugin) {
+        MediaExtractor *extractor,
+        const sp<DataSource> &source,
+        const sp<RefBase> &plugin) {
     if (extractor == nullptr) {
         return nullptr;
     }
-    return new RemoteMediaExtractor(extractor, plugin);
+    return new RemoteMediaExtractor(extractor, source, plugin);
 }
 
 }  // namespace android
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index e2db0f5..179e0e6 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -47,12 +47,6 @@
 StagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
     ALOGV("~StagefrightMetadataRetriever()");
     clearMetadata();
-    // Explicitly release extractor before continuing with the destructor,
-    // some extractors might need to callback to close off the DataSource
-    // and we need to make sure it's still there.
-    if (mExtractor != NULL) {
-        mExtractor->release();
-    }
     if (mSource != NULL) {
         mSource->close();
     }
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 61403be..f4bba59 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -30,7 +30,7 @@
 
 static const size_t kMaxMetadataSize = 3 * 1024 * 1024;
 
-struct MemorySource : public DataSource {
+struct MemorySource : public DataSourceBase {
     MemorySource(const uint8_t *data, size_t size)
         : mData(data),
           mSize(size) {
@@ -56,7 +56,7 @@
     DISALLOW_EVIL_CONSTRUCTORS(MemorySource);
 };
 
-ID3::ID3(const sp<DataSource> &source, bool ignoreV1, off64_t offset)
+ID3::ID3(DataSourceBase *source, bool ignoreV1, off64_t offset)
     : mIsValid(false),
       mData(NULL),
       mSize(0),
@@ -77,7 +77,7 @@
       mFirstFrameOffset(0),
       mVersion(ID3_UNKNOWN),
       mRawSize(0) {
-    sp<MemorySource> source = new (std::nothrow) MemorySource(data, size);
+    MemorySource *source = new (std::nothrow) MemorySource(data, size);
 
     if (source == NULL)
         return;
@@ -87,6 +87,7 @@
     if (!mIsValid && !ignoreV1) {
         mIsValid = parseV1(source);
     }
+    delete source;
 }
 
 ID3::~ID3() {
@@ -118,7 +119,7 @@
     return true;
 }
 
-bool ID3::parseV2(const sp<DataSource> &source, off64_t offset) {
+bool ID3::parseV2(DataSourceBase *source, off64_t offset) {
 struct id3_header {
     char id[3];
     uint8_t version_major;
@@ -960,7 +961,7 @@
     return NULL;
 }
 
-bool ID3::parseV1(const sp<DataSource> &source) {
+bool ID3::parseV1(DataSourceBase *source) {
     const size_t V1_TAG_SIZE = 128;
 
     off64_t size;
diff --git a/media/libstagefright/id3/testid3.cpp b/media/libstagefright/id3/testid3.cpp
index 442a3ff..86e6adf 100644
--- a/media/libstagefright/id3/testid3.cpp
+++ b/media/libstagefright/id3/testid3.cpp
@@ -72,7 +72,7 @@
     sp<FileSource> file = new FileSource(path);
     CHECK_EQ(file->initCheck(), (status_t)OK);
 
-    ID3 tag(file);
+    ID3 tag(file.get());
     if (!tag.isValid()) {
         printf("FAIL %s\n", path);
     } else {
diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h
index 11682f8..7c2391e 100644
--- a/media/libstagefright/include/ID3.h
+++ b/media/libstagefright/include/ID3.h
@@ -22,7 +22,7 @@
 
 namespace android {
 
-class DataSource;
+class DataSourceBase;
 class String8;
 
 struct ID3 {
@@ -35,7 +35,7 @@
         ID3_V2_4,
     };
 
-    explicit ID3(const sp<DataSource> &source, bool ignoreV1 = false, off64_t offset = 0);
+    explicit ID3(DataSourceBase *source, bool ignoreV1 = false, off64_t offset = 0);
     ID3(const uint8_t *data, size_t size, bool ignoreV1 = false);
     ~ID3();
 
@@ -85,8 +85,8 @@
     // only valid for IDV2+
     size_t mRawSize;
 
-    bool parseV1(const sp<DataSource> &source);
-    bool parseV2(const sp<DataSource> &source, off64_t offset);
+    bool parseV1(DataSourceBase *source);
+    bool parseV2(DataSourceBase *source, off64_t offset);
     void removeUnsynchronization();
     bool removeUnsynchronizationV2_4(bool iTunesHack);
 
diff --git a/media/libstagefright/include/media/stagefright/InterfaceUtils.h b/media/libstagefright/include/media/stagefright/InterfaceUtils.h
index ceeaf31..568c735 100644
--- a/media/libstagefright/include/media/stagefright/InterfaceUtils.h
+++ b/media/libstagefright/include/media/stagefright/InterfaceUtils.h
@@ -41,7 +41,9 @@
 
 // Creates an IMediaExtractor wrapper to the given MediaExtractor.
 sp<IMediaExtractor> CreateIMediaExtractorFromMediaExtractor(
-        MediaExtractor *extractor, const sp<RefBase> &plugin);
+        MediaExtractor *extractor,
+        const sp<DataSource> &source,
+        const sp<RefBase> &plugin);
 
 // Creates a MediaSource which wraps the given IMediaSource object.
 sp<MediaSource> CreateMediaSourceFromIMediaSource(const sp<IMediaSource> &source);
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 4610359..4d2f4f0 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -56,7 +56,7 @@
     static void RegisterExtractor(
             const sp<ExtractorPlugin> &plugin, List<sp<ExtractorPlugin>> &pluginList);
 
-    static MediaExtractor::CreatorFunc sniff(const sp<DataSource> &source,
+    static MediaExtractor::CreatorFunc sniff(DataSourceBase *source,
             String8 *mimeType, float *confidence, sp<AMessage> *meta,
             sp<ExtractorPlugin> &plugin);
 
diff --git a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
index 78f3a84..22a8210 100644
--- a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
@@ -28,7 +28,10 @@
 // IMediaExtractor wrapper to the MediaExtractor.
 class RemoteMediaExtractor : public BnMediaExtractor {
 public:
-    static sp<IMediaExtractor> wrap(MediaExtractor *extractor, const sp<RefBase> &plugin);
+    static sp<IMediaExtractor> wrap(
+            MediaExtractor *extractor,
+            const sp<DataSource> &source,
+            const sp<RefBase> &plugin);
 
     virtual ~RemoteMediaExtractor();
     virtual size_t countTracks();
@@ -41,15 +44,18 @@
     virtual void setUID(uid_t uid);
     virtual status_t setMediaCas(const HInterfaceToken &casToken);
     virtual const char * name();
-    virtual void release();
 
 private:
     MediaExtractor *mExtractor;
+    sp<DataSource> mSource;
     sp<RefBase> mExtractorPlugin;
 
     MediaAnalyticsItem *mAnalyticsItem;
 
-    explicit RemoteMediaExtractor(MediaExtractor *extractor, const sp<RefBase> &plugin);
+    explicit RemoteMediaExtractor(
+            MediaExtractor *extractor,
+            const sp<DataSource> &source,
+            const sp<RefBase> &plugin);
 
     DISALLOW_EVIL_CONSTRUCTORS(RemoteMediaExtractor);
 };