Add waitForHwService.

This is a helper method which will wait for a service that is supposed
to be binderized. This is an implementation detail of getService and is
only called when the VINTF indicates a service is supposed to be
binderized.

Note this is essentially a no-op because the only services which are
marked as hwbinder are Java services (which have a different getService
code path). I did test this code path, however, with nfc as specified in
the first test line.

Bug: 31458381
Test: marked nfc as hwbinder in the VINTF, and its start was
successfully delayed.
Test: ENABLE_TREBLE=false, manual tests of fingerprint/wifi/nfc/lights.
No associated log messages.
Test: ENABLE_TREBLE=true, same tests and results as above.

Change-Id: I373761df624ebf60661726bb81d979a8c7289b1d
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index 1734935..9a6a3b5 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -22,12 +22,14 @@
 #include <hidl/Status.h>
 
 #include <android-base/logging.h>
+#include <condition_variable>
 #include <dlfcn.h>
 #include <dirent.h>
 #include <hidl-util/FQName.h>
 #include <hidl-util/StringHelper.h>
 #include <hwbinder/IPCThreadState.h>
 #include <hwbinder/Parcel.h>
+#include <mutex>
 #include <unistd.h>
 
 #include <android/hidl/manager/1.0/IServiceManager.h>
@@ -175,5 +177,65 @@
     return manager;
 }
 
+namespace details {
+
+struct Waiter : IServiceNotification {
+    Return<void> onRegistration(const hidl_string& /* fqName */,
+                                const hidl_string& /* name */,
+                                bool /* preexisting */) override {
+        std::unique_lock<std::mutex> lock(mMutex);
+        if (mRegistered) {
+            return Void();
+        }
+        mRegistered = true;
+        lock.unlock();
+
+        mCondition.notify_one();
+        return Void();
+    }
+
+    void wait() {
+        std::unique_lock<std::mutex> lock(mMutex);
+        mCondition.wait(lock, [this]{
+            return mRegistered;
+        });
+    }
+
+private:
+    std::mutex mMutex;
+    std::condition_variable mCondition;
+    bool mRegistered = false;
+};
+
+void waitForHwService(
+        const std::string &interface, const std::string &instanceName) {
+    const sp<IServiceManager> manager = defaultServiceManager();
+
+    if (manager == nullptr) {
+        LOG(ERROR) << "Could not get default service manager.";
+        return;
+    }
+
+    sp<Waiter> waiter = new Waiter();
+    Return<bool> ret = manager->registerForNotifications(interface, instanceName, waiter);
+
+    if (!ret.isOk()) {
+        LOG(ERROR) << "Transport error, " << ret.description()
+            << ", during notification registration for "
+            << interface << "/" << instanceName << ".";
+        return;
+    }
+
+    if (!ret) {
+        LOG(ERROR) << "Could not register for notifications for "
+            << interface << "/" << instanceName << ".";
+        return;
+    }
+
+    waiter->wait();
+}
+
+}; // namespace details
+
 }; // namespace hardware
 }; // namespace android