summaryrefslogtreecommitdiff
path: root/media/jni/android_media_MediaCodec.cpp
diff options
context:
space:
mode:
authorWonsik Kim <wonsik@google.com>2020-06-18 23:52:03 -0700
committerWonsik Kim <wonsik@google.com>2020-06-19 13:04:02 -0700
commite37ef4bc9210b3882ef83bb2ef514239b30d4bdf (patch)
treea77e9e7095bde3f11f8bb669b1c84d5a83fa2335 /media/jni/android_media_MediaCodec.cpp
parent721a3ac8360cbd5346317c0092e95e8a83b21cd9 (diff)
media: fix race condition on async release
Clear Java object state at releaseAsync(), and delete native object upon async release complete. Clearing CodecBase object only led to a rare race condition which caused null pointer dereference. Bug: 158501286 Test: atest CtsMediaTestCases:MediaCodecTest#testAsyncRelease (100 times) Test: atest CtsMediaTestCases:MediaCodecCapabilitiesTest#testGetMaxSupportedInstances Test: atest CtsMediaTestCases -- --module-arg CtsMediaTestCases:size:small Change-Id: I691d39007c0ea770318f4038558ad338252bd2fb
Diffstat (limited to 'media/jni/android_media_MediaCodec.cpp')
-rw-r--r--media/jni/android_media_MediaCodec.cpp21
1 files changed, 15 insertions, 6 deletions
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index f970b598d6f8..0b0e162d4faf 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -235,7 +235,10 @@ void JMediaCodec::release() {
void JMediaCodec::releaseAsync() {
std::call_once(mAsyncReleaseFlag, [this] {
if (mCodec != NULL) {
- mCodec->releaseAsync(new AMessage(kWhatAsyncReleaseComplete, this));
+ sp<AMessage> notify = new AMessage(kWhatAsyncReleaseComplete, this);
+ // Hold strong reference to this until async release is complete
+ notify->setObject("this", this);
+ mCodec->releaseAsync(notify);
}
mInitStatus = NO_INIT;
});
@@ -1088,8 +1091,11 @@ void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
}
case kWhatAsyncReleaseComplete:
{
- mCodec.clear();
- mLooper->stop();
+ if (mLooper != NULL) {
+ mLooper->unregisterHandler(id());
+ mLooper->stop();
+ mLooper.clear();
+ }
break;
}
default:
@@ -1104,7 +1110,7 @@ void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
using namespace android;
static sp<JMediaCodec> setMediaCodec(
- JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) {
+ JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec, bool release = true) {
sp<JMediaCodec> old = (JMediaCodec *)env->CallLongMethod(thiz, gFields.lockAndGetContextID);
if (codec != NULL) {
codec->incStrong(thiz);
@@ -1115,7 +1121,9 @@ static sp<JMediaCodec> setMediaCodec(
* its message handler, doing release() from there will deadlock
* (as MediaCodec::release() post synchronous message to the same looper)
*/
- old->release();
+ if (release) {
+ old->release();
+ }
old->decStrong(thiz);
}
env->CallVoidMethod(thiz, gFields.setAndUnlockContextID, (jlong)codec.get());
@@ -1130,7 +1138,8 @@ static sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) {
}
static void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) {
- sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+ // Clear Java native reference.
+ sp<JMediaCodec> codec = setMediaCodec(env, thiz, nullptr, false /* release */);
if (codec != NULL) {
codec->releaseAsync();
}