summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
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
commit6225df010365d00b1d0f3b1ca13f18cea537c8e3 (patch)
treef8ec6b625745c57b4a0dbe6aab02072cf10be8d4
parentd7fa7deef9bc0cf22bf450fdb062327697c087c4 (diff)
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
-rw-r--r--api/current.txt1
-rwxr-xr-xdrm/java/android/drm/DrmManagerClient.java78
-rw-r--r--drm/jni/android_drm_DrmManagerClient.cpp34
3 files changed, 86 insertions, 27 deletions
diff --git a/api/current.txt b/api/current.txt
index ddf5baf30ff9..a0405ee5ad63 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7494,6 +7494,7 @@ package android.drm {
method public java.lang.String getOriginalMimeType(android.net.Uri);
method public int openConvertSession(java.lang.String);
method public int processDrmInfo(android.drm.DrmInfo);
+ method public void release();
method public int removeAllRights();
method public int removeRights(java.lang.String);
method public int removeRights(android.net.Uri);
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index 9a7194c4d637..f9567a56ae19 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 dfc7fb2c66a7..cf58177010f3 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},