概览
Activity 启动流程比较复杂,分析起来很容易陷入复杂的代码中去,所以我这篇分析文章不会深入的分析代码细节,尽量抛开不重要的东西把启动流程按照重点分成几个部分来分析。
下图是 Activity 启动流程的总览。
(上图红色方块是与 WMS 关联的部分,后面会从这里开始介绍 WMS)
后面我们将以 Android 29 为例,按照上图步骤逐步分析。
Intent 解析到 Activity
调用 startActivity 之后,经过几步辗转最终会调用到 AMS 中,而 AMS 又会调用 ActivityStarter 来启动 Activity。
解析 Intent 的任务将由PackageManagerService#resolveIntent
方法来处理。
Intent 匹配规则太负责了,我本意是想学习启动流程,所以就没深入进去看代码,就这样吧。
通过 Zygote 创建进程
如果目标进程未启动,则会先启动进程,这里先把启动进程的方法调用栈放上来,方便后面分析。
ActivityStackSupervisor#startSpecificActivityLocked
ActivityManagerService$LocalService#startProcess
ProcessList#startProcessLocked
Process#start
ZygoteProcess#start
方法最终是走到了 ZygoteProcess 中,这个类负责创建进程,我们知道 Android 系统的进程由 Zygote 创建,而 ZygoteProcess 实际上是负责与 Zygote 进行通信的类。
ZygoteProcess#attemptUsapSendArgsAndGetResult
方法中打开了一个 LocalSocket 连接,通过这个 Socket 与 Zygote 进行通信。
该 LocalSocket 服务端在 ZygoteServer 中,我们再看下服务端具体是如何做的。
我们主要关注ZygoteServer#runSelectLoop
方法,里面最重要的两行代码如下:
ZygoteConnection connection = peers.get(pollIndex);
final Runnable command = connection.processOneCommand(this);
那我们再跳到ZygoteConnection#processOneCommand
中看看。
Runnable processOneCommand(ZygoteServer zygoteServer) {
...
//处理并应用参数
args = Zygote.readArgumentList(mSocketReader);
parsedArgs = new ZygoteArguments(args);
Zygote.applyUidSecurityPolicy(parsedArgs, peer);
...
pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);
...
if (pid == 0) {
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
handleParentProc(pid, descriptors, serverPipeFd);
return null;
}
}
看到没,找了半天,终于找到了 Zygote,这里主要通过Zygote.forkAndSpecialize
方法来孵化进程,并获取 pid。
forkAndSpecialize 方法主要就是调用了Zygote.nativeForkAndSpecialize
方法,根据名字可以看出来这是一个原生方法,我们就到此为止吧,不继续了。
我们再回到ZygoteConnection#processOneCommand
方法中,进程创建完成后,还会继续调用 handleChildProc 方法,我们顺着这个方法继续看下去。
private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
FileDescriptor pipeFd, boolean