图解AndroidBinder 和 Service.docx
《图解AndroidBinder 和 Service.docx》由会员分享,可在线阅读,更多相关《图解AndroidBinder 和 Service.docx(39页珍藏版)》请在冰豆网上搜索。
图解AndroidBinder和Service
在Zygote启动过程 一文中我们说道,Zygote一生中最重要的一件事就是生下了SystemServer这个大儿子,SystemServer担负着提供系统Service的重任,在深入了解这些Service之前,我们首先要了解什么是Service?
它的工作原理是什么?
1.Service是什么?
简单来说,Service就是提供服务的代码,这些代码最终体现为一个个的接口函数,所以,Service就是实现一组函数的对象,通常也称为组件。
Android的Service有以下一些特点:
1. 请求Service服务的代码(Client) 和Service本身(Server)不在一个线程,很多情况下不在一个进程内。
跨进程的服务称为远端(Remote)服务,跨进程的调用称为IPC。
通常应用程序通过代理(Proxy)对象来访问远端的Service。
2. Service可以运行在native端(C/C++),也可以运行在Java端。
同样,Proxy可以从native端访问JavaService,也可以从Java端访问nativeservice,也就是说,service的访问与语言无关。
3. Android里大部分的跨进程的IPC都是基于Binder实现。
4. Proxy通过Interface类定义的接口访问Server端代码。
5. Service可以分为匿名和具名Service.前者没有注册到ServiceManager,应用无法通过名字获取到访问该服务的Proxy对象。
所以,要了解Service,我们得先从Binder入手。
2. Binder
先给一张Binder相关的类图一瞰Binder全貌,从上面的类图(点击看大图)跟Binder大致有这么几部分:
Native实现:
IBinder, BBinder,BpBinder,IPCThread,ProcessState,IInterface,etc
Java实现:
IBinder,Binder,BinderProxy,Stub,Proxy.
BinderDriver:
binder_proc,binder_thread,binder_node,etc.
我们将分别对这三部分进行详细的分析,首先从中间的Native实现开始。
通常来说,接口是分析代码的入口,Android中'I'打头的类统统是接口类(C++里就是抽象类),自然,分析Binder就得先从IBinder下手。
先看看他的定义。
classIBinder:
publicvirtualRefBase
{
public:
virtualspqueryLocalInterface(constString16&descriptor);//返回一个IInterface对象
...
virtualconstString16&getInterfaceDescriptor()const=0;
virtualboolisBinderAlive()const=0;
virtualstatus_tpingBinder()=0;
virtualstatus_tdump(intfd,constVector&args)=0;
virtualstatus_ttransact(uint32_tcode,
constParcel&data,
Parcel*reply,
uint32_tflags=0)=0;
virtualstatus_tlinkToDeath(constsp&recipient,
void*cookie=NULL,
uint32_tflags=0)=0;
virtualstatus_tunlinkToDeath(constwp&recipient,
void*cookie=NULL,
uint32_tflags=0,
wp*outRecipient=NULL)=0;
...
virtualBBinder*localBinder();//返回一个BBinder对象
virtualBpBinder*remoteBinder();//返回一个BpBinder对象
};
有接口必然有实现,从图中可以看出,BBinder和BpBinder都是IBinder的实现类,它们干啥用的,有啥区别?
有兴趣同学可以去分别去读读他们的代码,分别在
∙ Bpinder:
frameworks/native/lib/binder/BpBinder.cpp
∙ BBinder:
frameworks/native/lib/binder/Binder.cpp
这里我们简单总结一下他们的区别:
接口
BBinder
BpBinder
queryLocalInterface()
没有实现,默认实现IBinder默认{reutrnNULL};
没有实现IBinder默认实现{returnNULL}
getInterfaceDescriptor()
{returnsEmptyDescriptor;}
(this)->transact(INTERFACE_TRANSACTION,send,&reply);
...
mDescriptorCache=res;
isBinderAlive()
{returntrue;}
{returnmAlive!
=0;}
pingBinder()
{returnNoError;}
{transact(PING_TRANSACTION,send,&reply);
linkToDeath()
{returnINVALID_OPERATION;}
{self->requestDeathNotification(mHandle,this);}
unlinkToDeath()
{returnINVALID_OPERATION;}
{self->clearDeathNotification(mHandle,this);}
localBinder()
{returnthis;}
没有实现,IBinder默认实现{returnNULL};
remoteBinder()
没有实现,IBinder默认实现{returnNULL;}
{returnthis};
transact()
{err=onTransact(code,data,reply,flags);}
IPCThreadState:
:
self()->transact(mHandle,code,data,reply,flags);
onTransact()
switch(code){
caseINTERFACE_TRANSACTION:
reply->writeString16(getInterfaceDescriptor());
returnNO_ERROR; ...
没有实现
看出来了吧,它们的差异在于它们是通信两端的不同实现,BBinder是服务端,而BpBinder是客户端,为什么这么说?
1. pingBinder,BBinder直接返回OK,而BpBinder需要运行一个transact函数,这个函数具体做什么,我们后面会介绍。
2. linkToDeath()是用来在服务挂的时候通知客户端的,那服务端当然不需要自己监视自己咯,所以BBinder直接返回非法,而Bpbinder需要通过requestDeathNotification()要求某人完成这个事情,究竟是谁提供这个服务?
答案后面揭晓。
3. 在Android中,remote一般代表某个远端对象的本地代理,想象一下航空公司和机票代理,BBinder是航空公司,当然没有remote的了,那BpBinder就是机票代理了,所以remote()自然返回自己了。
4. Transact的英文意思是交易,就是买卖嘛,那自然transact()就是买的操作,而onTransact()就是卖的操作,BBinder的transact()的实现就是onTransact(),航空公司的买票当然不用通过机票代理了,直接找自己人就好了。
所以结论是,BBinder代表着服务端,而BpBinder则是它在客户端的代理,客户程序通过BpBinder的transact()发起请求,而服务器端的BBinder在onTranscat()里响应请求,并将结果返回。
可是交易肯定有目标的吧,回到航空公司和机票代理的例子,如果要订去某个地方的机票,我们怎么也得先查询一下都有那些航班,然后才能告诉机票代理订具体的航班号吧。
这里的查询和预订可以看成服务的接口函数,而航班号就是我们传递给机票代理的参数。
客户程序通过queryLocalInterface()可以知道航空公司都提供哪些服务。
可是奇怪的是BBinder和BpBinder都没有实现这个接口啊,那肯定另有他人实现这个类了,这个人就是IInterface.h,看看代码
template
inlinespBnInterface:
:
queryLocalInterface(
constString16&_descriptor)
{
if(_descriptor==INTERFACE:
:
descriptor)returnthis;
returnNULL;
}
BnInterface对象将自己强制转换成IInterface对象返回,看看BnInterface的定义:
template
classBnInterface:
publicINTERFACE,publicBBinder
{
public:
virtualspqueryLocalInterface(constString16&_descriptor);
virtualconstString16&getInterfaceDescriptor()const;
protected:
virtualIBinder*onAsBinder();
};
是一个模板类,继承了BBinder,还有模板INTERFACE。
我们刚才已经看过,BBinder没有实现queryLocalInterface(),而BnInterface返回自己,可以他并没有继承IInterface,怎么可以强制转换呢,唯一的解释就是INTERFACE模板必须继承和实现IInterface.
classIInterface:
publicvirtualRefBase
{
public:
IInterface();
spasBinder();
spasBinder()const;
protected:
virtual~IInterface();
virtualIBinder*onAsBinder()=0;
};
这也太简单了吧,只是定义了从Interface到IBinder的转换接口asBinder,而刚才我们研究的queryLocalInterface()正好反过来,说明IBinder和IInterface之间是可以互转的,一个人怎么可以变成另外一个人呢?
唯一的解释就是这个人有双重性格,要么他同时继承IInterface和IBinder,要么他体内有这两个对象同时存在,不卖关子了,在服务端,这个双重性格的人就是BnXXX,XXX代表某个具体的服务,我们以图中的BnMediaPlayer为例,看看他的定义
classBnMediaPlayer:
publicBnInterface
{
public:
virtualstatus_tonTransact(uint32_tcode,
constParcel&data,
Parcel*reply,
uint32_tflags=0);
};
classIMediaPlayer:
publicIInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayer);
...
}
这下本性都露出来了,IBinder和IInterface的影子都露出来了,让我们用图梳理一下(箭头代表继承关系)
归纳一下,
1. BBinder实现了大部分的IBinder接口,除了onTransact()和queryLocalInterface(),getInterfaceDescriptor();
2. BnInterface实现了IBinder的queryLocalInterface()和getInterfaceDescriptor(),但是其必须借助实际的接口类。
3. BnMediaPlayer只是定义了onTransact(),没有实现。
4. onTransact()的具体实现在Client类。
为什么搞得那么复杂?
Google是希望通过这些封装尽可能减少开发者的工作量,开发一个native的service开发者只需要做这么几件事(上图中深色部分):
1.定义一个接口文件,IXXXService,继承IInterface
2.定义BnXXX(),继承BnInterface3.实现一个XXXService类,继承BnXXX(),并具体实现onTransact()函数。
那客户端呢?
我们的目标是找到一个类,它必须同时拥有IBinder和IIterface的特性,先看看BpBinder吧
classBpBinder:
publicIBinder
跟IInterface没有关系,那一定是别人,看看BpInterface吧,
template
classBpInterface:
publicINTERFACE,publicBpRefBase
{
public:
BpInterface(constsp&remote);
protected:
virtualIBinder*onAsBinder();
};
我们刚才已经知道了,INTERFACE是IMediaPlayer,它继承了IInterface,IInterface的对象找到了,但跟IBinder没关系?
只剩下BpRefBase了,
classBpRefBase:
publicvirtualRefBase
{
protected:
...
inlineIBinder*remote(){returnmRemote;}
...
private:
...
IBinder*constmRemote;
RefBase:
:
weakref_type*mRefs;
volatileint32_tmState;
};
有了,BpRefBase里有IBinder成员变量,看来在客户端,没有一个类同时继承IBinder和IInterface,但是有一个类继承了其一,但包含了另外一个,这种在设计模式里成为组合(Composition).
还是不太明白?
还是用图解释吧,
看明白了?
从BpInterface开始,通过BpRefBase我们可以找到IBinder,这个转换就在asBinder()的实现里,看看代码
spIInterface:
:
asBinder(){
returnthis?
onAsBinder():
NULL;
}
spIInterface:
:
asBinder()const{
returnthis?
const_cast(this)->onAsBinder():
NULL;
}
template
inlineIBinder*BpInterface:
:
onAsBinder()
{
returnremote();
}
template
IBinder*BnInterface:
:
onAsBinder()
{
returnthis;
}
这里印证我们上面两张图的正确性,onAsBinder是转换的发生的地方,服务端(BnInterface)的实现直接返回了自己,因为它继承了两者,而客户端(BpInterface)则需要通过remote()(返回mRemote成员变量)获取,因为他自己本身不是IBinder,
那个BpRefbase的mRemote是如何被赋值的?
看看以下代码
//frameworks/native/libs/binder/binder.cpp
BpRefBase:
:
BpRefBase(constsp&o)
:
mRemote(o.get()),mRefs(NULL),mState(0)
{
...
}
//frameworks/native/include/binder/iinterface.h
template
inlineBpInterface:
:
BpInterface(constsp&remote)
:
BpRefBase(remote)
{
}
//frameworks/av/media/libmedia/IMediaPlayer.cpp
classBpMediaPlayer:
publicBpInterface
{
public:
BpMediaPlayer(constsp&impl)
:
BpInterface(impl)
{
}
...
}
原来是从子类一级一级注入的,那唯一的问题就是在哪里完成这个注入操作,马上搜索"newBpMediaPlayer",奇怪,竟然没有,试试搜索"IMediaPlayer“,发现了一点线索
//av/media/libmedia/IMediaPlayerService.cpp
70:
virtualspcreate(
71:
constsp&client,intaudioSessionId){
72Parceldata,reply;
73:
...
77remote()->transact(CREATE,data,&reply);
78:
returninterface_cast(reply.readStrongBinder());//reply里读出IBinder,然后转成IMediaPlayer接口对象
79}
这里通过interface_cast直接把IBinder转换成了IMediaPlayer,interface_cast到底有什么魔力?
template
inlinespinterface_cast(constsp&obj)
{
returnINTERFACE:
:
asInterface(obj);
}
继续跟进asInterface,结果发现里以下代码
#defineDECLARE_META_INTERFACE(INTERFACE)\
staticconstandroid:
:
String16descriptor;\
staticandroid:
:
spasInterface(\
constandroid:
:
sp:
IBinder>&obj);\
virtualconstandroid:
:
String16&getInterfaceDescriptor()const;\
I##INTERFACE();\
virtual~I##INTERFACE();\
#defineIMPLEMENT_META_INTERFACE(INTERFACE,NAME)\
constandroid:
:
String16I##INTERFACE:
:
descriptor(NAME);\
constandroid:
:
String16&\
I##INTERFACE:
:
getInterfaceDescriptor()const{\
returnI##INTERFACE:
:
descriptor;\
}\
android:
:
spI##INTERFACE:
:
asInterface(\
constandroid:
:
sp:
IBinder>&obj)\
{\
android:
:
spintr;\
if(obj!
=NULL){\
intr=static_cast(\
obj->queryLocalInterface(\
I##INTERFACE:
:
descriptor).get());\
if(intr==NULL){\
intr=newBp##INTERFACE(