Add preloadPassthroughService.
This will preload the appropriate libraries
in the appropriate namespaces so that getService
will be faster.
Test: hidl_test
Bug: 62376972
Bug: 63899698
Merged-In: Iaaf0f75b31d0b0aea7ad5fe4672ae861271d184f
Change-Id: Iaaf0f75b31d0b0aea7ad5fe4672ae861271d184f
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index 0b7ec34..8be2c76 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -248,21 +248,20 @@
}
struct PassthroughServiceManager : IServiceManager {
- Return<sp<IBase>> get(const hidl_string& fqName,
- const hidl_string& name) override {
- std::string stdFqName(fqName.c_str());
-
+ static void openLibs(const std::string& fqName,
+ std::function<bool /* continue */(void* /* handle */,
+ const std::string& /* lib */, const std::string& /* sym */)> eachLib) {
//fqName looks like android.hardware.foo@1.0::IFoo
- size_t idx = stdFqName.find("::");
+ size_t idx = fqName.find("::");
if (idx == std::string::npos ||
- idx + strlen("::") + 1 >= stdFqName.size()) {
+ idx + strlen("::") + 1 >= fqName.size()) {
LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
- return nullptr;
+ return;
}
- std::string packageAndVersion = stdFqName.substr(0, idx);
- std::string ifaceName = stdFqName.substr(idx + strlen("::"));
+ std::string packageAndVersion = fqName.substr(0, idx);
+ std::string ifaceName = fqName.substr(idx + strlen("::"));
const std::string prefix = packageAndVersion + "-impl";
const std::string sym = "HIDL_FETCH_" + ifaceName;
@@ -270,9 +269,6 @@
const int dlMode = RTLD_LAZY;
void *handle = nullptr;
- // TODO: lookup in VINTF instead
- // TODO(b/34135607): Remove HAL_LIBRARY_PATH_SYSTEM
-
dlerror(); // clear
for (const std::string &path : {
@@ -291,31 +287,41 @@
continue;
}
- IBase* (*generator)(const char* name);
- *(void **)(&generator) = dlsym(handle, sym.c_str());
- if(!generator) {
- const char* error = dlerror();
- LOG(ERROR) << "Passthrough lookup opened " << lib
- << " but could not find symbol " << sym << ": "
- << (error == nullptr ? "unknown error" : error);
- dlclose(handle);
- continue;
+ if (!eachLib(handle, lib, sym)) {
+ return;
}
-
- IBase *interface = (*generator)(name.c_str());
-
- if (interface == nullptr) {
- dlclose(handle);
- continue; // this module doesn't provide this instance name
- }
-
- registerReference(fqName, name);
-
- return interface;
}
}
+ }
- return nullptr;
+ Return<sp<IBase>> get(const hidl_string& fqName,
+ const hidl_string& name) override {
+ sp<IBase> ret = nullptr;
+
+ openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {
+ IBase* (*generator)(const char* name);
+ *(void **)(&generator) = dlsym(handle, sym.c_str());
+ if(!generator) {
+ const char* error = dlerror();
+ LOG(ERROR) << "Passthrough lookup opened " << lib
+ << " but could not find symbol " << sym << ": "
+ << (error == nullptr ? "unknown error" : error);
+ dlclose(handle);
+ return true;
+ }
+
+ ret = (*generator)(name.c_str());
+
+ if (ret == nullptr) {
+ dlclose(handle);
+ return true; // this module doesn't provide this instance name
+ }
+
+ registerReference(fqName, name);
+ return false;
+ });
+
+ return ret;
}
Return<bool> add(const hidl_string& /* name */,
@@ -406,6 +412,14 @@
namespace details {
+void preloadPassthroughService(const std::string &descriptor) {
+ PassthroughServiceManager::openLibs(descriptor,
+ [&](void* /* handle */, const std::string& /* lib */, const std::string& /* sym */) {
+ // do nothing
+ return true; // open all libs
+ });
+}
+
struct Waiter : IServiceNotification {
Return<void> onRegistration(const hidl_string& /* fqName */,
const hidl_string& /* name */,
diff --git a/transport/include/hidl/ServiceManagement.h b/transport/include/hidl/ServiceManagement.h
index 2b2266b..324a584 100644
--- a/transport/include/hidl/ServiceManagement.h
+++ b/transport/include/hidl/ServiceManagement.h
@@ -32,12 +32,6 @@
namespace hardware {
-// These functions are for internal use by hidl. If you want to get ahold
-// of an interface, the best way to do this is by calling IFoo::getService()
-
-sp<::android::hidl::manager::V1_0::IServiceManager> defaultServiceManager();
-sp<::android::hidl::manager::V1_0::IServiceManager> getPassthroughServiceManager();
-
namespace details {
// e.x.: android.hardware.foo@1.0, IFoo, default
void onRegistration(const std::string &packageName,
@@ -46,8 +40,26 @@
// e.x.: android.hardware.foo@1.0::IFoo, default
void waitForHwService(const std::string &interface, const std::string &instanceName);
+
+void preloadPassthroughService(const std::string &descriptor);
};
+// These functions are for internal use by hidl. If you want to get ahold
+// of an interface, the best way to do this is by calling IFoo::getService()
+sp<::android::hidl::manager::V1_0::IServiceManager> defaultServiceManager();
+sp<::android::hidl::manager::V1_0::IServiceManager> getPassthroughServiceManager();
+
+/**
+ * Given a service that is in passthrough mode, this function will go ahead and load the
+ * required passthrough module library (but not call HIDL_FETCH_I* functions to instantiate it).
+ *
+ * E.x.: preloadPassthroughService<IFoo>();
+ */
+template<typename I>
+static inline void preloadPassthroughService() {
+ details::preloadPassthroughService(I::descriptor);
+}
+
}; // namespace hardware
}; // namespace android