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