summaryrefslogtreecommitdiffstats
path: root/media/libmediaplayerservice/Drm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libmediaplayerservice/Drm.cpp')
-rw-r--r--media/libmediaplayerservice/Drm.cpp161
1 files changed, 143 insertions, 18 deletions
diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp
index 9d5ba15..a7f6f8b 100644
--- a/media/libmediaplayerservice/Drm.cpp
+++ b/media/libmediaplayerservice/Drm.cpp
@@ -23,6 +23,8 @@
#include "Drm.h"
+#include "DrmSessionClientInterface.h"
+#include "DrmSessionManager.h"
#include <media/drm/DrmAPI.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
@@ -33,6 +35,10 @@
namespace android {
+static inline int getCallingPid() {
+ return IPCThreadState::self()->getCallingPid();
+}
+
static bool checkPermission(const char* permissionString) {
#ifndef HAVE_ANDROID_OS
return true;
@@ -58,14 +64,41 @@ static bool operator<(const Vector<uint8_t> &lhs, const Vector<uint8_t> &rhs) {
return memcmp((void *)lhs.array(), (void *)rhs.array(), rhs.size()) < 0;
}
+struct DrmSessionClient : public DrmSessionClientInterface {
+ DrmSessionClient(Drm* drm) : mDrm(drm) {}
+
+ virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
+ sp<Drm> drm = mDrm.promote();
+ if (drm == NULL) {
+ return true;
+ }
+ status_t err = drm->closeSession(sessionId);
+ if (err != OK) {
+ return false;
+ }
+ drm->sendEvent(DrmPlugin::kDrmPluginEventSessionReclaimed, 0, &sessionId, NULL);
+ return true;
+ }
+
+protected:
+ virtual ~DrmSessionClient() {}
+
+private:
+ wp<Drm> mDrm;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
+};
+
Drm::Drm()
: mInitCheck(NO_INIT),
+ mDrmSessionClient(new DrmSessionClient(this)),
mListener(NULL),
mFactory(NULL),
mPlugin(NULL) {
}
Drm::~Drm() {
+ DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
delete mPlugin;
mPlugin = NULL;
closeFactory();
@@ -104,22 +137,54 @@ void Drm::sendEvent(DrmPlugin::EventType eventType, int extra,
if (listener != NULL) {
Parcel obj;
- if (sessionId && sessionId->size()) {
- obj.writeInt32(sessionId->size());
- obj.write(sessionId->array(), sessionId->size());
- } else {
- obj.writeInt32(0);
- }
+ writeByteArray(obj, sessionId);
+ writeByteArray(obj, data);
- if (data && data->size()) {
- obj.writeInt32(data->size());
- obj.write(data->array(), data->size());
- } else {
- obj.writeInt32(0);
+ Mutex::Autolock lock(mNotifyLock);
+ listener->notify(eventType, extra, &obj);
+ }
+}
+
+void Drm::sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+ int64_t expiryTimeInMS)
+{
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Parcel obj;
+ writeByteArray(obj, sessionId);
+ obj.writeInt64(expiryTimeInMS);
+
+ Mutex::Autolock lock(mNotifyLock);
+ listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
+ }
+}
+
+void Drm::sendKeysChange(Vector<uint8_t> const *sessionId,
+ Vector<DrmPlugin::KeyStatus> const *keyStatusList,
+ bool hasNewUsableKey)
+{
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Parcel obj;
+ writeByteArray(obj, sessionId);
+
+ size_t nkeys = keyStatusList->size();
+ obj.writeInt32(keyStatusList->size());
+ for (size_t i = 0; i < nkeys; ++i) {
+ const DrmPlugin::KeyStatus *keyStatus = &keyStatusList->itemAt(i);
+ writeByteArray(obj, &keyStatus->mKeyId);
+ obj.writeInt32(keyStatus->mType);
}
+ obj.writeInt32(hasNewUsableKey);
Mutex::Autolock lock(mNotifyLock);
- listener->notify(eventType, extra, &obj);
+ listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
}
}
@@ -145,7 +210,7 @@ void Drm::findFactoryForScheme(const uint8_t uuid[16]) {
// first check cache
Vector<uint8_t> uuidVector;
- uuidVector.appendArray(uuid, sizeof(uuid));
+ uuidVector.appendArray(uuid, sizeof(uuid[0]) * 16);
ssize_t index = mUUIDToLibraryPathMap.indexOfKey(uuidVector);
if (index >= 0) {
if (loadLibraryForScheme(mUUIDToLibraryPathMap[index], uuid)) {
@@ -290,7 +355,29 @@ status_t Drm::openSession(Vector<uint8_t> &sessionId) {
return -EINVAL;
}
- return mPlugin->openSession(sessionId);
+ status_t err = mPlugin->openSession(sessionId);
+ if (err == ERROR_DRM_RESOURCE_BUSY) {
+ bool retry = false;
+ mLock.unlock();
+ // reclaimSession may call back to closeSession, since mLock is shared between Drm
+ // instances, we should unlock here to avoid deadlock.
+ retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
+ mLock.lock();
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+ if (retry) {
+ err = mPlugin->openSession(sessionId);
+ }
+ }
+ if (err == OK) {
+ DrmSessionManager::Instance()->addSession(getCallingPid(), mDrmSessionClient, sessionId);
+ }
+ return err;
}
status_t Drm::closeSession(Vector<uint8_t> const &sessionId) {
@@ -304,14 +391,19 @@ status_t Drm::closeSession(Vector<uint8_t> const &sessionId) {
return -EINVAL;
}
- return mPlugin->closeSession(sessionId);
+ status_t err = mPlugin->closeSession(sessionId);
+ if (err == OK) {
+ DrmSessionManager::Instance()->removeSession(sessionId);
+ }
+ return err;
}
status_t Drm::getKeyRequest(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &initData,
String8 const &mimeType, DrmPlugin::KeyType keyType,
KeyedVector<String8, String8> const &optionalParameters,
- Vector<uint8_t> &request, String8 &defaultUrl) {
+ Vector<uint8_t> &request, String8 &defaultUrl,
+ DrmPlugin::KeyRequestType *keyRequestType) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
@@ -322,8 +414,11 @@ status_t Drm::getKeyRequest(Vector<uint8_t> const &sessionId,
return -EINVAL;
}
+ DrmSessionManager::Instance()->useSession(sessionId);
+
return mPlugin->getKeyRequest(sessionId, initData, mimeType, keyType,
- optionalParameters, request, defaultUrl);
+ optionalParameters, request, defaultUrl,
+ keyRequestType);
}
status_t Drm::provideKeyResponse(Vector<uint8_t> const &sessionId,
@@ -339,6 +434,8 @@ status_t Drm::provideKeyResponse(Vector<uint8_t> const &sessionId,
return -EINVAL;
}
+ DrmSessionManager::Instance()->useSession(sessionId);
+
return mPlugin->provideKeyResponse(sessionId, response, keySetId);
}
@@ -368,6 +465,8 @@ status_t Drm::restoreKeys(Vector<uint8_t> const &sessionId,
return -EINVAL;
}
+ DrmSessionManager::Instance()->useSession(sessionId);
+
return mPlugin->restoreKeys(sessionId, keySetId);
}
@@ -383,6 +482,8 @@ status_t Drm::queryKeyStatus(Vector<uint8_t> const &sessionId,
return -EINVAL;
}
+ DrmSessionManager::Instance()->useSession(sessionId);
+
return mPlugin->queryKeyStatus(sessionId, infoMap);
}
@@ -562,6 +663,8 @@ status_t Drm::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
return -EINVAL;
}
+ DrmSessionManager::Instance()->useSession(sessionId);
+
return mPlugin->setCipherAlgorithm(sessionId, algorithm);
}
@@ -577,6 +680,8 @@ status_t Drm::setMacAlgorithm(Vector<uint8_t> const &sessionId,
return -EINVAL;
}
+ DrmSessionManager::Instance()->useSession(sessionId);
+
return mPlugin->setMacAlgorithm(sessionId, algorithm);
}
@@ -595,6 +700,8 @@ status_t Drm::encrypt(Vector<uint8_t> const &sessionId,
return -EINVAL;
}
+ DrmSessionManager::Instance()->useSession(sessionId);
+
return mPlugin->encrypt(sessionId, keyId, input, iv, output);
}
@@ -613,6 +720,8 @@ status_t Drm::decrypt(Vector<uint8_t> const &sessionId,
return -EINVAL;
}
+ DrmSessionManager::Instance()->useSession(sessionId);
+
return mPlugin->decrypt(sessionId, keyId, input, iv, output);
}
@@ -630,6 +739,8 @@ status_t Drm::sign(Vector<uint8_t> const &sessionId,
return -EINVAL;
}
+ DrmSessionManager::Instance()->useSession(sessionId);
+
return mPlugin->sign(sessionId, keyId, message, signature);
}
@@ -648,6 +759,8 @@ status_t Drm::verify(Vector<uint8_t> const &sessionId,
return -EINVAL;
}
+ DrmSessionManager::Instance()->useSession(sessionId);
+
return mPlugin->verify(sessionId, keyId, message, signature, match);
}
@@ -670,10 +783,12 @@ status_t Drm::signRSA(Vector<uint8_t> const &sessionId,
return -EPERM;
}
+ DrmSessionManager::Instance()->useSession(sessionId);
+
return mPlugin->signRSA(sessionId, algorithm, message, wrappedKey, signature);
}
-void Drm::binderDied(const wp<IBinder> &the_late_who)
+void Drm::binderDied(const wp<IBinder> &the_late_who __unused)
{
mEventLock.lock();
mListener.clear();
@@ -685,4 +800,14 @@ void Drm::binderDied(const wp<IBinder> &the_late_who)
closeFactory();
}
+void Drm::writeByteArray(Parcel &obj, Vector<uint8_t> const *array)
+{
+ if (array && array->size()) {
+ obj.writeInt32(array->size());
+ obj.write(array->array(), array->size());
+ } else {
+ obj.writeInt32(0);
+ }
+}
+
} // namespace android