android activity启动流程_App 竟然是这样跑起来的 —— Android App/Activity 启动流程分析...

v2-3f05687a494d890c6ea4b6e4daddcd34_1440w.jpg?source=172ae18b

在我的上一篇文章:

AJie:按下电源键后竟然发生了这一幕 —— Android 系统启动流程分析​zhuanlan.zhihu.com
v2-63b2f1010eb8e109b6fb7a224bd70faa_180x120.jpg

我们分析了系统在开机以后的一系列行为,其中最后一阶段 AMS(ActivityManagerService) 会启动 Launcher 来展示我们手机中所有已安装的应用图标,点击图标后相应的应用程序将会被系统启动运行并展示在我们面前,那么,点击了图标之后系统道理做了哪些工作呢?应用进程是怎么被启动的呢?Activity 的生命周期是什么时候被谁调用的呢?本文将继续基于 Android Nougat 的 frameworks 层源码的解答这些问题。

阅读建议: 如果你是首次阅读这个过程的源码,建议你忽略一些细枝末节的代码,先抓主干代码,从整体上理解代码的执行流程(右下角文章目录视图中可以点击跳转到相应章节),否则将会被细节的代码扰乱思路。最后可以回头多看几遍,这时候如果有需要可以追踪一些枝干代码,做到融会贯通。

1. Launcher —— AMS

1.1 调用过程分析

1.1.1 Launcher.onClick

在 Launcher app 的主 Activity —— Launcher.java 中,App 图标的点击事件最终会回调 Launcher.java 中的 onClick 方法,

packages/apps/Launcher3/src/com/android/launcher3/Launcher.java:

public 

1.1.2 Launcher.onClickAppShortcut

如果是快捷方式图标,则调用 onClickAppShortcut 方法进而调用 startAppShortcutOrInfoActivity 方法:

@Thunk 

1.1.3 Launcher.startActivity

获取相应 App 的 Intent 信息之后,调用 startActivity 方法:

private 

1.1.4 Activity.startActivity

这里最终调用了 Activity 中的 startActivity 方法,并且设置 Flag 为 FLAG_ACTIVITY_NEW_TASK。到此为止,已经跟启动普通的 Activity 流程汇合起来了,继续往下分析。

frameworks/base/core/java/android/app/Activity.java:

@Override

1.1.5 Activity.startActivityForResult

调用 Activity 的 startActivityForResult 方法

public 

1.1.6 Instrumentation.execStartActivity

frameworks/base/core/java/android/app/Instrumentation.java:

public 

1.1.7 ActivityManagerProxy.startActivity

以上过程是在 Launcher App 所在的进程中发生的,在我的另外一篇文章

AJie:借助 AIDL 理解 Android Binder 机制——AIDL 的使用和原理分析​zhuanlan.zhihu.com
v2-d537760920dccb5b376b8b5754fed420_180x120.jpg

中我们分析了 AIDL 的实现过程,由于远程 Service 跟使用 Service 的 Activity 不在同一个进程中,因此他们之间交互需要通过 Binder IPC 机制的支持,在这个过程中Client 首先获取到 Server 端的代理对象,在 Client 看来 Server 代理对象同样具有 Server 本地对象承诺的能力,因此 Client 可以调用 Server 代理对象跟 Sever 本地对象进行数据交互,Binder 驱动作为桥梁在他们中间起到中间人的作用。

在Android 系统启动流程分析中曾经分析过,AMS 是运行在 system_server 线程中的,这时 AMS 就相当于 AIDL 中的远程 Service,App 进程要与 AMS 交互,需要通过 AMS 的代理对象 AMP(ActivityManagerProxy) 来完成,来看 ActivityManagerNative.getDefault() 拿到的是什么:

frameworks/base/core/java/android/app/ActivityManagerNative.java:

static 

getDefault 是一个静态变量:

private 

同样,在文章

AJie:借助 AIDL 理解 Android Binder 机制——Binder 来龙去脉​zhuanlan.zhihu.com
v2-d537760920dccb5b376b8b5754fed420_180x120.jpg

中也讲到过:

ServiceManager 是 Binder IPC 通信过程的核心,是上下文的管理者,Binder 服务端必须先向 ServerManager 注册才能够为客户端提供服务,Binder 客户端在与服务端通信之前需要从 ServerManager 中查找并获取 Binder 服务端的引用。

这里通过 "activity" 这个名字向 ServiceManager 查询 AMS 的引用,获取 AMS 的引用后,调用 asInterface 方法:

static 

因为 AMS 与 Launcher App 不在同一个进程中,这里返回的 IBinder 对象是一个 Binder 代理对象,因此这类将其包装成 AMP(ActivityManagerProxy) 对象并返回,AMP 是 AMN(ActivityManagerNative) 的内部类,查看 AMP 类 :

class 

可以看到,AMP 里面将客户端的请求通过 mRemote.transact 进行转发,mRemote 对象正是 Binder 驱动返回来的 Binder Proxy 对象,通过 Binder Proxy,Binder 驱动最终将调用处于 Binder Server 端 AMN 中的 onTransact 方法:

@Override

1.1.8 ActivityManagerService.startActivity

AMN 是一个抽象类,它的 startActivity 为抽象方法,具体的实现在 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java 中:

@Override

1.2 小结

从 Launcher App 到 AMS 的调用过程中使用了 Binder IPC 机制,如果你已经看了上面提到的我之前写的两篇文章——借助 AIDL 理解 Android Binder 机制——Binder 来龙去脉和借助 AIDL 理解 Android Binder 机制——AIDL 的使用和原理分析,并且运行了文章中使用到的 Demo,你应该可以发现,相对于 AIDL 的调用过程,调用方 Launcher App 相当于 AIDL 过程中的 Activity 所在的 App,充当 Clinent 的角色;AMS 相当于远程 Service 的角色,充当 Server 端角色,他们的调用过程总体上都是一样的。

从 Launcher App 到 AMS 的时序图如下:

v2-50d1f49f757dd9c35bf4b48dd654d8cb_b.jpg

2. AMS —— zygote

2.1 调用过程分析

2.1.1 ActivityManagerService.startActivityAsUser

接着从 AMS 的 startActivityAsUser 方法开始分析:

@Override

2.1.2 ActivityStarter.startActivityMayWait

继续跟进 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java:

final 

2.1.3 ActivityStarter.startActivityLocked

查看 startActivityLocked 方法:

final 

2.1.4 ActivityStarter.doPendingActivityLaunchesLocked

查看 doPendingActivityLaunchesLocked 方法:

final 

2.1.5 ActivityStarter.startActivityUnchecked

查看 startActivityUnchecked 方法:

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
    ...  
    // 调用 ActivityStackSupervisor 的 resumeFocusedStackTopActivityLocked 方法
    mSupervisor.resumeFocusedStackTopActivityLocked();  
    ... 
    return START_SUCCESS;
}

2.1.6 ActivityStackSupervisor.resumeFocusedStackTopActivityLocked

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java:

boolean 

2.1.7 ActivityStack.resumeTopActivityUncheckedLocked

查看 ActivityStack 的 resumeTopActivityUncheckedLocked 方法:

boolean 

2.1.8 ActivityStack.resumeTopActivityInnerLocked

查看 resumeTopActivityInnerLocked 方法:

private 

2.1.9 ActivityStackSupervisor.startSpecificActivityLocked

回到 ActivityStackSupervisor 的 startSpecificActivityLocked 方法:

void 

首先,在方法中获取了当前 Activity 附属的 Application,如果已经在运行了,说明这个 App 是已经被启动过了的,这时候调用 realStartActivityLocked 方法就可以进入下一步的流程了,同一个 App 中不同 Activity 的相互启动就是走的这个流程。当 Application 没有运行的时候,就需要调用 AMS 的 startProcessLocked 方法启动一个进程去承载它然后完成后续的工作,顺便铺垫一下,当新进程被启动完成后还会调用回到这个方法,查看 AMS 的 startProcessLocked 方法:

2.1.10 ActivityManagerService.startProcessLocked

final 

2.1.11 ActivityManagerService.startProcessLocked

调用 startProcessLocked 方法:

final 

2.1.12 ActivityManagerService.startProcessLocked

调用 startProcessLocked 的重载方法:

private 

2.1.13 Process.start

frameworks/base/services/core/java/android/os/Process.java:

public 

2.1.14 Process.startViaZygote

查看 startViaZygote 方法:

private 

2.1.15 Process.zygoteSendArgsAndGetResult、Process.openZygoteSocketIfNeeded

查看 zygoteSendArgsAndGetResult 方法:

private 

在 zygoteSendArgsAndGetResult 中等待 Socket 服务端,也就是 zygote 进程返回创建新进程的结果,这里 zygoteState 参数是由 openZygoteSocketIfNeeded 方法返回的,openZygoteSocketIfNeeded 方法则负责根据 abi 向 Zygote 进程发起连接请求:

private 

2.2 小结

如果是从桌面新启动一个 App 中的 Activity,此时是没有进程去承载这个 App 的,因此需要通过 AMS 向 zygote 继承发起请求去完成这个任务,AMS 运行在 system_server 进程中,它通过 Socket 向 zygote 发起 fock 进程的请求,从 AMS 开始的调用时序图如下:

v2-2ce49d58480de90c661e00d2bc27840b_b.jpg

3. zygote —— ActivityThread

3.1 调用过程分析

3.1.1 ZygoteInit.main

在 Android 系统启动流程分析 文中提到过 zygote 进程的其中一项任务就是:

调用 registerZygoteSocket() 函数建立 Socket 通道,使 zygote 进程成为 Socket 服务端,并通过 runSelectLoop() 函数等待 ActivityManagerService 发送请求创建新的应用程序进程。

zygote 终于要再次上场了!接下来从 ZygoteInit.java 的 main 方法开始回顾一下 zygote 进程的工作:

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java:

public 

3.1.2 ZygoteInit.runSelectLoop

查看 runSelectLoop 方法:

private 

3.1.3 ZygoteConnection.runOnce

查看 frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java 的 runOnce 方法:

boolean 

3.1.4 ZygoteConnection.handleChildProc

首先解析 Socket 客户端传过来的参数,Zygote.java 的 forkAndSpecialize 返回的 pid == 0 的时候表示此时在 fock 出来的子进程中执行,继续调用 handleChildProc 方法,并将参数继续层层传递:

private 

3.1.5 RuntimeInit.zygoteInit

查看 frameworks/base/core/java/com/android/internal/os/RuntimeInit.java 的 zygoteInit 方法:

public 

3.1.6 RuntimeInit.applicationInit

继续调用 applicationInit 方法:

private 

3.1.7 RuntimeInit.invokeStaticMain

主要调用了 invokeStaticMain 方法:

private 

3.1.8 MethodAndArgsCaller.run

回到 ZygoteInit 的 main 方法:

public 

跟 system_server 进程的启动过程一样,这里同样通过抛出异常的方式来清空调用 ActivityThread.main 之前的方法栈帧。

ZygoteInit 的 MethodAndArgsCaller 类是一个 Exception 类,同时也实现了 Runnable 接口:

public 

3.1.9 ActivityThread .main

最后通过反射调用到 ActivityThread 的 main 方法:

public 

3.2 小结

zygote 进程作为 Socket 服务端在接收到作为客户端的 AMS 发送过来的请求和参数之后,fock 出新的进程并根据各种参数进程了初始化的工作,这个过程和 zygote 启动 system_server 进程的过程如出一辙,时序图如下所示:

v2-8335460e744915d135ac1f5155d98c32_b.jpg

4. ActivityThread —— Activity

4.1 调用过程分析

4.1.1 ActivityThread.attach

上一小节的最后,ActivityThread 的 main 通过反射被运行起来了,接着会调用 ActivityThread 的 attach 方法:

private 

这里,我们再一次通过 Binder IPC 机制跟 AMS 通信,通信模型跟前面 Launcher App 调用 AMS 的 startActivity 方法一样,getDefault 过程不重复分析,这次是调用了 AMS 的 attachApplication 方法,注意这里将 ApplicationThead 类型的 mAppThread 对象作为参数传递了过去,ApplicationThead 是 ActivityThread 的一个内部类,后面我们会讲到,先查看 AMP 的 attachApplication 方法:

4.1.2 ActivityManagerProxy.attachApplication

public 

4.1.3 ActivityManagerNative.onTransact

public 

asInterface 将 ActivityThread 对象转换成了 ApplicationThreadNative(ATN) 的 Binder 代理对象 ApplicationThreadProxy(ATP),并作为参数传给 attachApplication 方法,其中 ATP 是 ATN 的内部类。

4.1.4 ActivityManagerService.attachApplication

public 

4.1.5 ActivityManagerService.attachApplicationLocked

private 

首先,通过 ATP 使用 Binder 向 ATN 发起 bindApplication 请求,然后通过 normalMode 字段判断是否为 Activity,如果是则执行 ActivityStackSupervisor 的 attachApplicationLocked 方法。

4.1.5.1 ActivityThread.java::ApplicationThread.bindApplication

thread 对象类型是 ATP,通过 Binder 驱动调到了 ATN 的方法,ATN 是一个抽象类,它的实现都委托给了 ApplicationThread(这跟 AMS 跟 AMN 的关系一样),ApplicationThread 作为 ActivityThread 的内部类存在,它的 binderApplication 方法如下:

ActivityThread.java::ApplicationThread:

public 

H 是 ActivityThread 中的一个 Handler 对象,用于处理发送过来的各种消息:

private 

调用了 handleBindApplication 方法:

private 

4.1.5.2 ActivityStackSupervisor.attachApplicationLocked

4.1.4 小节中通过 Binder 向 ActivityThread 发起 bindApplication 请求后,会根据启动组件的类型去做相应的处理,如果是 Acitivity,则会调用 ActivityStackSupervisor 的 attachApplicationLocked 方法:

boolean 

4.1.5.2.1 ActivityStackSupervisor.realStartActivityLocked

前面 2.1.8 ActivityStackSupervisor.startSpecificActivityLocked 小节中分析过,如果当前 Activity 依附的 Application 已经被启动,则调用 realStartActivityLocked 方法,否则创建新的进程,再创建新的进程之后,两个流程的在这里合并起来了:

final 

这里有一次使用 Binder 调用 ApplicationThread 的 scheduleLaunchActivity 方法。

4.1.5.2.2 ApplicationThread.scheduleLaunchActivity

public 

上面提到过,H 是 ActivityThread 中一个 Handler 类,它接收到 LAUNCH_ACTIVITY 消息后会调用 handleLaunchActivity 方法。

4.1.5.2.3 ActivityThread.handleLaunchActivity

private 

4.1.4.2.4 ApplicationThread.performLaunchActivity

private 

4.1.5.2.5 Instrumentation.callActivityOnCreate

public 

4.1.5.2.6 Activity.performCreate

final 

终于,onCreate 方法被调用了!!!

4.2 小结

从 ActivityThread 到最终 Activity 被创建及生命周期被调用,核心过程涉及到了三次 Binder IPC 过程,分别是:ActivityThread 调用 AMS 的 attachApplication 方法、AMS 调用 ApplicationThread 的 bindApplication 方法、ASS 调用 Application 的 attachApplicationLocked 方法,整个过程的时序图如下:

v2-d69321034752cc14c89a5c27417a6fc0_b.jpg

5. 总结

纵观整个过程,从 Launcher 到 AMS、从 AMS 再到 Zygote、再从 Zygote 到 ActivityThread,最后在 ActivitThread 中层层调用到 Activity 的生命周期方法,中间涉及到了无数的细节,但总体上脉络还是非常清晰的,各个 Android 版本的 Framework 层代码可以某些过程的实现不太一样,但是整个调用流程大体上也是相同的,借用 Gityuan 大神的一张图作为结尾:

v2-1ba96cc3216a47e04b9a220ea1eb64a3_b.jpg

系列文章

AJie:按下电源键后竟然发生了这一幕 —— Android 系统启动流程分析​zhuanlan.zhihu.com
v2-63b2f1010eb8e109b6fb7a224bd70faa_180x120.jpg
AJie:App 竟然是这样跑起来的 —— Android App/Activity 启动流程分析​zhuanlan.zhihu.com
v2-3f05687a494d890c6ea4b6e4daddcd34_180x120.jpg
AJie:屏幕上内容究竟是怎样画出来的 —— Android View 工作原理详解​zhuanlan.zhihu.com
v2-39bc41dca1987ab9ad0f4c7bde5264dc_ipico.jpg

参考文章

startActivity启动过程分析 - Gityuan博客 | 袁辉辉的技术博客

Android深入四大组件(一)应用程序启动过程(前篇)

如果你对文章内容有疑问或者有不同的意见,欢迎留言,我们一同探讨。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值