Android Binder机制(四) ------- 客户端分析
客户端首先通过defaultServiceManager获得IServiceManager接口。然后调用IServiceManager的getSerivice接口得到服务的IBInder接口,该接口指向一个BpBinder实体对象。但是问题是我们通过IBInder接口无法调用到我们的服务,还必须经过接口转化才能得到我们真正的服务代理接口。
*outService = interface_cast<INTERFACE>(sm->getService(name));
- 模板函数interface_cast的功能就是将IBinder接口转化为对应的服务代理接口,看看它的实现
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
- 这函数也没干什么事,就是封装了下。调用INTERFACE::asInterface实现接口转化。asInterface接口的声明和实现是用宏定义。
#define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor; \
static android::sp<I##INTERFACE> asInterface( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const android::String16 I##INTERFACE::descriptor(NAME); \
const android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
const android::sp<android::IBinder>& obj) \
{ \
android::sp<I##INTERFACE> intr; \
if (obj != NULL) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \
#define CHECK_INTERFACE(interface, data, reply) \
if (!data.checkInterface(this)) { return PERMISSION_DENIED; } \
- asInterface首先去查询本地接口,如果之后已经获得,返回之前的接口指针给intr。
- 如果之前没有获得过该接口,intr为NULL,那么重新创建一个Bp##INTERFACE服务代理接口对象。
- 最后返回去的就是Bp##INTERFACE对象指针,我们就可以用该接口指针调用所需要服务。
- Bp##INTERFACE类的构造函数是一个IBinder引用,我们看下这个引用最终保存在哪里(这个引用很关键,与服务的交互就靠它了)
BpSurfaceComposer(const sp<IBinder>& impl)
: BpInterface<ISurfaceComposer>(impl)
{
}
BpSurfaceComposer构造函数中将IBinder引用传给了其父类BpInterface,那继续往上看
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{
}
BpInterface的构造函数又将IBinder引用传给了其父类BpRefBase,那我们在看看BpRefBase的构造函数
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
if (mRemote) {
mRemote->incStrong(this); // Removed on first IncStrong().
mRefs = mRemote->createWeak(this); // Held for our entire lifetime.
}
}
BpRefBase将IBinder引用赋值给了其成员变量mRemote中。在来看看BpRefBase的类定义
class BpRefBase : public virtual RefBase
{
protected:
BpRefBase(const sp<IBinder>& o);
virtual ~BpRefBase();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
inline IBinder* remote() { return mRemote; }
inline IBinder* remote() const { return mRemote; }
private:
BpRefBase(const BpRefBase& o);
BpRefBase& operator=(const BpRefBase& o);
IBinder* const mRemote;
RefBase::weakref_type* mRefs;
volatile int32_t mState;
};
比较关键的是其成员函数remote()返回了mRemote的值。
先总结一下,Bp##INTERFACE的创建的时候会传入IBinder引用。构造函数会将IBinder引用保存在成员变量mRemote中。然后其成员函数remote()会返回mRemote的值。到这里Bp##INTERFACE代理接口对象构建完了,接下来在看看怎么调用里面的接口方法实现与服务进程的通讯。(以接口ISurfaceComposer的bootFinished方法为例 )
当客户端调通过接口指针(ISurfaceComposer *)调用bootFinished方法时,由于指针实际所指对象为BpSurfaceComposer。所以实质上调用BpSurfaceComposer的bootFinished方法。
virtual void bootFinished()
{
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
}
- 通过remote()函数所返回的对象指针,调用transact函数
- 由上文可知,remote()所返回的指针类类型为IBinder *, 但它所指向的对象为BpBinder
- 所以最终调用BpBinder里的transact方法
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
- 这个函数里也没做什么事,只是调用了IPCThreadState的transact方法
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
......
if (err == NO_ERROR) {
LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) {
#if 0
if (code == 4) { // relayout
ALOGI(">>>>>> CALLING transaction 4");
} else {
ALOGI(">>>>>> CALLING transaction %d", code);
}
#endif
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
#if 0
if (code == 4) { // relayout
ALOGI("<<<<<< RETURNING transaction 4");
} else {
ALOGI("<<<<<< RETURNING transaction %d", code);
}
#endif
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "
<< handle << ": ";
if (reply) alog << indent << *reply << dedent << endl;
else alog << "(none requested)" << endl;
}
} else {
err = waitForResponse(NULL, NULL);
}
return err;
}
- writeTransactionData函数,它将客户端请求封装成数据包binder_transaction_data
- binder_transaction_data函数,调用talkWithDriver与Binder驱动进行数据交互。将请求写入到Binder驱动,并不断从Binder驱动中读取返回来的数据。
- 将返回来的数据放在reply中,并返回给调用者
总结,客户端在调用Binder代理接口方法时,最终通过IPCThreadState::transact与Binder驱动通讯,将请求写入到Binder驱动,并Binder驱动中读取返回的结果,然后返回给调用者。客户端的调用流程就大致走完了。