Merge "In "special" mode we now establish a UDP RTCP channel in addition to the" into jb-mr2-dev
diff --git a/include/media/ICrypto.h b/include/media/ICrypto.h
index 61059bd..9dcb8d9 100644
--- a/include/media/ICrypto.h
+++ b/include/media/ICrypto.h
@@ -31,7 +31,7 @@
 
     virtual status_t initCheck() const = 0;
 
-    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const = 0;
+    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) = 0;
 
     virtual status_t createPlugin(
             const uint8_t uuid[16], const void *data, size_t size) = 0;
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 @@
         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/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 42584fe..1c0268f 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -885,6 +885,11 @@
     if ((toneType < 0) || (toneType >= NUM_TONES))
         return lResult;
 
+    toneType = getToneForRegion(toneType);
+    if (toneType == TONE_CDMA_SIGNAL_OFF) {
+        return true;
+    }
+
     if (mState == TONE_IDLE) {
         ALOGV("startTone: try to re-init AudioTrack");
         if (!initAudioTrack()) {
@@ -897,7 +902,6 @@
     mLock.lock();
 
     // Get descriptor for requested tone
-    toneType = getToneForRegion(toneType);
     mpNewToneDesc = &sToneDescriptors[toneType];
 
     mDurationMs = durationMs;
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;
+        }
+    }
+
+    // no luck, have to search
+    String8 dirPath("/vendor/lib/mediadrm");
+    String8 pluginPath;
+
+    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;
+                }
+            }
+        }
+
+        closedir(pDir);
+    }
+
+    // try the legacy libdrmdecrypt.so
+    pluginPath = "libdrmdecrypt.so";
+    if (loadLibraryForScheme(pluginPath, uuid)) {
+        mUUIDToLibraryPathMap.add(uuidVector, pluginPath);
+        mInitCheck = OK;
+        return;
+    }
+
+    ALOGE("Failed to find crypto plugin");
+    mInitCheck = ERROR_UNSUPPORTED;
+}
+
+bool Crypto::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 CryptoFactory *(*CreateCryptoFactoryFunc)();
+
     CreateCryptoFactoryFunc createCryptoFactory =
-        (CreateCryptoFactoryFunc)dlsym(mLibHandle, "createCryptoFactory");
+        (CreateCryptoFactoryFunc)mLibrary->lookup("createCryptoFactory");
 
-    if (createCryptoFactory == NULL
-            || ((mFactory = createCryptoFactory()) == NULL)) {
-        if (createCryptoFactory == NULL) {
-            ALOGE("Unable to find symbol 'createCryptoFactory'.");
-        } else {
-            ALOGE("createCryptoFactory() failed.");
-        }
-
-        dlclose(mLibHandle);
-        mLibHandle = NULL;
-
-        return ERROR_UNSUPPORTED;
-    }
-
-    return OK;
-}
-
-bool Crypto::isCryptoSchemeSupported(const uint8_t uuid[16]) const {
-    Mutex::Autolock autoLock(mLock);
-
-    if (mInitCheck != OK) {
+    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 @@
 
     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 @@
     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);
 };