summaryrefslogtreecommitdiffstats
path: root/media/libmediaplayerservice/Drm.cpp
diff options
context:
space:
mode:
authorJeff Tinker <jtinker@google.com>2013-02-08 10:18:35 -0800
committerJeff Tinker <jtinker@google.com>2013-03-13 13:39:48 -0700
commitcc82dc6d500023eba6048616301a4b12682458db (patch)
tree1f36f887af92cb4bee147e962b85ce10f35d587a /media/libmediaplayerservice/Drm.cpp
parentc93484ab9fdf044fd32f2388a3ce29040d2ba319 (diff)
downloadframeworks_av-cc82dc6d500023eba6048616301a4b12682458db.zip
frameworks_av-cc82dc6d500023eba6048616301a4b12682458db.tar.gz
frameworks_av-cc82dc6d500023eba6048616301a4b12682458db.tar.bz2
Implementing MediaDrm APIs
Change-Id: I9ff8eeb7d0c383b5c0c68cd54eb54ce7d2d22fe6
Diffstat (limited to 'media/libmediaplayerservice/Drm.cpp')
-rw-r--r--media/libmediaplayerservice/Drm.cpp423
1 files changed, 423 insertions, 0 deletions
diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp
new file mode 100644
index 0000000..6ac7530
--- /dev/null
+++ b/media/libmediaplayerservice/Drm.cpp
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Drm"
+#include <utils/Log.h>
+
+#include <dirent.h>
+#include <dlfcn.h>
+
+#include "Drm.h"
+
+#include <media/drm/DrmAPI.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+KeyedVector<Vector<uint8_t>, String8> Drm::mUUIDToLibraryPathMap;
+KeyedVector<String8, wp<SharedLibrary> > Drm::mLibraryPathToOpenLibraryMap;
+Mutex Drm::mMapLock;
+
+static bool operator<(const Vector<uint8_t> &lhs, const Vector<uint8_t> &rhs) {
+ if (lhs.size() < rhs.size()) {
+ return true;
+ } else if (lhs.size() > rhs.size()) {
+ return false;
+ }
+
+ return memcmp((void *)lhs.array(), (void *)rhs.array(), rhs.size()) < 0;
+}
+
+Drm::Drm()
+ : mInitCheck(NO_INIT),
+ mFactory(NULL),
+ mPlugin(NULL) {
+}
+
+Drm::~Drm() {
+ delete mPlugin;
+ mPlugin = NULL;
+ closeFactory();
+}
+
+void Drm::closeFactory() {
+ delete mFactory;
+ mFactory = NULL;
+ mLibrary.clear();
+}
+
+status_t Drm::initCheck() const {
+ return mInitCheck;
+}
+
+
+/*
+ * Search the plugins directory for a plugin that supports the scheme
+ * specified by uuid
+ *
+ * If found:
+ * mLibrary holds a strong pointer to the dlopen'd library
+ * mFactory is set to the library's factory method
+ * mInitCheck is set to OK
+ *
+ * If not found:
+ * mLibrary is cleared and mFactory are set to NULL
+ * mInitCheck is set to an error (!OK)
+ */
+void Drm::findFactoryForScheme(const uint8_t uuid[16]) {
+
+ closeFactory();
+
+ // lock static maps
+ Mutex::Autolock autoLock(mMapLock);
+
+ // first check cache
+ Vector<uint8_t> uuidVector;
+ uuidVector.appendArray(uuid, sizeof(uuid));
+ ssize_t index = mUUIDToLibraryPathMap.indexOfKey(uuidVector);
+ if (index >= 0) {
+ if (loadLibraryForScheme(mUUIDToLibraryPathMap[index], uuid)) {
+ mInitCheck = OK;
+ return;
+ } else {
+ ALOGE("Failed to load from cached library path!");
+ mInitCheck = ERROR_UNSUPPORTED;
+ return;
+ }
+ }
+
+ // no luck, have to search
+ String8 dirPath("/vendor/lib/mediadrm");
+ DIR* pDir = opendir(dirPath.string());
+
+ if (pDir == NULL) {
+ mInitCheck = ERROR_UNSUPPORTED;
+ ALOGE("Failed to open plugin directory %s", dirPath.string());
+ return;
+ }
+
+
+ struct dirent* pEntry;
+ while ((pEntry = readdir(pDir))) {
+
+ String8 pluginPath = dirPath + "/" + pEntry->d_name;
+
+ if (pluginPath.getPathExtension() == ".so") {
+
+ if (loadLibraryForScheme(pluginPath, uuid)) {
+ mUUIDToLibraryPathMap.add(uuidVector, pluginPath);
+ mInitCheck = OK;
+ closedir(pDir);
+ return;
+ }
+ }
+ }
+
+ closedir(pDir);
+
+ ALOGE("Failed to find drm plugin");
+ mInitCheck = ERROR_UNSUPPORTED;
+}
+
+bool Drm::loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]) {
+
+ // get strong pointer to open shared library
+ ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
+ if (index >= 0) {
+ mLibrary = mLibraryPathToOpenLibraryMap[index].promote();
+ } else {
+ index = mLibraryPathToOpenLibraryMap.add(path, NULL);
+ }
+
+ if (!mLibrary.get()) {
+ mLibrary = new SharedLibrary(path);
+ if (!*mLibrary) {
+ return false;
+ }
+
+ mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
+ }
+
+ typedef DrmFactory *(*CreateDrmFactoryFunc)();
+
+ CreateDrmFactoryFunc createDrmFactory =
+ (CreateDrmFactoryFunc)mLibrary->lookup("createDrmFactory");
+
+ if (createDrmFactory == NULL ||
+ (mFactory = createDrmFactory()) == NULL ||
+ !mFactory->isCryptoSchemeSupported(uuid)) {
+ closeFactory();
+ return false;
+ }
+ return true;
+}
+
+bool Drm::isCryptoSchemeSupported(const uint8_t uuid[16]) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mFactory && mFactory->isCryptoSchemeSupported(uuid)) {
+ return true;
+ }
+
+ findFactoryForScheme(uuid);
+ return (mInitCheck == OK);
+}
+
+status_t Drm::createPlugin(const uint8_t uuid[16]) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mPlugin != NULL) {
+ return -EINVAL;
+ }
+
+ if (!mFactory || !mFactory->isCryptoSchemeSupported(uuid)) {
+ findFactoryForScheme(uuid);
+ }
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ return mFactory->createDrmPlugin(uuid, &mPlugin);
+}
+
+status_t Drm::destroyPlugin() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ delete mPlugin;
+ mPlugin = NULL;
+
+ return OK;
+}
+
+status_t Drm::openSession(Vector<uint8_t> &sessionId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->openSession(sessionId);
+}
+
+status_t Drm::closeSession(Vector<uint8_t> const &sessionId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->closeSession(sessionId);
+}
+
+status_t Drm::getLicenseRequest(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &initData,
+ String8 const &mimeType, DrmPlugin::LicenseType licenseType,
+ KeyedVector<String8, String8> const &optionalParameters,
+ Vector<uint8_t> &request, String8 &defaultUrl) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->getLicenseRequest(sessionId, initData, mimeType, licenseType,
+ optionalParameters, request, defaultUrl);
+}
+
+status_t Drm::provideLicenseResponse(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &response) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->provideLicenseResponse(sessionId, response);
+}
+
+status_t Drm::removeLicense(Vector<uint8_t> const &sessionId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->removeLicense(sessionId);
+}
+
+status_t Drm::queryLicenseStatus(Vector<uint8_t> const &sessionId,
+ KeyedVector<String8, String8> &infoMap) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->queryLicenseStatus(sessionId, infoMap);
+}
+
+status_t Drm::getProvisionRequest(Vector<uint8_t> &request, String8 &defaultUrl) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->getProvisionRequest(request, defaultUrl);
+}
+
+status_t Drm::provideProvisionResponse(Vector<uint8_t> const &response) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->provideProvisionResponse(response);
+}
+
+
+status_t Drm::getSecureStops(List<Vector<uint8_t> > &secureStops) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->getSecureStops(secureStops);
+}
+
+status_t Drm::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->releaseSecureStops(ssRelease);
+}
+
+status_t Drm::getPropertyString(String8 const &name, String8 &value ) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->getPropertyString(name, value);
+}
+
+status_t Drm::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->getPropertyByteArray(name, value);
+}
+
+status_t Drm::setPropertyString(String8 const &name, String8 const &value ) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->setPropertyString(name, value);
+}
+
+status_t Drm::setPropertyByteArray(String8 const &name,
+ Vector<uint8_t> const &value ) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ return mPlugin->setPropertyByteArray(name, value);
+}
+
+} // namespace android