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