本文参考《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类图。




参数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. Android消息机制Message消息池
  2. android中数据存储
  3. android ApiDemo学习(一)service总结
  4. Android之Handler用法总结
  5. android Application类的详细介绍
  6. 设置ScrollView滚动条的颜色
  7. Android的UI两大基石
  8. Android中Message机制的灵活应用
  9. Android中Message机制的灵活应用

随机推荐

  1. android之模仿QQ登陆的布局实现
  2. android菜鸟进阶之路——应用程序里嵌入
  3. 在系统里设置文件默认打开APP
  4. Android AppWidgetProvider 定时刷新问题
  5. Android实现发短信与打电话的功能
  6. Android android.support.v4.widget.Slid
  7. Android(安卓)Sqite数据库
  8. android 通过canvas旋转 绘制文字 竖直等
  9. android调用系统相机返回null的bug
  10. Android: 一个两点触控的案例