![Android进阶解密](https://wfqqreader-1252317822.image.myqcloud.com/cover/331/31186331/b_31186331.jpg)
4.2 Service的启动过程
Service的启动过程和根Activity启动过程有部分相似的知识点,另外Service启动过程涉及上下文Context的知识点,这里只关注流程而不会详细介绍Context,关于上下文Context 会在第5章进行介绍。Service的启动过程将分为两个部分来进行讲解,分别是ContextImpl到ActivityManageService的调用过程和ActivityThread启动Service。
4.2.1 ContextImpl到AMS的调用过程
ContextImpl到AMS的调用过程很简短,如图4-7所示。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer34.jpg?sign=1739533541-HozXpGURqliVbbYS3864hr0z83V1dz9V-0-6869cc34e2cbbc0b5fc52de282cc7842)
图4-7 ContextImpl到AMS的调用过程
要启动Service,我们会调用startService方法,它在ContextWrapper中实现,代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer35.jpg?sign=1739533541-6OWtEhNrVMIiX53pnxhjkpQRddLo4RF1-0-e7faa0dbb6fdca3f0940d0951a4bf765)
在startService方法中会调用mBase的startService方法,Context类型的mBase对象具体指的是什么呢?在4.1.3节中我们讲过,ActivityThread启动Activity时会调用如下代码创建Activity的上下文环境:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer36.jpg?sign=1739533541-Po32KnQRw9HsMFVovgQqC3JvVHzYgA5h-0-421de1797e5623a7a2e694b64927a1f4)
在注释1处创建上下文对象appContext,并传入Activity的attach方法中,将Activity与上下文对象appContext关联起来,这个上下文对象appContext的具体类型是什么?我们接着查看createBaseContextForActivity方法,代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer37.jpg?sign=1739533541-ELaBt89AKGZwCF96aCi6TiepuFyQTDrM-0-095d6d99d53d1231acdb5e81cc37c6be)
上下文对象appContext的具体类型就是ContextImpl,在Activity的attach方法中将ContextImpl赋值给ContextWrapper的成员变量mBase,因此,上面提出的问题就得到了解答,mBase具体指向的就是ContextImpl。那么,紧接着来查看ContextImpl的startService方法,代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer38.jpg?sign=1739533541-foHXcrnxwFdImBNVZtqkhWTDVaS9HPEf-0-ef931d71c743fd17076731702b17ed32)
在startService方法中会返回startServiceCommon方法,在startServiceCommon方法中会在注释1处调用AMS的代理IActivityManager的startService方法,最终调用的是AMS的startService方法,这一过程已经在4.1.1节讲过了,这里不再赘述。
4.2.2 ActivityThread启动Service
ActivityThread启动Service的时序图如图4-8所示。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer39.jpg?sign=1739533541-dc5jd3RGE9IHkkiHVTIf1T6CS7xzLWQ3-0-b1dbf9bc2843870182359a3ddfb4bacc)
图4-8 ActivityThread启动Service的时序图
接着我们来查看AMS的startService方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer40.jpg?sign=1739533541-im5JyuN4dfF2hwwfwi5gIhyOdrfj8nFJ-0-cc366c21a555253370f7bd0df069bf36)
注释1处调用mServices的startServiceLocked方法,mServices的类型是ActiveServices,ActiveServices的startServiceLocked方法代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer41.jpg?sign=1739533541-rZ9GXy3SABQ1cW5Aee5bjtf8nh3b8dCK-0-ba1291a025f366d132ac5112c30d39e6)
注释1处的retrieveServiceLocked方法会查找是否有与参数service对应的ServiceRecord,如果没有找到,就会调用PackageManagerService去获取参数service对应的Service信息,并封装到ServiceRecord中,最后将ServiceRecord封装为ServiceLookupResult返回。其中ServiceRecord用于描述一个Service,和此前讲过的ActivityRecord类似。在注释2处通过注释1处返回的ServiceLookupResult得到参数service对应的ServiceRecord,并传入到注释3处的startServiceInnerLocked方法中。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer42.jpg?sign=1739533541-dT9FXB27NlEJg8Ciks8zTdyrBWCuwY0K-0-3885873e4b476983c5cf0e52cd9da280)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer43.jpg?sign=1739533541-wfBCaF27KagNcdzi3etCdyEv5wToxbyS-0-6a88b477c2712ff5718d4ee015513eec)
在startServiceInnerLocked方法中又调用了bringUpServiceLocked方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer44.jpg?sign=1739533541-VzGuOX6FlxBQkw8UryVAZ9a5imLfw5qz-0-55d102ae1d52abe5cdba30c29b421542)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer45.jpg?sign=1739533541-V4anGbDlMJGFBxAjG1JOoYquCk8hqOCm-0-16cd9a8145a80fa8b6550e5333735503)
在注释1处得到ServiceRecord 的processName值并赋给procName,其中processName用来描述Service想要在哪个进程中运行,默认是当前进程,我们也可以在AndroidManifest文件中设置android:process 属性来新开启一个进程运行Service。在注释2处将procName和Service的uid传入到AMS的getProcessRecordLocked 方法中,查询是否存在一个与Service对应的ProcessRecord类型的对象app,ProcessRecord主要用来描述运行的应用程序进程的信息。在注释5处判断Service对应的app为null则说明用来运行Service的应用程序进程不存在,则调用注释6处的AMS的startProcessLocked方法来创建对应的应用程序进程,关于创建应用程序进程请查看第3章的内容,这里只讨论没有设置android:process属性,即应用程序进程存在的情况。在注释3处判断如果用来运行Service的应用程序进程存在,则调用注释4处的realStartServiceLocked方法来启动Service:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer46.jpg?sign=1739533541-cA3jJahi6C3Y8TxahqIXuwxYj3PWz5ze-0-63d66544b9929d45f968fdaa9d45dcb8)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer47.jpg?sign=1739533541-4rjhVCgtsaWMQn2wAFvYknlfTadvnVUj-0-a4d21a31e8bea2cd449488dcc7476ccb)
在realStartServiceLocked方法中调用了app.thread的scheduleCreateService方法。其中app.thread是IApplicationThread 类型的,它的实现是ActivityThread的内部类ApplicationThread。ApplicationThread的scheduleCreateService方法如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer48.jpg?sign=1739533541-MAKfmVrOy8iIVPnKpePZS99Np60MRk0N-0-005f8f242c67083b347ea5cf8ca48bc3)
scheduleLaunchActivity方法将启动Service的参数封装成ActivityClientRecord,sendMessage方法向H类发送类型为CREATE_SERVICE的消息,并将ActivityClientRecord传递过去,这个过程和4.1.3节ActivityThread启动Activity的过程是类似的。sendMessage方法有多个重载方法,最终调用的sendMessage方法如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer49.jpg?sign=1739533541-FBD33I7DaM7KjsIEguCp8QUMfyW4FdR8-0-14679c48f2391eb3c3b585bea1bafc59)
这里mH指的是H,它是ActivityThread的内部类并继承自Handler,是应用程序进程中主线程的消息管理类。我们接着查看H的handleMessage方法:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer50.jpg?sign=1739533541-ATPWBvbvou9R8ms9fHhDImbBZM0Z6sFk-0-1ef67d27e53d74286a5d239a1bdfd667)
handleMessage 方法根据消息类型为CREATE_SERVICE,会调用handleCreateService方法:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer51.jpg?sign=1739533541-kzJoHzysY5mpYgNpAcAxSYUG9xc8sRkL-0-6f2db80211c81da05064843cda8a3cea)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer52.jpg?sign=1739533541-YgZvbvNUCxktOTUH3O5oaHJyDgcjzxVA-0-a288a8da80447ab5e2ccf33653e22e57)
在注释1处获取要启动Service的应用程序的LoadedApk,LoadedApk是一个APK文件的描述类。在注释2处通过调用LoadedApk的getClassLoader方法来获取类加载器。接着在注释3处根据CreateServiceData对象中存储的Service信息,创建Service实例。在注释4处创建Service的上下文环境ContextImpl对象。在注释5处通过Service的attach方法来初始化Service。在注释6处调用Service的onCreate方法,这样Service就启动了。在注释7处将启动的Service加入到ActivityThread的成员变量mServices中,其中mServices是ArrayMap类型。Service的启动过程就讲到这里,接下来我们学习Service的绑定过程。