diff options
Diffstat (limited to 'libs/binder/IServiceManager.cpp')
-rw-r--r-- | libs/binder/IServiceManager.cpp | 67 |
1 files changed, 54 insertions, 13 deletions
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index a9f2d73951..f684cf672f 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -18,6 +18,9 @@ #include <binder/IServiceManager.h> +#include <inttypes.h> +#include <unistd.h> + #include <android/os/BnServiceCallback.h> #include <android/os/IServiceManager.h> #include <binder/IPCThreadState.h> @@ -36,8 +39,6 @@ #include "Static.h" -#include <unistd.h> - namespace android { using AidlServiceManager = android::os::IServiceManager; @@ -73,6 +74,8 @@ public: Vector<String16> listServices(int dumpsysPriority) override; sp<IBinder> waitForService(const String16& name16) override; bool isDeclared(const String16& name) override; + Vector<String16> getDeclaredInstances(const String16& interface) override; + std::optional<String16> updatableViaApex(const String16& name) override; // for legacy ABI const String16& getInterfaceDescriptor() const override { @@ -100,7 +103,7 @@ sp<IServiceManager> defaultServiceManager() } } - gDefaultServiceManager = new ServiceManagerShim(sm); + gDefaultServiceManager = sp<ServiceManagerShim>::make(sm); }); return gDefaultServiceManager; @@ -206,6 +209,10 @@ ServiceManagerShim::ServiceManagerShim(const sp<AidlServiceManager>& impl) : mTheRealServiceManager(impl) {} +// This implementation could be simplified and made more efficient by delegating +// to waitForService. However, this changes the threading structure in some +// cases and could potentially break prebuilts. Once we have higher logistical +// complexity, this could be attempted. sp<IBinder> ServiceManagerShim::getService(const String16& name) const { static bool gSystemBootCompleted = false; @@ -215,7 +222,8 @@ sp<IBinder> ServiceManagerShim::getService(const String16& name) const const bool isVendorService = strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0; - const long timeout = uptimeMillis() + 5000; + constexpr int64_t timeout = 5000; + int64_t startTime = uptimeMillis(); // Vendor code can't access system properties if (!gSystemBootCompleted && !isVendorService) { #ifdef __ANDROID__ @@ -227,17 +235,23 @@ sp<IBinder> ServiceManagerShim::getService(const String16& name) const #endif } // retry interval in millisecond; note that vendor services stay at 100ms - const long sleepTime = gSystemBootCompleted ? 1000 : 100; + const useconds_t sleepTime = gSystemBootCompleted ? 1000 : 100; + + ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(), + ProcessState::self()->getDriverName().c_str()); int n = 0; - while (uptimeMillis() < timeout) { + while (uptimeMillis() - startTime < timeout) { n++; - ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(), - ProcessState::self()->getDriverName().c_str()); usleep(1000*sleepTime); sp<IBinder> svc = checkService(name); - if (svc != nullptr) return svc; + if (svc != nullptr) { + ALOGI("Waiting for service '%s' on '%s' successful after waiting %" PRIi64 "ms", + String8(name).string(), ProcessState::self()->getDriverName().c_str(), + uptimeMillis() - startTime); + return svc; + } } ALOGW("Service %s didn't start. Returning NULL", String8(name).string()); return nullptr; @@ -297,7 +311,7 @@ sp<IBinder> ServiceManagerShim::waitForService(const String16& name16) // Simple RAII object to ensure a function call immediately before going out of scope class Defer { public: - Defer(std::function<void()>&& f) : mF(std::move(f)) {} + explicit Defer(std::function<void()>&& f) : mF(std::move(f)) {} ~Defer() { mF(); } private: std::function<void()> mF; @@ -311,7 +325,7 @@ sp<IBinder> ServiceManagerShim::waitForService(const String16& name16) } if (out != nullptr) return out; - sp<Waiter> waiter = new Waiter; + sp<Waiter> waiter = sp<Waiter>::make(); if (!mTheRealServiceManager->registerForNotifications( name, waiter).isOk()) { return nullptr; @@ -322,6 +336,11 @@ sp<IBinder> ServiceManagerShim::waitForService(const String16& name16) while(true) { { + // It would be really nice if we could read binder commands on this + // thread instead of needing a threadpool to be started, but for + // instance, if we call getAndExecuteCommand, it might be the case + // that another thread serves the callback, and we never get a + // command, so we hang indefinitely. std::unique_lock<std::mutex> lock(waiter->mMutex); using std::literals::chrono_literals::operator""s; waiter->mCv.wait_for(lock, 1s, [&] { @@ -330,6 +349,8 @@ sp<IBinder> ServiceManagerShim::waitForService(const String16& name16) if (waiter->mBinder != nullptr) return waiter->mBinder; } + ALOGW("Waited one second for %s (is service started? are binder threads started and available?)", name.c_str()); + // Handle race condition for lazy services. Here is what can happen: // - the service dies (not processed by init yet). // - sm processes death notification. @@ -343,8 +364,6 @@ sp<IBinder> ServiceManagerShim::waitForService(const String16& name16) return nullptr; } if (out != nullptr) return out; - - ALOGW("Waited one second for %s", name.c_str()); } } @@ -356,4 +375,26 @@ bool ServiceManagerShim::isDeclared(const String16& name) { return declared; } +Vector<String16> ServiceManagerShim::getDeclaredInstances(const String16& interface) { + std::vector<std::string> out; + if (!mTheRealServiceManager->getDeclaredInstances(String8(interface).c_str(), &out).isOk()) { + return {}; + } + + Vector<String16> res; + res.setCapacity(out.size()); + for (const std::string& instance : out) { + res.push(String16(instance.c_str())); + } + return res; +} + +std::optional<String16> ServiceManagerShim::updatableViaApex(const String16& name) { + std::optional<std::string> declared; + if (!mTheRealServiceManager->updatableViaApex(String8(name).c_str(), &declared).isOk()) { + return std::nullopt; + } + return declared ? std::optional<String16>(String16(declared.value().c_str())) : std::nullopt; +} + } // namespace android |