配色: 字号:
Android Service的绑定过程
2016-10-19 | 阅:  转:  |  分享 
  
AndroidService的绑定过程

通常我们使用Service都要和它通信,当想要与Service通信的时候,那么Service要处于绑定状态的。然后客户端可以拿到一个Binder与服务端进行通信,这个过程是很自然的。



那你真的了解过Service的绑定过程吗?为什么可以是Binder和Service通信?

同样的先看一张图大致了解一下,灰色背景框起来的是同一个类的方法,如下:



我们知道调用Context的bindService方法即可绑定一个Service,而ContextImpl是Context的实现类。那接下来就从源码的角度分析Service的绑定过程。



当然是从ContextImpl的bindService方法开始,如下:



@Override

publicbooleanbindService(Intentservice,ServiceConnectionconn,

intflags){

warnIfCallingFromSystemProcess();

returnbindServiceCommon(service,conn,flags,mMainThread.getHandler(),

Process.myUserHandle());

}



在bindService方法中又会转到bindServiceCommon方法,将Intent,ServiceConnection对象传进。



那就看看bindServiceCommon方法的实现。



privatebooleanbindServiceCommon(Intentservice,ServiceConnectionconn,intflags,Handler

handler,UserHandleuser){

IServiceConnectionsd;

if(conn==null){

thrownewIllegalArgumentException("connectionisnull");

}

if(mPackageInfo!=null){

sd=mPackageInfo.getServiceDispatcher(conn,getOuterContext(),handler,flags);

}else{

thrownewRuntimeException("Notsupportedinsystemcontext");

}

validateServiceIntent(service);

try{

IBindertoken=getActivityToken();

if(token==null&&(flags&BIND_AUTO_CREATE)==0&&mPackageInfo!=null

&&mPackageInfo.getApplicationInfo().targetSdkVersion


flags|=BIND_WAIVE_PRIORITY;

}

service.prepareToLeaveProcess(this);

intres=ActivityManagerNative.getDefault().bindService(

mMainThread.getApplicationThread(),getActivityToken(),service,

service.resolveTypeIfNeeded(getContentResolver()),

sd,flags,getOpPackageName(),user.getIdentifier());

if(res<0){

thrownewSecurityException(

"Notallowedtobindtoservice"+service);

}

returnres!=0;

}catch(RemoteExceptione){

throwe.rethrowFromSystemServer();

}

}



在上述代码中,调用了mPackageInfo(LoadedApk对象)的getServiceDispatcher方法。从getServiceDispatcher方法的名字可以看出是获取一个“服务分发者”。其实是根据这个“服务分发者”获取到一个Binder对象的。



那现在就看到getServiceDispatcher方法的实现。



publicfinalIServiceConnectiongetServiceDispatcher(ServiceConnectionc,

Contextcontext,Handlerhandler,intflags){

synchronized(mServices){

LoadedApk.ServiceDispatchersd=null;

ArrayMapmap=mServices.get(context);

if(map!=null){

sd=map.get(c);

}

if(sd==null){

sd=newServiceDispatcher(c,context,handler,flags);

if(map==null){

map=newArrayMap();

mServices.put(context,map);

}

map.put(c,sd);

}else{

sd.validate(context,handler);

}

returnsd.getIServiceConnection();

}

}



从getServiceDispatcher方法的实现可以知道,ServiceConnection和ServiceDispatcher构成了映射关系。当存储集合不为空的时候,根据传进的key,也就是ServiceConnection,来取出对应的ServiceDispatcher对象。

当取出ServiceDispatcher对象后,最后一行代码是关键,



returnsd.getIServiceConnection();



调用了ServiceDispatcher对象的getIServiceConnection方法。这个方法肯定是获取一个IServiceConnection的。



IServiceConnectiongetIServiceConnection(){

returnmIServiceConnection;

}



那么mIServiceConnection是什么?现在就可以来看下ServiceDispatcher类了。ServiceDispatcher是LoadedApk的内部类,里面封装了InnerConnection和ServiceConnection。如下:



staticfinalclassServiceDispatcher{

privatefinalServiceDispatcher.InnerConnectionmIServiceConnection;

privatefinalServiceConnectionmConnection;

privatefinalContextmContext;

privatefinalHandlermActivityThread;

privatefinalServiceConnectionLeakedmLocation;

privatefinalintmFlags;



privateRuntimeExceptionmUnbindLocation;



privatebooleanmForgotten;



privatestaticclassConnectionInfo{

IBinderbinder;

IBinder.DeathRecipientdeathMonitor;

}



privatestaticclassInnerConnectionextendsIServiceConnection.Stub{

finalWeakReferencemDispatcher;



InnerConnection(LoadedApk.ServiceDispatchersd){

mDispatcher=newWeakReference(sd);

}



publicvoidconnected(ComponentNamename,IBinderservice)throwsRemoteException{

LoadedApk.ServiceDispatchersd=mDispatcher.get();

if(sd!=null){

sd.connected(name,service);

}

}

}



privatefinalArrayMapmActiveConnections

=newArrayMap();



ServiceDispatcher(ServiceConnectionconn,

Contextcontext,HandleractivityThread,intflags){

mIServiceConnection=newInnerConnection(this);

mConnection=conn;

mContext=context;

mActivityThread=activityThread;

mLocation=newServiceConnectionLeaked(null);

mLocation.fillInStackTrace();

mFlags=flags;

}



//代码省略



}



先看到ServiceDispatcher的构造方法,一个ServiceDispatcher关联一个InnerConnection对象。而InnerConnection呢?,它是一个Binder,有一个很重要的connected方法。至于为什么要用Binder,因为与Service通信可能是跨进程的。



好,到了这里先总结一下:调用bindService方法绑定服务,会转到bindServiceCommon方法。

在bindServiceCommon方法中,会调用LoadedApk的getServiceDispatcher方法,并将ServiceConnection传进,根据这个ServiceConnection取出与其映射的ServiceDispatcher对象,最后调用这个ServiceDispatcher对象的getIServiceConnection方法获取与其关联的InnerConnection对象并返回。简单点理解就是用ServiceConnection换来了InnerConnection。



现在回到bindServiceCommon方法,可以看到绑定Service的过程会转到ActivityManagerNative.getDefault()的bindService方法,其实从抛出的异常类型RemoteException也可以知道与Service通信可能是跨进程的,这个是很好理解的。



而ActivityManagerNative.getDefault()是ActivityManagerService,那么继续跟进ActivityManagerService的bindService方法即可,如下:



publicintbindService(IApplicationThreadcaller,IBindertoken,Intentservice,

StringresolvedType,IServiceConnectionconnection,intflags,StringcallingPackage,

intuserId)throwsTransactionTooLargeException{

enforceNotIsolatedCaller("bindService");



//Refusepossibleleakedfiledescriptors

if(service!=null&&service.hasFileDescriptors()==true){

thrownewIllegalArgumentException("FiledescriptorspassedinIntent");

}



if(callingPackage==null){

thrownewIllegalArgumentException("callingPackagecannotbenull");

}



synchronized(this){

returnmServices.bindServiceLocked(caller,token,service,

resolvedType,connection,flags,callingPackage,userId);

}

}



在上述代码中,绑定Service的过程转到ActiveServices的bindServiceLocked方法,那就跟进ActiveServices的bindServiceLocked方法瞧瞧。如下:



intbindServiceLocked(IApplicationThreadcaller,IBindertoken,Intentservice,

StringresolvedType,finalIServiceConnectionconnection,intflags,

StringcallingPackage,finalintuserId)throwsTransactionTooLargeException{



//代码省略



ConnectionRecordc=newConnectionRecord(b,activity,

connection,flags,clientLabel,clientIntent);



IBinderbinder=connection.asBinder();

ArrayListclist=s.connections.get(binder);

if(clist==null){

clist=newArrayList();

s.connections.put(binder,clist);

}

clist.add(c);



//代码省略



if((flags&Context.BIND_AUTO_CREATE)!=0){

s.lastActivity=SystemClock.uptimeMillis();

if(bringUpServiceLocked(s,service.getFlags(),callerFg,false,

permissionsReviewRequired)!=null){

return0;

}

}



//代码省略



return1;

}



将connection对象封装在ConnectionRecord中,这里的connection就是上面提到的InnerConnection对象。这一步很重要的。



然后调用了bringUpServiceLocked方法,那么就探探这个bringUpServiceLocked方法,



privateStringbringUpServiceLocked(ServiceRecordr,intintentFlags,booleanexecInFg,

booleanwhileRestarting,booleanpermissionsReviewRequired)

throwsTransactionTooLargeException{



//代码省略



if(app!=null&&app.thread!=null){

try{

app.addPackage(r.appInfo.packageName,r.appInfo.versionCode,mAm.mProcessStats);

realStartServiceLocked(r,app,execInFg);

returnnull;

}catch(TransactionTooLargeExceptione){

throwe;

}catch(RemoteExceptione){

Slog.w(TAG,"Exceptionwhenstartingservice"+r.shortName,e);

}



//Ifadeadobjectexceptionwasthrown--fallthroughto

//restarttheapplication.

}



//代码省略



returnnull;

}



可以看到调用了realStartServiceLocked方法,真正去启动Service了。



那么跟进realStartServiceLocked方法探探,如下:



privatefinalvoidrealStartServiceLocked(ServiceRecordr,

ProcessRecordapp,booleanexecInFg)throwsRemoteException{



//代码省略



app.thread.scheduleCreateService(r,r.serviceInfo,

mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),

app.repProcState);

r.postNotification();

created=true;



//代码省略



requestServiceBindingsLocked(r,execInFg);



updateServiceClientActivitiesLocked(app,null,true);



//Iftheserviceisinthestartedstate,andthereareno

//pendingarguments,thenfakeuponesoitsonStartCommand()will

//becalled.

if(r.startRequested&&r.callStart&&r.pendingStarts.size()==0){

r.pendingStarts.add(newServiceRecord.StartItem(r,false,r.makeNextStartId(),

null,null));

}



sendServiceArgsLocked(r,execInFg,true);



//代码省略

}



这里会调用app.thread的scheduleCreateService方法去创建一个Service,然后会回调Service的生命周期方法,然而绑定Service呢?

在上述代码中,找到一个requestServiceBindingsLocked方法,从名字看是请求绑定服务的意思,那么就是它没错了。



privatefinalvoidrequestServiceBindingsLocked(ServiceRecordr,booleanexecInFg)

throwsTransactionTooLargeException{

for(inti=r.bindings.size()-1;i>=0;i--){

IntentBindRecordibr=r.bindings.valueAt(i);

if(!requestServiceBindingLocked(r,ibr,execInFg,false)){

break;

}

}

}



咦,我再按住Ctrl+鼠标左键,点进去requestServiceBindingLocked方法。如下:



privatefinalbooleanrequestServiceBindingLocked(ServiceRecordr,IntentBindRecordi,

booleanexecInFg,booleanrebind)throwsTransactionTooLargeException{

if(r.app==null||r.app.thread==null){

//Ifserviceisnotcurrentlyrunning,can''tyetbind.

returnfalse;

}

if((!i.requested||rebind)&&i.apps.size()>0){

try{

bumpServiceExecutingLocked(r,execInFg,"bind");

r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);

r.app.thread.scheduleBindService(r,i.intent.getIntent(),rebind,

r.app.repProcState);

if(!rebind){

i.requested=true;

}

i.hasBound=true;

i.doRebind=false;

}



//代码省略



returntrue;

}



r.app.thread调用了scheduleBindService方法来绑定服务,而r.app.thread是ApplicationThread,现在关注到ApplicationThread即可,scheduleBindService方法如下:



publicfinalvoidscheduleBindService(IBindertoken,Intentintent,

booleanrebind,intprocessState){

updateProcessState(processState,false);

BindServiceDatas=newBindServiceData();

s.token=token;

s.intent=intent;

s.rebind=rebind;



if(DEBUG_SERVICE)

Slog.v(TAG,"scheduleBindServicetoken="+token+"intent="+intent+"uid="

+Binder.getCallingUid()+"pid="+Binder.getCallingPid());

sendMessage(H.BIND_SERVICE,s);

}



封装了待绑定的Service的信息,并发送了一个消息给主线程,



publicvoidhandleMessage(Messagemsg){

if(DEBUG_MESSAGES)Slog.v(TAG,">>>handling:"+codeToString(msg.what));

switch(msg.what){



//代码省略



caseBIND_SERVICE:

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"serviceBind");

handleBindService((BindServiceData)mswww.shanxiwang.netg.obj);

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

break;



//代码省略



}

}



调用了handleBindService方法,即将绑定完成啦。



privatevoidhandleBindService(BindServiceDatadata){

Services=mServices.get(data.token);

if(DEBUG_SERVICE)

Slog.v(TAG,"handleBindServices="+s+"rebind="+data.rebind);

if(s!=null){

try{

data.intent.setExtrasClassLoader(s.getClassLoader());

data.intent.prepareToEnterProcess();

try{

if(!data.rebind){

IBinderbinder=s.onBind(data.intent);

ActivityManagerNative.getDefault().publishService(

data.token,data.intent,binder);

}else{

s.onRebind(data.intent);

ActivityManagerNative.getDefault().serviceDoneExecuting(

data.token,SERVICE_DONE_EXECUTING_ANON,0,0);

}

ensureJitEnabled();

}catch(RemoteExceptionex){

throwex.rethrowFromSystemServer();

}

}catch(Exceptione){

if(!mInstrumentation.onException(s,e)){

thrownewRuntimeException(

"Unabletobindtoservice"+s

+"with"+data.intent+":"+e.toString(),e);

}

}

}

}



根据token获取到Service,然后Service回调onBind方法。结束了?



可是onBind方法返回了一个binder是用来干嘛的?

我们再看看ActivityManagerNative.getDefault()调用了publishService方法做了什么工作,此时又回到了ActivityManagerService。



publicvoidpublishService(IBindertoken,Intentintent,IBinderservice){

//Refusepossibleleakedfiledescriptors

if(intent!=null&&intent.hasFileDescriptors()==true){

thrownewIllegalArgumentException("FiledescriptorspassedinIntent");

}



synchronized(this){

if(!(tokeninstanceofServiceRecord)){

thrownewIllegalArgumentException("Invalidservicetoken");

}

mServices.publishServiceLocked((ServiceRecord)token,intent,service);

}

}



又会交给ActiveServices处理,转到了publishServiceLocked方法,那看到ActiveServices的publishServiceLocked方法,



voidpublishServiceLocked(ServiceRecordr,Intentintent,IBinderservice){

finallongorigId=Binder.clearCallingIdentity();

try{

if(DEBUG_SERVICE)Slog.v(TAG_SERVICE,"PUBLISHING"+r

+""+intent+":"+service);

if(r!=null){

Intent.FilterComparisonfilter

=newIntent.FilterComparison(intent);

IntentBindRecordb=r.bindings.get(filter);

if(b!=null&&!b.received){

b.binder=service;

b.requested=true;

b.received=true;

for(intconni=r.connections.size()-1;conni>=0;conni--){

ArrayListclist=r.connections.valueAt(conni);

for(inti=0;i
ConnectionRecordc=clist.get(i);

if(!filter.equals(c.binding.intent.intent)){

if(DEBUG_SERVICE)Slog.v(

TAG_SERVICE,"Notpublishingto:"+c);

if(DEBUG_SERVICE)Slog.v(

TAG_SERVICE,"Boundintent:"+c.binding.intent.intent);

if(DEBUG_SERVICE)Slog.v(

TAG_SERVICE,"Publishedintent:"+intent);

continue;

}

if(DEBUG_SERVICE)Slog.v(TAG_SERVICE,"Publishingto:"+c);

try{

c.conn.connected(r.name,service);

}



//代码省略



}



c.conn是什么?它是一个InnerConnection对象,对,就是那个那个Binder,上面也贴出了代码,在ActiveServices的bindServiceLocked方法中,InnerConnection对象被封装在ConnectionRecord中。那么现在它调用了connected方法,就很好理解了。



InnerConnection的connected方法如下:



publicvoidconnected(ComponentNamename,IBinderservice)throwsRemoteException{

LoadedApk.ServiceDispatchersd=mDispatcher.get();

if(sd!=null){

sd.connected(name,service);

}

}



会调用ServiceDispatcher的connected方法,如下



publicvoidconnected(ComponentNamename,IBinderservice){

if(mActivityThread!=null){

mActivityThread.post(newRunConnection(name,service,0));

}else{

doConnected(name,service);

}

}



从而ActivityThread会投递一个消息到主线程,此时就解决了跨进程通信。

那么你应该猜到了RunConnection一定有在主线程回调的onServiceConnected方法,



privatefinalclassRunConnectionimplementsRunnable{

RunConnection(ComponentNamename,IBinderservice,intcommand){

mName=name;

mService=service;

mCommand=command;

}



publicvoidrun(){

if(mCommand==0){

doConnected(mName,mService);

}elseif(mCommand==1){

doDeath(mName,mService);

}

}



finalComponentNamemName;

finalIBindermService;

finalintmCommand;

}



咦,还不出现?继续跟进doConnected方法,



publicvoiddoConnected(ComponentNamename,IBinderservice){

ServiceDispatcher.ConnectionInfoold;

ServiceDispatcher.ConnectionInfoinfo;



synchronized(this){

if(mForgotten){

//Weunboundbeforereceivingtheconnection;ignore

//anyconnectionreceived.

return;

}

old=mActiveConnections.get(name);

if(old!=null&&old.binder==service){

//Huh,alreadyhavethisone.Ohwell!

return;

}



if(service!=null){

//Anewserviceisbeingconnected...setitallup.

info=newConnectionInfo();

info.binder=service;

info.deathMonitor=newDeathMonitor(name,service);

try{

service.linkToDeath(info.deathMonitor,0);

mActiveConnections.put(name,info);

}catch(RemoteExceptione){

//Thisservicewasdeadbeforewegotit...just

//don''tdoanythingwithit.

mActiveConnections.remove(name);

return;

}



}else{

//Thenamedserviceisbeingdisconnected...cleanup.

mActiveConnections.remove(name);

}



if(old!=null){

old.binder.unlinkToDeath(old.deathMonitor,0);

}

}



//Iftherewasanoldservice,itisnotdisconnected.

if(old!=null){

mConnection.onServiceDisconnected(name);

}

//Ifthereisanewservice,itisnowconnected.

if(service!=null){

mConnection.onServiceConnected(name,service);

}

}



在最后一个if判断,终于找到了onServiceConnected方法!



总结一下,当Service回调onBind方法,其实还没有结束,会转到ActivityManagerService,然后又会在ActiveServices的publishServiceLocked方法中,从ConnectionRecord中取出InnerConnection对象。有了InnerConnection对象后,就回调了它的connected。在InnerConnection的connected方法中,又会调用ServiceDispatcher的connected方法,在ServiceDispatcher的connected方法向主线程扔了一个消息,切换到了主线程,之后就在主线程中回调了客户端传进的ServiceConnected对象的onServiceConnected方法。



至此,Service的绑定过程分析完毕。

献花(0)
+1
(本文系网络学习天...首藏)