本文参考《Android系统源代码情景分析》,作者罗升阳

一、测试代码:

~/Android/external/binder/server

----FregServer.cpp

~/Android/external/binder/common

----IFregService.cpp

----IFregService.h

~/Android/external/binder/client

----FregClient.cpp


Binder库(libbinder)代码:

~/Android/frameworks/base/libs/binder

----BpBinder.cpp

----Parcel.cpp

----ProcessState.cpp

----Binder.cpp

----IInterface.cpp

----IPCThreadState.cpp

----IServiceManager.cpp

----Static.cpp

~/Android/frameworks/base/include/binder

----Binder.h

----BpBinder.h

----IInterface.h

----IPCThreadState.h

----IServiceManager.h

----IBinder.h

----Parcel.h

----ProcessState.h


驱动层代码:

~/Android//kernel/goldfish/drivers/staging/android

----binder.c

----binder.h


二、源码分析

程序首先开始从Service进程FregServer.cpp的main函数开始执行

~/Android/external/binder/server

----FregServer.cpp

class FregService : public BnFregService{        ...........public:static void instantiate(){defaultServiceManager()->addService(String16(FREG_SERVICE), new FregService());//注册Service}        ...........};int main(int argc, char** argv){FregService::instantiate();ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();return 0;}
在Android Binder进程间通信---FregServer进程,获取ServiceManager代理对象 http://blog.csdn.net/jltxgcy/article/details/25953361,一文中我们已经分析了defaultServiceManager()获取了ServiceManager代理对象。现在调用addService来注册Service组件。
~/Android/frameworks/base/libs/binder

----IServiceManager.cpp

class BpServiceManager : public BpInterface<IServiceManager>{public:    .........    virtual status_t addService(const String16& name, const sp<IBinder>& service)    {        Parcel data, reply;        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());//写入一个Binder进程间通信请求头        data.writeString16(name);//写入将要注册的Service组件的名称        data.writeStrongBinder(service);//将要注册的Service组件封装成一个flat_binder_object结构体,写入data        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);        return err == NO_ERROR ? reply.readExceptionCode() : err;    }    ..........};
将进程间通信数据写入到一个Parcel对象data中,然后将Parcel对象data的内容传递给Binder驱动程序。

首先调用Parcel对象data的成员函数writeInterfaceToken写入一个Binder进程间通信请求头,它的实现如下所示:

~/Android/frameworks/base/libs/binder

----Parcel.cpp

status_t Parcel::writeInterfaceToken(const String16& interface){    writeInt32(IPCThreadState::self()->getStrictModePolicy() |               STRICT_MODE_PENALTY_GATHER);//整数值,用来描述一个Strict Mode Policy    // currently the interface identification token is just its name as a string    return writeString16(interface);//用来描述所请求服务的接口描述符}
Binder进程间通信请求头由两部分内容组成。第一部分内容是一个整数值,用来描述一个Strict Mode Policy,第二部分内容是一个字符串,用来描述所请求服务的接口描述符。

接着调用Parcel对象data的成员函数writeString16写入将要注册的Service组件的名称。

最后,调用Parcel对象data的成员函数writeStrongBinder将要注册的Service组件封装成一个flat_binder_object结构体,然后传递给Binder驱动程序。将一个Service组件封装成一个flat_binder_object结构体是Binder进程间通信过程的一个重要步骤,接下来我们就着重分析这个过程。
~/Android/frameworks/base/libs/binder
----Parcel.cpp

status_t Parcel::writeStrongBinder(const sp<IBinder>& val){    return flatten_binder(ProcessState::self(), val, this);}
调用flatten_binder。

status_t flatten_binder(const sp<ProcessState>& proc,    const sp<IBinder>& binder, Parcel* out){    flat_binder_object obj;        obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;    if (binder != NULL) {        IBinder *local = binder->localBinder();//Binder本地对象的        if (!local) {            .........        } else {            obj.type = BINDER_TYPE_BINDER;            obj.binder = local->getWeakRefs();//弱引用计数的地址            obj.cookie = local;//binder本地对象指针        }    } else {        .........    }        return finish_flatten_binder(binder, obj, out);//将flat_binder_object结构体obj写入到Parcel对象out中}

首先定义了一个flat_binder_object结构体obj,然后将它的标志值设置为0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS,其中,0x7f用来描述将要注册的Service组件在处理一个进程间通信请求时,它所使用的Server线程的优先级不能低于0x7f;而FLAT_BINDER_FLAG_ACCEPTS_FDS表示可以将包含文件描述符的进程间通信数据给将要注册的Service组件处理。

其中flat_binder_object结构体,实现如下:

~/Android/frameworks/base/include/binder

----binder.h

struct flat_binder_object { unsigned long type; unsigned long flags; union { void *binder; signed long handle; }; void *cookie;};

接下来调用binder->localBinder(),分析此函数前,我们先看一个uml类图。

FregServer进程,封装进程间通信数据_第1张图片


参数binder指向的是一个FregService组件,它继承了BBinder类,BBinder类是用来描述一个Binder本地对象的,它的成员函数localBinder用来返回一个Binder本地对象接口。对应实现代码如下:

~/Android/frameworks/base/libs/binder

----Binder.cpp

BBinder* BBinder::localBinder(){    return this;//BBinder对象指针}
接下来分别设置type为BINDER_TYPE_BINDER,binder为其内部的一个弱引用计数对象的地址值,cookie为上面返回的Binder本地对象指针。

最后调用全局函数finish_flatten_binder将flat_binder_object结构体obj写入到Parcel对象out中,它的实现如下所示:

~/Android/frameworks/base/libs/binder

---- Parcel.cpp

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_object结构体flat写入到内部}
它调用Parcel对象out的成员函数writeObject将flat_binder_object结构体flat写入到内部。Parcel类的成员函数writeObject的实现如下所示:

~/Android/frameworks/base/libs/binder
---- Parcel.cpp

status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData){    const bool enoughData = (mDataPos+sizeof(val)) <= mDataCapacity;//数据缓冲区如果有足够空间,enoughData为1    const bool enoughObjects = mObjectsSize < mObjectsCapacity;//偏移数组如果有足够空间,enoughObjects为1    if (enoughData && enoughObjects) {restart_write:        *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val;//flat_binder_object结构体存入数据缓冲区mData                // Need to write meta-data?        if (nullMetaData || val.binder != NULL) {            mObjects[mObjectsSize] = mDataPos;//flat_binder_object结构体在mData中偏移写入偏移数组mObjects            acquire_object(ProcessState::self(), val, this);            mObjectsSize++;//偏移数组mObjects下一个用于写入数据的位置加一        }                // remember if it's a file descriptor        if (val.type == BINDER_TYPE_FD) {            mHasFds = mFdsKnown = true;        }        return finishWrite(sizeof(flat_binder_object));//调整缓冲区mData下一个用来写入数据的位置    }    if (!enoughData) {//如果没有足够的空间,那么扩展后重新写入        const status_t err = growData(sizeof(val));        if (err != NO_ERROR) return err;    }    if (!enoughObjects) {//如果没有足够的空间,那么扩展后重新写入        size_t newSize = ((mObjectsSize+2)*3)/2;        size_t* objects = (size_t*)realloc(mObjects, newSize*sizeof(size_t));        if (objects == NULL) return NO_MEMORY;        mObjects = objects;        mObjectsCapacity = newSize;    }        goto restart_write;}
Parcel类内部有mData和mObjects两个缓冲区,其中,mData是一个数据缓冲区,它里面的内容可能包含有整数、字符串或者Binder对象,即flat_binder_object结构体;mObjects是一个偏移数组,它保存了数据缓冲区中所有Binder对象的位置。Binder驱动程序就是可以通过这个偏移数组找到进程间通信数据中的Binder对象的,以便对它们进行特殊处理。

Parcel类的成员变量mDataPos记录了数据缓冲区mData下一个用来写入数据的位置,而成员变量mDataCapacity则记录了数据缓冲区mData的总大小。成员变量mObjectSize记录了偏移数组mObjects下一个用于写入数据的位置,mObjectCapacity则记录了偏移数组mObjects的总大小。

如果有足够的缓冲区,那么要将flat_binder_object结构体存入数据缓冲区mData,flat_binder_object结构体在mData中偏移写入偏移数组mObjects。

如果数据缓冲区mData和偏移数组mObjects没有足够的空间来写入一个Binder对象,首先扩展他们的空间,然后再写入。

更多相关文章

  1. Delphi获取Android下GPS的NMEA 0183数据
  2. Android中Json数据解析
  3. Android之使用HttpPost提交数据到服务器(Android手机客户端和后台
  4. Android:数据存储之SQLite
  5. android中数据存储
  6. 转-Android数据存储(总结篇)

随机推荐

  1. android onResume is called before you
  2. android xml解析 XmlPullParser的使用
  3. (Android)Activity的生命的周期
  4. Android Goldfish详解之一
  5. Android截屏截图方法所有方法汇总(包括Act
  6. Android 自定义权限 ( )
  7. android LocationManager的使用
  8. Sqlite3常用简单指令
  9. Android Tasks、ActivityStack和Activity
  10. Kotlin 中Butterknife 和Android 中使用b