https://my.oschina.net/youranhongcha/blog/149575 侯 亮的Binder系列文章.
1、native层的Parcel.
1)、writeStrongBinder(service)分析 这感觉是最最最重要的一个函数了,在Parcel中,对于理解整个Binder流程也是至关重要的。从函数的名字皆可以看出,它是要往Parcel中写 入 一个Binder的引用或者实体. 位于android/frameworks/native/libs/binder/Parcel.cpp这个文件当中. 此处的service参数按照是一个MediaPlayerService对象它继承BnInterface、BBinder两个类。 status_t Parcel::writeStrongBinder(const sp<IBinder>& val) { return flatten_binder(ProcessState::self(), val, this); } status_t flatten_binder(const sp<ProcessState>& /*proc*/, //这里 const sp<IBinder>& binder, Parcel* out) { flat_binder_object obj; // 描述传输过程中的Binder.flatten使光滑,打包等等. //0x7f表示处理本Binder实体请求数据包的线程的最低优先级, //FLAT_BINDER_FLAG_ACCEPTS_FDS表示这个Binder实体可以接受文件描述符, //Binder实体在收到文件描述符时,就会在本进程中打开这个文件 obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; if (binder != NULL) { IBinder *local = binder->localBinder(); if (!local) { BpBinder *proxy = binder->remoteBinder(); if (proxy == NULL) { ALOGE("null proxy"); } const int32_t handle = proxy ? proxy->handle() : 0; obj.type = BINDER_TYPE_HANDLE; Binder引用的时候flat_binder_object 中的type = BINDER_TYPE_HANDLE. obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */ obj.handle = handle;//引用的时候为handle赋值,这个Handler就是初始化BpBinder的时候设置的. obj.cookie = 0; } else { //又由于MediaPlayerService继承自BBinder类,它是一个本地Binder实体,因此binder->localBinder返回一个BBinder指针, //就是服务端走这边. obj.type = BINDER_TYPE_BINDER;//Binder实体的时候flat_binder_object 中的type = BINDER_TYPE_BINDER. obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());//实体的时候为binder赋值. //果然只有在binder实体的时候才会有值,是Binder实体地址的指针. obj.cookie = reinterpret_cast<uintptr_t>(local);//指向这个Binder实体地址的指针local保存在flat_binder_obj的成员变量cookie中。 } } else { obj.type = BINDER_TYPE_BINDER;//Binder == null 的时候flat_binder_object 中的type = BINDER_TYPE_BINDER. obj.binder = 0; obj.cookie = 0; } return finish_flatten_binder(binder, obj, out);//进一步调用这个. } 此时有个知识点就是IBinder中定义了 localBinder、 remoteBinder两个virtual的方法,但是它都自己实现了,默认都是返回null的. BBinder* IBinder::localBinder() { return NULL; } BpBinder* IBinder::remoteBinder() { return NULL; } 而在BBinder中实现了 localBinder返回this,在BBinder中实现了 remoteBinder返回this,从名字上我们也可以很轻松的记住每个函数的用意. 先是调用binder->localBinder(),注意此时的binder传入的是 MediaPlayerService它是一个BBinder对象。它的 localBinder返回的是this,( BpBinder中没有看来是不会走到这里). BBinder* BBinder::localBinder() { return this; } 此时拿到这个BBinder对象,然后会走到else,但是我们都要分析一下: 结构体flat_binder_object进行对应的赋值,这个结构体我们在别的地方也有总结 它是用来描述一个传输中的binder对象.其中比较重要的一 个联合体,当是一个binder实体的时候binder_uintptr_t binder起作用。当 是一个binder引用的时候联合体的__u32 handle起作用,并且只 有当为binder实体的时候binder_uintptr_t cookie才起作用,那么究竟是怎 么实现的那?接下来就分析一下 struct flat_binder_object obj; 在if (!local)这个条件下: 此时是传入的这个IBinder对象是一个BpBinder对象,取出BpBinder对象的句柄handle然后obj.handle = handle。此时obj.binder = 0、 obj.cookie = 0都不起作用。还有一个很重要的赋值:obj.type = BINDER_TYPE_HANDLE.在传入的是Binder的引用也就是BpBinder对 象的时候进行的都是这些的赋值. 在else条件下:(此时是binder实体也就是BBinder对象) 和上面类似也是对一些自己想要的变量进行赋值操作:obj.type = BINDER_TYPE_BINDER、obj.binder = reinterpret_cast<uintptr_t> (local->getWeakRefs())、obj.cookie = reinterpret_cast<uintptr_t>(local)。把 local->getWeakRefs()强制转换然后存入到 obj.binder 然后就很关键了把这个Binder实体的地址强制转换然后保存在 flat_binder_object的cookie变量当中!!(难道客户端通过这个去取?) 最后调用finish_flatten_binder(binder, obj, out)这个就是把 obj也就是我们封装好的 flat_binder_object 写入到Pracel out当中。 inline static status_t finish_flatten_binder( const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out) { return out->writeObject(flat, false);//将这个flat_binder_obj写入到Parcel中去. } 接下来就是writeObject()了,把flat_binder_obj写到Parcel里面之内,还要记录这个flat_binder_obj在Parcel里面的偏移位置. status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData) { const bool enoughData = (mDataPos+sizeof(val)) <= mDataCapacity; const bool enoughObjects = mObjectsSize < mObjectsCapacity; if (enoughData && enoughObjects) {//空间够用. restart_write: *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val; // Need to write meta-data? if (nullMetaData || val.binder != 0) {//如果有binder对象 mObjects[mObjectsSize] = mDataPos;//记录这个flat_binder_obj在Parcel里面的偏移位置,(mDataPos前面普通数据存入的量,) //,如果进程间传输的数据间带有Binder对象的时候,Binder驱动程序需要作进一步的处理,以维护各个Binder实体的一致性, acquire_object(ProcessState::self(), val, this); mObjectsSize++; } // remember if it's a file descriptor if (val.type == BINDER_TYPE_FD) { if (!mAllowFds) { return FDS_NOT_ALLOWED; } mHasFds = mFdsKnown = true; } return finishWrite(sizeof(flat_binder_object));//完成最终处理. } if (!enoughData) { //......空间不足时候的一些处理 } if (!enoughObjects) { //......空间不足时候的一些处理 } goto restart_write; }