Loading cmds/dumpsys/tests/dumpsys_test.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ class ServiceManagerMock : public IServiceManager { MOCK_CONST_METHOD1(checkService, sp<IBinder>(const String16&)); MOCK_METHOD4(addService, status_t(const String16&, const sp<IBinder>&, bool, int)); MOCK_METHOD1(listServices, Vector<String16>(int)); MOCK_METHOD1(waitForService, sp<IBinder>(const String16&)); protected: MOCK_METHOD0(onAsBinder, IBinder*()); }; Loading libs/binder/IServiceManager.cpp +59 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <binder/IServiceManager.h> #include <android/os/BnServiceCallback.h> #include <android/os/IServiceManager.h> #include <utils/Log.h> #include <binder/IPCThreadState.h> Loading Loading @@ -212,6 +213,64 @@ public: return res; } sp<IBinder> waitForService(const String16& name16) override { class Waiter : public android::os::BnServiceCallback { Status onRegistration(const std::string& /*name*/, const sp<IBinder>& binder) override { std::unique_lock<std::mutex> lock(mMutex); mBinder = binder; lock.unlock(); mCv.notify_one(); return Status::ok(); } public: sp<IBinder> mBinder; std::mutex mMutex; std::condition_variable mCv; }; const std::string name = String8(name16).c_str(); sp<IBinder> out; if(!mTheRealServiceManager->checkService(name, &out).isOk()) { return nullptr; } if(out != nullptr) return out; sp<Waiter> waiter = new Waiter; if (!mTheRealServiceManager->registerForNotifications( name, waiter).isOk()) { return nullptr; } while(true) { { std::unique_lock<std::mutex> lock(waiter->mMutex); using std::literals::chrono_literals::operator""s; waiter->mCv.wait_for(lock, 1s, [&] { return waiter->mBinder != nullptr; }); if (waiter->mBinder != nullptr) return waiter->mBinder; } // Handle race condition for lazy services. Here is what can happen: // - the service dies (not processed by init yet). // - sm processes death notification. // - sm gets checkService and calls init to start service. // - init gets the start signal, but the service already appears // started, so it does nothing. // - init gets death signal, but doesn't know it needs to restart // the service // - we need to request service again to get it to start if(!mTheRealServiceManager->checkService(name, &out).isOk()) { return nullptr; } if(out != nullptr) return out; ALOGW("Waited one second for %s", name.c_str()); } } private: sp<AidlServiceManager> mTheRealServiceManager; }; Loading libs/binder/include/binder/IServiceManager.h +13 −0 Original line number Diff line number Diff line Loading @@ -71,10 +71,23 @@ public: */ // NOLINTNEXTLINE(google-default-arguments) virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0; /** * Efficiently wait for a service. * * Returns nullptr only for permission problem or fatal error. */ virtual sp<IBinder> waitForService(const String16& name) = 0; }; sp<IServiceManager> defaultServiceManager(); template<typename INTERFACE> sp<INTERFACE> waitForService(const String16& name) { const sp<IServiceManager> sm = defaultServiceManager(); return interface_cast<INTERFACE>(sm->waitForService(name)); } template<typename INTERFACE> status_t getService(const String16& name, sp<INTERFACE>* outService) { Loading Loading
cmds/dumpsys/tests/dumpsys_test.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ class ServiceManagerMock : public IServiceManager { MOCK_CONST_METHOD1(checkService, sp<IBinder>(const String16&)); MOCK_METHOD4(addService, status_t(const String16&, const sp<IBinder>&, bool, int)); MOCK_METHOD1(listServices, Vector<String16>(int)); MOCK_METHOD1(waitForService, sp<IBinder>(const String16&)); protected: MOCK_METHOD0(onAsBinder, IBinder*()); }; Loading
libs/binder/IServiceManager.cpp +59 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <binder/IServiceManager.h> #include <android/os/BnServiceCallback.h> #include <android/os/IServiceManager.h> #include <utils/Log.h> #include <binder/IPCThreadState.h> Loading Loading @@ -212,6 +213,64 @@ public: return res; } sp<IBinder> waitForService(const String16& name16) override { class Waiter : public android::os::BnServiceCallback { Status onRegistration(const std::string& /*name*/, const sp<IBinder>& binder) override { std::unique_lock<std::mutex> lock(mMutex); mBinder = binder; lock.unlock(); mCv.notify_one(); return Status::ok(); } public: sp<IBinder> mBinder; std::mutex mMutex; std::condition_variable mCv; }; const std::string name = String8(name16).c_str(); sp<IBinder> out; if(!mTheRealServiceManager->checkService(name, &out).isOk()) { return nullptr; } if(out != nullptr) return out; sp<Waiter> waiter = new Waiter; if (!mTheRealServiceManager->registerForNotifications( name, waiter).isOk()) { return nullptr; } while(true) { { std::unique_lock<std::mutex> lock(waiter->mMutex); using std::literals::chrono_literals::operator""s; waiter->mCv.wait_for(lock, 1s, [&] { return waiter->mBinder != nullptr; }); if (waiter->mBinder != nullptr) return waiter->mBinder; } // Handle race condition for lazy services. Here is what can happen: // - the service dies (not processed by init yet). // - sm processes death notification. // - sm gets checkService and calls init to start service. // - init gets the start signal, but the service already appears // started, so it does nothing. // - init gets death signal, but doesn't know it needs to restart // the service // - we need to request service again to get it to start if(!mTheRealServiceManager->checkService(name, &out).isOk()) { return nullptr; } if(out != nullptr) return out; ALOGW("Waited one second for %s", name.c_str()); } } private: sp<AidlServiceManager> mTheRealServiceManager; }; Loading
libs/binder/include/binder/IServiceManager.h +13 −0 Original line number Diff line number Diff line Loading @@ -71,10 +71,23 @@ public: */ // NOLINTNEXTLINE(google-default-arguments) virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0; /** * Efficiently wait for a service. * * Returns nullptr only for permission problem or fatal error. */ virtual sp<IBinder> waitForService(const String16& name) = 0; }; sp<IServiceManager> defaultServiceManager(); template<typename INTERFACE> sp<INTERFACE> waitForService(const String16& name) { const sp<IServiceManager> sm = defaultServiceManager(); return interface_cast<INTERFACE>(sm->waitForService(name)); } template<typename INTERFACE> status_t getService(const String16& name, sp<INTERFACE>* outService) { Loading