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信息。