Add a fake hwservicemanager for running w/o hwservicemanager
If hwservicemanager is not installed on a device, we can return this
fake hwservicemanager instance when clients ask for it.
This instance doesn't do anything when used, but allows client code to
remain the same to support devices that still have hwservicemanager
installed.
Bug: 218588089
Test: boot cuttlefish with and without hwservicemanager
Change-Id: Ie8efbaad0e6b1d399f54ffb73a8a58334afe535f
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index c638279..5d1979f 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -59,6 +59,7 @@
using IServiceManager1_1 = android::hidl::manager::V1_1::IServiceManager;
using IServiceManager1_2 = android::hidl::manager::V1_2::IServiceManager;
using ::android::hidl::manager::V1_0::IServiceNotification;
+using ::android::hidl::manager::V1_2::IClientCallback;
namespace android {
namespace hardware {
@@ -201,6 +202,109 @@
sp<IServiceManager1_1> defaultServiceManager1_1() {
return defaultServiceManager1_2();
}
+static bool isServiceManager(const hidl_string& fqName) {
+ return fqName == IServiceManager1_0::descriptor || fqName == IServiceManager1_1::descriptor ||
+ fqName == IServiceManager1_2::descriptor;
+}
+static bool isHwServiceManagerInstalled() {
+ return access("/system/bin/hwservicemanager", F_OK) == 0;
+}
+
+/*
+ * A replacement for hwservicemanager when it is not installed on a device.
+ *
+ * Clients in the framework need to continue supporting HIDL services through
+ * hwservicemanager for upgrading devices. Being unable to get an instance of
+ * hardware service manager is a hard error, so this implementation is returned
+ * to be able service the requests and tell clients there are no services
+ * registered.
+ */
+struct NoHwServiceManager : public IServiceManager1_2 {
+ Return<sp<IBase>> get(const hidl_string& fqName, const hidl_string&) override {
+ sp<IBase> ret = nullptr;
+
+ if (isServiceManager(fqName)) {
+ ret = defaultServiceManager1_2();
+ }
+ return ret;
+ }
+
+ Return<bool> add(const hidl_string& name, const sp<IBase>& /* service */) override {
+ LOG(INFO) << "Cannot add " << name << " without hwservicemanager";
+ return false;
+ }
+
+ Return<Transport> getTransport(const hidl_string& fqName, const hidl_string& name) {
+ LOG(INFO) << "Trying to get transport of " << fqName << "/" << name
+ << " without hwservicemanager";
+ return Transport::PASSTHROUGH;
+ }
+
+ Return<void> list(list_cb _hidl_cb) override {
+ _hidl_cb({});
+ LOG(INFO) << "Cannot list all services without hwservicemanager";
+ return Void();
+ }
+ Return<void> listByInterface(const hidl_string& fqName, listByInterface_cb _hidl_cb) override {
+ _hidl_cb({});
+ LOG(INFO) << "Cannot list service " << fqName << " without hwservicemanager";
+ return Void();
+ }
+
+ 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;
+ }
+
+ Return<void> debugDump(debugDump_cb _hidl_cb) override {
+ _hidl_cb({});
+ return Void();
+ }
+
+ Return<void> registerPassthroughClient(const hidl_string& fqName,
+ const hidl_string& name) override {
+ LOG(INFO) << "This process is a client of " << fqName << "/" << name
+ << " passthrough HAL, but it won't show up in lshal because hwservicemanager is "
+ "not installed";
+ 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> registerClientCallback(const hidl_string& fqName, const hidl_string& name,
+ const sp<IBase>&, const sp<IClientCallback>&) {
+ LOG(INFO) << "Cannot add client callback for " << fqName << "/" << name
+ << " without hwservicemanager";
+ return false;
+ }
+ Return<bool> unregisterClientCallback(const sp<IBase>&, const sp<IClientCallback>&) {
+ LOG(INFO) << "Cannot unregister client callbacks without hwservicemanager";
+ return false;
+ }
+ Return<bool> addWithChain(const hidl_string& fqName, const sp<IBase>&,
+ const hidl_vec<hidl_string>&) {
+ LOG(INFO) << "Cannot add " << fqName << " with chain without hwservicemanager";
+ return false;
+ }
+ Return<void> listManifestByInterface(const hidl_string& fqName, listManifestByInterface_cb) {
+ LOG(INFO) << "Cannot list manifest for " << fqName << " without hwservicemanager";
+ return Void();
+ }
+ Return<bool> tryUnregister(const hidl_string& fqName, const hidl_string& name,
+ const sp<IBase>&) {
+ LOG(INFO) << "Cannot unregister service " << fqName << "/" << name
+ << " without hwservicemanager";
+ return false;
+ }
+};
+
sp<IServiceManager1_2> defaultServiceManager1_2() {
using android::hidl::manager::V1_2::BnHwServiceManager;
using android::hidl::manager::V1_2::BpHwServiceManager;
@@ -214,6 +318,12 @@
return gDefaultServiceManager;
}
+ if (!isHwServiceManagerInstalled()) {
+ // hwservicemanager is not available on this device.
+ gDefaultServiceManager = sp<NoHwServiceManager>::make();
+ return gDefaultServiceManager;
+ }
+
if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) {
// HwBinder not available on this device or not accessible to
// this process.
@@ -410,6 +520,12 @@
Return<sp<IBase>> get(const hidl_string& fqName,
const hidl_string& name) override {
sp<IBase> ret = nullptr;
+ // This is required to run without hwservicemanager while we have
+ // passthrough HIDL services. Once the passthrough HIDL services have
+ // been removed, the PassthroughServiceManager will no longer be needed.
+ if (!isHwServiceManagerInstalled() && isServiceManager(fqName)) {
+ return defaultServiceManager1_2();
+ }
openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {
IBase* (*generator)(const char* name);