zoukankan      html  css  js  c++  java
  • 深入分析AndroidBinder机制(远程对象访问)

    介绍

    Binder是什么?它可以叫作:IPC、RPC、线程迁移、远程对象访问,本文中理解它为远程对象访问更贴切些,简而言之就是一个进程能访问另一个进程中的对象,调用该对象的方法,就好像对象在自己的进程中一样,这种访问是同步的访问,当然Binder也能实现异步的通信。

    Binder基于C/S架构:

    Binder分为Java和C++两套实现,分别用于Java应用和Native应用开发,Java Binder实际上也是基于C++ Binder的一个封装,因此本文只分析C++ Binder。

    服务分为2种:Native Service、Android Service。

    Native Service:是在系统init阶段通过init.rc脚本建立的服务,完全在C++空间完成的服务。

    Androids service:是系统二阶段(init2)初始化时建立的服务,是指在JVM空间完成的服务,虽然也要使用Navite上的框架,但是服务主体存在于Android空间,所有的Androids service都运行在一个进程中:systemsever进程。

    实现原理

    Binder本质上说就是一种数据传输方式,当通过服务代理调用服务对象的方法时,服务代理把参数序列化进行传输,服务对象反序列化取出参数,然后调用服务对象的方法。

    进程间的通信是通过Android专门为Linux增加的一个设备(/dev/binder)来实现的。

    本质上是使用了共享内存来进行通信,但该共享内存和我们平常理解会有一点不一样。

    我们平常使用的共享内存是两个进程之间,即点到点的,如果有N个进程要两两通信而又不相互干扰,那么就必须有N*N个共享内存。Binder使用的共享内存是进程与binder设备之间,即binder做为一个中间者进行传递,类似会议电视的MCU。

    使用了共享内存,在驱动中还是会有一次拷贝的,进程A向进程B传递数据时,数据会被驱动从进程A中拷贝到binder和进程B之间的共享内存中,然后进程B就可以直接读了。

    通信过程:

    所有要进行通信的进程都得打开/dev/binder设备

    binder设备驱动会为每个进程分配一个数据结构binder_proc,每进程中的每个用到了binder通信的线程分配数据结构binder_thread。

    binder设备驱动会为服务进程中的每个服务对象分配数据结构binder_node,它隶属于服务进程的binder_proc,是服务端相关的,binder_node中记录了服务对象在服务进程中的地址;会为客户进程中引用的每个服务分配binder_ref,是客户端相关的,binder_ref会指向客户进程引用的服务对象的binder_node。

    binder设备驱动为客户进程引用的每个服务都会维护一个handle,它存在于binder_ref中(binder_ref.desc),它就像进程打开某个文件产生的文件描述符一样,进程每引用一个服务,就会分配一个最小未使用的整数作为handle。handle是客户进程相关的,多个进程引用同一个服务得到的handle并不是一样的。

    当服务进程向ServiceManager注册服务时,会带上服务的名称字符串,驱动会为服务进程中的服务对象增加一个binder_node,归属于服务进程的binder_proc。

    当把注册服务的请求发给ServiceManager时,ServiceManager也是服务对象的一个引用者,驱动会为ServiceManager增加一个binder_ref,指向服务对象的binder_node。驱动把binder_ref.desc(ServiceManager)作为handle返回给ServiceManager,ServiceManager保存此handle和服务名称字符串。

    当客户进程向ServiceManager获取服务时,ServiceManager根据服务名称字符串找到服务对象在ServiceManager进程中的handle。在ServiceManager的应答的过程中,驱动根据此handle在ServiceManager进程的binder_proc找到对应的binder_ref,并根据它找到服务对象的binder_node。然后,驱动会为客户进程增加一个binder_ref,指向服务对象的binder_node,最后把binder_ref.desc(客户进程)作为handle返回给客户进程。

    客户进程使用得到的handle向服务进程发起请求,驱动会在根据此handle在客户进程的binder_proc查找对应的binder_ref,并找到它指向的binder_node,并找到binder_node所属的binder_proc,最终驱动把请求放入服务进程的接收队列中。

    服务进程收到请求后,从binder_node中找到服务对象的地址,然后调用该服务对象。所以,对于服务对象,在客户进程中表现出来的是handle,在服务进程中表现出来的是地址,驱动会对它们进行映射。

    Binder框架

    概览

    框架的层次结构:

    说明:

    Bn代表服务端,Bp代表代理

    ProcessState、IPCThreadState是进程、线程相关,是对Binder驱动的封装

    Binder核心库又是对ProcessState、IPCThreadState的封装

    C++ Binder框架是对Binder核心库和服务接口的封装

    类关系图:

    `

    说明:绿色部分是用户编写应用程序需要实现的

    IPCThreadState、ProcessState、Binder关系图:

     

    对于Binder核心库:

    IBinder:是一个接口,被BpBinder、Bbinder继承

    BpBinder:客户端,内部有一个成员mHandle记录了远程服务对象的handle

    BpRefBase:客户端,内部有一个成员指向BpBinder,采用的是Bridge设计模式,实际是是通过BpBinder来完成通信

    Bbinder:服务端

    对于C++ Binder框架:

    Iinterface:主要是定义了asBinder()、纯虚函数onAsBinder(),asBinder()直接调用onAsBinder(),onAsBinder()分别在BnInterface、BpInterface中进行了实现,用于获取BnInterface、BpBinder的地址,即IInterface的作用是通过接口获取对应的Binder对象的本地地址/代理BpBinder的地址。

    BpInterface<XXX>:是一个接口,一个模板类,是一个粘合类,即继承BpInterface<XXX>便等同于同时继承IXXX和BpRefBase。

    BnInterface<XXX>:是一个接口,一个模板类,是一个粘合类

    对于用户实现:

    IXXX:是一个接口类,继承IInterface,定义服务的方法,即纯虚函数method_1()等,不能被实例化

    BpXXX:是一个实现类,实现了IXXX中的纯虚函数,因为不是接口类,这个实现类不需要在接口中体现(即不需要在接口的头文件中体现,如:IMediaPlayer.h),它封装了IXXX的操作和BpBinder的操作;

    BnXXX:仍是一个接口类,未实现IXXX中的纯虚函数,不能被实例化,需要一个真正工作的类来继承、实现它,这个类才是真正执行具体功能的类。BnXXX仅实现了虚函数onTransact()(在BBinder::transact()被调用)。

    XXX:实现BnXXX,会有一个XXX::instantiate()函数来注册服务。

    Binder驱动

    源代码:

    kerneldriversstagingandroidinder.h

    kerneldriversstagingandroidinder.c

    参见下文驱动源代码的分析

    Binder Adapter

    源代码:

    frameworksaseincludeinderIPCThreadState.h

    frameworksaseincludeinderProcessState.h

    frameworksaselibsinderIPCThreadState.cpp

    frameworksaselibsinderProcessState.cpp

    ProcessState

    一个进程只有一个ProcessState对象,主要用于打开/dev/binder,设置设备支持的最大线程数,进行内存映射,把binder设备文件的句柄保存在mDriverFD以供IPCThreadState使用。维护进程中所有的Service代理(BpBinder对象)和其对应的handle(Binder驱动为每个Service维护一个handle,对handle的操作封装在ProcessState中维护的BpBinder对象中)

    ProcessState是singleton模式,使用静态成员函数ProcessState::self()来构造。

    构造函数:

    ProcessState::ProcessState()

    {

         mDriverFD(open_driver())  //打开binder设备

            open("/dev/binder", O_RDWR);

           ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);  //最大线程数设为15,保存在binder_proc.max_threads

         mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE |  MAP_NORESERVE, mDriverFD, 0); //内存映射,只读,用于接收transactions

    }

    ProcessState::getStrongProxyForHandle()

    作用:为Service的handle创建BpBinder对象。主要在Parcel::readStrongBinder()、ProcessState::getContextObject()中调用。

    sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t  handle)

    {

         sp<IBinder> result;

         AutoMutex _l(mLock);     //互斥锁,在ProcessState::expungeHandle()也有调用

    // 查询Service代理对象列表,如果未代理对象未创建,将在列表中增加相应位置,以保存下面将要创建的代理对象

    handle_entry* e = lookupHandleLocked(handle);

         if (e != NULL) {

             // 1、BpBinder对象在创建时设置了RefBase标志:OBJECT_LIFETIME_WEAK。并且重写了RefBase的虚方法:onFirstRef()、onLastStrongRef()。

             // 2、创建的BpBinder对象在该函数中,只是记录它的地址和它的引用记录的地址,未记录下它的强引用/弱引用

             // 3、调用attemptIncWeak()是安全的,假设BpBinder对象因为弱引用计数减为0而调用BpBinder析构函数(参见:RefBase::weakref_type::decWeak()),该析构函数中要调用ProcessState::expungeHandle(),而expungeHandle()要获取本函数中相同的互斥锁mLock,然后把e->binder置为NULL。所以,如果下面的代码e->binder不为NULL,expungeHandle()也无法执行把它置成NULL,析构函数也就无法完成,对象的空间也不会释放,e->refs指向的空间就是有效的。但此时对象的引用计数可能为0,这样调用attemptIncWeak()会失败,当析构函数完成后,对象的空间会被释放,所以就要重新创建一个对象。

             IBinder* b = e->binder;

             if (b == NULL || !e->refs->attemptIncWeak(this)) { //如果弱引用计数为0,则attemptIncWeak()返回失败

                b = new BpBinder(handle);

                e->binder = b;

                if (b) e->refs = b->getWeakRefs();   // e->refs是e->binder的引用记录的地址

                result = b;

             } else {

                // 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);     //调用的是 RefBase::forceIncStrong(),其中会调用BpBinder重写的onFirstRef()

                e->refs->decWeak(this);  //抵消上面的e->refs->attemptIncWeak()的增加

             }

         }

         return result;

    }

    ProcessState::startThreadPool()

    只启动一次,它直接调用ProcessState::spawnPooledThread(true),创建PoolThread对象并调用PoolThread::run()(实际上就创建了一个线程,没看到线程池的概念),PoolThread继承自Thread,实际上调用的是Thread::run(),其中创建线程函数_threadLoop(),其中调用PoolThread::threadLoop(),其中调用IPCThreadState::self()->joinThreadPool(mIsMain);,此处mIsMain==true,即表示进入looper

    IPCThreadState

    每个线程都有一个IPCThreadState对象,它有一个成员变量mProcess指向它所属的ProcessState对象,它主要负责Binder数据读写和命令处理,客户端调用transact(),服务端调用joinThreadPool()。

    IPCThreadState是singleton模式,使用静态成员函数IPCThreadState::self()来构造。

    构造函数:

    IPCThreadState::IPCThreadState()

    {

         mProcess(ProcessState::self())

         mMyThreadId(androidGetTid())       //调用gettid()或getpid(),返回pid_t,所以线程也是当成轻量级里程看待的

         pthread_setspecific(gTLS, this);   //设置线程私有数据,把IPCThreadState关联到全局静态变量gTLS(Thread Local Storage),而gTLS在IPCThreadState::self()中创建和获取,与gTLS关联的私有数据释放函数为IPCThreadState::threadDestructor(),当线程退出时调用该函数,其中又调用ioctl(self->mProcess->mDriverFD,  BINDER_THREAD_EXIT, 0);

    }

    transact():BpBinder实际上调用的是IPCThreadState::transact(),先调用writeTransactionData()构造数据,再调用waitForResponse()写入数据并等待应答

    talkWithDriver():读取/写入,调用ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr),把IPCThreadState::mOut(Parcel)中包含的binder_transaction_data封装成binder_write_read写到驱动,从驱动读取到的binder_write_read中包含的binder_transaction_data写到IPCThreadState::mIn(Parcel)

    executeCommand():BR_***命令处理,对于BR_TRANSACTION,会调用BBinder::transact()。在joinThreadPool()、waitForResponse()中调用

    joinThreadPool():循环结构,调用talkWithDriver()读取命令,然后调用executeCommand()处理。函数名为加入线程池,更准确地说是调用binder_get_thread()在进程的内核数据中分配了一个binder_thread

    writeTransactionData():把用户的Parcel先转换成binder_transaction_data,再把binder_transaction_data写入IPCThreadState::mOut(也是Parcel),仅用来构造mOut。在transact()、sendReply()中调用

    waitForResponse():写入命令并等待应答,先调用talkWithDriver()写入/读取,然后再处理BR_***

    Binder核心库

    源代码:

    frameworksaseincludeinderBinder.h

    frameworksaseincludeinderBpBinder.h

    frameworksaseincludeinderIBinder.h

    frameworksaselibsinderBinder.cpp

    frameworksaselibsinderBpBinder.cpp

    BpBinder

    在ProcessState::getStrongProxyForHandle()创建,创建时会记录下Service的handle,并增加句柄的引用计数(IPCThreadState::self()->incWeakHandle(handle);)

    构造函数

    参数为服务的handle

    BpBinder::BpBinder(int32_t handle)

         : mHandle(handle)

    {

         extendObjectLifetime(OBJECT_LIFETIME_WEAK); 

         IPCThreadState::self()->incWeakHandle(handle); 

    }

           IPCThreadState::incWeakHandle()就是向驱动写入了一个BC_INCREFS命令。

    BpBinder::transact()

    向服务端发送数据,实际上是调用IPCThreadState::transact()来实现。

    BpBinder::transact()

    {

    IPCThreadState::self()->transact(mHandle,...)     // mHandle在ProcessState::getStrongProxyForHandle()创建BpBinder时设置

    IPCThreadState::writeTransactionData(BC_TRANSACTION,...)    //构造写入数据

                IPCThreadState::waitForResponse()                      //写入命令并等待应答

                     IPCThreadState::talkWithDriver                       //写入和读取

                      ioctl(mProcess->mDriverFD,  BINDER_WRITE_READ, &bwr)

                  // 处理BR_REPLY,...等命令

    }

    BpRefBase

    采用Bridge设计模式,它的构造函数中有一个参数sp<IBinder>,它有一个成员mRemote指向BpBinder,实际的通信工作是通过BpBinder来完成的。

    对于一个服务对象,在进程中只有一个BpBinder,但可以有多个BpRefBase引用这个BpBinder

    构造函数

    参数为BpBinder

    BpRefBase::BpRefBase(const sp<IBinder>&  o)

         : mRemote(o.get()), mRefs(NULL), mState(0)

    {

         if (mRemote) {

             mRemote->incStrong(this);            // Removed on first IncStrong().

             mRefs = mRemote->createWeak(this);   // Held for our entire lifetime.

         }

    }

    BBinder

    IPCThreadState收到请求后,调用IPCThreadState::executeCommand()处理请求,其中会调用服务对象的BBinder::transact()方法,BBinder::transact()中又继续调用BBinder派生类BnXXX重写的onTransact()方法

    Parcel

    Parcel顾名思义:邮包,即是应用程序通过binder通信所使用的数据容器。

    两个重要的函数:Parcel::writeStrongBinder()、Parcel::readStrongBinder(),它们中会调用ProcessState::self()打开设备

    Parcel::writeStrongBinder(constsp<IBinder>& val)

    发送请求时,将binder信息写入Parcel

    Parcel::writeStrongBinder()

    //输入BpBinder或BBinder,构造flat_binder_object

    {

         flat_binder_object obj;

         flatten_binder(ProcessState::self(), val, this);

             IBinder *local = binder->localBinder();         // localBinder()被IBinder定义且实现(返回NULL),被BBinder重写(返回this)

             if (!local) {     //参数是BpBinder,传递服务代理信息,客户端A把它得到的服务对象的BpBinder告诉客户端B,客户端B不查询ServiceManager也能使用服务,实现服务信息共享

                BpBinder *proxy = binder->remoteBinder();   // remoteBinder()被IBinder定义且实现(返回NULL),被BpBinder重写(返回this)

                const int32_t handle = proxy ?  proxy->handle() : 0;

                obj.type = BINDER_TYPE_HANDLE;

                obj.handle = handle;     //服务对象的handle

                obj.cookie = NULL;

             } else {          //参数是BBinder,传递服务对象信息

                obj.type = BINDER_TYPE_BINDER;

                obj.binder = local->getWeakRefs();  //服务对象的引用记录的地址

                obj.cookie = local;      //服务对象的地址

             }

             finish_flatten_binder()      //把flat_binder_object写到Parcel.mObjects缓冲区,在驱动传输的过程中(binder_transaction()),为创建binder_node、binder_ref

                Parcel::writeObject()

    }

    Parcel::readStrongBinder()

    接收应答时,从Parcel取出binder信息

    Parcel::readStrongBinder()

    //返回BpBinder或BBinder,会把handle转换成BpBinder

    {

         unflatten_binder(ProcessState::self(), *this, &val);

             Parcel::readObject()              //从Parcel.mObjects缓冲区读取flat_binder_object

             switch (flat->type) {             //读取结构  flat_binder_object

                case BINDER_TYPE_BINDER:     //客户端和服务在同一进程,返回BBinder

                    *out = static_cast<IBinder*>(flat->cookie);

                case BINDER_TYPE_HANDLE:     //客户端和服务不在同一进程,返回BpBinder

                    *out = proc->getStrongProxyForHandle(flat->handle);

    }

    C++ Binder框架

    源代码:

    frameworksaseincludeinderIInterface.h

    frameworksaseincludeinderParcel.h

    frameworksaselibsinderIInterface.cpp

    frameworksaselibsinderParcel.cpp

    IInterface

    IInterface::asBinder()

    asBinder()直接调用纯虚函数IInterface::onAsBinder(),onAsBinder()分别在BnInterface、BpInterface中进行了实现,用于获取BnInterface、BpBinder的地址,即IInterface的作用是通过接口获取对应的Binder对象的本地地址/代理BpBinder的地址

    sp<IBinder> IInterface::asBinder()

    {

         return this ? onAsBinder() : NULL;

    }

    template<typename INTERFACE>

    IBinder* BnInterface<INTERFACE>::onAsBinder()

    {

         return this;

    }

    template<typename INTERFACE>

    inline IBinder* BpInterface<INTERFACE>::onAsBinder()

    {

         return remote();

    }

    BpInterface<XXX>

    构造函数

    参数为BpBinder

    template<typename INTERFACE>

    inline BpInterface<INTERFACE>::BpInterface(const  sp<IBinder>& remote)

         : BpRefBase(remote)

    {

    }

    interface_cast<XXX>(constsp<IBinder>& obj)

    看名字就知道它是一个进行类型转换的函数,前面根据handle创建了BpBinder,进而创建了BpBinder,接下来就是要利用模板函数interface_cast<XXX>()根据BpBinder创建BpXXX。

    函数的参数可以是BpBinder或BBinder,返回的是BpXXX或BnXXX。

    template<typename INTERFACE>

    inline sp<INTERFACE> interface_cast(const  sp<IBinder>& obj)

    {

         return INTERFACE::asInterface(obj);

    }

           函数直接调用了IXXX::asInterface(),它是通过宏DECLARE_META_INTERFACE、IMPLEMENT_META_INTERFACE来声明和实现的。

    DECLARE_META_INTERFACE、IMPLEMENT_META_INTERFACE

    在IXXX类的声明中,调用DECLARE_META_INTERFACE(XXX);,在IXXX类的实现中,调用IMPLEMENT_META_INTERFACE(XXX, "接口名称");

    其中关键的实现为:

    #define  IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                      

         ...

         android::sp<I##INTERFACE> I##INTERFACE::asInterface(                

                const android::sp<android::IBinder>&  obj)                  

         {                                                                   

             android::sp<I##INTERFACE> intr;                                

             if (obj != NULL) {                                              

                intr = static_cast<I##INTERFACE*>(                         

                    obj->queryLocalInterface(                              

                            I##INTERFACE::descriptor).get());               

                if (intr == NULL) {                                        

                    intr = new Bp##INTERFACE(obj);                         

                }                                                           

             }                                                               

             return intr;                                                    

         }                                                                   

    注释:

    IBinder定义并实现了虚函数queryLocalInterface()(为空函数直接返回NULL),BpBinder继承IBinder但未重写该虚函数,BnInterface继承BBinder继承IBinder,重写了该函数(if (_descriptor ==INTERFACE::descriptor) return this;),所以,如果asInterface()的参数为BpBinder,那么每次调用都会创建一个BpXXX,如果参数为BBinder,只是直接返回BBinder对象的地址,作用是在同一个进程中调用Binder将直接得到BBinder对象的地址。调用者无需要关心调用的对象是远程的还是本地的

    参数NAME只是接口的名字,无实质作用,和服务的名字不是一回事

    实现服务

    参考代码:

    frameworksaseincludemediaIMediaPlayerService.h

    frameworksasemedialibmediaIMediaPlayerService.cpp

    frameworksasemedialibmediaplayerserviceMediaPlayerService.h

    frameworksasemedialibmediaplayerserviceMediaPlayerService.cpp

    编码

    IXXX.h:

    定义class IXXX:public IInterface:
    调用宏DECLARE_META_INTERFACE(XXX);;
    定义一系列接口用到的纯虚函数,如:method_1()、method_2()

    定义class BnXXX:public BnInterface<IXXX>:
    重写onTransact()

    IXXX.cpp:

    定义class BpXXX:public BpInterface<IXXX>:
    构造函数中调用BpInterface<IXXX >(impl);
    调用宏IMPLEMENT_META_INTERFACE(XXX,"android.xxx.IXXX");;
    实现接口的方法(其中调用remote()->transact)

    实现BnXXX::onTransact():
    重写onTransact(),其中调用由BnXXX派生类XXX实现的接口方法

    XXX.h、XXX.cpp:

    定义class XXX:public BnXXX
    实现接口的方法

    BpXXX

    构造函数

    参数为BpBinder,BpXXX的构造函数中有一个参数sp<IBinder>& impl,说明它采用了Bridge模式,BpBinder是它的实现。

    BpXXX(const sp<IBinder>& impl)

         : BpInterface<IXXX>(impl)

    {

    }

    BpXXX::method_1()

    该函数内不执行具体的操作,只是把请求发给服务端

    virtual void method_1(int id)

    {

         Parcel data, reply;

         data.writeInt32(id);  //构造发送数据

         remote()->transact(CMD_METHOD_1, data, &reply);  // CMD_METHOD_1是发送的命令

    }

    BpXXX继承BpRefBase,BpRefBase定义了成员函数remote(),该函数返回的实际上就是BpBinder,然后调用BpBinder::transact()发送数据

    BnXXX

    BnXXX::onTransact()

    BnXXX::onTransact()在BBinder::transact()中调用,它根据收到的命令,分别调用对应的方法。

    status_t BnXXX::onTransact(uint32_t code,  const Parcel& data, Parcel* reply, uint32_t flags)

    {

         switch(code) {

             case CMD_METHOD_1: {

                pid_t pid = data.readInt32();

                rtn = method_1(pid);  //调用的是BnXXX的派生类XXX实现的method_1()

                reply->writeInt32(rtn);

             }

         }

    }    

    XXX

    实现XXX::method_1()

    ServiceManager

    源代码:

    frameworksasecmdsservicemanager*

    服务进程向ServiceManager注册服务,客户进程向ServiceManager查询服务,从而得到访问服务对象的handle。

    ServiceManager维护服务名称字符串,它本身也是一个服务,调用binder_become_context_manager()变为“Server大总管”的服务,他对于其它进程来说,它的handle永远是0。它是第一个启动的服务,在/init.rc中启动。

    ISericeManager本地功能BnServiceManager并没有实现,本地功能实际上由servicemanager守护进程执行,而用户程序通过调用BpServiceManager来获得其他的服务。

    ServiceManager主程序代码

    frameworksasecmdsservicemanagerservice_manager.c

    main()

    {

         // 其中调用binder_***()函数位于frameworksasecmdsservicemanagerinder.c

         binder_open(128*1024);

             open("/dev/binder")         //调用驱动的binder_open()

             mmap()                      //把/dev/binder映射到一个128*1024字节大小的内存

         binder_become_context_manager()

             ioctl(BINDER_SET_CONTEXT_MGR)

         binder_loop(bs, svcmgr_handler);  //注册请求处理函数 svcmgr_handler()                   

             binder_write()              //写命令BC_ENTER_LOOPER

             // 开始循环

             ioctl(BINDER_WRITE_READ);  //只是读取

             binder_parse()              //调用svcmgr_handler()处理BR_TRANSACTION,...等命令,

    }

    svcmgr_handler()

    请求处理函数

    对于客户端请求服务,返回的是Service的handle,binder类型是BINDER_TYPE_HANDLE,见函数bio_put_ref(),然后在驱动层binder_thread_write() ->binder_transaction()会进行转换,如果请求的服务在同一进程里,则转换类型成BINDER_TYPE_BINDER,直接使用服务对象的地址,而不使用handle,这在unflatten_binder()中有体现。

    获取ServiceManager服务代理

    sp<IServiceManager>  defaultServiceManager()

    {

         if (gDefaultServiceManager != NULL) return gDefaultServiceManager; //单一实例

         

         {

             AutoMutex _l(gDefaultServiceManagerLock);

             if (gDefaultServiceManager == NULL) {

                gDefaultServiceManager =  interface_cast<IServiceManager>(   //调用interface_cast<XXX>根据BpBinder生成BpServiceManager

                    ProcessState::self()->getContextObject(NULL));

             }

         }

         

         return gDefaultServiceManager;

    }

    sp<IBinder> ProcessState::getContextObject(const  sp<IBinder>& caller)

    {

         if (supportsProcesses()) {

             return getStrongProxyForHandle(0);   //调用ProcessState::getStrongProxyForHandle()创建BpBinder,handle为0

         } else {

             return getContextObject(String16("default"), caller);

         }

    }

    注册服务

    status_t BpServiceManager::addService(const  String16& name, const sp<IBinder>& service)

    //参数service可以是BpBinder或BBinder,binder驱动会记录下对象的地址

    {

         data.writeStrongBinder(service);

         remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);

    }

    查询服务

    sp<IBinder> BpServiceManager::getService(const  String16& name)

    //函数返回BpBinder或BBinder

    {

         BpServiceManager::checkService()

             remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);

             reply.readStrongBinder()

    }

    调用服务

    服务端

    服务端如何工作

    创建ProcessState对象,打开/dev/binder,映射好内存

    调用defaultServiceManager()创建ServiceManager的代理

    调用服务端类的方法instantiate(),创建服务端对象,并向ServiceManager注册

    ProcessState::self()->startThreadPool();,其中也会调用IPCThreadState::joinThreadPool(),参数是true,加上下面的,总共调用了2次

    IPCThreadState::self()->joinThreadPool();,参数默认也是true,进入服务的循环监听状态。(网上有人测试过把最后一句屏蔽掉,也能正常工作。但是难道主线程提出了,程序还能不退出吗?)

    参考代码:

    frameworksasemediamediaservermain_mediaserver.cpp

    int main(int argc, char** argv)

    {

         sp<ProcessState> proc(ProcessState::self());

         sp<IServiceManager> sm = defaultServiceManager();

         LOGI("ServiceManager: %p", sm.get());

         AudioFlinger::instantiate();

         MediaPlayerService::instantiate();

         CameraService::instantiate();

         AudioPolicyService::instantiate();

         ProcessState::self()->startThreadPool();

         IPCThreadState::self()->joinThreadPool();

    }

    void MediaPlayerService::instantiate() {

         defaultServiceManager()->addService(

                String16("media.player"),  new MediaPlayerService());  //注册时,要附上服务名称、服务对象的地址,服务对象的地址最终是记录在驱动中

    }

    客户端

    客户端如何调用服务

    调用defaultServiceManager()创建ServiceManager的代理,其中会创建ProcessState对象

    调用BpServiceManager::getService()获取服务的handle,并生成对应的BpBinder

    调用BpBinder::linkToDeath(),注册服务死亡的通知

    调用interface_cast<IXXX>()利用BpBinder生成BpXXX

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    年轻人如何创业?有什么好的建议?
    青年创新创业大赛北京赛区总决赛举行
    90后瘫痪女孩靠创业改变人生
    怎么利用淘宝赚钱?具体方法有哪些?
    淘宝赚钱的方法有哪些?做淘宝要注意哪些?
    现在做淘宝赚钱吗?要注意哪些?
    2019年开淘宝店赚钱吗?需要注意什么?
    淘宝赚钱软件有哪些?具体怎么赚钱?
  • 原文地址:https://www.cnblogs.com/feng9exe/p/12361999.html
Copyright © 2011-2022 走看看