Android源码分析--Service的启动和绑定
Service的启动过程
Service的启动和根Activity的启动很类似。Service的启动同样需要保证该应用程序的进程已经被启动。
启动大纲
-
ContextImpl请求AMS启动Service.
-
AMS请求ActivityThread启动Service.
ContextImpl请求AMS启动Service
-
当我们需要启动一个Service时,我们会使用
context.startService
。而Context只是一个抽象的类,它的实现是在ContextWrapper中。 -
在ContextWrapper的
startService
方法中,又会调用其内部的Context类型的mBase变量,而该变量的创建详见ActivityThread的createBaseContextForActivity
方法,它的实现类是ContextImpl
。 -
在ContextImpl的
startService
方法中,又会调用其自身的startServiceCommon
方法。 -
在ContextImpl的
startServiceCommon
方法中,会使用ActivityManager
获取AMS的代理IActivityManager
,并调用其startService
方法。
AMS请求ActivityThread启动Service
-
AMS的
startService
方法中调用ActiveService的startServiceLocked
方法,其中调用retrieveServiceLocked
用于获取启动服务的Intent参数所对应的ServiceRecord
,它主要用于描述一个Service,启动Service所必须的参数。 -
在ActiveService的
startServiceLocked
方法中获取到相应的ServiceRecord
之后,就会调用其自身的startServiceInnerLocked方法,而它又会去调用bringUpServiceLocked
方法。在bringUpServiceLocked方法中主要做了以下三个工作:
(1)获取Service运行所在的进程。
(2)如果Service运行所在的应用程序进程ProcessRecord
存在,则调用其自身的realStartServiceLocked
方法来启动Service.
(3)如果Service运行所在的应用程序进程ProcessRecord
不存在,则需要调用AMS的startProcessLocked
方法来启动应用程序进程。
-
在ActiveService的
realStartServiceLocked
方法中,会使用ProcessRecord
的IApplicationThread
类型的引用(实现类是ActivityThread的内部类ApplicationThread),调用其scheduleCreateService方法。 -
在ActivityThread的
scheduleCreateService
方法中,会向其内部类并继承自Handler的H
发送CREATE_SERVICE
消息,并由H
进行处理,最终会调用handleCreateService
方法。 -
在ActivityThread的
handleCreateService
方法中主要做了如下几件事:
(1)获取要启动Service的应用程序的LoadApk(包信息),并通过它获取类的加载器,通过反射创建Service的实例。
(2)调用ContextImpl
的createAppContext
方法,为Service创建上下文环境ContextImpl对象。
(3)调用Service
的attach
方法,对Service进行初始化。
(4)调用Service
的onCreate
方法,这样Service就启动了。
Service的绑定过程
除了使用Context的startService来启动Service外,我们也可以通过Context的bindService来绑定Service。绑定Service的过程要比启动Service的过程复杂一些。
启动大纲
-
ContextImpl请求AMS绑定Service.
-
AMS请求ActivityThread处理Service绑定.
-
AMS进行Service的绑定.
ContextImpl请求AMS绑定Service
-
当我们需要绑定一个Service时,我们会使用
context.bindService
。而Context只是一个抽象的类,它的实现是在ContextWrapper中。 -
在ContextWrapper的
bindService
方法中,又会调用其内部的Context类型的mBase变量,而该变量的创建详见ActivityThread的createBaseContextForActivity
方法,它的实现类是ContextImpl
。 -
在ContextImpl的
bindService
方法中,又会调用其自身的bindServiceCommon
方法。 -
在ContextImpl的
bindServiceCommon
方法中,首先调用LoadedApk的getServiceDispatcher
方法获取ServiceConnection的封装类(本地的代理)IServiceConnection
(用于跨进程通信),然后使用ActivityManager
获取AMS的代理IActivityManager
,调用其bindService
方法并将IServiceConnection
对象传入。
AMS请求ActivityThread处理Service绑定
-
AMS的
bindService
方法中调用方法中调用ActiveService的bindServiceLocked
方法,其中同样的和startServiceLocked
一样调用retrieveServiceLocked
用于获取启动服务的Intent参数所对应的ServiceRecord
,然后调用ServiceRecord的retrieveAppBindingLocked
方法来获取应用和服务的绑定信息AppBindRecord
,最后调用requestServiceBindingLocked
方法,将之前获取的AppBindRecord
信息传入,来发出服务绑定的请求。 -
除此之外,在
bindServiceLocked
方法调用requestServiceBindingLocked
请求绑定前,还调用了bringUpServiceLocked
方法去启动服务。 -
在ActiveService的
requestServiceBindingLocked
方法中最终会调用ActivityThread
的scheduleBindService方法,然后封装BindServiceData数据并将其传入sendMessage
方法中,向H发送BIND_SERVICE
消息。在H对应的消息处理中会调用handleBindService方法。在handleBindService
方法中,对未绑定服务的,先后调用Service的onBind
方法和AMS的publishService方法;对已绑定服务的,先后调用Service的onRebind
方法和AMS的serviceDoneExecuting方法。
-
在AMS的publishService方法中又调用了
ActiveService
的publishServiceLocked方法。 -
在
publishServiceLocked
方法中会调用IServiceConnection
的connected
方法来建立服务连接,最终会调用执行LoadApk
中的RunConnection任务,执行doConnected方法建立服务绑定连接。
与Service绑定相关的对象类型介绍:
-
ServiceRecord:用于描述一个Service。
-
ProcessRecord:一个进程所包含的信息。
-
ConnectionRecord:用于描述应用程序进程和Service建立的一次通信。
-
AppBindRecord: 用于维护Service与应用进程之间的绑定信息。
-
IntentBindRecord:用于描述绑定Service的Intent信息。