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


二、源码分析

1、程序首先开始从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());}        ...........};int main(int argc, char** argv){FregService::instantiate();ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();return 0;}
main函数首先调用静态方法instantiate,在instantiate中调用了defaultServiceManager(),因为include#include <binder/IServiceManager.h>,所以可以调用 defaultServiceManager()函数实现如下:

~/Android/frameworks/base/libs/binder

----IServiceManager.cpp

sp<IServiceManager> defaultServiceManager(){    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;//如果已经创建了代理对象,那么就直接返回        {        AutoMutex _l(gDefaultServiceManagerLock);//使用锁,来实现单例模式        if (gDefaultServiceManager == NULL) {            gDefaultServiceManager = interface_cast<IServiceManager>(//分三步获取Service Manager代理对象                ProcessState::self()->getContextObject(NULL));        }    }        return gDefaultServiceManager;}
其中gDefaultServiceManagerLock,gDefaultServiceManager都定义在Static.cpp中。

~/Android/frameworks/base/libs/binder

----Static.cpp

Mutex gDefaultServiceManagerLock;   //锁sp<IServiceManager> gDefaultServiceManager; //IServiceManager的强指针
全局变量 gDefaultServiceManager是一个类型为IServiceManager的强指针,它指向进程内的一个BpServiceManager对象,即Service Manager代理对象;而全局变量gDefaultServiceManagerLock是用来保证一个进程至多只有一个Service Manager代理对象。结合锁机制来保证对象在进程中的唯一性,这是单例设计模式的经典实现。

如果已经创建了代理对象,那么就直接返回。如果没有创建,那么分三步创建:

(1)、调用ProcessState类的静态成员函数self获取进程内的一个ProcessState对象。

(2)、调用前面获得的ProcessState对象的成员函数getContextObject创建一个Binder代理对象

(3)、调用模板函数interface_cast<IServiceManager>将前面获得的Binder代理对象封装成一个Service Manager代理对象。


2、调用ProcessState类的静态成员函数self获取进程内的一个ProcessState对象

~/Android/frameworks/base/libs/binder

----ProcessState.cpp

sp<ProcessState> ProcessState::self(){    if (gProcess != NULL) return gProcess;//如果已经创建了,就直接返回        AutoMutex _l(gProcessMutex);    if (gProcess == NULL) gProcess = new ProcessState;//创建ProcessState对象    return gProcess;}
其中gProcess,gProcessMutex都位于Static.cpp中

Mutex gProcessMutex;sp<ProcessState> gProcess;
全局变量gProcess是一个类型为ProcessState的强指针,它指向进程内的一个ProcessState对象;而全局变量gProcessMutex是一个互斥锁,是用来保证一个进程至多只有一个ProcessState对象的,同样是一个单例模式。


首次进入,故创建ProcessState对象。

~/Android/frameworks/base/libs/binder

----ProcessState.cpp

ProcessState::ProcessState()    : mDriverFD(open_driver())    , mVMStart(MAP_FAILED)    .....{    if (mDriverFD >= 0) {       ...........        // mmap the binder, providing a chunk of virtual address space to receive transactions.        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);       ...........}
在初始化构造函数中调用了open_driver方法。

~/Android/frameworks/base/libs/binder

----ProcessState.cpp

static int open_driver(){    if (gSingleProcess) {        return -1;    }    int fd = open("/dev/binder", O_RDWR);//又一个进程打开了设备文件,binder_procs又多了一个进程的结构体    if (fd >= 0) {        fcntl(fd, F_SETFD, FD_CLOEXEC);        int vers;#if defined(HAVE_ANDROID_OS)        status_t result = ioctl(fd, BINDER_VERSION, &vers);//调用ioctl传入BINDER_VERSION参数来获取vers#else        status_t result = -1;        errno = EPERM;#endif        if (result == -1) {            LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));            close(fd);            fd = -1;        }        if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {            LOGE("Binder driver protocol does not match user space protocol!");            close(fd);            fd = -1;        }#if defined(HAVE_ANDROID_OS)        size_t maxThreads = 15;        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);//调用ioctl传入BINDER_SET_MAX_THREADS参数来设备该进程所支持的最大线程数        if (result == -1) {            LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));        }#endif            } else {        LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));    }    return fd;}
open_driver首先调用了open打开设备文件,在http://blog.csdn.net/jltxgcy/article/details/25797011这盘文章中已经讲解了驱动层的binder_open所做的事。然后的调用ioctl传入BINDER_VERSION参数来获取vers。最后调用ioctl传入BINDER_SET_MAX_THREADS参数来设备该进程所支持的最大线程数。

在初始化列表中调用mmap把设备文件/dev/binder映射到进程的地址空间,其实将/dev/binder映射到进程的地址空间实际上是请求Binder驱动程序为进程分配内核缓冲区。


3、调用前面获得的ProcessState对象的成员函数getContextObject创建一个Binder代理对象

~/Android/frameworks/base/libs/binder

----ProcessState.cpp

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller){    if (supportsProcesses()) {//为true        return getStrongProxyForHandle(0);    } else {        return getContextObject(String16("default"), caller);    }}

~/Android/frameworks/base/libs/binder

----ProcessState.cpp

bool ProcessState::supportsProcesses() const{    return mDriverFD >= 0;}
由于在open_driver时,mDriverFD已经大于0,所以程序开始执行getStrongProxyForHandle(0)。

~/Android/frameworks/base/libs/binder

----ProcessState.cpp

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle){    sp<IBinder> result;    AutoMutex _l(mLock);    handle_entry* e = lookupHandleLocked(handle);//检查成员变量mHandleToObject是否已经存在一个与句柄值handle对应的handle_entry结构体    if (e != NULL) {        // We need to create a new BpBinder if there isn't currently one, OR we        // are unable to acquire a weak reference on this current one.  See comment        // in getWeakProxyForHandle() for more info about this.        IBinder* b = e->binder;        if (b == NULL || !e->refs->attemptIncWeak(this)) {//如果进程尚未为句柄值handle创建过Binder代理对象,或者创建了Binder代理对象但已经销毁了            b = new BpBinder(handle); //Binder代理对象,handle为0            e->binder = b;//保存再e的成员变量binder中            if (b) e->refs = b->getWeakRefs();//将弱引用计数对象保存在e的成员变量refs中            result = b;//返回结果        } else {//如果进程已经创建了Binder代理对象,并且没有销毁,那么直接返回            // This little bit of nastyness is to allow us to add a primary            // reference to the remote proxy when this team doesn't have one            // but another team is sending the handle to us.            result.force_set(b);//设置返回结果result            e->refs->decWeak(this);//减少弱引用计数,因为attemptIncWeak增加了弱引用计数        }    }    return result;}
参数handle的值等于0,表示要创建的Binder代理对象的句柄值等于0,即要创建一个Binder代理对象。Binder库为每个进程维护了一个handle_entry类型的Binder代理对象列表,它以句柄值作为关键字来维护进程内部所有的Binder代理对象。这个Binder代理对象列表保存在ProcessState类的成员变量mHandleToObject,它的定义如下:

~/Android/frameworks/base/include/binder

----ProcessState.h

class ProcessState : public virtual RefBase{            .......                       struct handle_entry {                IBinder* binder;//Binder代理对象                RefBase::weakref_type* refs;//一个弱引用计数对象            };                        ..........            Vector<handle_entry>mHandleToObject;//列表            .........};

每一个Binder代理对象都使用一个handle_entry结构体来描述。结构体handle_entry的两个成员变量binder和refs分别指向一个Binder代理对象,以及它内部的一个弱引用计数对象。

回到ProcessState类的成员函数getStrongProxyForHandle(0),首先调用成员函数lookupHandleLocked来检查成员变量mHandleToObject是否已经存在一个与句柄值handle对应的handle_entry结构体,它的实现如下:

~/Android/frameworks/base/libs/binder

----ProcessState.cpp

ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle){    const size_t N=mHandleToObject.size();//列表的大小    if (N <= (size_t)handle) {如果句柄值大于或者等于列表大小,否则直接返回指向该结构体的指针        handle_entry e;//创建handle_entry结构体        e.binder = NULL;//初始化        e.refs = NULL;        status_t err = mHandleToObject.insertAt(e, N, handle+1-N);//插入到对应位置        if (err < NO_ERROR) return NULL;    }    return &mHandleToObject.editItemAt(handle);//返回指向该结构体的指针}
一个Binder代理对象的句柄值同时也是它在列表mHandleToObject中的索引值。首先检查句柄值handle是否大于或者等于列表mHandleToObject的大小,如果是,那么mHandleToObject列表里面就不存在一个与句柄值handle对应的handle_entry结构体,那么创建一个handle_entry结构体,并插入到对应位置,最后返回指向该结构体的指针。

程序继续执行,如果hanle_entry结构体e的成员变量binder的值为NULL,说明进程尚未为句柄值handle创建过Binder代理对象,因此就会根据句柄值handle创建一个Binder代理对象,并且将它保存在handle_entry结构体e的成员变量binder中。并且把弱引用计数对象保存在e的成员变量refs中。

如果hanle_entry结构体e的成员变量binder的值不为NULL,即它已经指向了一个Binder代理对象,就需要继续检查这个Binder代理对象是否还活着,方法是调用它的弱引用计数对象的成员函数attemptIncWeek来尝试增加它的弱引用数。由于Binder代理对象(即BpBinder对象)的生命周期是受弱引用计数控制的,因此如果不能成功增加它的弱引用计数,那么就说明它已经被销毁了。在这种情况下,也需要重新为句柄值handle创建一个Binder代理对象。

如果handle_entry结构体e成员变量binder的值不等于NULL,并且调用它的成员attmptIncWeek能够成功地增加与它对应的一个Binder代理对象的弱引用计数,那么就说明在进程中已经有一个Binder代理对象与句柄值handle相对应,并且这个Binder代理对象是有效的,因此,可以直接将它返回调用调用者。注意函数在将这个Binder代理对象返回给调用者之前,会减少它的弱引用计数,因为attemptIncWeek增加了弱应用计数。


下面我们分析下如何创建Binder代理对象,即new BpBinder(handle)究竟做了什么?

~/Android/frameworks/base/include/binder
----BpBinder.cpp

BpBinder::BpBinder(int32_t handle)    : mHandle(handle)//mHandle等于0    , mAlive(1)    , mObitsSent(0)    , mObituaries(NULL){    LOGV("Creating BpBinder %p handle %d\n", this, mHandle);    extendObjectLifetime(OBJECT_LIFETIME_WEAK);    IPCThreadState::self()->incWeakHandle(handle);//调用了IPCThreadState的成员函数self()}
又调用了IPCThreadState的成员函数self(),实现如下:

~/Android/frameworks/base/libs/binder

----IPCThreadState.cpp

IPCThreadState* IPCThreadState::self(){    if (gHaveTLS) {//第二次为truerestart:        const pthread_key_t k = gTLS;//利用第一次创建的gTLS        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);//获取IPCThreadState类,有pthread_getspecific(k),就一定有phread_setspecific;从线程本地存储空间获取对象        if (st) return st;        return new IPCThreadState;//构造函数中有phread_setspecific    }        if (gShutdown) return NULL;        pthread_mutex_lock(&gTLSMutex);    if (!gHaveTLS) {//第一次执行这里,创建了gTLS        if (pthread_key_create(&gTLS, threadDestructor) != 0) {//创建线程本地存储空间            pthread_mutex_unlock(&gTLSMutex);            return NULL;        }        gHaveTLS = true;//为第二次做准备    }    pthread_mutex_unlock(&gTLSMutex);    goto restart;//返回开头}
第一次,gHaveTLS为false,所以进入下面的代码,创建了gTLS,而且gHaveTLS为true。第二次gHaveTLS为true,利用第一次创建的gTLS,获取IPCThreadState类,如果获取不到,就创建该类,在创建该类的过程中,调用了phread_setspecific函数,new IPCThreadState实现如下:

~/Android/frameworks/base/libs/binder

----IPCThreadState.cpp

IPCThreadState::IPCThreadState()    : mProcess(ProcessState::self()),//因为单例模式,就是刚才创建的ProcessState对象      mMyThreadId(androidGetTid()),      mStrictModePolicy(0),      mLastTransactionBinderFlags(0){    pthread_setspecific(gTLS, this);//调用了这个函数,下次就是pthread_getspecific获取到了;将对象保存在线程本地存储空间    clearCaller();    mIn.setDataCapacity(256);//输入容量256    mOut.setDataCapacity(256);//输出容量256}

由于是单例模式,所以mProcess保存的就是刚刚创建的ProcessState对象。下次调用IPCThreadState::self只要在同一个线程中,就返回刚刚创建的IPCThreadState对象,因为每个线程有独一无二的gTLS。


开始执行incWeakHandle,参考博客http://blog.csdn.net/jltxgcy/article/details/27638717,此时Server进程等到下次使用IO控制命令BINDER_WRITE_READ进入到Binder驱动程序时,再请求Binder驱动程序增加相应的Binder引用对象的强引用计数和弱引用计数。



4、调用模板函数interface_cast<IServiceManager>将前面获得的Binder代理对象封装成一个Service Manager代理对象,因为#include <binder/IServiceManager.h>。IServiceManager.h包含了#include <binder/IInterface.h>,所以可以调用。

~/Android/frameworks/base/include/binder

----IInterface.h

template<typename INTERFACE>inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj){    return INTERFACE::asInterface(obj);}
由于INTERFACE为IServiceManger,所以展开如下:

template<typename IServiceManager>inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj){    return IServiceManager::asInterface(obj);//静态方法所以直接调用}
调用IServiceManager接口的成员函数asInterface,将一个句柄值为0的Binder代理对象封装为一个Service Manger代理对象。

IServiceManager接口的成员函数asInterface是通过宏IMPLEMENT_META_INTERFACE实现,如下所示:

~/Android/frameworks/base/libs/binder

----IServiceManager.cpp

IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
展开后如下:

android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj)                                              {                                                                                     android::sp<IServiceManager> intr;                                                    if (obj != NULL) {                                                                     intr = static_cast<IServiceManager*>(                                                                      obj->queryLocalInterface(IServiceManager::descriptor).get());//返回NULLif (intr == NULL) {                intr = new BpServiceManager(obj);  //创建了Service Manager代理对象                                      }                                          }return intr;                                  }   
参数obj指向一个Binder代理对象,即一个BpBinder对象,它的成员函数queryLocalInterface的返回值为NULL。因此,最后会创建一个Service Manager代理对象,即一个BpServiceManger对象,并且将它的IServiceManager接口返回给调用者。

uml类图如下:




BpBinder代理对象被保存在BpRefBase类的成员变量mRemote中。


三、目前为止各对象的引用计数

BpServiceManager受弱指针控制,ProcessState受强指针控制,BpBinder受弱指针控制。

static void instantiate(){defaultServiceManager()->addService(String16(FREG_SERVICE), new FregService());}
出了这个函数,sp<IServiceManager>的强引用计数为1,弱引用计数为1,指向了全局的变量。

sp<ProcessState>的强引用计数为1,弱引用计数为1,指向了全局的变量。

sp<IBinder>的强引用计数为1,弱引用计数为1,指向了刚刚new BpBinder(0),即FregServer进程的Binder代理对象。

因为如下代码:

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.    }}

更多相关文章

  1. 【翻译】(8-补丁1)Android接口定义语言(AIDL)
  2. Android应用程序键盘(Keyboard)消息处理机制分析(26)
  3. 【Fragment】 Android(安卓)Fragment生命周期详解(图文)
  4. 【Android】Android中的数据传递(2)
  5. android之wifi体系架构源码流程分析
  6. android通过程序收起通知栏
  7. Android(安卓)通过继承TextView类自定义字体默认颜色
  8. Android(安卓)ListView(Selector 背景图片 全选 Checkbox等按钮)
  9. view measure详解

随机推荐

  1. 方法数据库android轻量型数据库sqlite的
  2. android实现在线播放流媒体
  3. Andorid Dialog万能去黑边去白底方法
  4. android 实现支付宝及微信内部捐赠功能
  5. android 图片放大缩小 多点缩放
  6. Android(安卓)软引用内存缓存图片
  7. Android判断后台服务是否开启的两种方法
  8. 实现Android(安卓)获取cache缓存的目录路
  9. Android(安卓)开源控件系列_2
  10. Android中自制通讯录中显示出数据库中的