本文主要介绍Android的App应用进程、Application和launch activity的初始化过程,希望看完后对应用启动过程有更清晰的认识,了解这部分内容对以后研究应用启动耗时的计算逻辑也有一定帮助。
Android启动进程概述
Android系统启动过程中,先由init进程通过解析init.rc文件fork生成Zygote进程,该进程也是Android系统的首个Java进程。之后Zygote进程负责孵化System Server进程和App进程。
System Server进程:
- 由Zygote进程fork生成,System Server是Zygote孵化的第一个进程
- 负责启动、管理整个Java Framework,包含ActivityManager、WindowManager、PackageManager等服务
App进程:
- Zygote进程在App层中孵化出的第一个进程是Launcher进程,即手机的桌面App(桌面本身是一个App)
- Zygote还会孵化出Browser、Email、Phone等App进程,每个App至少运行在一个进程上
- 所有App进程都由Zygote进程fork生成
应用启动流程
当用户点击手机桌面某个应用的图标时,将由Launcher进程发起,通过binder发消息给System Server进程,然后System Server进程通过socket建立与zygote进程的连接,由zygote进程为目标应用创建进程。
各家厂商一般会定制Launcher,在Android 9.0中,我们以Android默认启动页为例,即launcher3/Launcher.java跟踪代码。当应用图标被点击时,由桌面程序Launcher响应,首先执行ItemClickHandler.onClick()
:
Launcher响应桌面Icon点击
方法调用栈
先看这一部分的方法调用,有个宏观认识后再对其中重要步骤展开:
1 | - ItemClickHandler.onClick() |
ItemClickHandler.onClick()
从Launcher响应用户点击应用的桌面Icon开始,看下ItemClickHandler.onClick()
:
1 | com.android.launcher3.touch.ItemClickHandler |
ItemClickHandler响应点击事件后,交给Launcher处理,最终通过启动目标应用。
ActivityStack.resumeTopActivityInnerLocked()
根据前面列的整体代码调用流程,从Activity.startActivity()
开始,后续会调用到ActivityStack.resumeTopActivityInnerLocked()
,看下该方法的具体实现逻辑:
1 | com.android.server.am.ActivityStack |
上面代码会去判断是否有栈顶Activity处于Resume状态,即mResumedActivity != null
,如果有的话会,通过startPausingLocked()
先让栈顶Activity执行Pause过程,然后再执行ActivityStackSupervisor.startSpecificActivityLocked()
启动目标Activity。因为是冷启动,内部会先创建应用进程,再启动launch activity。
ActivityStackSupervisor.startSpecificActivityLocked()
看下startSpecificActivityLocked()
逻辑:
1 | com.android.server.am.ActivityStackSupervisor |
上面代码中会去根据进程和线程是否存在判断App是否已经启动,如果已经启动,就会调用ActivityManagerService.realStartActivityLocked()
方法启动目标Activity。如果没有启动则调用ActivityManagerService.startProcessLocked()
优先为待启动App创建进程。
下面我们看下AMS如何为APP创建进程。
创建应用进程
创建应用进程主要分两块工作:
- system server进程中,从AMS.startProcess()开始,先配置新建进程参数,然后通过socket建立与zygote进程的连接,将参数列表写给zygote进程,等待zygote进程fork新的进程,返回pid
- zygote进程被system server进程的socket连接请求唤醒,在native层fork目标进程
system server发起请求
该部分方法调用栈如下:
1 | - ActivityManagerService.startProcessLocked() // 后续会执行几个重载方法 |
上面《应用启动流程》部分,最后代码跟到mService.startProcessLocked()
,该方法内部会执行一系列AMS的startProcessLocked
重载方法。最终会调用ActivityManagerService.startProcess()
:
1 | com.android.server.am.ActivityManagerService |
Process.start()
后续会依次执行ZygoteProcess.start()
、ZygoteProcess.startViaZygote()
,在ZygoteProcess.startViaZygote()
内部为创建的目标进程设置参数:
1 | android.os.ZygoteProcess |
从上面可以看到,先配置一系列进程参数,之后执行openZygoteSocketIfNeeded()
建立与Zygote进程的通信连接,再调用zygoteSendArgsAndGetResult()
向zygote进程传递参数。
看下如何建立和Zygote进程的通信连接:
1 | android.os.ZygoteProcess |
从上面代码主要描述SystemServer进程利用socket建立和Zygote进程的通信,具体可以看一下ZygoteState.connect()
的逻辑:
1 | android.os.ZygoteProcess.ZygoteState |
connect()操作主要获取socket的输入流、输出流,封装到ZygoteState中,交给zygoteSendArgsAndGetResult()
使用。看下zygoteSendArgsAndGetResult()
:
1 | android.os.ZygoteProcess |
上面代码将前面设置的创建进程的参数写给Zygote进程,然后阻塞,直到zygote进程fork出新的进程,并返回新进程的pid。
下面看看zygote进程如何fork新的进程。
zygote创建app进程
该部分方法调用栈如下:
1 | - ZygoteInit.main() |
zygote进程由init进程通过解析init.rc文件fork生成,zygote进程启动后会执行ZygoteInit.main()
。
1 | com.android.internal.os.ZygoteInit |
看下zygoteServer.runSelectLoop()
:
1 | com.android.internal.os.ZygoteServer |
上面方法的内容系统注释也说的比较清楚,zygote进程会进入loop循环等待来自客户端socket的连接,即前面讲到system server进程通过socket发起与zygote进程的连接。
zygote进程收到socket连接后,执行acceptCommandPeer()
创建ZygoteConnection:
1 | private ZygoteConnection acceptCommandPeer(String abiList) { |
ZygoteConnection创建后,接着执行ZygoteConnection.processOneCommand()
:
1 | com.android.internal.os.ZygoteConnection |
上面方法先读取待创建进程的参数列表,即前面ZygoteProcess.startViaZygote()
中提到的,然后通过Zygote.forkAndSpecialize()
fork出app进程:
1 | com.android.internal.os.Zygote |
后续走到native层nativeForkAndSpecialize()
:
1 | com_android_internal_os_Zygote.cpp |
看下ForkCommon
:
1 | // Utility routine to fork a process from the zygote. |
上面代码的逻辑主要是zygote进程通过ForkCommon,fork子进程,然后将pid返回给java层。
整个流程到这里就结束了,回顾一下:
- system server进程通过socket建立和zygote进程的连接,请求创建app进程
- zygote进程启动时进程进入loop状态,当收到客户端socket请求后便被唤醒,读取app进程参数,通过native层的fork机制创建app进程,并返回对应的pid。
初始化主线程
应用进程创建完后会执行ActivityThread.main()
,看下这部分内容:
1 | android.app.ActivityThread |
从上面可以看到执行了Looper的prepare和loop方法,开启了主线程消息队列的轮询,做法和我们在子线程初始化Handler的逻辑是一样的。
初始化Application
Application初始化流程内容也比较多,这里先列一下主要的方法调用栈,后续对部分细节不了解可以参考这个调用栈自行跟进学习。
方法调用栈
1 | - ActivityThread.main() |
ActivityThread:
前面讲主线程初始化时,在代码ActivityThread.attach()
的注释中提到内部会初始化Application,看下这部分逻辑:
1 | android.app.ActivityThread |
上面ActivityThread.attach()
主要做了三件事:
- 在AMS中创建Application,具体实现在
ActivityManagerService.attachApplication()
- 添加GC监听器,系统触发GC时,占用内容量超过进程总量3/4时尝试进行内存释放
- 为ViewRootImpl,即跟View添加Config回调
AMS:
重点看下ActivityThread.attach()
中第一件事ActivityManagerService.attachApplication()
的实现逻辑:
1 | com.android.server.am.ActivityManagerService |
看下上面代码attachApplicationLocked()
的实现:
1 | com.android.server.am.ActivityManagerService |
ActivityStackSupervisor:
上面代码执行了mStackSupervisor.attachApplicationLocked()
:
1 | com.android.server.am.ActivityStackSupervisor |
看下上面代码中ActivityStackSupervisor.realStartActivityLocked()
的逻辑:
1 | com.android.server.am.ActivityStackSupervisor |
上面代码中为ClientTransaction对象添加callback,即LaunchActivityItem。然后设置当前的生命周期状态,最后调用ClientLifecycleManager.scheduleTransaction()
。scheduleTransaction()
内部执行ClientTransaction.schedule()
:
1 | android.app.servertransaction.ClientTransaction |
上面方法中的mClient对象,代码中可以只能看到声明类型是IApplicationThread
,实际上其实现类是ActivityThread.ApplicationThread
。这个点跟下下面代码流程就可以知道这个内容:
1 | - ActivityThread.main() |
下面看看ClientTransaction的执行逻辑。
ClientTransaction:
Android9.0之后,系统引入了ClientTransaction来辅助管理应用及页面生命周期。
继上面接着讲ClientTransaction.schedule()
,内部执行mClient.scheduleTransaction(this)
。上面讲到mClient
实现类是ActivityThread.ApplicationThread
,那看下ActivityThread.ApplicationThread.scheduleTransaction()
。该方法内部实现比较简单,主要是执行了下面的代码调用:
1 | - ActivityThread.ApplicationThread.scheduleTransaction() |
看下上面方法调用栈中的ClientTransactionHandler.scheduleTransaction()
:
1 | public abstract class ClientTransactionHandler { |
上面sendMessage()
的实现在子类ActivityThread中:
1 | android.app.ActivityThread |
所以,从ClientTransactionHandler.scheduleTransaction()
和ActivityThread.sendMessage()
这两个方法的实现我们可以知道,其实是向ActivityThread.mH
发送个消息,msg.what为EXECUTE_TRANSACTION,object为ClientTransaction。
关于ActivityThread.mH中如何处理消息及ClientTransaction的我们后续会讲到。
总结:
- 从ActivityThread.main()开始,经过ActivityManagerService、ActivityStackSupervisor,最后通过ClientTransaction把LaunchActivityItem组装为ClientTransaction的一个Callback
- ClientTransaction通过
ActivityThread.ApplicationThread
给ActivityThread.mH发送主线程消息,其中消息的what为EXECUTE_TRANSACTION,object为ClientTransaction - 在执行消息任务时执行ClientTransaction的Callback,即LaunchActivityItem,其内部发起Application、launch activity相关初始化流程,这部分后面会讲到
ActivityThread.mH:
ActivityThread.mH接收到msg.what == EXECUTE_TRANSACTION
的消息后执行TransactionExecutor.execute()
,代码如下:
1 | android.app.ActivityThread.H |
在mTransactionExecutor.execute()
内部会执行ClientTransaction中的Callback回调方法execute()
。这里的Callback就是LaunchActivityItem。
LaunchActivityItem:
看下LaunchActivityItem的execute()
的逻辑:
1 | android.app.servertransaction.LaunchActivityItem |
ActivityThread.handleLaunchActivity()
上面代码中,client的实现类是ActivityThread
,ActivityThread.handleLaunchActivity()
的主要实现逻辑在ActivityThread.performLaunchActivity()
:
1 | android.app.ActivityThread |
上面这段代码主要做Application、Activity、Context的初始化,建立三者之间的关系,执行Activity、Fragment的onCreate生命周期方法:
- 通过Intent解析Component,为实例化目标Activity做准备
- 利用Instrument实例化目标Activity,启动阶段将实例化luanch activity
- 初始化Application和Context,并将Context attach到Application。内部会执行Application的attachBaseContext()、onCreate()
- 将前面实例化的Activity对象进行相关初始化工作,包括创建Window、绑定mApplication/mIntent等
- 给Activity设置主题
- 调用Activity.onCreate(),如果Activity中有Fragment,则执行Fragment.onCreate()
总结
App整体启动流程内容比较多,可以通过Launcher响应屏幕点击、应用进程的创建、Application初始化这三部分来理解。
由Launcher响应用户点击屏幕应用Icon事件
system server进程通过socket建立与zygote的通信,从AMS.startProcess()开始为目标APP申请创建进程
zygote进程被system server进程的socket连接请求唤醒,在native层fork目标进程
应用进程创建后执行ActivityTread.main(),先初始化主线程,再实例化Application对象,并启动launch Activity