概述:
“应用程序启动过程”其实说的就是“冷启动”过程。
App启动流程总体是由以下3部分组成
- 为目标App启动做准备
- 启动App进程
- App进程内部操作
为目标App启动做准备(详细请戳 <<为目标App启动做准备>>)
这部分内容概括来说主要就是2件事:
- “Launcher进程把待启动App的信息封装到Intent中,然后通过Binder把该信息发送给system_server进程中的AMS服务。
- 然后AMS拿这些信息为启动App做一些前期的准备工作”。
这些工作内容细分如下:
- 通过PMS.resolveIntent()根据提供的待启动Activity的Intent信息,从已安装的应用中解析出与该Activity相对应的ActivityInfo。
- 检查传递来的参数,如果参数不正确,将会返回相应的err信息,用于提醒用户出现了什么错误。
- 如果,Intent获取的要启动的Activity组件的"ComponentName"信息为null的话(未通过Intent指定要跳转的Activity的确切的类名信息),则不会继续后续操作,并会返回此err。
- 如果,通过PMS找不到待启动Activity的详细信息(ActivityInfo),则不会继续后续操作,并会返回此err。
- 与Activity栈相关操作
- 为待启动Activity组件新创建一个ActivityRecord。
- 缓存待启动ActivityRecord、调用者的ActivityRecord、Intent等信息。
- 初始化代启动Activity的lauchMode与launchFlags。
- 为代启动ActivityRcord创建或者选取一个可用的TaskRecord(因为启动的其它app的根Activity,所以会为该Activity创建一个新的TaskRecord)。
- 添加待启动ActivityRecord至“前台栈”的栈顶。
- 显示theme中设置的预览窗口。
- “暂停所有ActivityStack中处于RESUMED状态的Activity”,此时Launcher这个Activity也会被 Pause 掉。
- 激活“前台栈”中处于栈顶位置的待启动Activity。
启动App进程(详细请戳 <<启动App进程>>)
启动应用程序的进程主要分2个方面:
-
AMS向Zygote发起fork子进程的过程
- AMS调用其内部的“startProcessLocked()”来开启启动app进程的入口。该方法主要做的是:组装发给zygote进城的用于启动子进程的参数列表(这些参数包括:uid,gid,entryPoint 参数等,entryPoint参数的值为ActivityThread的类全限定名。该参数用于fork子进程之后启动每个app进程的ActivityThread去做初始化操作。)
- 通过层层调用最终会执行 ZygoteProcess.startViaZygote()。
1:首先,该方法首先会把AMS服务传过来的参数封装到一个argsForZygote参数列表中。
2:其次,调用ZygoteProcess内部的openZygoteSocketIfNeeded()与Zygote进程建立Socket连接。
3:最后,调用ZygoteProcess的zygoteSendArgsAndGetResult(),该方法主要做的事情是:将请求参数列表发送到zygote进程,并接收Zygote进程启动子进程的响应结果。
-
Zygote接收AMS的请求创建子进程过程
-
Zygote进程被init进程拉起后,会通过反射调用ZygotInit的main(),该方法主要做的事情是:
1:初始化ZygoteServer并创建服务端Socket用于接收、执行其它进程向Zygote进程发起的请求。
2:启动SystemServer进程。
3:最后调用runSelectLoop()开始循环接收其它进程发起的请求。 - 如果检测到有请求发过来,runSlectLoop()中会把一次Socket封装成ZygoteConnection,而后执行其runOnce()方法。
- 在runOnce()内部会调用Zygote.forkAndSpecialize():内部调用native方法进行实际的fork子进程操作。fork成功的话则子进程pid等于0,不为0则表示fork失败(fork()采用copy on write技术,这是linux创建进程的标准方法,调用一次,返回两次。)。
- 如果pid为0,则表示当前代码执行在子进程,需要执行handleChildProc(),该方法主要做的是:
1:关闭与Zygote进程的Socket连接。
2:执行ZygoteInit.zygoteInit()。
ZygoteInit.zygoteInit(),该方法主要执行"子进程"的运行时初始化操作(这些初始化包括:启动Binder线程池、创建VM、以及反射执行子进程ActivityThread线程等)。
-
Zygote进程被init进程拉起后,会通过反射调用ZygotInit的main(),该方法主要做的事情是:
App进程内部操作(详细请戳 <<App进程内部操作>>)
执行ActivityThread.attach(),进行“连接”操作。其中主要包括:
AMS.attachApplication():此时所在进程是fork之后的子进程。通过ActivityService.getService()获取AMS服务在本地进程的代理对象,然后通过Binder调用AMS的attachApplication()。
-
AMS.attachApplicationLocked():
1:其内部会先调用ApplicationThread.bindApplication()初始化App进程的Application。具体的会向ActivityThread的Handler中发送一个BIND_APPLICATION消息。Handler在接收到发送的“BIND_APPLICATION消息”后去执行ActivityThread.handleBindApplication()。- ContextImpl.createAppContext():创建ContextImpl实例
- 反射初始化Instrumentation实例,并赋值给 mInstrumentation。执行Instrumentation.init()进行初始化操作。
- LoadApk.makeApplication():反射Application,并执行Application的attach(),onCreate()方法。
2:等启动完App的Applicaiton后,AMS会调用ASS.attachApplicationLocked()通过App的ApplicationThread通知app初始化根Activity。具体操作如下:
1:首先,调用ASS.attachApplicationLocked()。其内部会找到处于“前台栈”栈顶的待启动Activity。
2:最后,调用ASS.realStartActivityLocked()通过Binder来通知App进程初始化待启动也就是App注册的根Activity。