New helper functions for registering lazy HALs
Added:
* defaultLazyPassthroughServiceImplementation
* registerLazyPassthroughServiceImplementation
Test: Register HAL using defaultLazyPassthroughServiceImplementation and
check that it exits when it is not in use
Change-Id: I77b9f885f800c2838fad8003efc394bd1e1706da
diff --git a/transport/include/hidl/LegacySupport.h b/transport/include/hidl/LegacySupport.h
index f03d34d..573a793 100644
--- a/transport/include/hidl/LegacySupport.h
+++ b/transport/include/hidl/LegacySupport.h
@@ -14,25 +14,21 @@
* limitations under the License.
*/
+#include <hidl/HidlLazyUtils.h>
#include <hidl/HidlTransportSupport.h>
#include <sys/wait.h>
-#include <utils/Log.h>
#include <utils/Errors.h>
+#include <utils/Log.h>
#include <utils/StrongPointer.h>
-#ifndef ANDROID_HIDL_LEGACY_SUPPORT_H
-#define ANDROID_HIDL_LEGACY_SUPPORT_H
+#pragma once
namespace android {
namespace hardware {
-
-/**
- * Registers passthrough service implementation.
- */
-template<class Interface>
-__attribute__((warn_unused_result))
-status_t registerPassthroughServiceImplementation(
- std::string name = "default") {
+namespace details {
+template <class Interface, typename Func>
+__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
+ Func registerServiceCb, const std::string& name = "default") {
sp<Interface> service = Interface::getService(name, true /* getStub */);
if (service == nullptr) {
@@ -44,7 +40,7 @@
LOG_FATAL_IF(service->isRemote(), "Implementation of %s/%s is remote!",
Interface::descriptor, name.c_str());
- status_t status = service->registerAsService(name);
+ status_t status = registerServiceCb(service, name);
if (status == OK) {
ALOGI("Registration complete for %s/%s.",
@@ -56,16 +52,29 @@
return status;
}
+} // namespace details
+
+/**
+ * Registers passthrough service implementation.
+ */
+template <class Interface>
+__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
+ const std::string& name = "default") {
+ return details::registerPassthroughServiceImplementation<Interface>(
+ [](const sp<Interface>& service, const std::string& name) {
+ return service->registerAsService(name);
+ },
+ name);
+}
/**
* Creates default passthrough service implementation. This method never returns.
*
* Return value is exit status.
*/
-template<class Interface>
-__attribute__((warn_unused_result))
-status_t defaultPassthroughServiceImplementation(std::string name,
- size_t maxThreads = 1) {
+template <class Interface>
+__attribute__((warn_unused_result)) status_t defaultPassthroughServiceImplementation(
+ const std::string& name, size_t maxThreads = 1) {
configureRpcThreadpool(maxThreads, true);
status_t result = registerPassthroughServiceImplementation<Interface>(name);
@@ -82,7 +91,54 @@
return defaultPassthroughServiceImplementation<Interface>("default", maxThreads);
}
+/**
+ * Registers a passthrough service implementation that exits when there are 0 clients.
+ *
+ * If this function is called multiple times to register different services, then this process will
+ * only exit once all services have 0 clients. This function does not know about clients registered
+ * through registerPassthroughServiceImplementation, so if that function is used in conjuction with
+ * this one, the process may exit while a client is still using the HAL.
+ */
+template <class Interface>
+__attribute__((warn_unused_result)) status_t registerLazyPassthroughServiceImplementation(
+ const std::string& name = "default") {
+ // Make LazyServiceRegistrar static so that multiple calls to
+ // registerLazyPassthroughServiceImplementation work as expected: each HAL is registered and the
+ // process only exits once all HALs have 0 clients.
+ using android::hardware::LazyServiceRegistrar;
+ static auto serviceCounter(std::make_shared<LazyServiceRegistrar>());
+
+ return details::registerPassthroughServiceImplementation<Interface>(
+ [](const sp<Interface>& service, const std::string& name) {
+ return serviceCounter->registerServiceWithCallback(service, name);
+ },
+ name);
+}
+
+/**
+ * Creates default passthrough service implementation that exits when there are 0 clients. This
+ * method never returns.
+ *
+ * Return value is exit status.
+ */
+template <class Interface>
+__attribute__((warn_unused_result)) status_t defaultLazyPassthroughServiceImplementation(
+ const std::string& name, size_t maxThreads = 1) {
+ configureRpcThreadpool(maxThreads, true);
+ status_t result = registerLazyPassthroughServiceImplementation<Interface>(name);
+
+ if (result != OK) {
+ return result;
+ }
+
+ joinRpcThreadpool();
+ return UNKNOWN_ERROR;
+}
+template <class Interface>
+__attribute__((warn_unused_result)) status_t defaultLazyPassthroughServiceImplementation(
+ size_t maxThreads = 1) {
+ return defaultLazyPassthroughServiceImplementation<Interface>("default", maxThreads);
+}
+
} // namespace hardware
} // namespace android
-
-#endif // ANDROID_HIDL_LEGACY_SUPPORT_H