Skip to content

Commit 6225df0

Browse files
Kei TakahashiKei Takahashi
authored andcommitted
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
1 parent d7fa7de commit 6225df0

File tree

3 files changed

+86
-27
lines changed

3 files changed

+86
-27
lines changed

api/current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7494,6 +7494,7 @@ package android.drm {
74947494
method public java.lang.String getOriginalMimeType(android.net.Uri);
74957495
method public int openConvertSession(java.lang.String);
74967496
method public int processDrmInfo(android.drm.DrmInfo);
7497+
method public void release();
74977498
method public int removeAllRights();
74987499
method public int removeRights(java.lang.String);
74997500
method public int removeRights(android.net.Uri);

drm/java/android/drm/DrmManagerClient.java

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public class DrmManagerClient {
4949
*/
5050
public static final int ERROR_UNKNOWN = -2000;
5151

52+
HandlerThread mInfoThread;
53+
HandlerThread mEventThread;
5254
private static final String TAG = "DrmManagerClient";
5355

5456
static {
@@ -105,6 +107,7 @@ public interface OnErrorListener {
105107

106108
private int mUniqueId;
107109
private int mNativeContext;
110+
private boolean mReleased;
108111
private Context mContext;
109112
private InfoHandler mInfoHandler;
110113
private EventHandler mEventHandler;
@@ -238,32 +241,73 @@ public void handleMessage(Message msg) {
238241
*/
239242
public DrmManagerClient(Context context) {
240243
mContext = context;
241-
242-
HandlerThread infoThread = new HandlerThread("DrmManagerClient.InfoHandler");
243-
infoThread.start();
244-
mInfoHandler = new InfoHandler(infoThread.getLooper());
245-
246-
HandlerThread eventThread = new HandlerThread("DrmManagerClient.EventHandler");
247-
eventThread.start();
248-
mEventHandler = new EventHandler(eventThread.getLooper());
244+
mReleased = false;
249245

250246
// save the unique id
251-
mUniqueId = _initialize(new WeakReference<DrmManagerClient>(this));
247+
mUniqueId = _initialize();
252248
}
253249

254250
protected void finalize() {
255-
_finalize(mUniqueId);
251+
if (!mReleased) {
252+
Log.w(TAG, "You should have called release()");
253+
release();
254+
}
255+
}
256+
257+
/**
258+
* Releases resources associated with the current session of DrmManagerClient.
259+
*
260+
* It is considered good practice to call this method when the {@link DrmManagerClient} object
261+
* is no longer needed in your application. After release() is called,
262+
* {@link DrmManagerClient} is no longer usable since it has lost all of its required resource.
263+
*/
264+
public void release() {
265+
if (mReleased) {
266+
Log.w(TAG, "You have already called release()");
267+
return;
268+
}
269+
mReleased = true;
270+
if (mEventHandler != null) {
271+
mEventThread.quit();
272+
mEventThread = null;
273+
}
274+
if (mInfoHandler != null) {
275+
mInfoThread.quit();
276+
mInfoThread = null;
277+
}
278+
mEventHandler = null;
279+
mInfoHandler = null;
280+
mOnEventListener = null;
281+
mOnInfoListener = null;
282+
mOnErrorListener = null;
283+
_release(mUniqueId);
256284
}
257285

286+
287+
private void createListeners() {
288+
if (mEventHandler == null && mInfoHandler == null) {
289+
mInfoThread = new HandlerThread("DrmManagerClient.InfoHandler");
290+
mInfoThread.start();
291+
mInfoHandler = new InfoHandler(mInfoThread.getLooper());
292+
293+
mEventThread = new HandlerThread("DrmManagerClient.EventHandler");
294+
mEventThread.start();
295+
mEventHandler = new EventHandler(mEventThread.getLooper());
296+
_setListeners(mUniqueId, new WeakReference<DrmManagerClient>(this));
297+
}
298+
}
299+
300+
258301
/**
259302
* Registers an {@link DrmManagerClient.OnInfoListener} callback, which is invoked when the
260303
* DRM framework sends status or warning information during registration or rights acquisition.
261304
*
262305
* @param infoListener Interface definition for the callback.
263306
*/
264307
public synchronized void setOnInfoListener(OnInfoListener infoListener) {
308+
mOnInfoListener = infoListener;
265309
if (null != infoListener) {
266-
mOnInfoListener = infoListener;
310+
createListeners();
267311
}
268312
}
269313

@@ -274,8 +318,9 @@ public synchronized void setOnInfoListener(OnInfoListener infoListener) {
274318
* @param eventListener Interface definition for the callback.
275319
*/
276320
public synchronized void setOnEventListener(OnEventListener eventListener) {
321+
mOnEventListener = eventListener;
277322
if (null != eventListener) {
278-
mOnEventListener = eventListener;
323+
createListeners();
279324
}
280325
}
281326

@@ -286,8 +331,9 @@ public synchronized void setOnEventListener(OnEventListener eventListener) {
286331
* @param errorListener Interface definition for the callback.
287332
*/
288333
public synchronized void setOnErrorListener(OnErrorListener errorListener) {
334+
mOnErrorListener = errorListener;
289335
if (null != errorListener) {
290-
mOnErrorListener = errorListener;
336+
createListeners();
291337
}
292338
}
293339

@@ -792,9 +838,11 @@ private String convertUriToPath(Uri uri) {
792838
}
793839

794840
// private native interfaces
795-
private native int _initialize(Object weak_this);
841+
private native int _initialize();
842+
843+
private native void _setListeners(int uniqueId, Object weak_this);
796844

797-
private native void _finalize(int uniqueId);
845+
private native void _release(int uniqueId);
798846

799847
private native void _installDrmEngine(int uniqueId, String engineFilepath);
800848

drm/jni/android_drm_DrmManagerClient.cpp

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -225,25 +225,32 @@ static sp<DrmManagerClientImpl> getDrmManagerClientImpl(JNIEnv* env, jobject thi
225225
}
226226

227227
static jint android_drm_DrmManagerClient_initialize(
228-
JNIEnv* env, jobject thiz, jobject weak_thiz) {
228+
JNIEnv* env, jobject thiz) {
229229
ALOGV("initialize - Enter");
230230

231231
int uniqueId = 0;
232232
sp<DrmManagerClientImpl> drmManager = DrmManagerClientImpl::create(&uniqueId, false);
233233
drmManager->addClient(uniqueId);
234234

235-
// Set the listener to DrmManager
236-
sp<DrmManagerClient::OnInfoListener> listener = new JNIOnInfoListener(env, thiz, weak_thiz);
237-
drmManager->setOnInfoListener(uniqueId, listener);
238-
239235
setDrmManagerClientImpl(env, thiz, drmManager);
240236
ALOGV("initialize - Exit");
241-
242237
return uniqueId;
243238
}
244239

245-
static void android_drm_DrmManagerClient_finalize(JNIEnv* env, jobject thiz, jint uniqueId) {
246-
ALOGV("finalize - Enter");
240+
static void android_drm_DrmManagerClient_setListeners(
241+
JNIEnv* env, jobject thiz, jint uniqueId, jobject weak_thiz) {
242+
ALOGV("setListeners - Enter");
243+
244+
// Set the listener to DrmManager
245+
sp<DrmManagerClient::OnInfoListener> listener = new JNIOnInfoListener(env, thiz, weak_thiz);
246+
getDrmManagerClientImpl(env, thiz)->setOnInfoListener(uniqueId, listener);
247+
248+
ALOGV("setListeners - Exit");
249+
}
250+
251+
static void android_drm_DrmManagerClient_release(
252+
JNIEnv* env, jobject thiz, jint uniqueId) {
253+
ALOGV("release - Enter");
247254
DrmManagerClientImpl::remove(uniqueId);
248255
getDrmManagerClientImpl(env, thiz)->setOnInfoListener(uniqueId, NULL);
249256

@@ -252,7 +259,7 @@ static void android_drm_DrmManagerClient_finalize(JNIEnv* env, jobject thiz, jin
252259
oldClient->setOnInfoListener(uniqueId, NULL);
253260
oldClient->removeClient(uniqueId);
254261
}
255-
ALOGV("finalize - Exit");
262+
ALOGV("release - Exit");
256263
}
257264

258265
static jobject android_drm_DrmManagerClient_getConstraintsFromContent(
@@ -714,11 +721,14 @@ static jobject android_drm_DrmManagerClient_closeConvertSession(
714721

715722
static JNINativeMethod nativeMethods[] = {
716723

717-
{"_initialize", "(Ljava/lang/Object;)I",
724+
{"_initialize", "()I",
718725
(void*)android_drm_DrmManagerClient_initialize},
719726

720-
{"_finalize", "(I)V",
721-
(void*)android_drm_DrmManagerClient_finalize},
727+
{"_setListeners", "(ILjava/lang/Object;)V",
728+
(void*)android_drm_DrmManagerClient_setListeners},
729+
730+
{"_release", "(I)V",
731+
(void*)android_drm_DrmManagerClient_release},
722732

723733
{"_getConstraints", "(ILjava/lang/String;I)Landroid/content/ContentValues;",
724734
(void*)android_drm_DrmManagerClient_getConstraintsFromContent},

0 commit comments

Comments
 (0)