Binder源码分析之Native层(原)

来源:互联网 发布:文明太空mac版 编辑:程序博客网 时间:2024/05/21 15:44
        前面两节中介绍了Binder机制中的ServiceManagerBinder驱动,在这一节中,我们来介绍Native中的Binder通讯。

        为了更好的理解过程,我们挑选Native中的MediaServer进行分析。


一、MediaServer加载过程

        Android启动过程中会去执行init.rc脚本,在这个脚本中将会启动一些关键的系统服务,其中之一就是MediaServer:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @init.rc(google-code\system\core\rootdir\init.rc)  
  2. service media /system/bin/mediaserver  
  3.     class main  
  4.     user media  
  5.     group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc  
  6.     ioprio rt 4  
        这个脚本包含了几个重要信息:
        1、需要启动一个media的service,路径在/system/bin/mediaserver
        2、该服务的入口函数为main
        3、该服务运行在media的用户名下
        4、该服务属于以下组:audio camera inet等

        这些信息中,我们只关心service的名字(mediaserver)和入口函数(main),那么这个服务的入口函数究竟在那个文件里面呢?
        我们打开mediaserver模块,在模块的Android.mk文件中找到了这个Service的加载信息:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Android.mk(google-code\frameworks\av\media\mediaserver\)  
  2. LOCAL_PATH:= $(call my-dir)  
  3. include $(CLEAR_VARS)  
  4. LOCAL_SRC_FILES:= main_mediaserver.cpp   
  5. LOCAL_MODULE:= mediaserver  
        在这个脚本中,将main_mediaserver.cpp加载为mediaserver模块,因此,main_mediaserver.cpp文件就是我们要找的入口文件,而这个文件中的main函数就是我们要找的入口函数:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @main_mediaserver.cpp  
  2. int main(int argc, char** argv) {  
  3.     sp<ProcessState> proc(ProcessState::self());  
  4.     //得到ServiceManager  
  5.     sp<IServiceManager> sm = defaultServiceManager();  
  6.     //三个Service自身的初始化  
  7.     AudioFlinger::instantiate();  
  8.     MediaPlayerService::instantiate();  
  9.     CameraService::instantiate();  
  10.     AudioPolicyService::instantiate();  
  11.     ProcessState::self()->startThreadPool();  
  12.     IPCThreadState::self()->joinThreadPool();  
  13. }  

        下面我们就来详细看一下整个Service启动的流程。


二、ProcessState的初始化

        我们先来分析main中的第一步,也就是ProcessState::self()的过程。
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @ProcessState.cpp(google-code\frameworks\native\libs\binder\)  
  2. sp<ProcessState> ProcessState::self() {  
  3.     if (gProcess != NULL) return gProcess;  
  4.   
  5.     AutoMutex _l(gProcessMutex);  
  6.     if (gProcess == NULL) gProcess = new ProcessState;  
  7.     return gProcess;  
  8. }  
        这里我们看到,ProcessState是一个单例模式,所有的进程共享同一个ProcessState对象。如果初始化过了(gProcess!=NULL),就直接返回给客户端使用即可,没有的话需要创建ProcessState对象。这里我们假设当前没有被初始化过,那么就会调用他的构造函数:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. ProcessState::ProcessState()  
  2.     : mDriverFD(open_driver())  
  3.     , mVMStart(MAP_FAILED)  
  4.     , mManagesContexts(false)  
  5.     , mBinderContextCheckFunc(NULL)  
  6.     , mBinderContextUserData(NULL)  
  7.     , mThreadPoolStarted(false)  
  8.     , mThreadPoolSeq(1)   
  9. {  
  10.     if (mDriverFD >= 0) {  
  11.         //映射内存  
  12.         mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);  
  13.         if (mVMStart == MAP_FAILED) {  
  14.             close(mDriverFD);  
  15.             mDriverFD = -1;  
  16.         }  
  17.     }  
  18. }  
        在他的初始化过程中,主要完成了两个重要步骤:
        1、通过open_driver打开binder驱动,并把binder设备句柄传给mDriverFD
        2、通过mmap()将一块内核地址映射到用户空间,作为buffer传输数据

        由此,就完成了ProcessState的初始化工作。


三、得到ServiceManager代理对象的过程

        main函数的下一个动作就是要得到ServiceManager的对象:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. sp<IServiceManager> sm = defaultServiceManager();  
        那么是如何得到ServiceManager对象呢?得到的对象就是ServiceManager本身吗?我们从代码中找答案。
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @IServiceManager.cpp(google-code\frameworks\native\libs\binder\)  
  2. sp<IServiceManager> defaultServiceManager() {  
  3.     if (gDefaultServiceManager != NULL) return gDefaultServiceManager;  
  4.     AutoMutex _l(gDefaultServiceManagerLock);  
  5.     if (gDefaultServiceManager == NULL) {  
  6.         //得到ServiceManager  
  7.         gDefaultServiceManager = interface_cast<IServiceManager>( ProcessState::self()->getContextObject(NULL));  
  8.     }  
  9.     return gDefaultServiceManager;  
  10. }  
        这里我们发现,defaultServiceManager()也是单例模式,就是说,如果其他Service已经申请到了ServiceManager,其他Service就可以直接使用,这里我们假设是第一次申请,那么就要通过下面方法申请:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. gDefaultServiceManager = interface_cast<IServiceManager>( ProcessState::self()->getContextObject(NULL));  
        这个步骤稍微复杂,我们拆开分析:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. ProcessState::self()->getContextObject(NULL)  
  2. interface_cast<IServiceManager>()  

        上面第一步可以得到ServiceManager的BpBinder对象,第二步把得到的BpBinder对象转换为IServiceManager对象,下面我们逐步分析这两个过程。

3.1、得到ServiceManager的BpBinder对象

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. ProcessState::self()->getContextObject(NULL)  
        在第二节中我们介绍过,ProcessState::self()的过程就是完成ProcessState的初始化,然后返回ProcessState对象,因此,上面的代码相当于:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. ProcessState->getContextObject(NULL);  
        我们来看这个过程:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @ProcessState.cpp  
  2. sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller) {  
  3.     return getStrongProxyForHandle(0);  
  4. }  
        继续看getStrongProxyForHandle(),记住,传递下去的参数为0:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) {  
  2.     sp<IBinder> result;  
  3.     //从数组中查找handle_entry,不存在的话就创建一个  
  4.     handle_entry* e = lookupHandleLocked(handle);  
  5.     if (e != NULL) {  
  6.         IBinder* b = e->binder;  
  7.         if (b == NULL || !e->refs->attemptIncWeak(this)) {  
  8.             //new一个BpBinder返回给调用者  
  9.             b = new BpBinder(handle);   
  10.             e->binder = b;  
  11.             if (b) e->refs = b->getWeakRefs();  
  12.             result = b;  
  13.         } else {  
  14.             result.force_set(b);  
  15.             e->refs->decWeak(this);  
  16.         }  
  17.     }  
  18.     return result;  
  19. }  
        在这一步中,要先通过lookupHandleLocked()去查找当前handle的handle_entry对象,如果没有找到的话就会创建一个handle_entry,用于后续的Service使用,而且新建的handle_entry的binder变量为空,当前我们假设得到的就是新建的handle_entry对象,那么由于其e->binder为空,因此将会new一个BpBinder的对象作为其binder变量。
        这样一来,getStrongProxyForHandle()所返回的result就相当于我们刚刚new出来的BpBinder对象:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) {  
  2.     return new BpBinder(handle);   
  3. }  
        也就是说,我们通过getStrongProxyForHandle()得到的就是BpBinder对象,不仅如此,而且我们得到的是handle为0的BpBinder对象
        由此我们知道,通过:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. ProcessState::self()->getContextObject(NULL)  
        我们得到的是BpBinder(0)的对象。

        下面我们来看如何将这个对象转换为ServiceManager对象。

3.2、得到ServiceManager的BpServiceManager对象

        经过3.1的分析,我们可以将第三节中的:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. gDefaultServiceManager = interface_cast<IServiceManager>( ProcessState::self()->getContextObject(NULL));  
        转换为:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0));  
        下面我们来分析interface_cast是如何将BpBinder对象进行转换的。

3.2.1、函数模版转换

        我们先来看一下这个函数模版:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @IInterface.h(google-code\frameworks\native\include\binder\)  
  2. template<typename INTERFACE>  
  3. inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)  
  4. {  
  5.     return INTERFACE::asInterface(obj);  
  6. }  
        这里要补充一下函数模版的知识。上面这个函数组成了一个标准的函数模版功能。
            首先,他表示一个函数,这个函数名就叫interface_cast,参数必须是const类型的IBinder指针。
            其次,既然是“模版”,就说明他只提供了一个框架(或者一种形式),可以适应多种环境调用。
        具体来说就是,这个函数名叫interface_cast,调用这个函数必须传递进来一个IBinder的指针,但是他的返回值可以是不固定的,是根据传递进来的INTERFACE而定的。同时,返回值的具体值就是INTERFACE::asInterface(obj)。
        结合上面的代码来说,下面的语句:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0));  
        其实包含了4个信息:
            1、调用名叫interface_cast函数模版
            2、模版参数为IServiceManager
            3、函数参数为BpBinder(0)
            4、返回值赋值给了gDefaultServiceManager
        这样一来,这个函数模版就相当于:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. sp<IServiceManager> interface_cast(const sp<IBinder>& obj)  
  2. {  
  3.     return IServiceManager::asInterface(obj);  
  4. }  
        这里要求asInterface的参数obj是IBinder,而我们前面分析过我们得到的BpBinder对象就是IBinder类型的ServiceManager。因此,当初的:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0));  
        将会等价于:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. gDefaultServiceManager = IServiceManager::asInterface(BpBinder(0));  
        下面我们来看IServiceManager的asInterface()函数。

3.2.2、IServiceManager的asInterface函数

        在IServiceManager.cpp中我们并没有找到asInterface函数,但是在IServiceManager.h中却找到了一个宏控:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @IServiceManager.h  
  2. class IServiceManager : public IInterface {  
  3.     DECLARE_META_INTERFACE(ServiceManager);  
  4. };  
        我们查看这个宏控的定义:
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @IInterface.h(google-code\frameworks\native\include\binder\)  
  2. #define DECLARE_META_INTERFACE(INTERFACE)                               \  
  3.         static const android::String16 descriptor;                          \  
  4.         static android::sp<I##INTERFACE> asInterface(                       \  
  5.             const android::sp<android::IBinder>& obj);                  \  
  6.         virtual const android::String16& getInterfaceDescriptor() const;    \  
  7.         I##INTERFACE();                                                     \  
  8.         virtual ~I##INTERFACE();  
        这是一个宏定义可以看出,其中的asInterface()函数被宏定义为了:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static android::sp<I##INTERFACE> asInterface(const android::sp<android::IBinder>& obj);  
        替换掉INTERFACE可以得到:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static android::sp<IServiceManager> asInterface(const android::sp<android::IBinder>& obj);  
        也就是说,这段宏声明了asInterface函数,但是asInterface的定义呢?
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \  
  2.     const android::String16 I##INTERFACE::descriptor(NAME);             \  
  3.     const android::String16&                                            \  
  4.             I##INTERFACE::getInterfaceDescriptor() const {              \  
  5.         return I##INTERFACE::descriptor;                                \  
  6.     }                                                                   \  
  7.     android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \  
  8.             const android::sp<android::IBinder>& obj)                   \  
  9.     {                                                                   \  
  10.         android::sp<I##INTERFACE> intr;                                 \  
  11.         if (obj != NULL) {                                              \  
  12.             intr = static_cast<I##INTERFACE*>(                          \  
  13.                 obj->queryLocalInterface(                               \  
  14.                         I##INTERFACE::descriptor).get());               \  
  15.             if (intr == NULL) {                                         \  
  16.                 intr = new Bp##INTERFACE(obj);                          \  
  17.             }                                                           \  
  18.         }                                                               \  
  19.         return intr;                                                    \  
  20.     }                                                                   \  
  21.     I##INTERFACE::I##INTERFACE() { }                                    \  
  22.     I##INTERFACE::~I##INTERFACE() { }  
        这里面就包含了asInterface的定义:
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \  
  2.         const android::sp<android::IBinder>& obj)                   \  
  3. {                                                                   \  
  4.     android::sp<I##INTERFACE> intr;                                 \  
  5.     if (obj != NULL) {                                              \  
  6.         intr = static_cast<I##INTERFACE*>(                          \  
  7.             obj->queryLocalInterface(                               \  
  8.                     I##INTERFACE::descriptor).get());               \  
  9.         if (intr == NULL) {                                         \  
  10.             intr = new Bp##INTERFACE(obj);                          \  
  11.         }                                                           \  
  12.     }                                                               \  
  13.     return intr;                                                    \  
  14. }                                                                   \  
        同样的,我们替换掉INTERFACE,得到如下真实的定义:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. android::sp<IServiceManager> IServiceManager::asInterface( const android::sp<android::IBinder>& obj) {  
  2.     android::sp<IServiceManager> intr;  
  3.     if (obj != NULL) {  
  4.         intr = static_cast<IServiceManager*>(obj->queryLocalInterface(IServiceManager::descriptor).get());  
  5.         if (intr == NULL) {  
  6.             intr = new BpServiceManager(obj);  
  7.         }  
  8.     }  
  9.     return intr;  
  10. }  

        也就是说,经过函数模版的转换,我们得到的是BpServiceManager对象。而且初始化该对象时,我们传递了BpBinder(0)。

3.3、BpServiceManager

        经过上面3.1和3.2的分析,我们知道,通过defaultServiceManager()得到的是BpServiceManager对象,那么他是什么属性呢?功能又是什么呢?

3.3.1、继承关系

        我们先来看一下他的继承关系:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class BpServiceManager : public BpInterface<IServiceManager> { }  
        这说明BpInterface继承自BpInterface这个类模版(作用与函数模版类似)
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. template<typename INTERFACE>  
  2. class BpInterface : public INTERFACE, public BpRefBase { };  
        替换掉INTERFACE后得到:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class BpInterface : public IServiceManager, public BpRefBase { };  
        说明BpInterface继承了两个父类:IServiceManager和BpRefBase。

3.3.2、构造函数初始化过程

        下面我们再从BpServiceManager的构造函数来看他的初始化过程,在3.2节的最后我们分析到,创建BpServiceManager对象时,我们传递了BpBinder(0)作为参数,此时我们来看这样会发生什么。
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @IServiceManager.cpp  
  2. BpServiceManager(const sp<IBinder>& impl)  
  3.     : BpInterface<IServiceManager>(impl)  
  4. {  
  5. }  
        构造函数中会用BpBinder(0)初始化其父类BpInterface,我们来看其父类的构造函数:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. template<typename INTERFACE>  
  2. inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)  
  3.     : BpRefBase(remote)  
  4. {  
  5. }  
        这又是一个函数模版,其相当于:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. inline BpInterface<IServiceManager>::BpInterface(const sp<IBinder>& remote)  
  2.     : BpRefBase(remote)  
  3. {  
  4. }  
        我们看到,BpInterface的构造函数中又用BpBinder(0)去初始化其父类BpRefBase对象:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. BpRefBase::BpRefBase(const sp<IBinder>& o)  
  2.     : mRemote(o.get())  
  3.      , mRefs(NULL)  
  4.      , mState(0)  
  5. {  
  6.     extendObjectLifetime(OBJECT_LIFETIME_WEAK);  
  7.     if (mRemote) {  
  8.         mRemote->incStrong(this);           // Removed on first IncStrong().  
  9.         mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.  
  10.     }  
  11. }  
        在这里,我们又把BpBinder(0)这个对象传递给了BpRefBase对象的mRemote变量(并且增加这个对象的(指针的)强引用计数,这已属于SP/WP智能指针的知识范畴,我们不做详细分析)。
        经过两级父类传递,我们发现,BpServiceManager对象的初始化过程中,会把BpBinder(0)这个对象赋值给BpServiceManager的祖先类(其实是他的爷爷类)BpRefBase的mRemote变量
        这样做的作用我们待会儿就会明白。

3.3.3、成员函数

        前面分析了BpServiceManager的继承关系和构造函数初始化流程,下面我们来看一下他的成员函数。
        从继承关系上来讲,BpServiceManager既然继承了IServiceManager(他可是BpServiceManager的两个祖先类之一,另一个父类是BpRefBase),那么就应该实现IServiceManager所声明的所有虚函数,我们来看一下IServiceManager中的虚函数声明:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class IServiceManager : public IInterface {  
  2.     public:  
  3.         //这个宏定义已经分析过,其中包含asInterface的信息  
  4.         DECLARE_META_INTERFACE(ServiceManager);   
  5.         //得到一个Service  
  6.         virtual sp<IBinder> getService( const String16& name) const = 0;  
  7.         //检测Service  
  8.         virtual sp<IBinder> checkService( const String16& name) const = 0;  
  9.         //添加一个Service  
  10.         virtual status_t addService( const String16& name, const sp<IBinder>& service, bool allowIsolated = false) = 0;  
  11.         virtual Vector<String16> listServices() = 0;  
  12.   
  13.         enum {  
  14.             GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,  
  15.             CHECK_SERVICE_TRANSACTION,  
  16.             ADD_SERVICE_TRANSACTION,  
  17.             LIST_SERVICES_TRANSACTION,  
  18.         };  
  19. };  
        然后我们来看BpServiceManager的定义:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class BpServiceManager : public BpInterface<IServiceManager> {  
  2.     virtual sp<IBinder> getService(const String16& name) const{}  
  3.     virtual sp<IBinder> checkService( const String16& name) const{}  
  4.     virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated){}  
  5.     virtual Vector<String16> listServices(){}  
  6. };  
        正如我们所料,BpServiceManager确实实现了这些方法。通过这些方法,我们就可以对ServiceManager这一Service发送各种请求,比如得到、检查、添加一个Service。

3.3.4、BpServiceManager的作用

        经过上面的分析,我们现在来看一下BpServiceManager的作用。
        严格来说,我们通过defaultServiceManager()方法得到的并不是ServiceManager对象本身,而是得到了BpServiceManager对象,但是通过这个对象我们可以调用ServiceManager所暴露出来的各个方法,整个过程就像是直接调用ServiceManager一样,因此BpServiceManager对象的作用就是建立ServiceManager的“代理”,所有客户端对ServiceManager的请求,都需要通过BpServiceManager来“转达”。
        那么,为了得到BpServiceManager,我们经历了哪些步骤呢?
        首先,我们通过ProcessState::self()->getContextObject(NULL)得到了BpBinder(0)对象
        然后,我们用interface_cast<IServiceManager>(BpBinder(0))这个模版,将BpBinder(0)转换为IServiceManager类型的BpServiceManager对象

        下面用一张图来总结一下得到ServiceManager代理对象的过程:


   

 四、调用ServiceManager方法的过程

        上面我们分析了,通过defaultServiceManager()我们得到的是ServiceManager的代理对象:BpServiceManager,那么我们究竟是如何通过其代理调用到ServiceManager中的方法呢?
        在3.3中我们看到BpServiceManager中提供了ServiceManager的getService、addService、checkService等操作方法,下面我们挑选addService来分析,其余方法的调用过程都是类似的。

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @IServiceManager.cpp  
  2. virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated) {  
  3.     Parcel data, reply;  
  4.     data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());  
  5.     data.writeString16(name);  
  6.     data.writeStrongBinder(service);  
  7.     data.writeInt32(allowIsolated ? 1 : 0);  
  8.     status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);  
  9.     return err == NO_ERROR ? reply.readExceptionCode() : err;  
  10. }  
        我们看到,在ADD_SERVICE_TRANSACTION中,把要添加的Service的名字和IBinder对象放入Parcel类型的data中,然后调用remote()函数发送出去,同时标记当前数据的作用是ADD_SERVICE_TRANSACTION。
        那么,这里的remote()是什么呢?
        这要看remote()函数的定义了,他的定义在BpServiceManager的父类BpRefBase中:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Binder.h  
  2. inline  IBinder* remote() {  
  3.     return mRemote;   
  4. }  
        原来remote()在内部把mRemote返回了出来。
        现在回顾一下,我们在分析BpServiceManager初始化时分析道,BpBinder(0)这个对象最终是给了BpServiceManager的父类BpRefBase的mRemote成员变量,而此时我们通过remote()函数得到的对象应该就是BpBinder(0)这个对象。
        也就是说,在addService()中调用remote()->transact()的结果就相当于:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. BpBinder(0)->transact()  
        现在我们再回到BpBinder中继续分析:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @BpBinder.cpp  
  2. status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {  
  3.     if (mAlive) {  
  4.         //转移到IPCThreadState中的transact  
  5.         status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags);  
  6.         if (status == DEAD_OBJECT) mAlive = 0;  
  7.         return status;  
  8.     }  
  9.     return DEAD_OBJECT;  
  10. }  
        在这里又把transact()转移到了IPCThreadState中的transact(),并且此时的handle为0:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. status_t IPCThreadState::transact(int32_t handle,uint32_t code,const Parcel& data,Parcel* reply,uint32_t flags) {  
  2.     status_t err = data.errorCheck();  
  3.     flags |= TF_ACCEPT_FDS;  
  4.     if (err == NO_ERROR) {  
  5.         //封装数据  
  6.         err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);  
  7.     }  
  8.     if ((flags & TF_ONE_WAY) == 0) {  
  9.         if (reply) {  
  10.             err = waitForResponse(reply);  
  11.         } else {  
  12.             Parcel fakeReply;  
  13.             err = waitForResponse(&fakeReply);  
  14.         }  
  15.     } else {  
  16.         err = waitForResponse(NULL, NULL);  
  17.     }  
  18.     return err;  
  19. }  
        在transact()中,先通过errorCheck()检查数据错误信息,然后通过writeTransactionData()封装数据,最后通过waitForResponse()把数据发送出去。
        我们先来看封装数据的过程:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer) {  
  2.     binder_transaction_data tr;  
  3.     tr.target.handle = handle;  
  4.     tr.code = code;  
  5.     tr.flags = binderFlags;  
  6.     tr.cookie = 0;  
  7.     tr.sender_pid = 0;  
  8.     tr.sender_euid = 0;  
  9.     //错误检测  
  10.     const status_t err = data.errorCheck();  
  11.     if (err == NO_ERROR) {  
  12.         tr.data_size = data.ipcDataSize();  
  13.         tr.data.ptr.buffer = data.ipcData();  
  14.         tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);  
  15.         tr.data.ptr.offsets = data.ipcObjects();  
  16.     } else if (statusBuffer) {  
  17.         tr.flags |= TF_STATUS_CODE;  
  18.         *statusBuffer = err;  
  19.         tr.data_size = sizeof(status_t);  
  20.         tr.data.ptr.buffer = statusBuffer;  
  21.         tr.offsets_size = 0;  
  22.         tr.data.ptr.offsets = NULL;  
  23.     } else {  
  24.         return (mLastError = err);  
  25.     }  
  26.     //这里的cmd内容是BC_TRANSACTION  
  27.     mOut.writeInt32(cmd);  
  28.     mOut.write(&tr, sizeof(tr));  
  29.   
  30.     return NO_ERROR;  
  31. }  
        原来,数据封装的结果就是把在mOut中写入两个数据:命令和内容。在这里,命令就是BC_TRANSACTION,而数据就是“addService”。
        然后我们来看发送的过程:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) {  
  2.     int32_t cmd;  
  3.     while (1) {  
  4.         //发送数据  
  5.         if ((err=talkWithDriver()) < NO_ERROR) break;  
  6.         //检测接收的数据有效性  
  7.         err = mIn.errorCheck();  
  8.         if (err < NO_ERROR) break;  
  9.         if (mIn.dataAvail() == 0continue;  
  10.         //得到返回数据的内容  
  11.         cmd = mIn.readInt32();  
  12.         //根据返回命令做不同处理  
  13.         switch (cmd) {  
  14.             case BR_TRANSACTION_COMPLETE:  
  15.             case BR_DEAD_REPLY:  
  16.             case BR_FAILED_REPLY:  
  17.             case BR_ACQUIRE_RESULT:  
  18.             case BR_REPLY:  
  19.             default:  
  20.         }  
  21.     }  
  22.     return err;  
  23. }  
        发送数据是通过talkWithDriver()来完成的:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @IPCThreadState.cpp  
  2. status_t IPCThreadState::talkWithDriver(bool doReceive) {  
  3.     binder_write_read bwr;  
  4.     const bool needRead = mIn.dataPosition() >= mIn.dataSize();  
  5.     const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;  
  6.     //准备写入的数据  
  7.     bwr.write_size = outAvail;  
  8.     bwr.write_buffer = (long unsigned int)mOut.data();  
  9.   
  10.     if (doReceive && needRead) {  
  11.         //准备要读取的数据  
  12.         bwr.read_size = mIn.dataCapacity();  
  13.         bwr.read_buffer = (long unsigned int)mIn.data();  
  14.     } else {  
  15.         bwr.read_size = 0;  
  16.         bwr.read_buffer = 0;  
  17.     }  
  18.   
  19.     bwr.write_consumed = 0;  
  20.     bwr.read_consumed = 0;  
  21.     status_t err;  
  22.     do {  
  23.         //通过ioctl发送和接收数据  
  24.         if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)  
  25.             err = NO_ERROR;  
  26.         else  
  27.             err = -errno;  
  28.     } while (err == -EINTR);  
  29.     if (err >= NO_ERROR) {  
  30.         if (bwr.write_consumed > 0) {  
  31.             //清空mOut  
  32.             if (bwr.write_consumed < (ssize_t)mOut.dataSize())  
  33.                 mOut.remove(0, bwr.write_consumed);  
  34.             else  
  35.                 mOut.setDataSize(0);  
  36.         }  
  37.         //把返回值放入mIn中  
  38.         if (bwr.read_consumed > 0) {  
  39.             mIn.setDataSize(bwr.read_consumed);  
  40.             mIn.setDataPosition(0);  
  41.         }  
  42.         return NO_ERROR;  
  43.     }  
  44.     return err;  
  45. }  
        我们看到,在talkWithDriver()中构建了binder_write_read类型的数据,并把要写入的命令从mOut拿出放入write_buffer中,并准备read_buffer用来接收数据。最终通过ioctl()的方式与远程Binder进行数据交互。
        数据交互完成之后,就把mOut中内容删除,并把拿到的bwr中的read_buffer内容放入mIn和reply中。
        由此就同时完成了数据的读写操作
        以上就是addService()的过程,下面我们对比一下getService()的过程:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. virtual sp<IBinder> getService(const String16& name) const {  
  2.     unsigned n;  
  3.     for (n = 0; n < 5; n++){  
  4.         //调用了checkService()  
  5.         sp<IBinder> svc = checkService(name);  
  6.         if (svc != NULL) return svc;  
  7.         sleep(1);  
  8.     }  
  9.     return NULL;  
  10. }  
        继续看checkService()过程:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. virtual sp<IBinder> checkService( const String16& name) const {  
  2.     Parcel data, reply;  
  3.     data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());  
  4.     data.writeString16(name);  
  5.     //传输数据  
  6.     remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);  
  7.     //得到回应  
  8.     return reply.readStrongBinder();  
  9. }  
        我们看到,整个过程和addService()的类型是极其相似的,不同的是,在调用remote()的transact()时发送的是CHECK_SERVICE_TRANSACTION命令。而且在transact()函数之后,我们从reply中读取了返回值。而这个返回值就是我们要得到的远程Service的IBinder对象。
        下面我们小节一下通过BpServiceManager对象调用ServiceManager对象方法的过程:
        1、在BpServiceManager中的各项操作均转换为remote()->transact()方法,然后标记不同的命令,比如add、check、get等。
        2、remote()得到的其实就是mRemote变量,而这个变量就是当初构建BpServiceManager时传递进来的BpBinder(0)。
        3、在BpBinder对象的transact函数中,将会调用IPCThreadState的transact()方法,并且标明目标Service的handle(当前为0)
        4、在IPCThreadState的transact中先通过writeTransactionData把数据封装,封装的内容包括目标Service(当前就是0号Service),最后把封装后的数据放入mOut中
        5、在IPCThreadState的transact中接着逐步调用waitForResponse()和talkWithDriver()最终调用ioctl()将数据发送到远程的ServiceManager进程

        下面我们用图来小结一下本节的要点:



五、MediaPlayerService的初始化过程

        现在我们再回到最初的main中。

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int main(int argc, char** argv) {  
  2.     //ProcessState初始化  
  3.     sp<ProcessState> proc(ProcessState::self());  
  4.     //得到ServiceManager的IServiceManager对象  
  5.     sp<IServiceManager> sm = defaultServiceManager();  
  6.     AudioFlinger::instantiate();  
  7.     MediaPlayerService::instantiate();  
  8.     CameraService::instantiate();  
  9.     AudioPolicyService::instantiate();  
  10.     ProcessState::self()->startThreadPool();  
  11.     IPCThreadState::self()->joinThreadPool();  
  12. }  
        在前面的分析过程中,我们完成了ProcessState的初始化、并得到了ServiceManager的代理对象BpServiceManager,接下来是对AudioFlinger、MediaPlayerService、CameraService、AudioFlinger四个服务的初始化过程,由于这些Service本身不属于本文讨论的范围,因此我们挑选MediaPlayerService来简要看一下其初始化的流程。
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @MediaPlayerService.cpp(google-code\frameworks\av\media\libmediaplayerservice\)  
  2. void MediaPlayerService::instantiate() {  
  3.     defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService());  
  4. }  
        我们看到,MediaPlayerService初始化的过程就是把自己注册为"media.player"Service的过程,同时把MediaPlayerService对象传递给ServiceManager。
        下面我们来看一下MediaPlayerService对象的本质。
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class MediaPlayerService : public BnMediaPlayerService{}  
        上面的继承关系说明,MediaPlayerService是BnMediaPlayerService的子类,我们再来看BnMediaPlayerService的属性:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class BnMediaPlayerService: public BnInterface<IMediaPlayerService>{}  
        然后看BnInterface模版的定义:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @IInterface.h  
  2. template<typename INTERFACE>  
  3. class BnInterface : public INTERFACE, public BBinder { };  
        从继承关系上我们看出,BnInterface模版实现了双继承,其同时继承了BBinder和INTERFACE,而BBinder就是IBinder的子类:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class BBinder : public IBinder{}  

        也就是说,作为一个Service,向ServiceManager注册自己时,需要把继承自IXXXService和BBinder的传递给ServiceManager,注册完自己,Service就需要搭建自己的循环机制去检测客户端的请求了。


六、Service的线程池机制

        在上面的过程中,我们完成了ProcessState的初始化,得到了ServiceManager的代理对象,又完成了MediaPlayerService等服务的初始化,下面要做的就是搭建一个线程池用于扫描和处理客户端的请求。
        搭建线程池的过程可以从以下两步中体现:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. ProcessState::self()->startThreadPool();  
  2. IPCThreadState::self()->joinThreadPool();  
        我们先来看一下ProcessState的startThreadPool()方法:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @ProcessState.cpp  
  2. void ProcessState::startThreadPool() {  
  3.     AutoMutex _l(mLock);  
  4.     if (!mThreadPoolStarted) {  
  5.         mThreadPoolStarted = true;  
  6.         spawnPooledThread(true);  
  7.     }  
  8. }  
        我们来看spawnPooledThread(),需要注意,传进去的参数为true:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. void ProcessState::spawnPooledThread(bool isMain) {  
  2.     if (mThreadPoolStarted) {  
  3.         int32_t s = android_atomic_add(1, &mThreadPoolSeq);  
  4.         char buf[16];  
  5.         snprintf(buf, sizeof(buf), "Binder_%X", s);  
  6.         sp<Thread> t = new PoolThread(isMain);  
  7.         t->run(buf);  
  8.     }  
  9. }  
        在spawnPooledThread()中创建了一个线程(PoolThread)并运行,我们来看这个线程:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @ProcessState.cpp  
  2. class PoolThread : public Thread {  
  3.     public:  
  4.         PoolThread(bool isMain)  
  5.             : mIsMain(isMain)  
  6.         {  
  7.         }  
  8.   
  9.     protected:  
  10.         virtual bool threadLoop()  
  11.         {  
  12.             IPCThreadState::self()->joinThreadPool(mIsMain);  
  13.             return false;  
  14.         }  
  15.         const bool mIsMain;  
  16. };  
        这里可以看到,在startThreadPool()的内部,创建了一个新的线程,并在线程中调用IPCThreadState的joinThreadPool()方法。而在main函数的最后也是调用的IPCThreadState的joinThreadPool()方法,这就说明,搭建消息检测机制是在IPCThreadState的joinThreadPool()中实现的,下面我们就来看其具体过程。
        下面我们就来看这个方法的具体作用。

6.1、IPCThreadState的初始化过程

        为了弄明白IPCThreadState的joinThreadPool()方法,我们要先简要介绍一下IPCThreadState这个类。
        首先,他与ProcessState一样,都是单例模型,但是ProcessState是进程级别的,每个进程拥有同一个ProcessState,而IPCThreadState是线程级别的,每个线程拥有同一个IPCThreadState对象。
        其次,从作用上来讲,ProcessState的作用是打开Binder驱动并映射虚拟地址,而IPCThreadState的作用则是构建循环机制扫描客户端对服务端的请求,并把具体请求发给服务端处理,同时给客户端提供返回值。
        下面我们先来看IPCThreadState的初始化流程:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @IPCThreadState.cpp(google-code\frameworks\native\libs\binder\)  
  2. IPCThreadState* IPCThreadState::self() {  
  3.     //第一次调用gHaveTLS为false  
  4.     if (gHaveTLS) {  
  5. restart:  
  6.         const pthread_key_t k = gTLS;  
  7.         //当前线程再次获取IPCThreadState时,可以用key取出当前线程的IPCThreadState对象  
  8.         IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);  
  9.         if (st) return st;  
  10.         return new IPCThreadState;  
  11.     }  
  12.   
  13.     if (gShutdown) return NULL;  
  14.   
  15.     pthread_mutex_lock(&gTLSMutex);  
  16.     if (!gHaveTLS) {  
  17.         //创建当前线程的key  
  18.         if (pthread_key_create(&gTLS, threadDestructor) != 0) {  
  19.             pthread_mutex_unlock(&gTLSMutex);  
  20.             return NULL;  
  21.         }  
  22.         gHaveTLS = true;  
  23.     }  
  24.     pthread_mutex_unlock(&gTLSMutex);  
  25.     goto restart;  
  26. }  
        再来看其构造函数:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. IPCThreadState::IPCThreadState()  
  2.     : mProcess(ProcessState::self()),  
  3.     mMyThreadId(androidGetTid()),  
  4.     mStrictModePolicy(0),  
  5.     mLastTransactionBinderFlags(0)  
  6. {  
  7.     //把当前的IPCThreadState对象保存在key中  
  8.     pthread_setspecific(gTLS, this);  
  9.     clearCaller();  
  10.     mIn.setDataCapacity(256);  
  11.     mOut.setDataCapacity(256);  
  12. }  
        从上面初始化流程中可以看出IPCThreadState是单例模式。简要来说,一个线程第一次调用IPCThreadState时,由于gHaveTLS变量为false,因此会通过pthread_key_create创建当前线程的key,并在IPCThreadState的构造函数中,把当前new出来的IPCThreadState对象保存在key中,下次当前线程再调用IPCThreadState时,可以通过key将IPCThreadState对象取出来使用,以保证同一个线程只能拥有一份IPCThreadState对象。
        到这里,就完成了IPCThreadState对象的初始化过程,在这个过程中主要完成了两个重要的操作:
        1、初始化ProcessState对象,并将对象作为IPCThreadState的mProcess
        2、初始化mIn和mOut,他们是与Binder驱动交换数据用的buffer,并且设置buffer的大小为256

6.2、IPCThreadState建立消息循环过程

        前面说过,IPCThreadState的joinThreadPool()方法负责搭建消息循环机制。并且调用这个函数需要传递一个bool型的变量isMain,该变量标志着当前的IPCThreadState消息循环是否作为主循环在运作,在消息轮询的过程中,如果发生了超时的错误,非主循环将会退出,而主循环将会继续运行。
        现在回顾一下,在ProcessState中我们建立PoolThread线程并运行时,该线程调用的joinThreadPool()时传递的参数就是true。而我们在main_mediaserver.cpp中直接调用IPCThreadState的joinThreadPool()时没有传递参数,也就是为false。
        这就说明,在整个Service的初始化流程中,有两个线程拥有IPCThreadState并通过joinThreadPool()建立了消息的轮询机制,而且在ProcessState中建立的循环是主循环。
        下面我们来看具体的过程。
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @IPCThreadState.cpp  
  2. void IPCThreadState::joinThreadPool(bool isMain) {  
  3.     //向Binder驱动发送命令,要进入/注册 Loop状态了  
  4.     mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);  
  5.     status_t result;  
  6.     do {  
  7.         int32_t cmd;  
  8.         //清除接收缓存,准备接收数据  
  9.         if (mIn.dataPosition() >= mIn.dataSize()) {  
  10.             size_t numPending = mPendingWeakDerefs.size();  
  11.             if (numPending > 0) {  
  12.                 for (size_t i = 0; i < numPending; i++) {  
  13.                     RefBase::weakref_type* refs = mPendingWeakDerefs[i];  
  14.                     refs->decWeak(mProcess.get());  
  15.                 }  
  16.                 mPendingWeakDerefs.clear();  
  17.             }  
  18.             numPending = mPendingStrongDerefs.size();  
  19.             if (numPending > 0) {  
  20.                 for (size_t i = 0; i < numPending; i++) {  
  21.                     BBinder* obj = mPendingStrongDerefs[i];  
  22.                     obj->decStrong(mProcess.get());  
  23.                 }  
  24.                 mPendingStrongDerefs.clear();  
  25.             }  
  26.         }  
  27.   
  28.         //与Binder交换数据,发送命令并读取返回值  
  29.         result = talkWithDriver();  
  30.         if (result >= NO_ERROR) {  
  31.             size_t IN = mIn.dataAvail();  
  32.             if (IN < sizeof(int32_t)) continue;  
  33.             cmd = mIn.readInt32();  
  34.             //处理返回值  
  35.             result = executeCommand(cmd);  
  36.         }  
  37.   
  38.         if(result == TIMED_OUT && !isMain) {  
  39.             break;  
  40.         }  
  41.     } while (result != -ECONNREFUSED && result != -EBADF);  
  42.   
  43.     //退出Loop状态   
  44.     mOut.writeInt32(BC_EXIT_LOOPER);  
  45.     talkWithDriver(false);  
  46. }  
        在上面这个过程中,主要执行逻辑在于while-do循环中,在这个循环体中,先清除接收缓存,然后通过talkWithDriver向Binder发送/接收数据,最后再去解析(executeCommand)得到的返回值。而在进入while-do之前,需要告诉Binder自己需要进入/注册Loop状态,并在while-do之后,告诉Binder自己退出了Loop的状态。
        下面我们详细分析一下得到数据和处理数据的过程。

6.2.1、从Binder读取数据

        从Binder驱动读取数据是在talkWithDriver()中完成的,其实在3.3.4节中介绍BpServiceManager作用时就介绍过这个方法,其作用就是把mOut中的内容发送到Binder驱动中,同时把读取的数据放入mIn中。
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. status_t IPCThreadState::talkWithDriver(bool doReceive) {  
  2.     //确认Binder已经打开  
  3.     if (mProcess->mDriverFD <= 0) {  
  4.         return -EBADF;  
  5.     }  
  6.       
  7.     binder_write_read bwr;  
  8.     const bool needRead = mIn.dataPosition() >= mIn.dataSize();  
  9.     const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;  
  10.     bwr.write_size = outAvail;  
  11.     bwr.write_buffer = (long unsigned int)mOut.data();  
  12.     if (doReceive && needRead) {  
  13.         //准备接收缓存  
  14.         bwr.read_size = mIn.dataCapacity();  
  15.         bwr.read_buffer = (long unsigned int)mIn.data();  
  16.     } else {  
  17.         bwr.read_size = 0;  
  18.         bwr.read_buffer = 0;  
  19.     }  
  20.     if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;  
  21.   
  22.     bwr.write_consumed = 0;  
  23.     bwr.read_consumed = 0;  
  24.     status_t err;  
  25.     do {  
  26.         //通过ioctl()与Binder交换数据  
  27.         if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)  
  28.             err = NO_ERROR;  
  29.         else  
  30.             err = -errno;  
  31.         if (mProcess->mDriverFD <= 0) {  
  32.             err = -EBADF;  
  33.         }  
  34.     } while (err == -EINTR);  
  35.   
  36.     if (err >= NO_ERROR) {  
  37.         if (bwr.write_consumed > 0) {  
  38.             if (bwr.write_consumed < (ssize_t)mOut.dataSize())  
  39.                 mOut.remove(0, bwr.write_consumed);  
  40.             else  
  41.                 mOut.setDataSize(0);  
  42.         }  
  43.         //将接收数据放入mIn中  
  44.         if (bwr.read_consumed > 0) {  
  45.             mIn.setDataSize(bwr.read_consumed);  
  46.             mIn.setDataPosition(0);  
  47.         }  
  48.         return NO_ERROR;  
  49.     }  
  50.     return err;  
  51. }  
        整个数据交换过程还是比较清晰的,就是通过ioctl()来完成的。下面来看数据的处理过程,其要处理的数据是放在mIn中的。

6.2.2、IPCThreadState把数据转移给相应的Service过程

        经过上面的talkWithDriver()方法,就把数据读取到了mIn缓存中,接下来IPCThreadState将会把从Binder得到的请求通过executeCommand()转发给相应的Service。
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. status_t IPCThreadState::executeCommand(int32_t cmd) {  
  2.     BBinder* obj;  
  3.     RefBase::weakref_type* refs;  
  4.     status_t result = NO_ERROR;  
  5.   
  6.     switch (cmd) {  
  7.         case BR_ERROR: break;  
  8.         case BR_OK: break;  
  9.         case BR_ACQUIRE: break;  
  10.         case BR_RELEASE: break;  
  11.         case BR_INCREFS: break;  
  12.         case BR_DECREFS: break;  
  13.         case BR_ATTEMPT_ACQUIRE: break;  
  14.         case BR_TRANSACTION: break;  
  15.         case BR_DEAD_BINDER: break;  
  16.         case BR_CLEAR_DEATH_NOTIFICATION_DONE: break;  
  17.         case BR_FINISHED: break;  
  18.         case BR_NOOP: break;  
  19.         case BR_SPAWN_LOOPER: break;  
  20.         defaultbreak;  
  21.     }  
  22.     return result;  
  23. }  
        这里的分支分为两个重要的部分,一部分是BR_ACQUIRE、BR_RELEASE、BR_INCREFS、BR_DEAD_BINDER四个消息,主要作用是通过调用相应对象的incStrong、incWeak等方法添加或减少相应智能指针的引用计数。
        另外一个部分就是BR_TRANSACTION消息的处理。这里要特别说明一下,与ServiceManager类似,其他Service的客户端在得到Service的远程代理对象之后调用的所有方法都会转换成代理对象(BpXXXService)的transact()方法,经过BpBinder的传递,最终调用到IPCThreadState的transact()方法,在IPCThreadState的transact()内部将数据封装,而封装的过程就是把所有请求打包为BC_TRANSACTION消息发送到Binder驱动,并在数据内部标记当初客户端调用的是Service的哪个方法。
        因此这里拿到的mIn中数据的cmd将会是BR_TRANSACTION。
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. status_t IPCThreadState::executeCommand(int32_t cmd) {  
  2.     BBinder* obj;  
  3.     RefBase::weakref_type* refs;  
  4.     status_t result = NO_ERROR;  
  5.   
  6.     switch (cmd) {  
  7.         case BR_ERROR: break;  
  8.         case BR_OK: break;  
  9.         case BR_ACQUIRE: break;  
  10.         case BR_RELEASE: break;  
  11.         case BR_INCREFS: break;  
  12.         case BR_DECREFS: break;  
  13.         case BR_ATTEMPT_ACQUIRE: break;  
  14.         case BR_TRANSACTION: {  
  15.              binder_transaction_data tr;  
  16.              //读取从Binder驱动得到的客户端请求数据,并放到tr中  
  17.              result = mIn.read(&tr, sizeof(tr));  
  18.              if (result != NO_ERROR) break;  
  19.   
  20.              Parcel buffer;  
  21.              //将tr数据封装到Parcel型的buffer中  
  22.              buffer.ipcSetDataReference(  
  23.                      reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),  
  24.                      tr.data_size,  
  25.                      reinterpret_cast<const size_t*>(tr.data.ptr.offsets),  
  26.                      tr.offsets_size/sizeof(size_t), freeBuffer, this);  
  27.   
  28.              const pid_t origPid = mCallingPid;  
  29.              const uid_t origUid = mCallingUid;  
  30.   
  31.              //记录当前客户端的进程信息  
  32.              mCallingPid = tr.sender_pid;  
  33.              mCallingUid = tr.sender_euid;  
  34.              int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);  
  35.              if (gDisableBackgroundScheduling) {  
  36.                  if (curPrio > ANDROID_PRIORITY_NORMAL) {  
  37.                      //设置线程优先级  
  38.                      setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);  
  39.                  }  
  40.              } else {  
  41.                  if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {  
  42.                      set_sched_policy(mMyThreadId, SP_BACKGROUND);  
  43.                  }  
  44.              }  
  45.   
  46.              Parcel reply;  
  47.              if (tr.target.ptr) {  
  48.                  sp<BBinder> b((BBinder*)tr.cookie);  
  49.                  //把数据转交给相应Service  
  50.                  const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);  
  51.                  if (error < NO_ERROR) reply.setError(error);  
  52.   
  53.              } else {  
  54.                  const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);  
  55.                  if (error < NO_ERROR) reply.setError(error);  
  56.              }  
  57.   
  58.   
  59.              if ((tr.flags & TF_ONE_WAY) == 0) {  
  60.                  sendReply(reply, 0);  
  61.              } else {  
  62.                  LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);  
  63.              }  
  64.   
  65.              mCallingPid = origPid;  
  66.              mCallingUid = origUid;  
  67.          }  
  68.          break;  
  69.         defaultbreak;  
  70.     }  
  71.     return result;  
  72. }  
        在这个过程中,我们发现IPCThreadState把从mIn读取的tr型数据重新封装到Parcel类型的buffer中之后,调用目标Service的BBinder对象的transact()函数将数据转交给相应的Service。
        那么这个BBinder对象和目标Service有什么关系呢?
        我们再来看一下Service把自己注册给ServiceManager时传递的参数:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. defaultServiceManager()->addService(String16("media.player"), new MediaPlayerService());  
        从上面的我们看到在调用addService()时,把MediaPlayerService对象传递给了ServiceManager,并且在第五节中分析过,这个MediaPlayerService对象的本质是IMediaPlayerService和BBinder的子类,因此这里得到的BBinder就是MediaPlayerService的父类对象。
        由此,我们看到了完整的IPCThreadState中消息循环的流程,简单来说就是:
        1、在joinThreadPool()中搭建do-while死循环
        2、while循环中通过talkWithDriver()从Binder驱动读取客户端请求

        3、while循环中得到请求后,调用executeCommand将客户端请求重新打包成Parcel数据发送给Service的BBinder对象

6.3、Service处理数据的过程

        上一节我们看到,IPCThreadState是把数据交给了Service的BBinder对象,这一节中我们将会分析BBinder如何把数据转移给相应的Service对象本身。
        我们直接来看BBinder的transact()方法的实现。
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Binder.cpp(google-code\frameworks\native\libs\binder\)  
  2. status_t BBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {  
  3.     data.setDataPosition(0);  
  4.     status_t err = NO_ERROR;  
  5.     switch (code) {  
  6.         case PING_TRANSACTION:  
  7.             reply->writeInt32(pingBinder());  
  8.         break;  
  9.         default:  
  10.             //调用onTransact方法  
  11.             err = onTransact(code, data, reply, flags);  
  12.         break;  
  13.     }  
  14.     if (reply != NULL) {  
  15.         reply->setDataPosition(0);  
  16.     }  
  17.     return err;  
  18. }  
        在transact()内部调用了onTransact()的方法,而这里的onTransact()方法被BBinder的子类BnMediaPlayerService所实现:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @IMediaPlayerService.cpp(google-code\frameworks\av\media\libmedia\)  
  2. status_t BnMediaPlayerService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {  
  3.     switch (code) {  
  4.     case CREATE: { } break;  
  5.     case DECODE_URL: { } break;  
  6.     case DECODE_FD: { } break;  
  7.     case CREATE_MEDIA_RECORDER: { } break;  
  8.     case CREATE_METADATA_RETRIEVER: { } break;  
  9.     case GET_OMX: { } break;  
  10.     case MAKE_CRYPTO: { } break;  
  11.     case MAKE_HDCP: { } break;  
  12.     case ADD_BATTERY_DATA: { } break;  
  13.     case PULL_BATTERY_DATA: { } break;  
  14.     case LISTEN_FOR_REMOTE_DISPLAY: { } break;  
  15.     defaultreturn BBinder::onTransact(code, data, reply, flags);  
  16.     }  
  17. }  
        至此,BBinder对象就把对Service的请求发送给了BnMediaPlayerService,接下来我们挑选一个case继续跟踪:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. status_t BnMediaPlayerService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {  
  2.     switch (code) {  
  3.     case CREATE: {  
  4.             //权限检查  
  5.             CHECK_INTERFACE(IMediaPlayerService, data, reply);  
  6.             //得到调用者的pid  
  7.             pid_t pid = data.readInt32();  
  8.             sp<IMediaPlayerClient> client = interface_cast<IMediaPlayerClient>(data.readStrongBinder());  
  9.             int audioSessionId = data.readInt32();  
  10.             //调用create()  
  11.             sp<IMediaPlayer> player = create(pid, client, audioSessionId);  
  12.             reply->writeStrongBinder(player->asBinder());  
  13.             return NO_ERROR;  
  14.         } break;  
  15.     }  
  16. }  
        在CREATE分支的内部,调用了create()方法,由于MediaPlayerService是BnMediaPlayerService的子类,因此create()方法是在BnMediaPlayerService中实现的:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @MediaPlayerService.cpp(google-code\frameworks\av\media\libmediaplayerservice\)  
  2. sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId) {  
  3.     int32_t connId = android_atomic_inc(&mNextConnId);  
  4.     //创建客户端对象  
  5.     sp<Client> c = new Client(this,pid,connId,client,audioSessionId,IPCThreadState::self()->getCallingUid());  
  6.     //把客户端对象返回给申请者  
  7.     return c;  
  8. }  
        在create()内部,MediaPlayerService将会常见一个client的对象返回给申请者。
        至此,IPCThreadState的消息机制就把一个客户端的请求从Binder驱动拿到后,完整的交给了Service并由Service完成了所有的处理。
        但是,这只是跨进程的“远端”操作部分,那么近端的流程是怎样的呢?

        也就是说,一个客户端是如何把请求发送到Binder驱动呢?


七、客户端发送请求的过程

        其实我们在前面介绍MediaPlayerService向ServiceManager注册自己的过程中,就可以看到客户端发送请求的过程。
        因为对于ServiceManager来说,刚刚我们分析的MediaPlayerService对象就是他的客户端之一,而MediaPlayerService发起的addService()的请求过程就是一个典型的客户端对服务端请求的过程。
        但为了理顺思路,我们重新来分析一下作为MediaPlayerService的客户端,是如何将请求发送到Binder驱动的。
        在stream.cpp的main()中我们找到了MediaPlayerService的客户端用法:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @stream.cpp(google-code\frameworks\av\cmds\stagefright\stream.cpp)  
  2. int main(int argc, char **argv) {  
  3.     sp<IServiceManager> sm = defaultServiceManager();  
  4.     sp<IBinder> binder = sm->getService(String16("media.player"));  
  5.     sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);  
  6.     sp<IMediaPlayer> player = service->create(getpid(), client, 0);  
  7. }  
        在这个main中,通过getService()得到了MediaPlayerService的远程代理对象binder,然后经过interface_cast模版转换成IMediaPlayer类型的service,最后调用其create()方法。
        我们需要在以下分析过程中,解决2个疑问:
        1、客户端是如何得到Service的远程代理对象的

        2、调用代理对象service的方法,是如何发送到binder驱动的

7.1、客户端得到Service的远程代理对象

        我们用两个步骤得到了Service的远程代理对象:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. sp<IBinder> binder = sm->getService(String16("media.player"));  
  2. sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);  
        下面我们先来看一下通过ServiceManager的getService()方法得到的binder对象究竟是什么属性。
        在前面我们已经分析过,通过defaultServiceManager()得到的是BpServiceManager对象,他是ServiceManager的代理对象,那么这里的getService()就应该是在BpServiceManager中:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @IServiceManager.cpp  
  2. virtual sp<IBinder> getService(const String16& name) const  
  3. {  
  4.     unsigned n;  
  5.     for (n = 0; n < 5; n++){  
  6.         //调用checkService()方法  
  7.         sp<IBinder> svc = checkService(name);  
  8.         if (svc != NULL) return svc;  
  9.         sleep(1);  
  10.     }  
  11.     return NULL;  
  12. }  
        在getService()的内部调用了checkService()方法,并把返回值给了客户端,来看checkService():
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. virtual sp<IBinder> checkService( const String16& name) const  
  2. {  
  3.     Parcel data, reply;  
  4.     data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());  
  5.     data.writeString16(name);  
  6.     //调用ServiceManager的CHECK_SERVICE_TRANSACTION命令  
  7.     remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);  
  8.     return reply.readStrongBinder();  
  9. }  
        我们看到,客户端得到的对象需要经过两步:
        1、remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
        2、reply.readStrongBinder();
        下面我们逐步来分析。

7.1.1、得到ServiceManager的返回值

        在前面的分析中我们应该熟悉remote()->transact()这个过程。
        其实就是调用BpBinder(0)对象的transact()方法,并间接调用到IPCThreadState的transact()方法,然后经过IPCThreadState封装数据后,把Parcel类型的数据发送到binder驱动中。同时在binder驱动的另一侧,ServiceManager将会通过svcmgr_handler()方法去处理所有的请求,而对于CHECK_SERVICE_TRANSACTION这个请求,其具体操作如下:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @service_manager.c  
  2. int svcmgr_handler(struct binder_state *bs,struct binder_txn *txn,struct binder_io *msg,struct binder_io *reply){  
  3.     switch(txn->code) {  
  4.         case SVC_MGR_GET_SERVICE:  
  5.         case SVC_MGR_CHECK_SERVICE:  
  6.             s = bio_get_string16(msg, &len);  
  7.             //查找目标Service  
  8.             ptr = do_find_service(bs, s, len, txn->sender_euid);  
  9.             if (!ptr)  
  10.                 break;  
  11.             //构建返回值  
  12.             bio_put_ref(reply, ptr);  
  13.             return 0;  
  14.         case SVC_MGR_ADD_SERVICE:  
  15.         case SVC_MGR_LIST_SERVICES:  
  16.         default:  
  17.     }  
  18.     return 0;  
  19. }  
        我们看到,对于“得到一个Service”这样的请求,ServiceManager会先通过do_find_service()去查找目标Service,然后通过bio_put_ref()构建返回值,我们直接来看其构建的返回值:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @binder.c  
  2. void bio_put_ref(struct binder_io *bio, void *ptr) {  
  3.     struct binder_object *obj;  
  4.     if (ptr)  
  5.         //分配结构体内存  
  6.         obj = bio_alloc_obj(bio);  
  7.     else  
  8.         obj = bio_alloc(bio, sizeof(*obj));  
  9.   
  10.     if (!obj)  
  11.         return;  
  12.   
  13.     obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;  
  14.     //标记类型为BINDER_TYPE_HANDLE  
  15.     obj->type = BINDER_TYPE_HANDLE;  
  16.     obj->pointer = ptr;  
  17.     obj->cookie = 0;  
  18. }  
        记得,这里标记的返回值type是BINDER_TYPE_HANDLE。
        到这里,ServiceManager就完成了他的任务,接下来将会再次经过Binder驱动,把返回值数据经过IPCThreadState返回给BpServiceManager,这就是我们通过BpServiceManager的remote()->transact()得到的数据。

7.1.2、用ServiceManager的返回值构建BpBinder对象

        得到ServiceManager的数据之后,这一步需要把数据解析成客户端可用的IBinder类型的对象。
        我们来看reply.readStrongBinder()的细节:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Parcel.cpp  
  2. sp<IBinder> Parcel::readStrongBinder() const {  
  3.     sp<IBinder> val;  
  4.     unflatten_binder(ProcessState::self(), *this, &val);  
  5.     return val;  
  6. }  
        看来在Parcel中是通过unflatten_binder()去生成IBinder对象的:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. status_t unflatten_binder(const sp<ProcessState>& proc, const Parcel& in, sp<IBinder>* out) {  
  2.     //读取ServiceManager给出的返回值  
  3.     const flat_binder_object* flat = in.readObject(false);  
  4.     if (flat) {  
  5.         switch (flat->type) {  
  6.             case BINDER_TYPE_BINDER:  
  7.                 *out = static_cast<IBinder*>(flat->cookie);  
  8.                 return finish_unflatten_binder(NULL, *flat, in);  
  9.             case BINDER_TYPE_HANDLE:  
  10.                 //在ServiceManager构建返回值时用的就是这个type  
  11.                 *out = proc->getStrongProxyForHandle(flat->handle);  
  12.                 return finish_unflatten_binder( static_cast<BpBinder*>(out->get()), *flat, in);  
  13.         }          
  14.     }  
  15.     return BAD_TYPE;  
  16. }  
        在Parcel解析ServiceManager返回值的过程中,需要根据返回值的类型去做不同的操作,我们在7.1.1的bio_put_ref()方法中看到,当初标记的type是BINDER_TYPE_HANDLE,因此Parcel将会利用ProcessState继续解析返回值:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @ProcessState.cpp  
  2. sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) {  
  3.     sp<IBinder> result;  
  4.     //先去查找,看有没有目标Service的缓存  
  5.     handle_entry* e = lookupHandleLocked(handle);  
  6.     if (e != NULL) {  
  7.         IBinder* b = e->binder;  
  8.         if (b == NULL || !e->refs->attemptIncWeak(this)) {  
  9.             //看到了吧,客户端得到的是IBinder对象其实就是BpBinder对象  
  10.             b = new BpBinder(handle);   
  11.             e->binder = b;  
  12.             if (b) e->refs = b->getWeakRefs();  
  13.             result = b;  
  14.         } else {  
  15.             result.force_set(b);  
  16.             e->refs->decWeak(this);  
  17.         }  
  18.     }  
  19.     return result;  
  20. }      
        到这里,我们终于找到了客户端得到的IBinder类型数据,就是BpBinder对象!
        也就是说,我们通过ServiceManager去得到的所有Service对象,都是BpBinder对象,而不同的Service的BpBinder对象的handle是不同的。
        联系到ServiceManager的分析,每个Service注册自己的时候,ServiceManager都将为其分配不同的id,而客户端申请得到某个Service的时候,就是用目标Service的id生成的不同BpBinder对象。

7.1.3、利用BpBinder得到BpMediaPlayerService对象

        现在我们得到了IBinder类型的BpBinder对象,但是客户端拿到这个对象还不能直接调用到相应Service的方法,需要经过interface_cast的转换才可以使用。并且这个函数模版在3.2节已经介绍的很清晰,经过interface_cast的转换,我们将会得到相应的BpXXXService对象。对于当前环境来说,得到的就是BpMediaPlayerService对象。

7.2、如何通过代理对象将请求发送到Binder驱动

        经过7.1节的介绍,客户端得到了MediaPlayerService的BpMediaPlayerService对象,然后就可以调用其中的方法了,下面我们就来看调用其create()方法后,如何将请求发送到Binder驱动。
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @IMediaPlayerService.cpp(google-code\frameworks\av\media\libmedia\IMediaPlayerService.cpp)  
  2. virtual sp<IMediaPlayer> create( pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId) {  
  3.     Parcel data, reply;  
  4.     data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());  
  5.     data.writeInt32(pid);  
  6.     data.writeStrongBinder(client->asBinder());  
  7.     data.writeInt32(audioSessionId);  
  8.   
  9.     //调用BpBinder的transact()  
  10.     remote()->transact(CREATE, data, &reply);  
  11.     return interface_cast<IMediaPlayer>(reply.readStrongBinder());  
  12. }  
        这里我们再次强调,客户端得到BpMediaPlayerService对象之后,无论调用其任何方法,都将会被封装为Parcel类型的数据,然后用remote()->transact()这种形式发送,并通过transact()不同参数来区分不同的方法,而且这里的remote()就是相应的BpBinder对象。
        接下来的过程就是第四节中介绍的步骤了,BpBinder会在transact()中调用IPCThreadState的transact(),IPCThreadState接着在transact()内部经过waitForResponse()-->talkWithDriver()-->ioctl()将数据发送到Binder驱动中。
        发送到Binder驱动之后,MediaPlayerService将会在IPCThreadState的joinThreadPool中检测到该请求,然后就是第六节中介绍的Service端处理数据的过程了。
        下面我们结合第六节中的消息循环来看一下从客户端到服务端整个数据流的过程:



八、总结

        现在我们来总结一下整个数据传输的过程:
    1、一个Service向ServiceManager注册自己的时候,需要向ServiceManager传递2个数据:name+BnXXXService
        这个BnXXXService是双继承结构,同时继承了IMediaPlayerService和BBinder
        ServiceManager会针对该Service生成一个ID,也就是handle值
    2、客户端向ServiceManager申请Service代理对象的时候,将会得到目标Service的BpBinder对象
        ServiceManager只负责把相应Service的handle值返回出来
        BpServiceManager得到handle之后,经过Parcel的解析,调用到ProcessState的getStrongProxyForHandle()
        而ProcessState将会在getStrongProxyForHandle()中利用得到的handle创建目标Service的BpBinder(handle)对象
        如果要得到的目标Service就是ServiceManager,那么其handle值就是0
    3、然后客户端用interface_cast<IXXXService>的模版将BpBinder对象转换为BpXXXService对象
        interface_cast的函数模版转换的原理是在内部调用IMediaPlayerService的asInterface()方法
        而asInterface()方法的结果就是用得到的BpBinder对象作为参数,去创建BpXXXService的对象
        而BpXXXService的构造函数中会把BpBinder暂存在其祖先类BpRefBase的mRemote变量中
    4、客户端拿到BpXXXService对象之后,可以调用IXXXService中的各种方法
        客户端无论调用哪个方法,都会调用到remote()->transact()方法,只是参数不同而已
        而remote()所返回的就是BpXXXService祖先类中暂存的BpBinder对象
        调用BpBinder的transact()方法将会调用到IPCThreadState的transact()方法
        IPCThreadState的transact()调用writeTransactionData()将客户端的请求封装到mOut中,然后经过waitForResponse()和talkWithDriver()最终调用ioctl()将请求发送到Binder驱动中
    5、服务端的IPCThreadState通过内部建立的joinThreadPool()循环机制不断检测客户端请求
        得到请求后调用executeCommand()和BR_TRANSACTION的case分支,将请求发送到服务侧所注册的BBinder对象的transact()方法
        调用BBinder的transact()将会在内部调用到onTransact()方法,并且这个方法是在BBinder的子类BnXXXService所实现
        BnXXXService内部的onTransact()构建了switc语句来处理各种请求,而各个请求所调用的方法,都会在子类中实现
        而BnXXXService的子类就是MediaPlayerService本身

        完


原文地址:http://blog.csdn.net/u010961631/article/details/20922145

0 0
原创粉丝点击