summaryrefslogtreecommitdiff
path: root/media/jni/android_media_MediaPlayer.cpp
diff options
context:
space:
mode:
authorHassan Shojania <shojania@google.com>2017-02-06 21:09:42 -0800
committerHassan Shojania <shojania@google.com>2017-02-15 18:44:54 -0800
commit06b25fb2367d1962da5445d1c3c033c73a4b95eb (patch)
treecc44d6aeda9b03802fc4cf26c5b1eb640c36c8f9 /media/jni/android_media_MediaPlayer.cpp
parent9f1b5b73e8d83e4509b2f68aa8aab6f10e5a61e3 (diff)
Modular DRM for MediaPlayer
Bug: 34559906 Test: Manual through the test app Change-Id: I1b1ca61e74f250d63ff5ff462905facb81fe44e0
Diffstat (limited to 'media/jni/android_media_MediaPlayer.cpp')
-rw-r--r--media/jni/android_media_MediaPlayer.cpp419
1 files changed, 21 insertions, 398 deletions
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index c941766c07d6..636727eb0ac0 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -58,86 +58,20 @@
#include "android_util_Binder.h"
// Modular DRM begin
-#include <media/drm/DrmAPI.h>
-
#define FIND_CLASS(var, className) \
var = env->FindClass(className); \
LOG_FATAL_IF(! (var), "Unable to find class " className);
-#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
-var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
-LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
-
#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
LOG_FATAL_IF(! (var), "Unable to find method " fieldName);
-#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
-var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
-LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
-
-
-// TODO: investigate if these can be shared with their MediaDrm counterparts
-struct RequestFields {
- jfieldID data;
- jfieldID defaultUrl;
- jfieldID requestType;
-};
-
-struct HashmapFields {
- jmethodID init;
- jmethodID get;
- jmethodID put;
- jmethodID entrySet;
-};
-
-struct SetFields {
- jmethodID iterator;
-};
-
-struct IteratorFields {
- jmethodID next;
- jmethodID hasNext;
-};
-
-struct EntryFields {
- jmethodID getKey;
- jmethodID getValue;
-};
-
-struct KeyTypes {
- jint kKeyTypeStreaming;
- jint kKeyTypeOffline;
- jint kKeyTypeRelease;
-};
-
-static KeyTypes gKeyTypes;
-
-struct KeyRequestTypes {
- jint kKeyRequestTypeInitial;
- jint kKeyRequestTypeRenewal;
- jint kKeyRequestTypeRelease;
-};
-
-static KeyRequestTypes gKeyRequestTypes;
-
struct StateExceptionFields {
jmethodID init;
jclass classId;
};
-struct drm_fields_t {
- RequestFields keyRequest;
- HashmapFields hashmap;
- SetFields set;
- IteratorFields iterator;
- EntryFields entry;
- StateExceptionFields stateException;
- jclass stringClassId;
-};
-
-static drm_fields_t gFields;
-
+static StateExceptionFields gStateExceptionFields;
// Modular DRM end
// ----------------------------------------------------------------------------
@@ -1041,50 +975,14 @@ android_media_MediaPlayer_native_init(JNIEnv *env)
gBufferingParamsFields.init(env);
// Modular DRM
- FIND_CLASS(clazz, "android/media/MediaDrm");
- if (clazz) {
- jfieldID field;
- GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
- gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
- gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
- gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
-
- env->DeleteLocalRef(clazz);
- } else {
- ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't "
- "get clazz android/media/MediaDrm");
- }
-
- FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
- if (clazz) {
- GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
- GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
- GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
-
- jfieldID field;
- GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
- gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
- gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
- gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
-
- env->DeleteLocalRef(clazz);
- } else {
- ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't "
- "get clazz android/media/MediaDrm$KeyRequest");
- }
-
FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
if (clazz) {
- GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
- gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
+ GET_METHOD_ID(gStateExceptionFields.init, clazz, "<init>", "(ILjava/lang/String;)V");
+ gStateExceptionFields.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
env->DeleteLocalRef(clazz);
} else {
- ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't "
+ ALOGE("JNI android_media_MediaPlayer_native_init couldn't "
"get clazz android/media/MediaDrm$MediaDrmStateException");
}
@@ -1315,8 +1213,8 @@ static void throwDrmStateException(JNIEnv *env, const char *msg, status_t err)
{
ALOGE("Illegal DRM state exception: %s (%d)", msg, err);
- jobject exception = env->NewObject(gFields.stateException.classId,
- gFields.stateException.init, static_cast<int>(err),
+ jobject exception = env->NewObject(gStateExceptionFields.classId,
+ gStateExceptionFields.init, static_cast<int>(err),
env->NewStringUTF(msg));
env->Throw(static_cast<jthrowable>(exception));
}
@@ -1393,18 +1291,6 @@ static bool throwDrmExceptionAsNecessary(JNIEnv *env, status_t err, const char *
return false;
}
-// TODO: investigate if these can be shared with their MediaDrm counterparts
-static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector)
-{
- size_t length = vector.size();
- jbyteArray result = env->NewByteArray(length);
- if (result != NULL) {
- env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
- }
- return result;
-}
-
-// TODO: investigate if these can be shared with their MediaDrm counterparts
static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray)
{
Vector<uint8_t> vector;
@@ -1414,74 +1300,8 @@ static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArr
return vector;
}
-// TODO: investigate if these can be shared with their MediaDrm counterparts
-static String8 JStringToString8(JNIEnv *env, jstring const &jstr)
-{
- String8 result;
-
- const char *s = env->GetStringUTFChars(jstr, NULL);
- if (s) {
- result = s;
- env->ReleaseStringUTFChars(jstr, s);
- }
- return result;
-}
-
-// TODO: investigate if these can be shared with their MediaDrm counterparts
-static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env,
- jobject &hashMap, bool* pIsOK)
-{
- jclass clazz = gFields.stringClassId;
- KeyedVector<String8, String8> keyedVector;
- *pIsOK = true;
-
- jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
- if (entrySet) {
- jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
- if (iterator) {
- jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
- while (hasNext) {
- jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
- if (entry) {
- jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
- if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "HashMap key is not a String");
- env->DeleteLocalRef(entry);
- *pIsOK = false;
- break;
- }
- jstring jkey = static_cast<jstring>(obj);
-
- obj = env->CallObjectMethod(entry, gFields.entry.getValue);
- if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "HashMap value is not a String");
- env->DeleteLocalRef(entry);
- *pIsOK = false;
- break;
- }
- jstring jvalue = static_cast<jstring>(obj);
-
- String8 key = JStringToString8(env, jkey);
- String8 value = JStringToString8(env, jvalue);
- keyedVector.add(key, value);
-
- env->DeleteLocalRef(jkey);
- env->DeleteLocalRef(jvalue);
- hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
- }
- env->DeleteLocalRef(entry);
- }
- env->DeleteLocalRef(iterator);
- }
- env->DeleteLocalRef(entrySet);
- }
- return keyedVector;
-}
-
static void android_media_MediaPlayer_prepareDrm(JNIEnv *env, jobject thiz,
- jbyteArray uuidObj, jint mode)
+ jbyteArray uuidObj, jbyteArray drmSessionIdObj)
{
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
if (mp == NULL) {
@@ -1504,13 +1324,23 @@ static void android_media_MediaPlayer_prepareDrm(JNIEnv *env, jobject thiz,
return;
}
- status_t err = mp->prepareDrm(uuid.array(), mode);
+ Vector<uint8_t> drmSessionId = JByteArrayToVector(env, drmSessionIdObj);
+
+ if (drmSessionId.size() == 0) {
+ jniThrowException(
+ env,
+ "java/lang/IllegalArgumentException",
+ "empty drmSessionId");
+ return;
+ }
+
+ status_t err = mp->prepareDrm(uuid.array(), drmSessionId);
if (err != OK) {
if (err == INVALID_OPERATION) {
jniThrowException(
env,
"java/lang/IllegalStateException",
- "The player is not prepared yet.");
+ "The player must be in prepared state.");
} else if (err == ERROR_DRM_CANNOT_HANDLE) {
jniThrowException(
env,
@@ -1536,210 +1366,9 @@ static void android_media_MediaPlayer_releaseDrm(JNIEnv *env, jobject thiz)
jniThrowException(
env,
"java/lang/IllegalStateException",
- "The player is not prepared yet.");
- }
- }
-}
-
-static jobject android_media_MediaPlayer_getKeyRequest(JNIEnv *env, jobject thiz, jbyteArray jscope,
- jstring jmimeType, jint jkeyType, jobject joptParams)
-{
- sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
- if (mp == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return NULL;
- }
-
- Vector<uint8_t> scope;
- if (jscope != NULL) {
- scope = JByteArrayToVector(env, jscope);
- }
-
- String8 mimeType;
- if (jmimeType != NULL) {
- mimeType = JStringToString8(env, jmimeType);
- }
-
- DrmPlugin::KeyType keyType;
- if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
- keyType = DrmPlugin::kKeyType_Streaming;
- } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
- keyType = DrmPlugin::kKeyType_Offline;
- } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
- keyType = DrmPlugin::kKeyType_Release;
- } else {
- jniThrowException(env, "java/lang/IllegalArgumentException", "invalid keyType");
- return NULL;
- }
-
- KeyedVector<String8, String8> optParams;
- if (joptParams != NULL) {
- bool isOK;
- optParams = HashMapToKeyedVector(env, joptParams, &isOK);
- if (!isOK) {
- return NULL;
- }
- }
-
- Vector<uint8_t> request;
- String8 defaultUrl;
- DrmPlugin::KeyRequestType keyRequestType;
- status_t err = mp->getKeyRequest(scope, mimeType, keyType, optParams, request, defaultUrl,
- keyRequestType);
-
- if (throwDrmExceptionAsNecessary(env, err, "Failed to get key request")) {
- return NULL;
- }
-
- ALOGV("JNI getKeyRequest err %d request %d url %s keyReqType %d",
- err, (int)request.size(), defaultUrl.string(), (int)keyRequestType);
-
- // Fill out return obj
- jclass clazz;
- FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
-
- jobject keyObj = NULL;
-
- if (clazz) {
- keyObj = env->AllocObject(clazz);
- jbyteArray jrequest = VectorToJByteArray(env, request);
- env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
-
- jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
- env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
-
- switch (keyRequestType) {
- case DrmPlugin::kKeyRequestType_Initial:
- env->SetIntField(keyObj, gFields.keyRequest.requestType,
- gKeyRequestTypes.kKeyRequestTypeInitial);
- break;
- case DrmPlugin::kKeyRequestType_Renewal:
- env->SetIntField(keyObj, gFields.keyRequest.requestType,
- gKeyRequestTypes.kKeyRequestTypeRenewal);
- break;
- case DrmPlugin::kKeyRequestType_Release:
- env->SetIntField(keyObj, gFields.keyRequest.requestType,
- gKeyRequestTypes.kKeyRequestTypeRelease);
- break;
- default:
- throwDrmStateException(env, "MediaPlayer/DRM plugin failure: unknown "
- "key request type", ERROR_DRM_UNKNOWN);
- break;
+ "Can not release DRM in an active player state.");
}
}
-
- return keyObj;
-}
-
-static jbyteArray android_media_MediaPlayer_provideKeyResponse(JNIEnv *env, jobject thiz,
- jbyteArray jreleaseKeySetId, jbyteArray jresponse)
-{
- sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
- if (mp == NULL ) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return NULL;
- }
-
- if (jresponse == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "key response is null");
- return NULL;
- }
-
- Vector<uint8_t> releaseKeySetId;
- if (jreleaseKeySetId != NULL) {
- releaseKeySetId = JByteArrayToVector(env, jreleaseKeySetId);
- }
-
- Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
- Vector<uint8_t> keySetId;
-
- status_t err = mp->provideKeyResponse(releaseKeySetId, response, keySetId);
-
- if (throwDrmExceptionAsNecessary(env, err, "Failed to handle key response")) {
- return NULL;
- }
- return VectorToJByteArray(env, keySetId);
-}
-
-static void android_media_MediaPlayer_restoreKeys(JNIEnv *env, jobject thiz, jbyteArray jkeySetId)
-{
- sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
- if (mp == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return;
- }
-
- if (jkeySetId == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "invalid keyType");
- return;
- }
-
- Vector<uint8_t> keySetId;
- keySetId = JByteArrayToVector(env, jkeySetId);
-
- status_t err = mp->restoreKeys(keySetId);
-
- ALOGV("JNI restoreKeys err %d ", err);
- throwDrmExceptionAsNecessary(env, err, "Failed to restore keys");
-}
-
-static jstring android_media_MediaPlayer_getDrmPropertyString(JNIEnv *env, jobject thiz,
- jstring jname)
-{
- sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
- if (mp == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return NULL;
- }
-
- if (jname == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "property name String is null");
- return NULL;
- }
-
- String8 name = JStringToString8(env, jname);
- String8 value;
-
- status_t err = mp->getDrmPropertyString(name, value);
-
- ALOGV("JNI getPropertyString err %d", err);
-
- if (throwDrmExceptionAsNecessary(env, err, "Failed to get property")) {
- return NULL;
- }
-
- return env->NewStringUTF(value.string());
-}
-
-static void android_media_MediaPlayer_setDrmPropertyString(JNIEnv *env, jobject thiz,
- jstring jname, jstring jvalue)
-{
- sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
- if (mp == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return;
- }
-
- if (jname == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "property name String is null");
- return;
- }
-
- if (jvalue == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "property value String is null");
- return;
- }
-
- String8 name = JStringToString8(env, jname);
- String8 value = JStringToString8(env, jvalue);
-
- status_t err = mp->setDrmPropertyString(name, value);
-
- ALOGV("JNI setPropertyString err %d", err);
- throwDrmExceptionAsNecessary(env, err, "Failed to set property");
}
// Modular DRM end
// ----------------------------------------------------------------------------
@@ -1802,14 +1431,8 @@ static const JNINativeMethod gMethods[] = {
"(I)Landroid/media/VolumeShaper$State;",
(void *)android_media_MediaPlayer_getVolumeShaperState},
// Modular DRM
- { "_prepareDrm", "([BI)V", (void *)android_media_MediaPlayer_prepareDrm },
+ { "_prepareDrm", "([B[B)V", (void *)android_media_MediaPlayer_prepareDrm },
{ "_releaseDrm", "()V", (void *)android_media_MediaPlayer_releaseDrm },
- { "_getKeyRequest", "([BLjava/lang/String;ILjava/util/Map;)" "Landroid/media/MediaDrm$KeyRequest;",
- (void *)android_media_MediaPlayer_getKeyRequest },
- { "_provideKeyResponse", "([B[B)[B", (void *)android_media_MediaPlayer_provideKeyResponse },
- { "_getDrmPropertyString", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_MediaPlayer_getDrmPropertyString },
- { "_setDrmPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",(void *)android_media_MediaPlayer_setDrmPropertyString },
- { "_restoreKeys", "([B)V", (void *)android_media_MediaPlayer_restoreKeys },
};
// This function only registers the native methods