diff options
| -rw-r--r-- | libs/binder/IPCThreadState.cpp | 2 | ||||
| -rw-r--r-- | libs/binder/include/binder/IPCThreadState.h | 4 | ||||
| -rw-r--r-- | libs/binder/ndk/include_platform/android/binder_process.h | 28 | ||||
| -rw-r--r-- | libs/binder/ndk/libbinder_ndk.map.txt | 2 | ||||
| -rw-r--r-- | libs/binder/ndk/process.cpp | 8 | ||||
| -rw-r--r-- | libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp | 35 |
6 files changed, 69 insertions, 10 deletions
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index d67ce15ca9..157538e63f 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -614,7 +614,7 @@ void IPCThreadState::joinThreadPool(bool isMain) talkWithDriver(false); } -int IPCThreadState::setupPolling(int* fd) +status_t IPCThreadState::setupPolling(int* fd) { if (mProcess->mDriverFD < 0) { return -EBADF; diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h index 8d51cdc049..2bd39a7759 100644 --- a/libs/binder/include/binder/IPCThreadState.h +++ b/libs/binder/include/binder/IPCThreadState.h @@ -85,8 +85,8 @@ public: int64_t clearCallingIdentity(); // Restores PID/UID (not SID) void restoreCallingIdentity(int64_t token); - - int setupPolling(int* fd); + + status_t setupPolling(int* fd); status_t handlePolledCommands(); void flushCommands(); diff --git a/libs/binder/ndk/include_platform/android/binder_process.h b/libs/binder/ndk/include_platform/android/binder_process.h index fdefbb4b8a..f408fadee0 100644 --- a/libs/binder/ndk/include_platform/android/binder_process.h +++ b/libs/binder/ndk/include_platform/android/binder_process.h @@ -19,10 +19,15 @@ #include <stdint.h> #include <sys/cdefs.h> +#include <android/binder_status.h> + __BEGIN_DECLS /** * This creates a threadpool for incoming binder transactions if it has not already been created. + * + * When using this, it is expected that ABinderProcess_setupPolling and + * ABinderProcess_handlePolledCommands are not used. */ void ABinderProcess_startThreadPool(); /** @@ -37,4 +42,27 @@ bool ABinderProcess_setThreadPoolMaxThreadCount(uint32_t numThreads); */ void ABinderProcess_joinThreadPool(); +/** + * This gives you an fd to wait on. Whenever data is available on the fd, + * ABinderProcess_handlePolledCommands can be called to handle binder queries. + * This is expected to be used in a single threaded process which waits on + * events from multiple different fds. + * + * When using this, it is expected ABinderProcess_startThreadPool and + * ABinderProcess_joinThreadPool are not used. + * + * \param fd out param corresponding to the binder domain opened in this + * process. + * \return STATUS_OK on success + */ +__attribute__((weak)) binder_status_t ABinderProcess_setupPolling(int* fd) __INTRODUCED_IN(31); + +/** + * This will handle all queued binder commands in this process and then return. + * It is expected to be called whenever there is data on the fd. + * + * \return STATUS_OK on success + */ +__attribute__((weak)) binder_status_t ABinderProcess_handlePolledCommands() __INTRODUCED_IN(31); + __END_DECLS diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt index 9b5fa26303..d4353823a0 100644 --- a/libs/binder/ndk/libbinder_ndk.map.txt +++ b/libs/binder/ndk/libbinder_ndk.map.txt @@ -113,6 +113,8 @@ LIBBINDER_NDK30 { # introduced=30 LIBBINDER_NDK31 { # introduced=31 global: + ABinderProcess_handlePolledCommands; # apex + ABinderProcess_setupPolling; # apex AIBinder_getCallingSid; # apex AIBinder_setRequestingSid; # apex }; diff --git a/libs/binder/ndk/process.cpp b/libs/binder/ndk/process.cpp index c89caaf349..ac582a412e 100644 --- a/libs/binder/ndk/process.cpp +++ b/libs/binder/ndk/process.cpp @@ -34,3 +34,11 @@ bool ABinderProcess_setThreadPoolMaxThreadCount(uint32_t numThreads) { void ABinderProcess_joinThreadPool() { IPCThreadState::self()->joinThreadPool(); } + +binder_status_t ABinderProcess_setupPolling(int* fd) { + return IPCThreadState::self()->setupPolling(fd); +} + +binder_status_t ABinderProcess_handlePolledCommands() { + return IPCThreadState::self()->handlePolledCommands(); +} diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp index e3fdb4bab3..9b2fcf009a 100644 --- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp @@ -24,6 +24,7 @@ #include <android/binder_process.h> #include <gtest/gtest.h> #include <iface/iface.h> +#include <utils/Looper.h> // warning: this is assuming that libbinder_ndk is using the same copy // of libbinder that we are. @@ -107,19 +108,39 @@ class MyFoo : public IFoo { } }; -int manualService(const char* instance) { - ABinderProcess_setThreadPoolMaxThreadCount(0); - +void manualService(const char* instance) { // Strong reference to MyFoo kept by service manager. binder_status_t status = (new MyFoo)->addService(instance); if (status != STATUS_OK) { LOG(FATAL) << "Could not register: " << status << " " << instance; } +} +int manualPollingService(const char* instance) { + int fd; + CHECK(STATUS_OK == ABinderProcess_setupPolling(&fd)); + manualService(instance); + + class Handler : public LooperCallback { + int handleEvent(int /*fd*/, int /*events*/, void* /*data*/) override { + ABinderProcess_handlePolledCommands(); + return 1; // Continue receiving callbacks. + } + }; + sp<Looper> looper = Looper::prepare(0 /* opts */); + looper->addFd(fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, new Handler(), nullptr /*data*/); + // normally, would add additional fds + while (true) { + looper->pollAll(-1 /* timeoutMillis */); + } + return 1; // should not reach +} +int manualThreadPoolService(const char* instance) { + ABinderProcess_setThreadPoolMaxThreadCount(0); + manualService(instance); ABinderProcess_joinThreadPool(); - - return 1; // should not return + return 1; } // This is too slow @@ -448,11 +469,11 @@ int main(int argc, char* argv[]) { if (fork() == 0) { prctl(PR_SET_PDEATHSIG, SIGHUP); - return manualService(IFoo::kInstanceNameToDieFor); + return manualThreadPoolService(IFoo::kInstanceNameToDieFor); } if (fork() == 0) { prctl(PR_SET_PDEATHSIG, SIGHUP); - return manualService(IFoo::kSomeInstanceName); + return manualPollingService(IFoo::kSomeInstanceName); } if (fork() == 0) { prctl(PR_SET_PDEATHSIG, SIGHUP); |