Service 的启动过程
service 的启动过程从 ContextWrapper 的 startService() 方法开始,如下:
|
|
mBase 的类型是 Context,Context 是一个 abstract class,ContextImpl 继承自 Context, 从 ContextWrapper 的实现来看,大部分操作都是通过 mBase 来实现的,这是一种典型的桥接模式。
下面我们来看 ContextImpl 的 startService() 方法,如下:
|
|
上述代码中,调用 ActivityManagerNative.getDefault().startService() 方法,通过我们分析 Activity 的启动过程,我们对它很熟悉,下面在 AMS 中看下 startService() 方法,如下:
|
|
ActiveServices 是一个辅助 AMS 进行 Service 管理的类,包括 Service 的启动、绑定和停止等,在其 startServiceLocked() 方法中,调用 startServiceInnerLocked() 方法,如下:
|
|
在上述代码中,ServiceRecord 描述的是一个 Service 的记录,startServiceInnerLocked() 方法并没有完成具体的工作,而是把任务交给了 bringUpServiceLocked() 方法,在这个方法中,又调用了 realStartServiceLocked() 方法,这是真正启动 Service 的方法,如下:
|
|
在上述方法中,通过调用 app.thread.scheduleCreateService() 方法来创建 Service 对象并调用其 onCreate() 方法,接着通过调用 sendServiceArgsLocked() 方法来调用其他生命周期的方法,app.thread 我们已经很熟悉啦,就是 ApplicationThread.因此我们需要去查看其 scheduleCreateService() 方法,如下:
|
|
很明显,通过发送消息给 H 来完成启动 Service 的任务,跟 Activity 的启动方式很相似,H 会接收这个 CREATE_SERVICE 消息并通过 ActivityThread 的 handleCreateService() 方法来完成 Service 的最终启动。handleCreateService() 方法如下:
|
|
handleCreateService() 方法主要万臣了如下几件事:
- 通过类加载器创建 Service实例
- 创建 Application 实例并调用其 onCreate() 方法;
- 创建 ContextImpl 对象并通过 Service 的 attach() 方法建立二者之间的联系。
- 调用 Service 的 onCreate() 方法将 Service 对象存储到 一个列表中。
ActivityThread 通过handleServiceArgs() 方法调用 Service 的 onStartCommand() 方法,如下:
|
|
到此为止,启动 Service 的过程就已经结束。
Service 的绑定过程
从 ContextWrapper 开始执行 BindService,代码如下:
|
|
mBase 是 ContextImpl 的对象,接着调用 bindServiceCommon() 方法,如下:
|
|
在上述方法中,首先将 ServiceConnection 对象转化成 ServiceDispatcher.InnerConnection 对象, ServiceDispatcher 起着连接 ServiceConnection 和 InnerConnection 的作用,这个过程是由 LoadedApk 的 getServiceDispatcher 方法来完成的,如下:
|
|
mService 存储了一个应用当前活动的 ServiceConnection 和 ServiceDispatcher 的映射关系,系统首先会查找是否存在相同的 ServiceConnection,如果不存在就重新创建一个 ServiceDispatcher 对象并将其存储在 mService 中,key 是ServiceConnection,value 是 ServiceDispatcher,在 ServiceDispatcher 的内部又保存了 ServiceConnection 和 InnerConnection 对象,当 Service 和客户端建立连接后,系统会通过 InnerConnection 来调用 ServiceConnection 中的 onServiceConnected() 方法,这个过程有可能是跨进程的,当 ServiceDispatcher 创建好了之后,getServiceDispatcher 会返回其保存的 InnerConnection 对象。
在 bindServiceCommon() 方法中通过 AMS 来完成 Service 的绑定过程,如下:
|
|
在上述方法中,调用 bindServiceLocked() 方法,接着在调用 bringUpServiceLocked() 方法,再调用 realStartServiceLocked() 方法,最终都是通过 ApplicationThread 来完成 Service 实例的创建并执行其 onCreate() 方法。
Service 的绑定过程会调用 app.thread 的 scheduleBindService 方法,这个过程的实现在 ActiveServices 的 requestServiceBindingLocked() 方法中,如下:
|
|
这个过程我们太熟悉啦,在 ActivityThread 的 handleBindService() 方法中,如下:
|
|
首先根据 Service 的token 取出 Service 对象,在调用 onBind() 方法,在 Service 的方法中会返回一个 Binder 对象给客户端使用,此时 Service 已经处于绑定状态。接下来由 ActivityManagerNative.getDefault().publishService() 方法来通知客户端,我们继续看 AMS 的 publishService() 方法,如下:
|
|
mService 是 ActiveService 对象,publishServiceLocked() 方法的代码如下,
|
|
最关键的一句话:c.conn.connected(r.name,service);其中 c 的类型是 ConnectionRecord,c.conn 类型是 ServiceDispatcher.InnerConnection,service 是 Service 的 onBind() 方法返回的 Binder 对象。我们先看 ServiceDispatcher.InnerConnection 的定义,ServiceDispather 是 LoadedApk 的内部类,如下:
|
|
在它的方法里,又调用了 ServiceDispatcher 的 connected() 方法,如下:
|
|
mActivityThread 是一个 Handler,它就是 ActivityThread 的 H,从 ServiceDispatcher 的创建过程来看,mActivityThread 不会为null,这样 RunConnection() 方法就由 H 的 post 方法从而运行在主线程中,客户端的 ServiceConnection 中的方法在主线程中被回调,如下:
|
|
调用了 ServiceDispathcer 的 doConnected() 方法,如下:
|
|
其中 mConnection 是客户端的ServiceConnection 对象,因此很容易调用 ServiceConnection 对象的 onServiceConnected() 方法。
到此为止,Service 的绑定过程就结束啦,