aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Langlois <pierre.langlois@arm.com>2015-03-05 14:38:09 +0000
committerPierre Langlois <pierre.langlois@arm.com>2016-03-04 18:01:17 +0000
commita4444561cb4e52ae8890a9670357e44d6ba4d0bc (patch)
tree4a44cbcc43709ee3506fae64af62d22bfe2e9b32
parent7543ae41473ce906918783d300873c2311f6d119 (diff)
downloadkdbinder-a4444561cb4e52ae8890a9670357e44d6ba4d0bc.tar.gz
libkdbinder: implement sending Binder objects
This commit implements a mechanism for sending a Binder object across the bus. It is implemented by the `writeStrongBinder` and `readStrongBinder` method of `Parcel`. In any case, we do not really send an object but in fact send its associated handle. So, the ID of the connection on the bus that we need to talk to when issuing a transaction. * Sending a Binder: - If the Binder is a remote: We already know the connection ID associated with it. Send it. - If the Binder is local: We do not know what its connection ID is, but we can find out by reading the current process' service table. However, the object might not be registered in this table. So in this case, we just add it before sending it. * Receiving a Binder: We simply read the corresponding handle and create a Binder object from it. However, the Binder we received could as well be local to us so we need to read the process' service table first. If it's local, return the local Binder, if it isn't we simply create a new remote Binder. * Implementation: This commit implements this by adding two new private methods to `ProcessState`: ~~~ // Get the handle of a given Binder. // - If the Binder is local: // Search it in mServiceTable and return the handle. If it // does not find it, it will add it to the table and return the new // handle. // - If the Binder is remote: // Simply lookup its handle and return it. int32_t getHandleForBinder(sp<IBinder> binder); // Get the Binder object with the given handle. // This method will search mServiceTable and return the local Binder // that it found. If it did not find it, then it will create a new // remove Binder. sp<IBinder> getBinderForHandle(int32_t handle); ~~~ They take care of the conversion between a handle and a Binder object. They will search the process' service table to see if a given Binder/handle corresponds to a local service. The `Parcel` methods then simply call these methods to convert a Binder to a handle when sending, and a handle to a Binder when receiving. Change-Id: Ie5eabcd0e8a36c587ea1858b1d399873f087bab0
-rw-r--r--include/kdbinder/binder/ProcessState.h17
-rw-r--r--libs/kdbinder/binder/Parcel.cpp12
-rw-r--r--libs/kdbinder/binder/ProcessState.cpp50
3 files changed, 73 insertions, 6 deletions
diff --git a/include/kdbinder/binder/ProcessState.h b/include/kdbinder/binder/ProcessState.h
index 0e5893d..97c831b 100644
--- a/include/kdbinder/binder/ProcessState.h
+++ b/include/kdbinder/binder/ProcessState.h
@@ -46,6 +46,7 @@ class ProcessState : public virtual RefBase {
friend class IPCThreadState;
// BpServiceManager needs to call registerService.
friend class BpServiceManager;
+ friend class Parcel;
ProcessState();
~ProcessState() = default;
@@ -59,6 +60,22 @@ class ProcessState : public virtual RefBase {
// Add the given Binder object in mServiceTable.
int32_t registerService(sp<IBinder> binder, String16 name);
+ int32_t registerBinder(sp<IBinder> binder);
+
+ // Get the handle of a given Binder.
+ // - If the Binder is local:
+ // Search it in mServiceTable and return the handle. If it
+ // does not find it, it will add it to the table and return the new
+ // handle.
+ // - If the Binder is remote:
+ // Simply lookup its handle and return it.
+ int32_t getHandleForBinder(sp<IBinder> binder);
+
+ // Get the Binder object with the given handle.
+ // This method will search mServiceTable and return the local Binder
+ // that it found. If it did not find it, then it will create a new
+ // remove Binder.
+ sp<IBinder> getBinderForHandle(int32_t handle);
// Each Binder object managed by ProcessState need a kdbus::Connection
// associated with them.
diff --git a/libs/kdbinder/binder/Parcel.cpp b/libs/kdbinder/binder/Parcel.cpp
index 0e10fd2..a3fad31 100644
--- a/libs/kdbinder/binder/Parcel.cpp
+++ b/libs/kdbinder/binder/Parcel.cpp
@@ -431,8 +431,9 @@ status_t Parcel::writeString16(const char16_t* str, size_t len) {
}
status_t Parcel::writeStrongBinder(const sp<IBinder>& val) {
- // TODO: unimplemented
- return flatten_binder(ProcessState::self(), val, this);
+ int64_t handle = ProcessState::self()->getHandleForBinder(val);
+
+ return writeInt64(handle);
}
status_t Parcel::writeWeakBinder(const wp<IBinder>& val) {
@@ -777,10 +778,9 @@ const char16_t* Parcel::readString16Inplace(size_t* outLen) const {
}
sp<IBinder> Parcel::readStrongBinder() const {
- sp<IBinder> val;
- // TODO: unimplemented
- unflatten_binder(ProcessState::self(), *this, &val);
- return val;
+ int64_t handle = readInt64();
+
+ return ProcessState::self()->getBinderForHandle(handle);
}
wp<IBinder> Parcel::readWeakBinder() const {
diff --git a/libs/kdbinder/binder/ProcessState.cpp b/libs/kdbinder/binder/ProcessState.cpp
index 5235510..8ea144d 100644
--- a/libs/kdbinder/binder/ProcessState.cpp
+++ b/libs/kdbinder/binder/ProcessState.cpp
@@ -99,4 +99,54 @@ int32_t ProcessState::registerService(sp<IBinder> binder, String16 name) {
return handle;
}
+int32_t ProcessState::registerBinder(sp<IBinder> binder) {
+ auto connection_for_binder = kdbus::Connection::hello(
+ "0-services",
+ "BBinder");
+
+ int32_t handle = connection_for_binder->id;
+
+ {
+ // add binder to table.
+ AutoMutex _l(mServiceLock);
+ mServiceTable.emplace_back(std::move(connection_for_binder), binder);
+ }
+
+ return handle;
+}
+
+int32_t ProcessState::getHandleForBinder(sp<IBinder> binder) {
+ IBinder *local = binder->localBinder();
+
+ if (local) {
+ auto it = std::find_if(mServiceTable.cbegin(),
+ mServiceTable.cend(),
+ [&binder](const struct binder_entry& entry) {
+ return entry.binder == binder;
+ });
+ if (it == mServiceTable.cend()) {
+ return registerBinder(binder);
+ } else {
+ return it->connection->id;
+ }
+ } else {
+ BpBinder *remote = binder->remoteBinder();
+
+ return remote->handle();
+ }
+}
+
+sp<IBinder> ProcessState::getBinderForHandle(int32_t handle) {
+ auto it = std::find_if(mServiceTable.cbegin(),
+ mServiceTable.cend(),
+ [&handle](const struct binder_entry& entry) {
+ return entry.connection->id == (uint64_t) handle;
+ });
+ if (it != mServiceTable.cend()) {
+ return it->binder;
+ } else {
+ return new BpBinder(handle);
+ }
+}
+
} // namespace android