libbinder: add IBinder::withLock
BpBinder (and BBinder, once its mExtra allocation is made) have very
nice and shiny locks which they keep all for themselves! Stop it,
IBinder! Share that lock!
This provides convenient access to IBinder's lock, in order to avoid
needing additional locks elsewhere.
Bug: 192023359
Test: N/A
Change-Id: Id3485a2ac66d19379dcad2f0b41d6cb7a8a96725
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 4965386..53750c9 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -179,6 +179,17 @@
return transact(SET_RPC_CLIENT_TRANSACTION, data, &reply);
}
+void IBinder::withLock(const std::function<void()>& doWithLock) {
+ BBinder* local = localBinder();
+ if (local) {
+ local->withLock(doWithLock);
+ return;
+ }
+ BpBinder* proxy = this->remoteBinder();
+ LOG_ALWAYS_FATAL_IF(proxy == nullptr, "binder object must be either local or remote");
+ proxy->withLock(doWithLock);
+}
+
// ---------------------------------------------------------------------------
class BBinder::RpcServerLink : public IBinder::DeathRecipient {
@@ -337,6 +348,14 @@
return e->mObjects.detach(objectID);
}
+void BBinder::withLock(const std::function<void()>& doWithLock) {
+ Extras* e = getOrCreateExtras();
+ LOG_ALWAYS_FATAL_IF(!e, "no memory");
+
+ AutoMutex _l(e->mLock);
+ doWithLock();
+}
+
BBinder* BBinder::localBinder()
{
return this;
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 1f67825..3099296 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -427,6 +427,11 @@
return mObjects.detach(objectID);
}
+void BpBinder::withLock(const std::function<void()>& doWithLock) {
+ AutoMutex _l(mLock);
+ doWithLock();
+}
+
BpBinder* BpBinder::remoteBinder()
{
return this;
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index b2fa250..46223bb 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -58,6 +58,7 @@
object_cleanup_func func) final;
virtual void* findObject(const void* objectID) const final;
virtual void* detachObject(const void* objectID) final;
+ void withLock(const std::function<void()>& doWithLock);
virtual BBinder* localBinder();
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 7c89759..c69bb9e 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -76,6 +76,7 @@
object_cleanup_func func) final;
virtual void* findObject(const void* objectID) const final;
virtual void* detachObject(const void* objectID) final;
+ void withLock(const std::function<void()>& doWithLock);
virtual BpBinder* remoteBinder();
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 4e0952f..c484d83 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -22,6 +22,8 @@
#include <utils/String16.h>
#include <utils/Vector.h>
+#include <functional>
+
// linux/binder.h defines this, but we don't want to include it here in order to
// avoid exporting the kernel headers
#ifndef B_PACK_CHARS
@@ -273,6 +275,14 @@
*/
virtual void* detachObject(const void* objectID) = 0;
+ /**
+ * Use the lock that this binder contains internally. For instance, this can
+ * be used to modify an attached object without needing to add an additional
+ * lock (though, that attached object must be retrieved before calling this
+ * method). Calling (most) IBinder methods inside this will deadlock.
+ */
+ void withLock(const std::function<void()>& doWithLock);
+
virtual BBinder* localBinder();
virtual BpBinder* remoteBinder();