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