Make mediaserver listen to Codec2 services' deaths

Test: Kill media.extractor or mediaswcodec and observe logcat

Bug: 130071409

Change-Id: Ie785642da99dfe4ff13e78d878817dae3de9f34a
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 5061024..dfd3933 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -34,7 +34,7 @@
 
 #include <utils/misc.h>
 
-#include <android/hardware/media/omx/1.0/IOmxStore.h>
+#include <android/hardware/media/omx/1.0/IOmx.h>
 #include <android/hardware/media/c2/1.0/IComponentStore.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
@@ -47,6 +47,7 @@
 #include <utils/Timers.h>
 #include <utils/Vector.h>
 
+#include <codec2/hidl/client.h>
 #include <media/IMediaHTTPService.h>
 #include <media/IRemoteDisplay.h>
 #include <media/IRemoteDisplayClient.h>
@@ -591,7 +592,6 @@
     if (mAudioAttributes != NULL) {
         free(mAudioAttributes);
     }
-    clearDeathNotifiers_l();
     mAudioDeviceUpdatedListener.clear();
 }
 
@@ -647,59 +647,6 @@
     return p;
 }
 
-MediaPlayerService::Client::ServiceDeathNotifier::ServiceDeathNotifier(
-        const sp<IBinder>& service,
-        const sp<MediaPlayerBase>& listener,
-        int which) {
-    mService = service;
-    mHService = nullptr;
-    mListener = listener;
-    mWhich = which;
-}
-
-MediaPlayerService::Client::ServiceDeathNotifier::ServiceDeathNotifier(
-        const sp<android::hidl::base::V1_0::IBase>& hService,
-        const sp<MediaPlayerBase>& listener,
-        int which) {
-    mService = nullptr;
-    mHService = hService;
-    mListener = listener;
-    mWhich = which;
-}
-
-MediaPlayerService::Client::ServiceDeathNotifier::~ServiceDeathNotifier() {
-}
-
-void MediaPlayerService::Client::ServiceDeathNotifier::binderDied(const wp<IBinder>& /*who*/) {
-    sp<MediaPlayerBase> listener = mListener.promote();
-    if (listener != NULL) {
-        listener->sendEvent(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, mWhich);
-    } else {
-        ALOGW("listener for process %d death is gone", mWhich);
-    }
-}
-
-void MediaPlayerService::Client::ServiceDeathNotifier::serviceDied(
-        uint64_t /* cookie */,
-        const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
-    sp<MediaPlayerBase> listener = mListener.promote();
-    if (listener != NULL) {
-        listener->sendEvent(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, mWhich);
-    } else {
-        ALOGW("listener for process %d death is gone", mWhich);
-    }
-}
-
-void MediaPlayerService::Client::ServiceDeathNotifier::unlinkToDeath() {
-    if (mService != nullptr) {
-        mService->unlinkToDeath(this);
-        mService = nullptr;
-    } else if (mHService != nullptr) {
-        mHService->unlinkToDeath(this);
-        mHService = nullptr;
-    }
-}
-
 void MediaPlayerService::Client::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate(
         audio_io_handle_t audioIo,
         audio_port_handle_t deviceId) {
@@ -711,19 +658,6 @@
     }
 }
 
-void MediaPlayerService::Client::clearDeathNotifiers_l() {
-    if (mExtractorDeathListener != nullptr) {
-        mExtractorDeathListener->unlinkToDeath();
-        mExtractorDeathListener = nullptr;
-    }
-    for (const sp<ServiceDeathNotifier>& codecDeathListener : mCodecDeathListeners) {
-        if (codecDeathListener != nullptr) {
-            codecDeathListener->unlinkToDeath();
-        }
-    }
-    mCodecDeathListeners.clear();
-}
-
 sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
         player_type playerType)
 {
@@ -735,66 +669,83 @@
         return p;
     }
 
+    std::vector<DeathNotifier> deathNotifiers;
+
+    // Listen to death of media.extractor service
     sp<IServiceManager> sm = defaultServiceManager();
     sp<IBinder> binder = sm->getService(String16("media.extractor"));
     if (binder == NULL) {
         ALOGE("extractor service not available");
         return NULL;
     }
-    sp<ServiceDeathNotifier> extractorDeathListener =
-            new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
-    binder->linkToDeath(extractorDeathListener);
+    deathNotifiers.emplace_back(
+            binder, [l = wp<MediaPlayerBase>(p)]() {
+        sp<MediaPlayerBase> listener = l.promote();
+        if (listener) {
+            ALOGI("media.extractor died. Sending death notification.");
+            listener->sendEvent(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
+                                MEDIAEXTRACTOR_PROCESS_DEATH);
+        } else {
+            ALOGW("media.extractor died without a death handler.");
+        }
+    });
 
-    std::vector<sp<ServiceDeathNotifier>> codecDeathListeners;
     {
         using ::android::hidl::base::V1_0::IBase;
 
-        // Listen to OMX's IOmxStore/default
+        // Listen to death of OMX service
         {
-            sp<IBase> store = ::android::hardware::media::omx::V1_0::
-                    IOmxStore::getService();
-            if (store == nullptr) {
+            sp<IBase> base = ::android::hardware::media::omx::V1_0::
+                    IOmx::getService();
+            if (base == nullptr) {
                 ALOGD("OMX service is not available");
             } else {
-                sp<ServiceDeathNotifier> codecDeathListener =
-                        new ServiceDeathNotifier(store, p, MEDIACODEC_PROCESS_DEATH);
-                store->linkToDeath(codecDeathListener, 0);
-                codecDeathListeners.emplace_back(codecDeathListener);
+                deathNotifiers.emplace_back(
+                        base, [l = wp<MediaPlayerBase>(p)]() {
+                    sp<MediaPlayerBase> listener = l.promote();
+                    if (listener) {
+                        ALOGI("OMX service died. "
+                              "Sending death notification.");
+                        listener->sendEvent(
+                                MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
+                                MEDIACODEC_PROCESS_DEATH);
+                    } else {
+                        ALOGW("OMX service died without a death handler.");
+                    }
+                });
             }
         }
 
-        // Listen to Codec2's IComponentStore/software
-        // TODO: Listen to all Codec2 services.
+        // Listen to death of Codec2 services
         {
-            sp<IBase> store = ::android::hardware::media::c2::V1_0::
-                    IComponentStore::getService();
-            if (store == nullptr) {
-                ALOGD("Codec2 system service is not available");
-            } else {
-                sp<ServiceDeathNotifier> codecDeathListener =
-                        new ServiceDeathNotifier(store, p, MEDIACODEC_PROCESS_DEATH);
-                store->linkToDeath(codecDeathListener, 0);
-                codecDeathListeners.emplace_back(codecDeathListener);
-            }
-
-            store = ::android::hardware::media::c2::V1_0::
-                    IComponentStore::getService("software");
-            if (store == nullptr) {
-                ALOGD("Codec2 swcodec service is not available");
-            } else {
-                sp<ServiceDeathNotifier> codecDeathListener =
-                        new ServiceDeathNotifier(store, p, MEDIACODEC_PROCESS_DEATH);
-                store->linkToDeath(codecDeathListener, 0);
-                codecDeathListeners.emplace_back(codecDeathListener);
+            for (std::shared_ptr<Codec2Client> const& client :
+                    Codec2Client::CreateFromAllServices()) {
+                sp<IBase> base = client->getBase();
+                deathNotifiers.emplace_back(
+                        base, [l = wp<MediaPlayerBase>(p),
+                               name = std::string(client->getServiceName())]() {
+                    sp<MediaPlayerBase> listener = l.promote();
+                    if (listener) {
+                        ALOGI("Codec2 service \"%s\" died. "
+                              "Sending death notification.",
+                              name.c_str());
+                        listener->sendEvent(
+                                MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
+                                MEDIACODEC_PROCESS_DEATH);
+                    } else {
+                        ALOGW("Codec2 service \"%s\" died "
+                              "without a death handler.",
+                              name.c_str());
+                    }
+                });
             }
         }
     }
 
     Mutex::Autolock lock(mLock);
 
-    clearDeathNotifiers_l();
-    mExtractorDeathListener = extractorDeathListener;
-    mCodecDeathListeners.swap(codecDeathListeners);
+    mDeathNotifiers.clear();
+    mDeathNotifiers.swap(deathNotifiers);
     mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p);
 
     if (!p->hardwareOutput()) {