Android深入四大组件三Service的绑定过程.docx

上传人:b****7 文档编号:9036780 上传时间:2023-02-02 格式:DOCX 页数:12 大小:103.73KB
下载 相关 举报
Android深入四大组件三Service的绑定过程.docx_第1页
第1页 / 共12页
Android深入四大组件三Service的绑定过程.docx_第2页
第2页 / 共12页
Android深入四大组件三Service的绑定过程.docx_第3页
第3页 / 共12页
Android深入四大组件三Service的绑定过程.docx_第4页
第4页 / 共12页
Android深入四大组件三Service的绑定过程.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

Android深入四大组件三Service的绑定过程.docx

《Android深入四大组件三Service的绑定过程.docx》由会员分享,可在线阅读,更多相关《Android深入四大组件三Service的绑定过程.docx(12页珍藏版)》请在冰豆网上搜索。

Android深入四大组件三Service的绑定过程.docx

Android深入四大组件三Service的绑定过程

Android深入四大组件(三)Service的绑定过程

1.ContextImpl到ActivityManageService的调用过程

我们可以用bindService方法来绑定Service,它的实现在ContextWrapper中,代码如下所示。

frameworks/base/core/Java/Android/content/ContextWrapper.java

@Override

publicbooleanbindService(Intentservice,ServiceConnectionconn,

intflags){

returnmBase.bindService(service,conn,flags);

}

查看ContextImpl的bindService方法:

frameworks/base/core/java/android/app/ContextImpl.java

@Override

publicbooleanbindService(Intentservice,ServiceConnectionconn,

intflags){

warnIfCallingFromSystemProcess();

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

Process.myUserHandle());

}

在bindService方法中,又return了bindServiceCommon方法,代码如下所示。

frameworks/base/core/java/android/app/ContextImpl.java

privatebooleanbindServiceCommon(Intentservice,ServiceConnectionconn,intflags,Handler

handler,UserHandleuser){

IServiceConnectionsd;

if(conn==null){

thrownewIllegalArgumentException("connectionisnull");

}

if(mPackageInfo!

=null){

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

}else{

thrownewRuntimeException("Notsupportedinsystemcontext");

}

validateServiceIntent(service);

try{

...

/**

*2

*/

intres=ActivityManagerNative.getDefault().bindService(

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

service.resolveTypeIfNeeded(getContentResolver()),

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

...

}catch(RemoteExceptione){

throwe.rethrowFromSystemServer();

}

}

在注释1处调用了LoadedApk类型的对象mPackageInfo的getServiceDispatcher方法,它的主要作用是将ServiceConnection封装为IServiceConnection类型的对象sd,从IServiceConnection的名字我们就能得知它实现了Binder机制,这样Service的绑定就支持了跨进程。

接着在注释2处我们又看见了熟悉的代码,最终会调用AMS的bindService方法。

ContextImpl到ActivityManageService的调用过程如下面的时序图所示。

2.Service的绑定过程

AMS的bindService方法代码如下所示。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

publicintbindService(IApplicationThreadcaller,IBindertoken,Intentservice,

StringresolvedType,IServiceConnectionconnection,intflags,StringcallingPackage,

intuserId)throwsTransactionTooLargeException{

enforceNotIsolatedCaller("bindService");

...

synchronized(this){

returnmServices.bindServiceLocked(caller,token,service,

resolvedType,connection,flags,callingPackage,userId);

}

}

bindService方法最后会调用ActiveServices类型的对象mServices的bindServiceLocked方法:

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

intbindServiceLocked(IApplicationThreadcaller,IBindertoken,Intentservice,

StringresolvedType,finalIServiceConnectionconnection,intflags,

StringcallingPackage,finalintuserId)throwsTransactionTooLargeException{

...

if((flags&Context.BIND_AUTO_CREATE)!

=0){

s.lastActivity=SystemClock.uptimeMillis();

/**

*1

*/

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

permissionsReviewRequired)!

=null){

return0;

}

}

...

if(s.app!

=null&&b.intent.received){//2

try{

c.conn.connected(s.name,b.intent.binder);//3

}catch(Exceptione){

...

}

if(b.intent.apps.size()==1&&b.intent.doRebind){//4

requestServiceBindingLocked(s,b.intent,callerFg,true);//5

}

}elseif(!

b.intent.requested){//6

requestServiceBindingLocked(s,b.intent,callerFg,false);//7

}

getServiceMap(s.userId).ensureNotStartingBackground(s);

}finally{

Binder.restoreCallingIdentity(origId);

}

return1;

}

在注释1处会bringUpServiceLocked方法,在bringUpServiceLocked方法中又会调用realStartServiceLocked方法,最终由ActivityThread来调用Service的onCreate方法启动Service,

在注释2处s.app!

=null表示Service已经运行,其中s是ServiceRecord类型对象,app是ProcessRecord类型对象。

b.intent.received表示当前应用程序进程的Client端已经接收到绑定Service时返回的Binder,这样应用程序进程的Client端就可以通过Binder来获取要绑定的Service的访问接口。

注释3处调用c.conn的connected方法,其中c.conn指的是IServiceConnection,它的具体实现为ServiceDispatcher.InnerConnection,其中ServiceDispatcher是LoadedApk的内部类,InnerConnection的connected方法内部会调用H的post方法向主线程发送消息,从而解决当前应用程序进程和Service跨进程通信的问题,在后面会详细介绍这一过程。

在注释4处如果当前应用程序进程的Client端第一次与Service进行绑定的,并且Service已经调用过onUnBind方法,则需要调用注释5的代码。

注释6处如果应用程序进程的Client端没有发送过绑定Service的请求,则会调用注释7的代码,注释7和注释5的代码区别就是最后一个参数rebind为false,表示不是重新绑定。

接着我们查看注释7的requestServiceBindingLocked方法,代码如下所示。

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

privatefinalbooleanrequestServiceBindingLocked(ServiceRecordr,IntentBindRecordi,

booleanexecInFg,booleanrebind)throwsTransactionTooLargeException{

...

if((!

i.requested||rebind)&&i.apps.size()>0){//1

try{

bumpServiceExecutingLocked(r,execInFg,"bind");

r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);

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

r.app.repProcState);//2

...

}

...

}

returntrue;

}

注释1处i.requested表示是否发送过绑定Service的请求,从前面的代码得知是没有发送过,因此,!

i.requested为true。

从前面的代码得知rebind值为false,那么(!

i.requested||rebind)的值为true。

如果IntentBindRecord中的应用程序进程记录大于0,则会调用注释2的代码,r.app.thread的类型为IApplicationThread,它的实现我们已经很熟悉了,是ActivityThread的内部类ApplicationThread,scheduleBindService方法如下所示。

frameworks/base/core/java/android/app/ActivityThread.java

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的信息封装成BindServiceData对象,需要注意的BindServiceData的成员变量rebind的值为false,后面会用到它。

接着将BindServiceData传入到sendMessage方法中。

sendMessage向H发送消息,我们接着查看H的handleMessage方法。

frameworks/base/core/java/android/app/ActivityThread.java

publicvoidhandleMessage(Messagemsg){

if(DEBUG_MESSAGES)Slog.v(TAG,">>>handling:

"+codeToString(g.what));

switch(msg.what){

...

caseBIND_SERVICE:

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

handleBindService((BindServiceData)msg.obj);

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

break;

...

}

...

}

...

}

H在接收到BIND_SERVICE类型消息时,会在handleMessage方法中会调用handleBindService方法:

frameworks/base/core/java/android/app/ActivityThread.java

privatevoidhandleBindService(BindServiceDatadata){

Services=mServices.get(data.token);//1

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){//2

IBinderbinder=s.onBind(data.intent);//3

ActivityManagerNative.getDefault().publishService(

data.token,data.intent,binder);//4

}else{

s.onRebind(data.intent);//5

ActivityManagerNative.getDefault().serviceDoneExecuting(

data.token,SERVICE_DONE_EXECUTING_ANON,0,0);

}

ensureJitEnabled();

}

...

}

...

}

}

注释1处获取要绑定的Service。

注释2处的BindServiceData的成员变量rebind的值为false,这样会调用注释3处的代码来调用Service的onBind方法,这样Service处于绑定状态了。

如果rebind的值为true就会调用注释5处的Service的onRebind方法,结合前文的bindServiceLocked方法的注释4处,我们得知如果当前应用程序进程的Client端第一次与Service进行绑定,并且Service已经调用过onUnBind方法,则会调用Service的onRebind方法。

接着查看注释4的代码,实际上是调用AMS的publishService方法。

讲到这,先给出这一部分的代码时序图(不包括Service启动过程)

我们接着来查看AMS的publishService方法,代码如下所示。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

publicvoidpublishService(IBindertoken,Intentintent,IBinderservice){

...

synchronized(this){

if(!

(tokeninstanceofServiceRecord)){

thrownewIllegalArgumentException("Invalidservicetoken");

}

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

}

}

publishService方法中,调用了ActiveServices类型的mServices对象的publishServiceLocked方法:

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

voidpublishServiceLocked(ServiceRecordr,Intentintent,IBinderservice){

finallongorigId=Binder.clearCallingIdentity();

try{

...

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

ArrayListclist=r.connections.valueAt(conni);

for(inti=0;i

...

try{

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

}catch(Exceptione){

...

}

}

}

}

serviceDoneExecutingLocked(r,mDestroyingServices.contains(r),false);

}

}finally{

Binder.restoreCallingIdentity(origId);

}

}

注释1处的代码,我在前面介绍过,c.conn指的是IServiceConnection,它的具体实现为ServiceDispatcher.InnerConnection,其中ServiceDispatcher是LoadedApk的内部类,ServiceDispatcher.InnerConnectiond的connected方法的代码如下所示。

frameworks/base/core/java/android/app/LoadedApk.java

staticfinalclassServiceDispatcher{

...

privatestaticclassInnerConnectionextendsIServiceConnection.Stub{

finalWeakReferencemDispatcher;

InnerConnection(LoadedApk.ServiceDispatchersd){

mDatcher=newWeakReference(sd);

}

publicvoidconnected(ComponentNamename,IBinderservice)throwsRemoteException{

LoadedApk.ServiceDispatchersd=mDispatcher.get();

if(sd!

=null){

sd.connected(name,service);//1

}

}

}

...

}

在注释1处调用了ServiceDispatcher类型的sd对象的connected方法,代码如下所示。

frameworks/base/core/java/android/app/LoadedApk.java

publicvoidconnected(ComponentNamename,IBinderservice){

if(mActivityThread!

=null){

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

}else{

doConnected(name,service);

}

}

注释1处调用Handler类型的对象mActivityThread的post方法,mActivityThread实际上指向的是H。

因此,通过调用H的post方法将RunConnection对象的内容运行在主线程中。

RunConnection的定义如下所示。

frameworks/base/core/java/android/app/LoadedApk.java

privatefinalclassRunConnectionimplementsRunnable{

RunConnection(ComponentNamename,IBinderservice

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 农学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1