Loading media/java/android/media/MediaDrm.java +16 −9 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.Bundle; import android.os.Parcel; import android.util.Log; /** Loading Loading @@ -136,10 +137,8 @@ public final class MediaDrm { public static final int MEDIA_DRM_EVENT_KEY_EXPIRED = 3; public static final int MEDIA_DRM_EVENT_VENDOR_DEFINED = 4; /* Do not change these values without updating their counterparts * in include/media/mediadrm.h! */ private static final int DRM_EVENT = 200; private class EventHandler extends Handler { private MediaDrm mMediaDrm; Loading @@ -161,11 +160,19 @@ public final class MediaDrm { Log.i(TAG, "Drm event (" + msg.arg1 + "," + msg.arg2 + ")"); if (mOnEventListener != null) { Bundle bundle = msg.getData(); byte[] sessionId = bundle.getByteArray("sessionId"); byte[] data = bundle.getByteArray("data"); if (msg.obj != null && msg.obj instanceof Parcel) { Parcel parcel = (Parcel)msg.obj; byte[] sessionId = parcel.createByteArray(); if (sessionId.length == 0) { sessionId = null; } byte[] data = parcel.createByteArray(); if (data.length == 0) { data = null; } mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data); } } return; default: Loading @@ -183,14 +190,14 @@ public final class MediaDrm { * the cookie passed to native_setup().) */ private static void postEventFromNative(Object mediadrm_ref, int what, int arg1, int arg2, Object obj) int eventType, int extra, Object obj) { MediaDrm md = (MediaDrm)((WeakReference)mediadrm_ref).get(); if (md == null) { return; } if (md.mEventHandler != null) { Message m = md.mEventHandler.obtainMessage(what, arg1, arg2, obj); Message m = md.mEventHandler.obtainMessage(DRM_EVENT, eventType, extra, obj); md.mEventHandler.sendMessage(m); } } Loading media/jni/android_media_MediaDrm.cpp +142 −3 Original line number Diff line number Diff line Loading @@ -21,10 +21,12 @@ #include "android_media_MediaDrm.h" #include "android_runtime/AndroidRuntime.h" #include "android_os_Parcel.h" #include "jni.h" #include "JNIHelp.h" #include <binder/IServiceManager.h> #include <binder/Parcel.h> #include <media/IDrm.h> #include <media/IMediaPlayerService.h> #include <media/stagefright/foundation/ADebug.h> Loading @@ -43,6 +45,15 @@ namespace android { 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); #define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \ var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \ LOG_FATAL_IF(! var, "Unable to find static method " fieldName); struct RequestFields { jfieldID data; jfieldID defaultUrl; Loading Loading @@ -74,8 +85,16 @@ struct EntryFields { jmethodID getValue; }; struct EventTypes { int kEventProvisionRequired; int kEventKeyRequired; int kEventKeyExpired; int kEventVendorDefined; } gEventTypes; struct fields_t { jfieldID context; jmethodID post_event; RequestFields keyRequest; RequestFields provisionRequest; ArrayListFields arraylist; Loading @@ -87,6 +106,88 @@ struct fields_t { static fields_t gFields; // ---------------------------------------------------------------------------- // ref-counted object for callbacks class JNIDrmListener: public DrmListener { public: JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz); ~JNIDrmListener(); virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj = NULL); private: JNIDrmListener(); jclass mClass; // Reference to MediaDrm class jobject mObject; // Weak ref to MediaDrm Java object to call on }; JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz) { // Hold onto the MediaDrm class for use in calling the static method // that posts events to the application thread. jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { ALOGE("Can't find android/media/MediaDrm"); jniThrowException(env, "java/lang/Exception", NULL); return; } mClass = (jclass)env->NewGlobalRef(clazz); // We use a weak reference so the MediaDrm object can be garbage collected. // The reference is only used as a proxy for callbacks. mObject = env->NewGlobalRef(weak_thiz); } JNIDrmListener::~JNIDrmListener() { // remove global references JNIEnv *env = AndroidRuntime::getJNIEnv(); env->DeleteGlobalRef(mObject); env->DeleteGlobalRef(mClass); } void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) { jint jeventType; // translate DrmPlugin event types into their java equivalents switch(eventType) { case DrmPlugin::kDrmPluginEventProvisionRequired: jeventType = gEventTypes.kEventProvisionRequired; break; case DrmPlugin::kDrmPluginEventKeyNeeded: jeventType = gEventTypes.kEventKeyRequired; break; case DrmPlugin::kDrmPluginEventKeyExpired: jeventType = gEventTypes.kEventKeyExpired; break; case DrmPlugin::kDrmPluginEventVendorDefined: jeventType = gEventTypes.kEventVendorDefined; break; default: ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType); return; } JNIEnv *env = AndroidRuntime::getJNIEnv(); if (obj && obj->dataSize() > 0) { jobject jParcel = createJavaParcelObject(env); if (jParcel != NULL) { Parcel* nativeParcel = parcelForJavaObject(env, jParcel); nativeParcel->setData(obj->data(), obj->dataSize()); env->CallStaticVoidMethod(mClass, gFields.post_event, mObject, jeventType, extra, jParcel); } } if (env->ExceptionCheck()) { ALOGW("An exception occurred while notifying an event."); LOGW_EX(env); env->ExceptionClear(); } } static bool throwExceptionAsNecessary( JNIEnv *env, status_t err, const char *msg = NULL) { Loading @@ -109,6 +210,9 @@ JDrm::JDrm( JNIEnv *env, jobject thiz, const uint8_t uuid[16]) { mObject = env->NewWeakGlobalRef(thiz); mDrm = MakeDrm(uuid); if (mDrm != NULL) { mDrm->setListener(this); } } JDrm::~JDrm() { Loading Loading @@ -160,6 +264,25 @@ sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16]) { return drm; } status_t JDrm::setListener(const sp<DrmListener>& listener) { Mutex::Autolock lock(mLock); mListener = listener; return OK; } void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) { sp<DrmListener> listener; mLock.lock(); listener = mListener; mLock.unlock(); if (listener != NULL) { Mutex::Autolock lock(mNotifyLock); listener->notify(eventType, extra, obj); } } // static bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16]) { sp<IDrm> drm = MakeDrm(); Loading Loading @@ -194,10 +317,9 @@ static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) } static String8 JStringToString8(JNIEnv *env, jstring const &jstr) { jboolean isCopy; String8 result; const char *s = env->GetStringUTFChars(jstr, &isCopy); const char *s = env->GetStringUTFChars(jstr, NULL); if (s) { result = s; env->ReleaseStringUTFChars(jstr, s); Loading Loading @@ -322,13 +444,28 @@ static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jse } static void android_media_MediaDrm_release(JNIEnv *env, jobject thiz) { setDrm(env, thiz, NULL); sp<JDrm> drm = setDrm(env, thiz, NULL); if (drm != NULL) { drm->setListener(NULL); } } static void android_media_MediaDrm_native_init(JNIEnv *env) { jclass clazz; FIND_CLASS(clazz, "android/media/MediaDrm"); GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "I"); GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative", "(Ljava/lang/Object;IILjava/lang/Object;)V"); jfieldID field; GET_STATIC_FIELD_ID(field, clazz, "MEDIA_DRM_EVENT_PROVISION_REQUIRED", "I"); gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field); GET_STATIC_FIELD_ID(field, clazz, "MEDIA_DRM_EVENT_KEY_REQUIRED", "I"); gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field); GET_STATIC_FIELD_ID(field, clazz, "MEDIA_DRM_EVENT_KEY_EXPIRED", "I"); gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field); GET_STATIC_FIELD_ID(field, clazz, "MEDIA_DRM_EVENT_VENDOR_DEFINED", "I"); gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field); FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest"); GET_FIELD_ID(gFields.keyRequest.data, clazz, "data", "[B"); Loading Loading @@ -389,6 +526,8 @@ static void android_media_MediaDrm_native_setup( return; } sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this); drm->setListener(listener); setDrm(env, thiz, drm); } Loading media/jni/android_media_MediaDrm.h +17 −2 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include "jni.h" #include <media/stagefright/foundation/ABase.h> #include <media/IDrm.h> #include <media/IDrmClient.h> #include <utils/Errors.h> #include <utils/RefBase.h> Loading @@ -27,15 +29,24 @@ namespace android { struct IDrm; struct JDrm : public RefBase { class DrmListener: virtual public RefBase { public: virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) = 0; }; struct JDrm : public BnDrmClient { static bool IsCryptoSchemeSupported(const uint8_t uuid[16]); JDrm(JNIEnv *env, jobject thiz, const uint8_t uuid[16]); status_t initCheck() const; sp<IDrm> getDrm() { return mDrm; } void notify(DrmPlugin::EventType, int extra, const Parcel *obj); status_t setListener(const sp<DrmListener>& listener); protected: virtual ~JDrm(); Loading @@ -43,6 +54,10 @@ private: jweak mObject; sp<IDrm> mDrm; sp<DrmListener> mListener; Mutex mNotifyLock; Mutex mLock; static sp<IDrm> MakeDrm(); static sp<IDrm> MakeDrm(const uint8_t uuid[16]); Loading Loading
media/java/android/media/MediaDrm.java +16 −9 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.Bundle; import android.os.Parcel; import android.util.Log; /** Loading Loading @@ -136,10 +137,8 @@ public final class MediaDrm { public static final int MEDIA_DRM_EVENT_KEY_EXPIRED = 3; public static final int MEDIA_DRM_EVENT_VENDOR_DEFINED = 4; /* Do not change these values without updating their counterparts * in include/media/mediadrm.h! */ private static final int DRM_EVENT = 200; private class EventHandler extends Handler { private MediaDrm mMediaDrm; Loading @@ -161,11 +160,19 @@ public final class MediaDrm { Log.i(TAG, "Drm event (" + msg.arg1 + "," + msg.arg2 + ")"); if (mOnEventListener != null) { Bundle bundle = msg.getData(); byte[] sessionId = bundle.getByteArray("sessionId"); byte[] data = bundle.getByteArray("data"); if (msg.obj != null && msg.obj instanceof Parcel) { Parcel parcel = (Parcel)msg.obj; byte[] sessionId = parcel.createByteArray(); if (sessionId.length == 0) { sessionId = null; } byte[] data = parcel.createByteArray(); if (data.length == 0) { data = null; } mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data); } } return; default: Loading @@ -183,14 +190,14 @@ public final class MediaDrm { * the cookie passed to native_setup().) */ private static void postEventFromNative(Object mediadrm_ref, int what, int arg1, int arg2, Object obj) int eventType, int extra, Object obj) { MediaDrm md = (MediaDrm)((WeakReference)mediadrm_ref).get(); if (md == null) { return; } if (md.mEventHandler != null) { Message m = md.mEventHandler.obtainMessage(what, arg1, arg2, obj); Message m = md.mEventHandler.obtainMessage(DRM_EVENT, eventType, extra, obj); md.mEventHandler.sendMessage(m); } } Loading
media/jni/android_media_MediaDrm.cpp +142 −3 Original line number Diff line number Diff line Loading @@ -21,10 +21,12 @@ #include "android_media_MediaDrm.h" #include "android_runtime/AndroidRuntime.h" #include "android_os_Parcel.h" #include "jni.h" #include "JNIHelp.h" #include <binder/IServiceManager.h> #include <binder/Parcel.h> #include <media/IDrm.h> #include <media/IMediaPlayerService.h> #include <media/stagefright/foundation/ADebug.h> Loading @@ -43,6 +45,15 @@ namespace android { 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); #define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \ var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \ LOG_FATAL_IF(! var, "Unable to find static method " fieldName); struct RequestFields { jfieldID data; jfieldID defaultUrl; Loading Loading @@ -74,8 +85,16 @@ struct EntryFields { jmethodID getValue; }; struct EventTypes { int kEventProvisionRequired; int kEventKeyRequired; int kEventKeyExpired; int kEventVendorDefined; } gEventTypes; struct fields_t { jfieldID context; jmethodID post_event; RequestFields keyRequest; RequestFields provisionRequest; ArrayListFields arraylist; Loading @@ -87,6 +106,88 @@ struct fields_t { static fields_t gFields; // ---------------------------------------------------------------------------- // ref-counted object for callbacks class JNIDrmListener: public DrmListener { public: JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz); ~JNIDrmListener(); virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj = NULL); private: JNIDrmListener(); jclass mClass; // Reference to MediaDrm class jobject mObject; // Weak ref to MediaDrm Java object to call on }; JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz) { // Hold onto the MediaDrm class for use in calling the static method // that posts events to the application thread. jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { ALOGE("Can't find android/media/MediaDrm"); jniThrowException(env, "java/lang/Exception", NULL); return; } mClass = (jclass)env->NewGlobalRef(clazz); // We use a weak reference so the MediaDrm object can be garbage collected. // The reference is only used as a proxy for callbacks. mObject = env->NewGlobalRef(weak_thiz); } JNIDrmListener::~JNIDrmListener() { // remove global references JNIEnv *env = AndroidRuntime::getJNIEnv(); env->DeleteGlobalRef(mObject); env->DeleteGlobalRef(mClass); } void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) { jint jeventType; // translate DrmPlugin event types into their java equivalents switch(eventType) { case DrmPlugin::kDrmPluginEventProvisionRequired: jeventType = gEventTypes.kEventProvisionRequired; break; case DrmPlugin::kDrmPluginEventKeyNeeded: jeventType = gEventTypes.kEventKeyRequired; break; case DrmPlugin::kDrmPluginEventKeyExpired: jeventType = gEventTypes.kEventKeyExpired; break; case DrmPlugin::kDrmPluginEventVendorDefined: jeventType = gEventTypes.kEventVendorDefined; break; default: ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType); return; } JNIEnv *env = AndroidRuntime::getJNIEnv(); if (obj && obj->dataSize() > 0) { jobject jParcel = createJavaParcelObject(env); if (jParcel != NULL) { Parcel* nativeParcel = parcelForJavaObject(env, jParcel); nativeParcel->setData(obj->data(), obj->dataSize()); env->CallStaticVoidMethod(mClass, gFields.post_event, mObject, jeventType, extra, jParcel); } } if (env->ExceptionCheck()) { ALOGW("An exception occurred while notifying an event."); LOGW_EX(env); env->ExceptionClear(); } } static bool throwExceptionAsNecessary( JNIEnv *env, status_t err, const char *msg = NULL) { Loading @@ -109,6 +210,9 @@ JDrm::JDrm( JNIEnv *env, jobject thiz, const uint8_t uuid[16]) { mObject = env->NewWeakGlobalRef(thiz); mDrm = MakeDrm(uuid); if (mDrm != NULL) { mDrm->setListener(this); } } JDrm::~JDrm() { Loading Loading @@ -160,6 +264,25 @@ sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16]) { return drm; } status_t JDrm::setListener(const sp<DrmListener>& listener) { Mutex::Autolock lock(mLock); mListener = listener; return OK; } void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) { sp<DrmListener> listener; mLock.lock(); listener = mListener; mLock.unlock(); if (listener != NULL) { Mutex::Autolock lock(mNotifyLock); listener->notify(eventType, extra, obj); } } // static bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16]) { sp<IDrm> drm = MakeDrm(); Loading Loading @@ -194,10 +317,9 @@ static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) } static String8 JStringToString8(JNIEnv *env, jstring const &jstr) { jboolean isCopy; String8 result; const char *s = env->GetStringUTFChars(jstr, &isCopy); const char *s = env->GetStringUTFChars(jstr, NULL); if (s) { result = s; env->ReleaseStringUTFChars(jstr, s); Loading Loading @@ -322,13 +444,28 @@ static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jse } static void android_media_MediaDrm_release(JNIEnv *env, jobject thiz) { setDrm(env, thiz, NULL); sp<JDrm> drm = setDrm(env, thiz, NULL); if (drm != NULL) { drm->setListener(NULL); } } static void android_media_MediaDrm_native_init(JNIEnv *env) { jclass clazz; FIND_CLASS(clazz, "android/media/MediaDrm"); GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "I"); GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative", "(Ljava/lang/Object;IILjava/lang/Object;)V"); jfieldID field; GET_STATIC_FIELD_ID(field, clazz, "MEDIA_DRM_EVENT_PROVISION_REQUIRED", "I"); gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field); GET_STATIC_FIELD_ID(field, clazz, "MEDIA_DRM_EVENT_KEY_REQUIRED", "I"); gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field); GET_STATIC_FIELD_ID(field, clazz, "MEDIA_DRM_EVENT_KEY_EXPIRED", "I"); gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field); GET_STATIC_FIELD_ID(field, clazz, "MEDIA_DRM_EVENT_VENDOR_DEFINED", "I"); gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field); FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest"); GET_FIELD_ID(gFields.keyRequest.data, clazz, "data", "[B"); Loading Loading @@ -389,6 +526,8 @@ static void android_media_MediaDrm_native_setup( return; } sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this); drm->setListener(listener); setDrm(env, thiz, drm); } Loading
media/jni/android_media_MediaDrm.h +17 −2 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include "jni.h" #include <media/stagefright/foundation/ABase.h> #include <media/IDrm.h> #include <media/IDrmClient.h> #include <utils/Errors.h> #include <utils/RefBase.h> Loading @@ -27,15 +29,24 @@ namespace android { struct IDrm; struct JDrm : public RefBase { class DrmListener: virtual public RefBase { public: virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) = 0; }; struct JDrm : public BnDrmClient { static bool IsCryptoSchemeSupported(const uint8_t uuid[16]); JDrm(JNIEnv *env, jobject thiz, const uint8_t uuid[16]); status_t initCheck() const; sp<IDrm> getDrm() { return mDrm; } void notify(DrmPlugin::EventType, int extra, const Parcel *obj); status_t setListener(const sp<DrmListener>& listener); protected: virtual ~JDrm(); Loading @@ -43,6 +54,10 @@ private: jweak mObject; sp<IDrm> mDrm; sp<DrmListener> mListener; Mutex mNotifyLock; Mutex mLock; static sp<IDrm> MakeDrm(); static sp<IDrm> MakeDrm(const uint8_t uuid[16]); Loading