diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/libmedia/ICrypto.cpp | 2 | ||||
-rw-r--r-- | media/libmediaplayerservice/Crypto.cpp | 161 | ||||
-rw-r--r-- | media/libmediaplayerservice/Crypto.h | 15 |
3 files changed, 139 insertions, 39 deletions
diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp index 2defc2d..98b183a 100644 --- a/media/libmedia/ICrypto.cpp +++ b/media/libmedia/ICrypto.cpp @@ -48,7 +48,7 @@ struct BpCrypto : public BpInterface<ICrypto> { return reply.readInt32(); } - virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const { + virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) { Parcel data, reply; data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); data.write(uuid, 16); diff --git a/media/libmediaplayerservice/Crypto.cpp b/media/libmediaplayerservice/Crypto.cpp index 0e8f913..ae4d845 100644 --- a/media/libmediaplayerservice/Crypto.cpp +++ b/media/libmediaplayerservice/Crypto.cpp @@ -17,6 +17,8 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "Crypto" #include <utils/Log.h> +#include <dirent.h> +#include <dlfcn.h> #include "Crypto.h" @@ -26,87 +28,176 @@ #include <media/stagefright/foundation/hexdump.h> #include <media/stagefright/MediaErrors.h> -#include <dlfcn.h> - namespace android { +KeyedVector<Vector<uint8_t>, String8> Crypto::mUUIDToLibraryPathMap; +KeyedVector<String8, wp<SharedLibrary> > Crypto::mLibraryPathToOpenLibraryMap; +Mutex Crypto::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; +} + Crypto::Crypto() : mInitCheck(NO_INIT), - mLibHandle(NULL), mFactory(NULL), mPlugin(NULL) { - mInitCheck = init(); } Crypto::~Crypto() { delete mPlugin; mPlugin = NULL; + closeFactory(); +} +void Crypto::closeFactory() { delete mFactory; mFactory = NULL; - - if (mLibHandle != NULL) { - dlclose(mLibHandle); - mLibHandle = NULL; - } + mLibrary.clear(); } status_t Crypto::initCheck() const { return mInitCheck; } -status_t Crypto::init() { - mLibHandle = dlopen("libdrmdecrypt.so", RTLD_NOW); +/* + * 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 Crypto::findFactoryForScheme(const uint8_t uuid[16]) { - if (mLibHandle == NULL) { - ALOGE("Unable to locate libdrmdecrypt.so"); + closeFactory(); - return ERROR_UNSUPPORTED; + // 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; + } } - typedef CryptoFactory *(*CreateCryptoFactoryFunc)(); - CreateCryptoFactoryFunc createCryptoFactory = - (CreateCryptoFactoryFunc)dlsym(mLibHandle, "createCryptoFactory"); + // no luck, have to search + String8 dirPath("/vendor/lib/mediadrm"); + String8 pluginPath; - if (createCryptoFactory == NULL - || ((mFactory = createCryptoFactory()) == NULL)) { - if (createCryptoFactory == NULL) { - ALOGE("Unable to find symbol 'createCryptoFactory'."); - } else { - ALOGE("createCryptoFactory() failed."); + DIR* pDir = opendir(dirPath.string()); + if (pDir) { + struct dirent* pEntry; + while ((pEntry = readdir(pDir))) { + + pluginPath = dirPath + "/" + pEntry->d_name; + + if (pluginPath.getPathExtension() == ".so") { + + if (loadLibraryForScheme(pluginPath, uuid)) { + mUUIDToLibraryPathMap.add(uuidVector, pluginPath); + mInitCheck = OK; + closedir(pDir); + return; + } + } } - dlclose(mLibHandle); - mLibHandle = NULL; + closedir(pDir); + } - return ERROR_UNSUPPORTED; + // try the legacy libdrmdecrypt.so + pluginPath = "libdrmdecrypt.so"; + if (loadLibraryForScheme(pluginPath, uuid)) { + mUUIDToLibraryPathMap.add(uuidVector, pluginPath); + mInitCheck = OK; + return; } - return OK; + ALOGE("Failed to find crypto plugin"); + mInitCheck = ERROR_UNSUPPORTED; } -bool Crypto::isCryptoSchemeSupported(const uint8_t uuid[16]) const { - Mutex::Autolock autoLock(mLock); +bool Crypto::loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]) { - if (mInitCheck != OK) { + // 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 CryptoFactory *(*CreateCryptoFactoryFunc)(); + + CreateCryptoFactoryFunc createCryptoFactory = + (CreateCryptoFactoryFunc)mLibrary->lookup("createCryptoFactory"); + + if (createCryptoFactory == NULL || + (mFactory = createCryptoFactory()) == NULL || + !mFactory->isCryptoSchemeSupported(uuid)) { + closeFactory(); return false; } + return true; +} - return mFactory->isCryptoSchemeSupported(uuid); +bool Crypto::isCryptoSchemeSupported(const uint8_t uuid[16]) { + Mutex::Autolock autoLock(mLock); + + if (mFactory && mFactory->isCryptoSchemeSupported(uuid)) { + return true; + } + + findFactoryForScheme(uuid); + return (mInitCheck == OK); } status_t Crypto::createPlugin( const uint8_t uuid[16], const void *data, size_t size) { Mutex::Autolock autoLock(mLock); - if (mInitCheck != OK) { - return mInitCheck; - } - if (mPlugin != NULL) { return -EINVAL; } + if (!mFactory || !mFactory->isCryptoSchemeSupported(uuid)) { + findFactoryForScheme(uuid); + } + + if (mInitCheck != OK) { + return mInitCheck; + } + return mFactory->createPlugin(uuid, data, size, &mPlugin); } diff --git a/media/libmediaplayerservice/Crypto.h b/media/libmediaplayerservice/Crypto.h index d066774..c44ae34 100644 --- a/media/libmediaplayerservice/Crypto.h +++ b/media/libmediaplayerservice/Crypto.h @@ -20,6 +20,9 @@ #include <media/ICrypto.h> #include <utils/threads.h> +#include <utils/KeyedVector.h> + +#include "SharedLibrary.h" namespace android { @@ -32,7 +35,7 @@ struct Crypto : public BnCrypto { virtual status_t initCheck() const; - virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const; + virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]); virtual status_t createPlugin( const uint8_t uuid[16], const void *data, size_t size); @@ -56,11 +59,17 @@ private: mutable Mutex mLock; status_t mInitCheck; - void *mLibHandle; + sp<SharedLibrary> mLibrary; CryptoFactory *mFactory; CryptoPlugin *mPlugin; - status_t init(); + static KeyedVector<Vector<uint8_t>, String8> mUUIDToLibraryPathMap; + static KeyedVector<String8, wp<SharedLibrary> > mLibraryPathToOpenLibraryMap; + static Mutex mMapLock; + + void findFactoryForScheme(const uint8_t uuid[16]); + bool loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]); + void closeFactory(); DISALLOW_EVIL_CONSTRUCTORS(Crypto); }; |