深入分析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驱动

源代码:

kernel\drivers\staging\android\binder.h

kernel\drivers\staging\android\binder.c

 

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

Binder Adapter

源代码:

frameworks\base\include\binder\IPCThreadState.h

frameworks\base\include\binder\ProcessState.h

frameworks\base\libs\binder\IPCThreadState.cpp

frameworks\base\libs\binder\ProcessState.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核心库

源代码:

frameworks\base\include\binder\Binder.h

frameworks\base\include\binder\BpBinder.h

frameworks\base\include\binder\IBinder.h

frameworks\base\libs\binder\Binder.cpp

frameworks\base\libs\binder\BpBinder.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框架

源代码:

frameworks\base\include\binder\IInterface.h

frameworks\base\include\binder\Parcel.h

frameworks\base\libs\binder\IInterface.cpp

frameworks\base\libs\binder\Parcel.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只是接口的名字,无实质作用,和服务的名字不是一回事

 

实现服务

参考代码:

frameworks\base\include\media\IMediaPlayerService.h

frameworks\base\media\libmedia\IMediaPlayerService.cpp

frameworks\base\media\libmediaplayerservice\MediaPlayerService.h

frameworks\base\media\libmediaplayerservice\MediaPlayerService.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

源代码:

frameworks\base\cmds\servicemanager\*

 

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

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

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

 

ServiceManager主程序代码

frameworks\base\cmds\servicemanager\service_manager.c

 

main()

{

     // 其中调用binder_***()函数位于frameworks\base\cmds\servicemanager\binder.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,进入服务的循环监听状态。(网上有人测试过把最后一句屏蔽掉,也能正常工作。但是难道主线程提出了,程序还能不退出吗?)

 

参考代码:

frameworks\base\media\mediaserver\main_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

posted @ 2020-02-25 15:33  zzfx  阅读(1626)  评论(0编辑  收藏  举报