Improve handling MediaCodec linkToDeath() resource manager
manage use of service pointer from MediaCodec to resource manager
to avoid race conditions during teardown.
Bug: 173791720
Test: manual audit since repo is unreliable
Merged-In: I7436e064b63a9b1833f0a2126319674d5ab50828
Change-Id: I843c2f5442557b64babdbba80fc1afd10d2ec5cb
(cherry picked from commit d11e1606e3183c97771ce46ea213a9d71223c45f)
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 4d617ae..553f59a 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -19,6 +19,8 @@
#define LOG_TAG "MediaCodec"
#include <utils/Log.h>
+#include <set>
+
#include <inttypes.h>
#include <stdlib.h>
@@ -201,6 +203,10 @@
// implements DeathRecipient
static void BinderDiedCallback(void* cookie);
void binderDied();
+ static Mutex sLockCookies;
+ static std::set<void*> sCookies;
+ static void addCookie(void* cookie);
+ static void removeCookie(void* cookie);
void addResource(const MediaResourceParcel &resource);
void removeResource(const MediaResourceParcel &resource);
@@ -227,8 +233,15 @@
}
MediaCodec::ResourceManagerServiceProxy::~ResourceManagerServiceProxy() {
+
+ // remove the cookie, so any in-flight death notification will get dropped
+ // by our handler.
+ removeCookie(this);
+
+ Mutex::Autolock _l(mLock);
if (mService != nullptr) {
AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
+ mService = nullptr;
}
}
@@ -240,6 +253,10 @@
return;
}
+ // so our handler will process the death notifications
+ addCookie(this);
+
+ // after this, require mLock whenever using mService
AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
// Kill clients pending removal.
@@ -247,9 +264,28 @@
}
//static
+Mutex MediaCodec::ResourceManagerServiceProxy::sLockCookies;
+std::set<void*> MediaCodec::ResourceManagerServiceProxy::sCookies;
+
+//static
+void MediaCodec::ResourceManagerServiceProxy::addCookie(void* cookie) {
+ Mutex::Autolock _l(sLockCookies);
+ sCookies.insert(cookie);
+}
+
+//static
+void MediaCodec::ResourceManagerServiceProxy::removeCookie(void* cookie) {
+ Mutex::Autolock _l(sLockCookies);
+ sCookies.erase(cookie);
+}
+
+//static
void MediaCodec::ResourceManagerServiceProxy::BinderDiedCallback(void* cookie) {
- auto thiz = static_cast<ResourceManagerServiceProxy*>(cookie);
- thiz->binderDied();
+ Mutex::Autolock _l(sLockCookies);
+ if (sCookies.find(cookie) != sCookies.end()) {
+ auto thiz = static_cast<ResourceManagerServiceProxy*>(cookie);
+ thiz->binderDied();
+ }
}
void MediaCodec::ResourceManagerServiceProxy::binderDied() {