diff options
author | Kei Takahashi <KeiA.Takahashi@jp.sony.com> | 2012-01-31 13:18:45 +0900 |
---|---|---|
committer | Kei Takahashi <KeiA.Takahashi@jp.sony.com> | 2012-02-29 12:59:53 +0900 |
commit | 6225df010365d00b1d0f3b1ca13f18cea537c8e3 (patch) | |
tree | f8ec6b625745c57b4a0dbe6aab02072cf10be8d4 /drm | |
parent | d7fa7deef9bc0cf22bf450fdb062327697c087c4 (diff) | |
download | frameworks_base-6225df010365d00b1d0f3b1ca13f18cea537c8e3.zip frameworks_base-6225df010365d00b1d0f3b1ca13f18cea537c8e3.tar.gz frameworks_base-6225df010365d00b1d0f3b1ca13f18cea537c8e3.tar.bz2 |
DRM framwork bug fix: add an API to release resources
When DrmManagerClient object is created and released many times,
the process suddenly crashes.
The case can happen when we make many thumbnails of
DRM-encrypted contents.
The problem is caused by shortage of file descriptors.
DrmManagerClient releases references of file descriptors
only when GC runs. So file descriptors are kept long time
even after the reference of DrmManagerClient are released.
By introducing DrmManagerClient#release() API,
the problem is solved. An application call this API
when we no longer need to use DrmManagerClient object.
Changes are made by SEMC and Sony.
Change-Id: Ie0bbc29cc33872449824285a8d67b1c3cdd8082b
Diffstat (limited to 'drm')
-rwxr-xr-x | drm/java/android/drm/DrmManagerClient.java | 78 | ||||
-rw-r--r-- | drm/jni/android_drm_DrmManagerClient.cpp | 34 |
2 files changed, 85 insertions, 27 deletions
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java index 9a7194c..f9567a5 100755 --- a/drm/java/android/drm/DrmManagerClient.java +++ b/drm/java/android/drm/DrmManagerClient.java @@ -49,6 +49,8 @@ public class DrmManagerClient { */ public static final int ERROR_UNKNOWN = -2000; + HandlerThread mInfoThread; + HandlerThread mEventThread; private static final String TAG = "DrmManagerClient"; static { @@ -105,6 +107,7 @@ public class DrmManagerClient { private int mUniqueId; private int mNativeContext; + private boolean mReleased; private Context mContext; private InfoHandler mInfoHandler; private EventHandler mEventHandler; @@ -238,23 +241,63 @@ public class DrmManagerClient { */ public DrmManagerClient(Context context) { mContext = context; - - HandlerThread infoThread = new HandlerThread("DrmManagerClient.InfoHandler"); - infoThread.start(); - mInfoHandler = new InfoHandler(infoThread.getLooper()); - - HandlerThread eventThread = new HandlerThread("DrmManagerClient.EventHandler"); - eventThread.start(); - mEventHandler = new EventHandler(eventThread.getLooper()); + mReleased = false; // save the unique id - mUniqueId = _initialize(new WeakReference<DrmManagerClient>(this)); + mUniqueId = _initialize(); } protected void finalize() { - _finalize(mUniqueId); + if (!mReleased) { + Log.w(TAG, "You should have called release()"); + release(); + } + } + + /** + * Releases resources associated with the current session of DrmManagerClient. + * + * It is considered good practice to call this method when the {@link DrmManagerClient} object + * is no longer needed in your application. After release() is called, + * {@link DrmManagerClient} is no longer usable since it has lost all of its required resource. + */ + public void release() { + if (mReleased) { + Log.w(TAG, "You have already called release()"); + return; + } + mReleased = true; + if (mEventHandler != null) { + mEventThread.quit(); + mEventThread = null; + } + if (mInfoHandler != null) { + mInfoThread.quit(); + mInfoThread = null; + } + mEventHandler = null; + mInfoHandler = null; + mOnEventListener = null; + mOnInfoListener = null; + mOnErrorListener = null; + _release(mUniqueId); } + + private void createListeners() { + if (mEventHandler == null && mInfoHandler == null) { + mInfoThread = new HandlerThread("DrmManagerClient.InfoHandler"); + mInfoThread.start(); + mInfoHandler = new InfoHandler(mInfoThread.getLooper()); + + mEventThread = new HandlerThread("DrmManagerClient.EventHandler"); + mEventThread.start(); + mEventHandler = new EventHandler(mEventThread.getLooper()); + _setListeners(mUniqueId, new WeakReference<DrmManagerClient>(this)); + } + } + + /** * Registers an {@link DrmManagerClient.OnInfoListener} callback, which is invoked when the * DRM framework sends status or warning information during registration or rights acquisition. @@ -262,8 +305,9 @@ public class DrmManagerClient { * @param infoListener Interface definition for the callback. */ public synchronized void setOnInfoListener(OnInfoListener infoListener) { + mOnInfoListener = infoListener; if (null != infoListener) { - mOnInfoListener = infoListener; + createListeners(); } } @@ -274,8 +318,9 @@ public class DrmManagerClient { * @param eventListener Interface definition for the callback. */ public synchronized void setOnEventListener(OnEventListener eventListener) { + mOnEventListener = eventListener; if (null != eventListener) { - mOnEventListener = eventListener; + createListeners(); } } @@ -286,8 +331,9 @@ public class DrmManagerClient { * @param errorListener Interface definition for the callback. */ public synchronized void setOnErrorListener(OnErrorListener errorListener) { + mOnErrorListener = errorListener; if (null != errorListener) { - mOnErrorListener = errorListener; + createListeners(); } } @@ -792,9 +838,11 @@ public class DrmManagerClient { } // private native interfaces - private native int _initialize(Object weak_this); + private native int _initialize(); + + private native void _setListeners(int uniqueId, Object weak_this); - private native void _finalize(int uniqueId); + private native void _release(int uniqueId); private native void _installDrmEngine(int uniqueId, String engineFilepath); diff --git a/drm/jni/android_drm_DrmManagerClient.cpp b/drm/jni/android_drm_DrmManagerClient.cpp index dfc7fb2..cf58177 100644 --- a/drm/jni/android_drm_DrmManagerClient.cpp +++ b/drm/jni/android_drm_DrmManagerClient.cpp @@ -225,25 +225,32 @@ static sp<DrmManagerClientImpl> getDrmManagerClientImpl(JNIEnv* env, jobject thi } static jint android_drm_DrmManagerClient_initialize( - JNIEnv* env, jobject thiz, jobject weak_thiz) { + JNIEnv* env, jobject thiz) { ALOGV("initialize - Enter"); int uniqueId = 0; sp<DrmManagerClientImpl> drmManager = DrmManagerClientImpl::create(&uniqueId, false); drmManager->addClient(uniqueId); - // Set the listener to DrmManager - sp<DrmManagerClient::OnInfoListener> listener = new JNIOnInfoListener(env, thiz, weak_thiz); - drmManager->setOnInfoListener(uniqueId, listener); - setDrmManagerClientImpl(env, thiz, drmManager); ALOGV("initialize - Exit"); - return uniqueId; } -static void android_drm_DrmManagerClient_finalize(JNIEnv* env, jobject thiz, jint uniqueId) { - ALOGV("finalize - Enter"); +static void android_drm_DrmManagerClient_setListeners( + JNIEnv* env, jobject thiz, jint uniqueId, jobject weak_thiz) { + ALOGV("setListeners - Enter"); + + // Set the listener to DrmManager + sp<DrmManagerClient::OnInfoListener> listener = new JNIOnInfoListener(env, thiz, weak_thiz); + getDrmManagerClientImpl(env, thiz)->setOnInfoListener(uniqueId, listener); + + ALOGV("setListeners - Exit"); +} + +static void android_drm_DrmManagerClient_release( + JNIEnv* env, jobject thiz, jint uniqueId) { + ALOGV("release - Enter"); DrmManagerClientImpl::remove(uniqueId); getDrmManagerClientImpl(env, thiz)->setOnInfoListener(uniqueId, NULL); @@ -252,7 +259,7 @@ static void android_drm_DrmManagerClient_finalize(JNIEnv* env, jobject thiz, jin oldClient->setOnInfoListener(uniqueId, NULL); oldClient->removeClient(uniqueId); } - ALOGV("finalize - Exit"); + ALOGV("release - Exit"); } static jobject android_drm_DrmManagerClient_getConstraintsFromContent( @@ -714,11 +721,14 @@ static jobject android_drm_DrmManagerClient_closeConvertSession( static JNINativeMethod nativeMethods[] = { - {"_initialize", "(Ljava/lang/Object;)I", + {"_initialize", "()I", (void*)android_drm_DrmManagerClient_initialize}, - {"_finalize", "(I)V", - (void*)android_drm_DrmManagerClient_finalize}, + {"_setListeners", "(ILjava/lang/Object;)V", + (void*)android_drm_DrmManagerClient_setListeners}, + + {"_release", "(I)V", + (void*)android_drm_DrmManagerClient_release}, {"_getConstraints", "(ILjava/lang/String;I)Landroid/content/ContentValues;", (void*)android_drm_DrmManagerClient_getConstraintsFromContent}, |