diff options
author | Pierre Langlois <pierre.langlois@arm.com> | 2015-03-05 14:38:09 +0000 |
---|---|---|
committer | Pierre Langlois <pierre.langlois@arm.com> | 2016-03-04 18:01:17 +0000 |
commit | a4444561cb4e52ae8890a9670357e44d6ba4d0bc (patch) | |
tree | 4a44cbcc43709ee3506fae64af62d22bfe2e9b32 | |
parent | 7543ae41473ce906918783d300873c2311f6d119 (diff) | |
download | kdbinder-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.h | 17 | ||||
-rw-r--r-- | libs/kdbinder/binder/Parcel.cpp | 12 | ||||
-rw-r--r-- | libs/kdbinder/binder/ProcessState.cpp | 50 |
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 |