Implement @1.1::IServiceManager

This adds the ability to unregisterServiceNotifications.

By doing this, we can avoid unnecessary memory from being held
and also avoid unnecessary IPC calls.

Test: hidl_test
Test: boot a marlin
Bug: 63940457

Change-Id: I949a3fb50a5210138b623ab1654dc3e7a5f15e1c
diff --git a/HidlService.cpp b/HidlService.cpp
index 13717cf..a0f2cab 100644
--- a/HidlService.cpp
+++ b/HidlService.cpp
@@ -2,12 +2,12 @@
 #include "HidlService.h"
 
 #include <android-base/logging.h>
+#include <hidl/HidlTransportSupport.h>
 #include <sstream>
 
 namespace android {
 namespace hidl {
 namespace manager {
-namespace V1_0 {
 namespace implementation {
 
 HidlService::HidlService(
@@ -56,10 +56,12 @@
 }
 
 bool HidlService::removeListener(const wp<IBase>& listener) {
+    using ::android::hardware::interfacesEqual;
+
     bool found = false;
 
     for (auto it = mListeners.begin(); it != mListeners.end();) {
-        if (*it == listener) {
+        if (interfacesEqual(*it, listener.promote())) {
             it = mListeners.erase(it);
             found = true;
         } else {
@@ -105,7 +107,6 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_0
 }  // namespace manager
 }  // namespace hidl
 }  // namespace android
diff --git a/HidlService.h b/HidlService.h
index 3de0abb..2fcb0d6 100644
--- a/HidlService.h
+++ b/HidlService.h
@@ -1,16 +1,15 @@
-#ifndef ANDROID_HARDWARE_MANAGER_V1_0_HIDLSERVICE_H
-#define ANDROID_HARDWARE_MANAGER_V1_0_HIDLSERVICE_H
+#ifndef ANDROID_HARDWARE_MANAGER_HIDLSERVICE_H
+#define ANDROID_HARDWARE_MANAGER_HIDLSERVICE_H
 
 #include <set>
 
-#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hidl/manager/1.1/IServiceManager.h>
 #include <hidl/Status.h>
 #include <hidl/MQDescriptor.h>
 
 namespace android {
 namespace hidl {
 namespace manager {
-namespace V1_0 {
 namespace implementation {
 
 using ::android::hardware::hidl_vec;
@@ -18,7 +17,8 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::hidl::base::V1_0::IBase;
-using ::android::hidl::manager::V1_0::IServiceManager;
+using ::android::hidl::manager::V1_0::IServiceNotification;
+using ::android::hidl::manager::V1_1::IServiceManager;
 using ::android::sp;
 
 struct HidlService {
@@ -55,7 +55,7 @@
 private:
     void sendRegistrationNotifications();
 
-    const std::string                     mInterfaceName; // e.x. "android.hardware.manager@1.0::IServiceManager"
+    const std::string                     mInterfaceName; // e.x. "android.hidl.manager@1.0::IServiceManager"
     const std::string                     mInstanceName;  // e.x. "manager"
     sp<IBase>                             mService;
 
@@ -65,9 +65,8 @@
 };
 
 }  // namespace implementation
-}  // namespace V1_0
 }  // namespace manager
 }  // namespace hidl
 }  // namespace android
 
-#endif // ANDROID_HARDWARE_MANAGER_V1_0_HIDLSERVICE_H
+#endif // ANDROID_HARDWARE_MANAGER_HIDLSERVICE_H
diff --git a/ServiceManager.cpp b/ServiceManager.cpp
index 973da58..1f78ed0 100644
--- a/ServiceManager.cpp
+++ b/ServiceManager.cpp
@@ -6,6 +6,7 @@
 #include <android-base/logging.h>
 #include <hwbinder/IPCThreadState.h>
 #include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
 #include <regex>
 #include <sstream>
 
@@ -14,7 +15,6 @@
 namespace android {
 namespace hidl {
 namespace manager {
-namespace V1_0 {
 namespace implementation {
 
 static constexpr uint64_t kServiceDiedCookie = 0;
@@ -51,7 +51,7 @@
 void ServiceManager::serviceDied(uint64_t cookie, const wp<IBase>& who) {
     switch (cookie) {
         case kServiceDiedCookie:
-            remove(who);
+            removeService(who);
             break;
         case kPackageListenerDiedCookie:
             removePackageListener(who);
@@ -132,10 +132,12 @@
 }
 
 bool ServiceManager::PackageInterfaceMap::removePackageListener(const wp<IBase>& who) {
+    using ::android::hardware::interfacesEqual;
+
     bool found = false;
 
     for (auto it = mPackageListeners.begin(); it != mPackageListeners.end();) {
-        if (*it == who) {
+        if (interfacesEqual(*it, who.promote())) {
             it = mPackageListeners.erase(it);
             found = true;
         } else {
@@ -146,6 +148,19 @@
     return found;
 }
 
+bool ServiceManager::PackageInterfaceMap::removeServiceListener(const wp<IBase>& who) {
+    using ::android::hardware::interfacesEqual;
+
+    bool found = false;
+
+    for (auto &servicePair : getInstanceMap()) {
+        const std::unique_ptr<HidlService> &service = servicePair.second;
+        found |= service->removeListener(who);
+    }
+
+    return found;
+}
+
 // Methods from ::android::hidl::manager::V1_0::IServiceManager follow.
 Return<sp<IBase>> ServiceManager::get(const hidl_string& fqName,
                                       const hidl_string& name) {
@@ -314,6 +329,42 @@
     return true;
 }
 
+Return<bool> ServiceManager::unregisterForNotifications(const hidl_string& fqName,
+                                                        const hidl_string& name,
+                                                        const sp<IServiceNotification>& callback) {
+    if (callback == nullptr) {
+        LOG(ERROR) << "Cannot unregister null callback for " << fqName << "/" << name;
+        return false;
+    }
+
+    // NOTE: don't need ACL since callback is binder token, and if someone has gotten it,
+    // then they already have access to it.
+
+    if (fqName.empty()) {
+        bool success = false;
+        success |= removePackageListener(callback);
+        success |= removeServiceListener(callback);
+        return success;
+    }
+
+    PackageInterfaceMap &ifaceMap = mServiceMap[fqName];
+
+    if (name.empty()) {
+        bool success = false;
+        success |= ifaceMap.removePackageListener(callback);
+        success |= ifaceMap.removeServiceListener(callback);
+        return success;
+    }
+
+    HidlService *service = ifaceMap.lookup(name);
+
+    if (service == nullptr) {
+        return false;
+    }
+
+    return service->removeListener(callback);
+}
+
 Return<void> ServiceManager::debugDump(debugDump_cb _cb) {
     std::vector<IServiceManager::InstanceDebugInfo> list;
     forEachServiceEntry([&] (const HidlService *service) {
@@ -363,14 +414,16 @@
     return Void();
 }
 
-bool ServiceManager::remove(const wp<IBase>& who) {
+bool ServiceManager::removeService(const wp<IBase>& who) {
+    using ::android::hardware::interfacesEqual;
+
     bool found = false;
     for (auto &interfaceMapping : mServiceMap) {
         auto &instanceMap = interfaceMapping.second.getInstanceMap();
 
         for (auto &servicePair : instanceMap) {
             const std::unique_ptr<HidlService> &service = servicePair.second;
-            if (service->getService() == who) {
+            if (interfacesEqual(service->getService(), who.promote())) {
                 service->setService(nullptr, static_cast<pid_t>(IServiceManager::PidConstant::NO_PID));
                 found = true;
             }
@@ -392,17 +445,13 @@
 bool ServiceManager::removeServiceListener(const wp<IBase>& who) {
     bool found = false;
     for (auto &interfaceMapping : mServiceMap) {
-        auto &instanceMap = interfaceMapping.second.getInstanceMap();
+        auto &packageInterfaceMap = interfaceMapping.second;
 
-        for (auto &servicePair : instanceMap) {
-            const std::unique_ptr<HidlService> &service = servicePair.second;
-            found |= service->removeListener(who);
-        }
+        found |= packageInterfaceMap.removeServiceListener(who);
     }
     return found;
 }
-} // namespace implementation
-}  // namespace V1_0
+}  // namespace implementation
 }  // namespace manager
 }  // namespace hidl
 }  // namespace android
diff --git a/ServiceManager.h b/ServiceManager.h
index 9fafadf..66225c5 100644
--- a/ServiceManager.h
+++ b/ServiceManager.h
@@ -1,7 +1,7 @@
-#ifndef ANDROID_HARDWARE_MANAGER_V1_0_SERVICEMANAGER_H
-#define ANDROID_HARDWARE_MANAGER_V1_0_SERVICEMANAGER_H
+#ifndef ANDROID_HARDWARE_MANAGER_SERVICEMANAGER_H
+#define ANDROID_HARDWARE_MANAGER_SERVICEMANAGER_H
 
-#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hidl/manager/1.1/IServiceManager.h>
 #include <hidl/Status.h>
 #include <hidl/MQDescriptor.h>
 #include <map>
@@ -11,7 +11,6 @@
 namespace android {
 namespace hidl {
 namespace manager {
-namespace V1_0 {
 namespace implementation {
 
 using ::android::hardware::hidl_death_recipient;
@@ -20,7 +19,7 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::hidl::base::V1_0::IBase;
-using ::android::hidl::manager::V1_0::IServiceManager;
+using ::android::hidl::manager::V1_1::IServiceManager;
 using ::android::hidl::manager::V1_0::IServiceNotification;
 using ::android::sp;
 using ::android::wp;
@@ -47,9 +46,14 @@
     Return<void> registerPassthroughClient(const hidl_string &fqName,
             const hidl_string &name) override;
 
+    // Methods from ::android::hidl::manager::V1_1::IServiceManager follow.
+    Return<bool> unregisterForNotifications(const hidl_string& fqName,
+                                            const hidl_string& name,
+                                            const sp<IServiceNotification>& callback) override;
+
     virtual void serviceDied(uint64_t cookie, const wp<IBase>& who);
 private:
-    bool remove(const wp<IBase>& who);
+    bool removeService(const wp<IBase>& who);
     bool removePackageListener(const wp<IBase>& who);
     bool removeServiceListener(const wp<IBase>& who);
     size_t countExistingService() const;
@@ -80,6 +84,7 @@
 
         void addPackageListener(sp<IServiceNotification> listener);
         bool removePackageListener(const wp<IBase>& who);
+        bool removeServiceListener(const wp<IBase>& who);
 
         void sendPackageRegistrationNotification(
             const hidl_string &fqName,
@@ -106,9 +111,8 @@
 };
 
 }  // namespace implementation
-}  // namespace V1_0
 }  // namespace manager
 }  // namespace hidl
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_MANAGER_V1_0_SERVICEMANAGER_H
+#endif  // ANDROID_HARDWARE_MANAGER_SERVICEMANAGER_H
diff --git a/service.cpp b/service.cpp
index 9c501be..56fcb0d 100644
--- a/service.cpp
+++ b/service.cpp
@@ -36,11 +36,11 @@
 
 // hidl types
 using android::hidl::manager::V1_0::BnHwServiceManager;
-using android::hidl::manager::V1_0::IServiceManager;
+using android::hidl::manager::V1_1::IServiceManager;
 using android::hidl::token::V1_0::ITokenManager;
 
 // implementations
-using android::hidl::manager::V1_0::implementation::ServiceManager;
+using android::hidl::manager::implementation::ServiceManager;
 using android::hidl::token::V1_0::implementation::TokenManager;
 
 static std::string serviceName = "default";