Loading libs/binder/ndk/include_platform/android/binder_manager.h +44 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <android/binder_ibinder.h> #include <android/binder_status.h> #include <sys/cdefs.h> __BEGIN_DECLS Loading Loading @@ -50,4 +51,47 @@ __attribute__((warn_unused_result)) AIBinder* AServiceManager_checkService(const */ __attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance); /** * Registers a lazy service with the default service manager under the 'instance' name. * Does not take ownership of binder. * The service must be configured statically with init so it can be restarted with * ctl.interface.* messages from servicemanager. * AServiceManager_registerLazyService cannot safely be used with AServiceManager_addService * in the same process. If one service is registered with AServiceManager_registerLazyService, * the entire process will have its lifetime controlled by servicemanager. * Instead, all services in the process should be registered using * AServiceManager_registerLazyService. * * \param binder object to register globally with the service manager. * \param instance identifier of the service. This will be used to lookup the service. * * \return STATUS_OK on success. */ binder_status_t AServiceManager_registerLazyService(AIBinder* binder, const char* instance) __INTRODUCED_IN(31); /** * Gets a binder object with this specific instance name. Efficiently waits for the service. * If the service is not declared, it will wait indefinitely. Requires the threadpool * to be started in the service. * This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible * for calling AIBinder_decStrong). * * \param instance identifier of the service used to lookup the service. * * \return service if registered, null if not. */ __attribute__((warn_unused_result)) AIBinder* AServiceManager_waitForService(const char* instance) __INTRODUCED_IN(31); /** * Check if a service is declared (e.g. VINTF manifest). * * \param instance identifier of the service. * * \return true on success, meaning AServiceManager_waitForService should always * be able to return the service. */ bool AServiceManager_isDeclared(const char* instance) __INTRODUCED_IN(31); __END_DECLS libs/binder/ndk/libbinder_ndk.map.txt +3 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,9 @@ LIBBINDER_NDK31 { # introduced=31 ABinderProcess_setupPolling; # apex AIBinder_getCallingSid; # apex AIBinder_setRequestingSid; # apex AServiceManager_isDeclared; # apex llndk AServiceManager_registerLazyService; # llndk AServiceManager_waitForService; # apex llndk }; LIBBINDER_NDK_PLATFORM { Loading libs/binder/ndk/service_manager.cpp +31 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include "status_internal.h" #include <binder/IServiceManager.h> #include <binder/LazyServiceRegistrar.h> using ::android::defaultServiceManager; using ::android::IBinder; Loading Loading @@ -61,3 +62,33 @@ AIBinder* AServiceManager_getService(const char* instance) { AIBinder_incStrong(ret.get()); return ret.get(); } binder_status_t AServiceManager_registerLazyService(AIBinder* binder, const char* instance) { if (binder == nullptr || instance == nullptr) { return STATUS_UNEXPECTED_NULL; } auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance(); status_t status = serviceRegistrar.registerService(binder->getBinder(), instance); return PruneStatusT(status); } AIBinder* AServiceManager_waitForService(const char* instance) { if (instance == nullptr) { return nullptr; } sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder = sm->waitForService(String16(instance)); sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(binder); AIBinder_incStrong(ret.get()); return ret.get(); } bool AServiceManager_isDeclared(const char* instance) { if (instance == nullptr) { return false; } sp<IServiceManager> sm = defaultServiceManager(); return sm->isDeclared(String16(instance)); } libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +53 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ using namespace android; constexpr char kExistingNonNdkService[] = "SurfaceFlinger"; constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest"; constexpr char kLazyBinderNdkUnitTestService[] = "LazyBinderNdkUnitTest"; class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest { ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) { Loading Loading @@ -143,6 +144,27 @@ int manualThreadPoolService(const char* instance) { return 1; } int lazyService(const char* instance) { ABinderProcess_setThreadPoolMaxThreadCount(0); // Wait to register this service to make sure the main test process will // actually wait for the service to be available. Tested with sleep(60), // and reduced for sake of time. sleep(1); // Strong reference to MyBinderNdkUnitTest kept by service manager. // This is just for testing, it has no corresponding init behavior. auto service = ndk::SharedRefBase::make<MyBinderNdkUnitTest>(); auto binder = service->asBinder(); binder_status_t status = AServiceManager_registerLazyService(binder.get(), instance); if (status != STATUS_OK) { LOG(FATAL) << "Could not register: " << status << " " << instance; } ABinderProcess_joinThreadPool(); return 1; // should not return } // This is too slow // TEST(NdkBinder, GetServiceThatDoesntExist) { // sp<IFoo> foo = IFoo::getService("asdfghkl;"); Loading Loading @@ -171,6 +193,33 @@ TEST(NdkBinder, DoubleNumber) { EXPECT_EQ(2, out); } TEST(NdkBinder, GetLazyService) { // Not declared in the vintf manifest ASSERT_FALSE(AServiceManager_isDeclared(kLazyBinderNdkUnitTestService)); ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService)); std::shared_ptr<aidl::IBinderNdkUnitTest> service = aidl::IBinderNdkUnitTest::fromBinder(binder); ASSERT_NE(service, nullptr); EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get())); } // This is too slow TEST(NdkBinder, CheckLazyServiceShutDown) { ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService)); std::shared_ptr<aidl::IBinderNdkUnitTest> service = aidl::IBinderNdkUnitTest::fromBinder(binder); ASSERT_NE(service, nullptr); EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get())); binder = nullptr; service = nullptr; IPCThreadState::self()->flushCommands(); // Make sure the service is dead after some time of no use sleep(10); ASSERT_EQ(nullptr, AServiceManager_checkService(kLazyBinderNdkUnitTestService)); } void LambdaOnDeath(void* cookie) { auto onDeath = static_cast<std::function<void(void)>*>(cookie); (*onDeath)(); Loading Loading @@ -475,6 +524,10 @@ int main(int argc, char* argv[]) { prctl(PR_SET_PDEATHSIG, SIGHUP); return manualPollingService(IFoo::kSomeInstanceName); } if (fork() == 0) { prctl(PR_SET_PDEATHSIG, SIGHUP); return lazyService(kLazyBinderNdkUnitTestService); } if (fork() == 0) { prctl(PR_SET_PDEATHSIG, SIGHUP); return generatedService(); Loading Loading
libs/binder/ndk/include_platform/android/binder_manager.h +44 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <android/binder_ibinder.h> #include <android/binder_status.h> #include <sys/cdefs.h> __BEGIN_DECLS Loading Loading @@ -50,4 +51,47 @@ __attribute__((warn_unused_result)) AIBinder* AServiceManager_checkService(const */ __attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance); /** * Registers a lazy service with the default service manager under the 'instance' name. * Does not take ownership of binder. * The service must be configured statically with init so it can be restarted with * ctl.interface.* messages from servicemanager. * AServiceManager_registerLazyService cannot safely be used with AServiceManager_addService * in the same process. If one service is registered with AServiceManager_registerLazyService, * the entire process will have its lifetime controlled by servicemanager. * Instead, all services in the process should be registered using * AServiceManager_registerLazyService. * * \param binder object to register globally with the service manager. * \param instance identifier of the service. This will be used to lookup the service. * * \return STATUS_OK on success. */ binder_status_t AServiceManager_registerLazyService(AIBinder* binder, const char* instance) __INTRODUCED_IN(31); /** * Gets a binder object with this specific instance name. Efficiently waits for the service. * If the service is not declared, it will wait indefinitely. Requires the threadpool * to be started in the service. * This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible * for calling AIBinder_decStrong). * * \param instance identifier of the service used to lookup the service. * * \return service if registered, null if not. */ __attribute__((warn_unused_result)) AIBinder* AServiceManager_waitForService(const char* instance) __INTRODUCED_IN(31); /** * Check if a service is declared (e.g. VINTF manifest). * * \param instance identifier of the service. * * \return true on success, meaning AServiceManager_waitForService should always * be able to return the service. */ bool AServiceManager_isDeclared(const char* instance) __INTRODUCED_IN(31); __END_DECLS
libs/binder/ndk/libbinder_ndk.map.txt +3 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,9 @@ LIBBINDER_NDK31 { # introduced=31 ABinderProcess_setupPolling; # apex AIBinder_getCallingSid; # apex AIBinder_setRequestingSid; # apex AServiceManager_isDeclared; # apex llndk AServiceManager_registerLazyService; # llndk AServiceManager_waitForService; # apex llndk }; LIBBINDER_NDK_PLATFORM { Loading
libs/binder/ndk/service_manager.cpp +31 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include "status_internal.h" #include <binder/IServiceManager.h> #include <binder/LazyServiceRegistrar.h> using ::android::defaultServiceManager; using ::android::IBinder; Loading Loading @@ -61,3 +62,33 @@ AIBinder* AServiceManager_getService(const char* instance) { AIBinder_incStrong(ret.get()); return ret.get(); } binder_status_t AServiceManager_registerLazyService(AIBinder* binder, const char* instance) { if (binder == nullptr || instance == nullptr) { return STATUS_UNEXPECTED_NULL; } auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance(); status_t status = serviceRegistrar.registerService(binder->getBinder(), instance); return PruneStatusT(status); } AIBinder* AServiceManager_waitForService(const char* instance) { if (instance == nullptr) { return nullptr; } sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder = sm->waitForService(String16(instance)); sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(binder); AIBinder_incStrong(ret.get()); return ret.get(); } bool AServiceManager_isDeclared(const char* instance) { if (instance == nullptr) { return false; } sp<IServiceManager> sm = defaultServiceManager(); return sm->isDeclared(String16(instance)); }
libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +53 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ using namespace android; constexpr char kExistingNonNdkService[] = "SurfaceFlinger"; constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest"; constexpr char kLazyBinderNdkUnitTestService[] = "LazyBinderNdkUnitTest"; class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest { ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) { Loading Loading @@ -143,6 +144,27 @@ int manualThreadPoolService(const char* instance) { return 1; } int lazyService(const char* instance) { ABinderProcess_setThreadPoolMaxThreadCount(0); // Wait to register this service to make sure the main test process will // actually wait for the service to be available. Tested with sleep(60), // and reduced for sake of time. sleep(1); // Strong reference to MyBinderNdkUnitTest kept by service manager. // This is just for testing, it has no corresponding init behavior. auto service = ndk::SharedRefBase::make<MyBinderNdkUnitTest>(); auto binder = service->asBinder(); binder_status_t status = AServiceManager_registerLazyService(binder.get(), instance); if (status != STATUS_OK) { LOG(FATAL) << "Could not register: " << status << " " << instance; } ABinderProcess_joinThreadPool(); return 1; // should not return } // This is too slow // TEST(NdkBinder, GetServiceThatDoesntExist) { // sp<IFoo> foo = IFoo::getService("asdfghkl;"); Loading Loading @@ -171,6 +193,33 @@ TEST(NdkBinder, DoubleNumber) { EXPECT_EQ(2, out); } TEST(NdkBinder, GetLazyService) { // Not declared in the vintf manifest ASSERT_FALSE(AServiceManager_isDeclared(kLazyBinderNdkUnitTestService)); ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService)); std::shared_ptr<aidl::IBinderNdkUnitTest> service = aidl::IBinderNdkUnitTest::fromBinder(binder); ASSERT_NE(service, nullptr); EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get())); } // This is too slow TEST(NdkBinder, CheckLazyServiceShutDown) { ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService)); std::shared_ptr<aidl::IBinderNdkUnitTest> service = aidl::IBinderNdkUnitTest::fromBinder(binder); ASSERT_NE(service, nullptr); EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get())); binder = nullptr; service = nullptr; IPCThreadState::self()->flushCommands(); // Make sure the service is dead after some time of no use sleep(10); ASSERT_EQ(nullptr, AServiceManager_checkService(kLazyBinderNdkUnitTestService)); } void LambdaOnDeath(void* cookie) { auto onDeath = static_cast<std::function<void(void)>*>(cookie); (*onDeath)(); Loading Loading @@ -475,6 +524,10 @@ int main(int argc, char* argv[]) { prctl(PR_SET_PDEATHSIG, SIGHUP); return manualPollingService(IFoo::kSomeInstanceName); } if (fork() == 0) { prctl(PR_SET_PDEATHSIG, SIGHUP); return lazyService(kLazyBinderNdkUnitTestService); } if (fork() == 0) { prctl(PR_SET_PDEATHSIG, SIGHUP); return generatedService(); Loading