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() {