NoHwServiceManager return true in registerForNotifications am: 2d2e4c0596

Original change: https://android-review.googlesource.com/c/platform/system/libhidl/+/2847957

Change-Id: I4e9cbc7921cd9d6115cd297a866482196b331c74
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index a759c50..c3d3fa4 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -236,7 +236,7 @@
  * to be able service the requests and tell clients there are no services
  * registered.
  */
-struct NoHwServiceManager : public IServiceManager1_2 {
+struct NoHwServiceManager : public IServiceManager1_2, hidl_death_recipient {
     Return<sp<IBase>> get(const hidl_string& fqName, const hidl_string&) override {
         sp<IBase> ret = nullptr;
 
@@ -274,11 +274,49 @@
         return Void();
     }
 
+    void serviceDied(uint64_t /* cookie */, const wp<IBase>& who) override {
+        sp<IBase> promoted = who.promote();
+        if (promoted) {
+            bool removed = false;
+            for (auto [name, callbacks] : mServiceNotifications) {
+                for (auto it = callbacks.begin(); it != callbacks.end();) {
+                    if (interfacesEqual(*it, promoted)) {
+                        callbacks.erase(it);
+                        removed = true;
+                    }
+                    it++;
+                }
+                if (removed) return;
+            }
+        }
+        LOG(ERROR) << "Could not find a registered callback for a service who died. "
+                   << "Service pointer: " << who.promote().get();
+    }
+
     Return<bool> registerForNotifications(const hidl_string& fqName, const hidl_string& name,
-                                          const sp<IServiceNotification>& /* callback */) override {
-        LOG(INFO) << "Cannot register for notifications for " << fqName << "/" << name
-                  << " without hwservicemanager";
-        return false;
+                                          const sp<IServiceNotification>& callback) override {
+        LOG(INFO) << "Will not get any notifications for " << fqName << "/" << name
+                  << " without hwservicemanager but keeping the callback.";
+        if (callback == nullptr) {
+            LOG(ERROR) << "Cannot register a null callback for " << fqName << "/" << name;
+            return false;
+        }
+        bool ret = callback->linkToDeath(this, 0);
+        if (!ret) {
+            LOG(ERROR) << "Failed to register death recipient for " << fqName << "/" << name;
+            return false;
+        }
+
+        auto [it, inserted] = mServiceNotifications[static_cast<std::string>(fqName) + "/" +
+                                                    static_cast<std::string>(name)]
+                                      .insert(callback);
+        if (!inserted) {
+            LOG(WARNING) << "This callback for " << fqName << "/" << name
+                         << " was already registered so "
+                         << "we are not keeping a reference to this one.";
+            return false;
+        }
+        return true;
     }
 
     Return<void> debugDump(debugDump_cb _hidl_cb) override {
@@ -294,13 +332,19 @@
         return Void();
     }
 
-    Return<bool> unregisterForNotifications(
-            const hidl_string& fqName, const hidl_string& name,
-            const sp<IServiceNotification>& /* callback */) override {
-        LOG(INFO) << "Cannot unregister for notifications for " << fqName << "/" << name
-                  << " without hwservicemanager";
-        return false;
+    Return<bool> unregisterForNotifications(const hidl_string& fqName, const hidl_string& name,
+                                            const sp<IServiceNotification>& callback) override {
+        auto ret = mServiceNotifications[static_cast<std::string>(fqName) + "/" +
+                                         static_cast<std::string>(name)]
+                           .erase(callback);
+        if (!ret) {
+            LOG(WARNING) << "This callback for " << fqName << "/" << name << " was not previously "
+                         << "registered so there is nothing to do.";
+            return false;
+        }
+        return true;
     }
+
     Return<bool> registerClientCallback(const hidl_string& fqName, const hidl_string& name,
                                         const sp<IBase>&, const sp<IClientCallback>&) {
         LOG(INFO) << "Cannot add client callback for " << fqName << "/" << name
@@ -326,6 +370,9 @@
                   << " without hwservicemanager";
         return false;
     }
+
+  private:
+    std::map<std::string, std::set<sp<IServiceNotification>>> mServiceNotifications;
 };
 
 sp<IServiceManager1_2> defaultServiceManager1_2() {