summaryrefslogtreecommitdiffstats
path: root/media/jni/android_media_MediaCodec.cpp
diff options
context:
space:
mode:
authorChong Zhang <chz@google.com>2014-03-01 18:04:13 -0800
committerChong Zhang <chz@google.com>2014-03-03 12:29:49 -0800
commit128b012cc8c2369136bb8450bc91c81aebe18506 (patch)
treec0054ed0e2473117e4aa7def54a6eedc638199d3 /media/jni/android_media_MediaCodec.cpp
parent6ef3c2cbbb72201e9b2216fb96d071e0fac654d1 (diff)
downloadframeworks_base-128b012cc8c2369136bb8450bc91c81aebe18506.zip
frameworks_base-128b012cc8c2369136bb8450bc91c81aebe18506.tar.gz
frameworks_base-128b012cc8c2369136bb8450bc91c81aebe18506.tar.bz2
fix MediaCodec release deadlock and resource leak
Bug: 12910147 Change-Id: I5f2c02b6ad5bfcd88797c6aa79dcaa23d030eacf
Diffstat (limited to 'media/jni/android_media_MediaCodec.cpp')
-rw-r--r--media/jni/android_media_MediaCodec.cpp31
1 files changed, 30 insertions, 1 deletions
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 3ce483d..b2fb2df 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -112,12 +112,35 @@ void JMediaCodec::registerSelf() {
mLooper->registerHandler(this);
}
-JMediaCodec::~JMediaCodec() {
+void JMediaCodec::release() {
if (mCodec != NULL) {
mCodec->release();
mCodec.clear();
}
+ if (mLooper != NULL) {
+ mLooper->unregisterHandler(id());
+ mLooper->stop();
+ mLooper.clear();
+ }
+}
+
+JMediaCodec::~JMediaCodec() {
+ if (mCodec != NULL || mLooper != NULL) {
+ /* MediaCodec and looper should have been released explicitly already
+ * in setMediaCodec() (see comments in setMediaCodec()).
+ *
+ * Otherwise JMediaCodec::~JMediaCodec() might be called from within the
+ * message handler, doing release() there risks deadlock as MediaCodec::
+ * release() post synchronous message to the same looper.
+ *
+ * Print a warning and try to proceed with releasing.
+ */
+ ALOGW("try to release MediaCodec from JMediaCodec::~JMediaCodec()...");
+ release();
+ ALOGW("done releasing MediaCodec from JMediaCodec::~JMediaCodec().");
+ }
+
JNIEnv *env = AndroidRuntime::getJNIEnv();
env->DeleteWeakGlobalRef(mObject);
@@ -432,6 +455,12 @@ static sp<JMediaCodec> setMediaCodec(
codec->incStrong(thiz);
}
if (old != NULL) {
+ /* release MediaCodec and stop the looper now before decStrong.
+ * otherwise JMediaCodec::~JMediaCodec() could be called from within
+ * its message handler, doing release() from there will deadlock
+ * (as MediaCodec::release() post synchronous message to the same looper)
+ */
+ old->release();
old->decStrong(thiz);
}
env->SetLongField(thiz, gFields.context, (jlong)codec.get());