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
diff --git a/transport/include/hidl/ServiceManagement.h b/transport/include/hidl/ServiceManagement.h
index d4552a7..2035fb7 100644
--- a/transport/include/hidl/ServiceManagement.h
+++ b/transport/include/hidl/ServiceManagement.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_HARDWARE_ISERVICE_MANAGER_H
#define ANDROID_HARDWARE_ISERVICE_MANAGER_H
+#include <string>
#include <utils/StrongPointer.h>
namespace android {
@@ -37,6 +38,10 @@
sp<::android::hidl::manager::V1_0::IServiceManager> defaultServiceManager();
sp<::android::hidl::manager::V1_0::IServiceManager> getPassthroughServiceManager();
+namespace details {
+void waitForHwService(const std::string &interface, const std::string &instanceName);
+};
+
}; // namespace hardware
}; // namespace android