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