Add linkToDeath support for RPC binder so a client can act on disconnect
This requires an incoming thread to be listening to the connection in
order to be notified.
Test: atest binderRpcTest
Test: atest binderRpcTestSingleThreaded
Bug: 182939380
Change-Id: I3746de6e8cff99bb267867c5dc60a6815b19fb92
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 82ebdd7..b6d35ef 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -343,11 +343,23 @@
status_t BpBinder::linkToDeath(
const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
{
- if (isRpcBinder()) return UNKNOWN_TRANSACTION;
-
- if constexpr (!kEnableKernelIpc) {
+ if (isRpcBinder()) {
+ if (rpcSession()->getMaxIncomingThreads() < 1) {
+ LOG_ALWAYS_FATAL("Cannot register a DeathRecipient without any incoming connections.");
+ return INVALID_OPERATION;
+ }
+ } else if constexpr (!kEnableKernelIpc) {
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
return INVALID_OPERATION;
+ } else {
+ if (ProcessState::self()->getThreadPoolMaxTotalThreadCount() == 0) {
+ ALOGW("Linking to death on %s but there are no threads (yet?) listening to incoming "
+ "transactions. See ProcessState::startThreadPool and "
+ "ProcessState::setThreadPoolMaxThreadCount. Generally you should setup the "
+ "binder "
+ "threadpool before other initialization steps.",
+ String8(getInterfaceDescriptor()).c_str());
+ }
}
Obituary ob;
@@ -358,14 +370,6 @@
LOG_ALWAYS_FATAL_IF(recipient == nullptr,
"linkToDeath(): recipient must be non-NULL");
- if (ProcessState::self()->getThreadPoolMaxTotalThreadCount() == 0) {
- ALOGW("Linking to death on %s but there are no threads (yet?) listening to incoming "
- "transactions. See ProcessState::startThreadPool and "
- "ProcessState::setThreadPoolMaxThreadCount. Generally you should setup the binder "
- "threadpool before other initialization steps.",
- String8(getInterfaceDescriptor()).c_str());
- }
-
{
AutoMutex _l(mLock);
@@ -376,10 +380,14 @@
return NO_MEMORY;
}
ALOGV("Requesting death notification: %p handle %d\n", this, binderHandle());
- getWeakRefs()->incWeak(this);
- IPCThreadState* self = IPCThreadState::self();
- self->requestDeathNotification(binderHandle(), this);
- self->flushCommands();
+ if (!isRpcBinder()) {
+ if constexpr (kEnableKernelIpc) {
+ getWeakRefs()->incWeak(this);
+ IPCThreadState* self = IPCThreadState::self();
+ self->requestDeathNotification(binderHandle(), this);
+ self->flushCommands();
+ }
+ }
}
ssize_t res = mObituaries->add(ob);
return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
@@ -394,9 +402,7 @@
const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
wp<DeathRecipient>* outRecipient)
{
- if (isRpcBinder()) return UNKNOWN_TRANSACTION;
-
- if constexpr (!kEnableKernelIpc) {
+ if (!kEnableKernelIpc && !isRpcBinder()) {
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
return INVALID_OPERATION;
}
@@ -419,9 +425,13 @@
mObituaries->removeAt(i);
if (mObituaries->size() == 0) {
ALOGV("Clearing death notification: %p handle %d\n", this, binderHandle());
- IPCThreadState* self = IPCThreadState::self();
- self->clearDeathNotification(binderHandle(), this);
- self->flushCommands();
+ if (!isRpcBinder()) {
+ if constexpr (kEnableKernelIpc) {
+ IPCThreadState* self = IPCThreadState::self();
+ self->clearDeathNotification(binderHandle(), this);
+ self->flushCommands();
+ }
+ }
delete mObituaries;
mObituaries = nullptr;
}
@@ -434,9 +444,7 @@
void BpBinder::sendObituary()
{
- LOG_ALWAYS_FATAL_IF(isRpcBinder(), "Cannot send obituary for remote binder.");
-
- if constexpr (!kEnableKernelIpc) {
+ if (!kEnableKernelIpc && !isRpcBinder()) {
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
return;
}
@@ -451,9 +459,13 @@
Vector<Obituary>* obits = mObituaries;
if(obits != nullptr) {
ALOGV("Clearing sent death notification: %p handle %d\n", this, binderHandle());
- IPCThreadState* self = IPCThreadState::self();
- self->clearDeathNotification(binderHandle(), this);
- self->flushCommands();
+ if (!isRpcBinder()) {
+ if constexpr (kEnableKernelIpc) {
+ IPCThreadState* self = IPCThreadState::self();
+ self->clearDeathNotification(binderHandle(), this);
+ self->flushCommands();
+ }
+ }
mObituaries = nullptr;
}
mObitsSent = 1;