1、图解Android Binder 和 Service在 Zygote启动过程一文中我们说道,Zygote一生中最重要的一件事就是生下了 System Server 这个大儿子,System Server 担负着提供系统 Service的重任,在深入了解这些Service 之前,我们首先要了解 什么是Service?它的工作原理是什么?1. Service是什么? 简单来说,Service就是提供服务的代码,这些代码最终体现为一个个的接口函数,所以,Service就是实现一组函数的对象,通常也称为组件。Android 的Service 有以下一些特点: 1. 请求Service服务的代码(Cli
2、ent) 和 Service本身(Server) 不在一个线程,很多情况下不在一个进程内。跨进程的服务称为远端(Remote)服务,跨进程的调用称为IPC。通常应用程序通过代理(Proxy)对象来访问远端的Service。 2. Service 可以运行在native 端(C/C+),也可以运行在Java 端。同样,Proxy 可以从native 端访问Java Service, 也可以从Java端访问native service, 也就是说,service的访问与语言无关。 3. Android里大部分的跨进程的IPC都是基于Binder实现。 4. Proxy 通过 Interface 类
3、定义的接口访问Server端代码。 5. Service可以分为匿名和具名Service. 前者没有注册到ServiceManager, 应用无法通过名字获取到访问该服务的Proxy对象。 所以,要了解Service,我们得先从 Binder 入手。 2. Binder 先给一张Binder相关的类图一瞰Binder全貌,从上面的类图(点击看大图)跟Binder大致有这么几部分: Native 实现: IBinder, BBinder, BpBinder, IPCThread, ProcessState, IInterface, etc Java 实现: IBinder, Binder, Bi
4、nderProxy, Stub, Proxy. Binder Driver: binder_proc, binder_thread, binder_node, etc. 我们将分别对这三部分进行详细的分析,首先从中间的Native实现开始。 通常来说,接口是分析代码的入口,Android中I 打头的类统统是接口类(C+里就是抽象类), 自然,分析Binder就得先从IBinder下手。先看看他的定义。class IBinder : public virtual RefBasepublic: virtual sp queryLocalInterface(const String16& descr
5、iptor); /返回一个IInterface对象 . virtual const String16& getInterfaceDescriptor() const = 0; virtual bool isBinderAlive() const = 0; virtual status_t pingBinder() = 0; virtual status_t dump(int fd, const Vector& args) = 0; virtual status_t transact( uint32_t code, const Parcel& data, Parcel* reply, uint3
6、2_t flags = 0) = 0; virtual status_t linkToDeath(const sp& recipient, void* cookie = NULL, uint32_t flags = 0) = 0; virtual status_t unlinkToDeath( const wp& recipient, void* cookie = NULL, uint32_t flags = 0, wp* outRecipient = NULL) = 0; . virtual BBinder* localBinder(); /返回一个BBinder对象 virtual BpB
7、inder* remoteBinder(); /返回一个BpBinder对象; 有接口必然有实现,从图中可以看出,BBinder和BpBinder都是IBinder的实现类,它们干啥用的,有啥区别?有兴趣同学可以去分别去读读他们的代码,分别在 Bpinder: frameworks/native/lib/binder/BpBinder.cpp BBinder: frameworks/native/lib/binder/Binder.cpp 这里我们简单总结一下他们的区别:接口BBinderBpBinderqueryLocalInterface()没有实现, 默认实现 IBinder 默认reu
8、trn NULL;没有实现 IBinder 默认实现 return NULLgetInterfaceDescriptor()return sEmptyDescriptor; (this)-transact(INTERFACE_TRANSACTION, send, &reply); . mDescriptorCache = res; isBinderAlive()return true;return mAlive != 0;pingBinder()return NoError;transact(PING_TRANSACTION, send, &reply);linkToDeath()return
9、 INVALID_OPERATION;self-requestDeathNotification(mHandle, this);unlinkToDeath()return INVALID_OPERATION;self-clearDeathNotification(mHandle, this);localBinder()return this;没有实现, IBinder默认实现 return NULL;remoteBinder()没有实现,IBinder默认实现 return NULL;return this;transact()err = onTransact(code, data, repl
10、y, flags);IPCThreadState:self()-transact(mHandle, code, data, reply, flags);onTransact() switch (code) case INTERFACE_TRANSACTION: reply-writeString16(getInterfaceDescriptor(); return NO_ERROR; .没有实现 看出来了吧,它们的差异在于它们是通信两端的不同实现,BBinder是服务端,而BpBinder是客户端,为什么这么说? 1. pingBinder, BBinder直接返回OK,而BpBinder需要
11、运行一个transact函数,这个函数具体做什么,我们后面会介绍。 2. linkToDeath()是用来在服务挂的时候通知客户端的,那服务端当然不需要自己监视自己咯,所以BBinder直接返回非法,而Bpbinder需要通过requestDeathNotification()要求某人完成这个事情,究竟是谁提供这个服务?答案后面揭晓。 3. 在Android中,remote一般代表某个远端对象的本地代理,想象一下航空公司和机票代理,BBinder是航空公司,当然没有remote的了,那BpBinder就是机票代理了,所以remote()自然返回自己了。 4. Transact的英文意思是交易,
12、就是买卖嘛,那自然transact()就是买的操作,而onTransact()就是卖的操作,BBinder的transact()的实现就是onTransact(), 航空公司的买票当然不用通过机票代理了,直接找自己人就好了。 所以结论是,BBinder代表着服务端,而BpBinder则是它在客户端的代理,客户程序通过BpBinder的transact()发起请求,而服务器端的BBinder在onTranscat()里响应请求,并将结果返回。可是交易肯定有目标的吧,回到航空公司和机票代理的例子,如果要订去某个地方的机票,我们怎么也得先查询一下都有那些航班,然后才能告诉机票代理订具体的航班号吧。这
13、里的查询和预订可以看成服务的接口函数,而航班号就是我们传递给机票代理的参数。客户程序通过queryLocalInterface() 可以知道航空公司都提供哪些服务。可是奇怪的是BBinder和BpBinder都没有实现这个接口啊,那肯定另有他人实现这个类了,这个人就是IInterface.h, 看看代码templateinline sp BnInterface:queryLocalInterface( const String16& _descriptor) if (_descriptor = INTERFACE:descriptor) return this; return NULL;BnI
14、nterface 对象将自己强制转换成 IInterface对象返回,看看BnInterface的定义:templateclass BnInterface : public INTERFACE, public BBinderpublic: virtual sp queryLocalInterface(const String16& _descriptor); virtual const String16& getInterfaceDescriptor() const; protected: virtual IBinder* onAsBinder();是一个模板类,继承了BBinder, 还有模
15、板 INTERFACE。我们刚才已经看过,BBinder没有实现queryLocalInterface(), 而BnInterface 返回自己,可以他并没有继承IInterface, 怎么可以强制转换呢,唯一的解释就是 INTERFACE模板必须继承和实现IInterface.class IInterface : public virtual RefBasepublic: IInterface(); sp asBinder(); sp asBinder() const; protected: virtual IInterface(); virtual IBinder* onAsBinder(
16、) = 0;这也太简单了吧,只是定义了 从Interface 到 IBinder的转换接口 asBinder, 而刚才我们研究的queryLocalInterface() 正好反过来,说明IBinder 和 IInterface 之间是可以互转的,一个人怎么可以变成另外一个人呢?唯一的解释就是这个人有双重性格,要么他同时继承 IInterface 和 IBinder, 要么他体内有这两个对象同时存在,不卖关子了,在服务端,这个双重性格的人就是BnXXX, XXX 代表某个具体的服务,我们以图中的BnMediaPlayer为例,看看他的定义class BnMediaPlayer: public
17、BnInterfacepublic: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);class IMediaPlayer: public IInterfacepublic: DECLARE_META_INTERFACE(MediaPlayer); .这下本性都露出来了,IBinder 和 IInterface 的影子都露出来了,让我们用图梳理一下 (箭头代表继承关系)归纳一下,1. BBinder 实现了大部分的IBinder 接口,除了onT
18、ransact() 和 queryLocalInterface(), getInterfaceDescriptor(); 2. BnInterface 实现了IBinder的queryLocalInterface()和getInterfaceDescriptor(), 但是其必须借助实际的接口类。 3. BnMediaPlayer只是定义了onTransact(), 没有实现。 4. onTransact()的具体实现在Client类。 为什么搞得那么复杂?Google 是希望通过这些封装尽可能减少开发者的工作量,开发一个native的service 开发者只需要做这么几件事(上图中深色部分)
19、:1. 定义一个接口文件, IXXXService, 继承IInterface 2. 定义BnXXX(), 继承 BnInterfaceIXXXService) 3. 实现一个XXXService类,继承BnXXX(), 并具体实现onTransact() 函数。 那客户端呢? 我们的目标是找到一个类,它必须同时拥有IBinder 和 IIterface的特性, 先看看BpBinder 吧class BpBinder : public IBinder跟IInterface 没有关系,那一定是别人,看看BpInterface 吧,templateclass BpInterface : publi
20、c INTERFACE, public BpRefBasepublic: BpInterface(const sp& remote);protected: virtual IBinder* onAsBinder();我们刚才已经知道了,INTERFACE 是 IMediaPlayer, 它继承了IInterface, IInterface 的对象找到了, 但跟IBinder 没关系?只剩下BpRefBase 了,class BpRefBase : public virtual RefBaseprotected: . inline IBinder* remote() return mRemote
21、; .private: . IBinder* const mRemote; RefBase:weakref_type* mRefs; volatile int32_t mState;有了,BpRefBase 里有IBinder 成员变量,看来在客户端,没有一个类同时继承IBinder 和 IInterface, 但是有一个类继承了其一,但包含了另外一个,这种在设计模式里成为组合(Composition).还是不太明白?还是用图解释吧,看明白了?从BpInterface开始,通过BpRefBase 我们可以找到IBinder, 这个转换就在 asBinder() 的实现里,看看代码sp IInt
22、erface:asBinder() return this ? onAsBinder() : NULL;sp IInterface:asBinder() const return this ? const_cast(this)-onAsBinder() : NULL;templateinline IBinder* BpInterface:onAsBinder() return remote();templateIBinder* BnInterface:onAsBinder() return this;这里印证我们上面两张图的正确性,onAsBinder是转换的发生的地方,服务端(BnInter
23、face)的实现直接返回了自己,因为它继承了两者,而客户端(BpInterface)则需要通过remote()(返回mRemote 成员变量)获取,因为他自己本身不是IBinder,那个BpRefbase的mRemote是如何被赋值的?看看以下代码/frameworks/native/libs/binder/binder.cppBpRefBase:BpRefBase(const sp& o) : mRemote(o.get(), mRefs(NULL), mState(0) ./frameworks/native/include/binder/iinterface.htemplateinlin
24、e BpInterface:BpInterface(const sp& remote) : BpRefBase(remote)/frameworks/av/media/libmedia/IMediaPlayer.cppclass BpMediaPlayer: public BpInterfacepublic: BpMediaPlayer(const sp& impl) : BpInterface(impl) .原来是从子类一级一级注入的,那唯一的问题就是在哪里完成这个注入操作, 马上搜索new BpMediaPlayer, 奇怪,竟然没有,试试搜索IMediaPlayer“,发现了一点线索 /
25、av/media/libmedia/IMediaPlayerService.cpp 70: virtual sp create( 71: const sp& client, int audioSessionId) 72 Parcel data, reply; 73: . 77 remote()-transact(CREATE, data, &reply); 78: return interface_cast(reply.readStrongBinder(); /reply里读出IBinder,然后转成IMediaPlayer接口对象 79 这里通过interface_cast 直接把IBind
26、er 转换成了 IMediaPlayer, interface_cast 到底有什么魔力?templateinline sp interface_cast(const sp& obj) return INTERFACE:asInterface(obj);继续跟进 asInterface, 结果发现里以下代码#define DECLARE_META_INTERFACE(INTERFACE) static const android:String16 descriptor; static android:sp asInterface( const android:sp& obj); virtual
27、 const android:String16& getInterfaceDescriptor() const; I#INTERFACE(); virtual I#INTERFACE(); #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) const android:String16 I#INTERFACE:descriptor(NAME); const android:String16& I#INTERFACE:getInterfaceDescriptor() const return I#INTERFACE:descriptor; android:sp I#INTERFACE:asInterface( const android:sp& obj) android:sp intr; if (obj != NULL) intr = static_cast( obj-queryLocalInterface( I#INTERFACE:descriptor).get(); if (intr = NULL) intr = new Bp#INTERFACE(
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1