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";