Kotlin进阶-10-Activity的启动流程

目录

1、介绍

2、Launcher 请求 AMS 过程

3、 AMS 到 ApplicationThread的调用过程

4、ActivityThread 启动 Activity 的过程

5、根 Activity 启动过程中涉及的进程


1、介绍

Activity的启动过程分为两种,一种是根Activity的启动过程,另一种是普通Activity的启动过程。根Activity指的是应用程序启动的第一个Activity,因此根Activity的启动过程一般情况下也可以理解为应用程序的启动过程。普通Activity指的是除应用程序启动的第一个Activity之外的其他Activity。

根Activity的启动过程比较复杂,因此这里分为 3 个部分来讲,分别是 :

1、Launcher 请求 AMS 过程

2、AMS 到 ApplicationThread 的调用过程

3、ActivityThread 启动 Activity

2、Launcher 请求 AMS 过程

在Android系统中,Launcher的重要作用有两点:
(1)作为Android系统的启动器,用来启动应用程序。
(2)作为Android系统的桌面,用于显示和管理应用程序的快捷图标或者其他桌面组件。

当 Luancher 启动后会将已安装应用程序的快捷图标显示到桌面上,这些应用程序的快捷图标就是启动根Activity的入口,当我们点击某个应用程序的快捷图标时,就会通过 Launcher 请求 AMS 来启动该应用程序。Launcher 请求 AMS 的时序图如图所示:

1、当我们点击应用程序的快捷图标时,就会调用 Launcher 的 startActivitySafely 方法,如下所示:

该类在该包内:packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

2、在红色框内处将 Flag 设置为 Intent.FLAG_ACTIVITY_NEW_TASK ,这样根 Activity 会在新的任务栈中启动;

在蓝色框处会调用 startActivity() 方法,这个 startActivity() 方法在 Activity 中实现,如下所示:

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

3、在 startActivity 方法中调用 startActivityForResult 方法,它的第二个参数为 -1,表示 Launcher 不需要知道 Activity 启动的结果,startActivityForResult 方法的代码如下所示:

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

4、上面的 mParent 是 Activity 类型的,表示当前 Activity 的父类。因为目前根 Activity 还没有创建出来,因此,mParent == null 成立。

接着调用 InstrumentationexecStartActivity() 方法,Instrumentation 主要用来监控应用程序和系统的交互,execStartActivity() 方法的代码如下所示:

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

5、首先调用 ActivityManager 的 getService() 方法来获取 AMS 的代理对象,按着调用它的 startActivity 方法。

这里与 Android 8.0 之前代码的逻辑有些不同,Android 8.0 之前是通过 ActivityManagerNative 的 getDefault 来获取 AMS 的代理对象的,现在这个逻辑封装到了 ActivityManager 中而不是 ActivityManagerNative 中。

首先我们来查看 ActivityManager 的 getService 方法做了什么:

frameworks/base/core/java/android/app/ActivityManager.java

6、getService() 方法调用了 IActivityManagerSingleton 的 get() 方法,我们接着往下看,IActivityManagerSingleton 是一个 Singleton 类。

在红框中第一行处得到名为 "activity" 的 Service 引用,也就是 IBinder 类型的 AMS 的引用。

接着在红框中第二行处将它转换成 IActivityManager 类型的对象,这段代码采用的是 AIDL,IActivityManager.java 类是由 AIDL 工具在编译时自动生成的,IActivityManager.aidl 的文件路径为 frameworks/base/core/java/android/app/IActivityManager.aidl

要实现进程间通信,服务器端也就是 AMS 只需要继承 IActivityManager.Stub 类并实现相应的方法就可以了。

注意 Android 8.0 之前并没有采用 AIDL,而是采用了类似 AIDL 的形式,用 AMS 的代理对象 ActivityManagerProxy 来与 AMS 进行进程间通信,Android 8.0 去除了 ActivityManagerNative 的内部类 ActivityManagerProxy,代替它的是 IActivityManager,它是 AMS 在本地的代理。

回到 Instrumentation 类的 execStartActivity 方法中,从上面得知 execStartActivity 方法最终调用的是 AMS 的 startActivity 方法。

3、 AMS 到 ApplicationThread的调用过程

Luancher 请求 AMS 后,代码逻辑已进入 AMS 中,接着是 AMS 到 ApplicationThread 的调用流程,时序图如果所示:

7、AMS中的startActivity()方法如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

8、在 AMS 的 startActivity() 方法中返回了 startActivityAsUser() 方法,可以发现 startActivityAsUser() 方法比 startActivity() 方法多了一个参数 UserHandle.getCallingUserId(),这个方法会获得调用者的 UserId,AMS 根据这个 UserId 来确定调用者的权限

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

9、在黄色框处判断调用者进程是否被隔离,如果被隔离则抛出 SecurityException 异常,

在绿色框 处检查调用者是否有权限,如果没有权限也会抛出 SecurityException 异常。

最后通过 mActivityStartController.obtainStarter()获取到了ActivityStarter对象,并执行了它的execute()方法。

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

10、在上面execute()方法中会通过mRequest.mayWait字段来判断最后执行startActivityMayWait()或者startActivity().(这一步是在Android9.0添加的)

mRequest.mayWait字段的值,在ActivityManagerService中调用execute()的前,就调用了setMayWait()方法赋值为了true。

最后调用了 startActivityMayWait() 方法,startActivityMayWait ()方法的参数要比 startActivityAsUser() 多几个,需要注意的是倒数第三个参数类型为 TaskRecord,代表启动的 Activity 所在的栈。

startActivityMayWait() 方法的代码如下所示:

11、ActivityStarter 是 Android 7.0 中新加入的类,它是加载 Activity 的控制类,会收集所有的逻辑来决定如何将 Intent 和 Flags 转换为 Activity,并将 Activity 和 Task 以及 Stack 相关联。

ActivityStarter 的 startActivityMayWait() 方法调用了 startActivity()方法,如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

12、在上面代码中我们看到会对启动原因 reason进行判断,判断启动的理由不为空,如果为空则抛出 IllegalArgumentException 异常。紧接着又调用了 startActivity 方法,如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

13、ActivityStarter 的 startActivity 方法逻辑比较多,这里列出部分我们需要关心的代码。

在蓝色框 处判断 IApplicationThread 类型的 caller 是否为 null,这个 caller 是方法调用一路传过来的,指向的是 Launcher 所在的应用程序的 ApplicationThread 对象;

在绿色框 处调用 AMS 的 getRecordForAppLocked 方法得到的是代表 Launcher 进程的 callerApp 对象,它是 ProcessRecord 类型的,ProcessRecord 用于描述一个应用程序进程。

同样地,ActivityRecord 用于描述一个 Activity,用来记录一个 Activity 的所有信息。接下来创建 ActivityRecord,用于描述将要启动的 Activity,并在红色框处将创建的 ActivityRecord 赋值给 ActivityRecord [] 类型的 outActivity,

这个 outActivity 会作为最底部 的 startActivity 方法的参数传递下去。

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

14、startActivity 方法紧接着调用了 startActivityUnchecked() 方法:

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

15、startActivityUnchecked 方法主要处理与栈管理相关的逻辑。

根据上文中 startActivitySafely 方法我们得知,启动根 Activity 时会将 Intent 的 Flag 设置为 FLAG_ACTIVITY_NEW_TASK,这样蓝色框 处的条件判断就会满足;

接着执行绿色框处的 setTaskFromReuseOrCreateNewTask 方法,其内部会创建一个新的 TaskRecord,用来描述一个 Activity 任务栈,也就是说 setTaskFromReuseOrCreateNewTask 方法内部会创建一个新的 Activity 任务栈。

在黄色框处会调用 ActivityStackSupervisor 的 resumeFocusedStackTopActivityLocked 方法,如下所示:

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

16、在红色框第一行 处调用 ActivityStack 的 topRunningActivityLocked 方法获取要启动的 Activity 所在栈的栈顶的不是处于停止状态的 ActivityRecord。

在红色框第二行处,如果 ActivityRecord 不为 null,或者要启动的 Activity 的状态不是 RESUMED 状态,就会调用红色框第三行  处的 ActivityStack 的 resumeTopActivityUncheckedLocked 方法。

对于即将启动的 Activity,红色框第二行 处的条件判断是肯定满足的,我们来查看 ActivityStack 的resumeTopActivityUncheckedLocked 方法,如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

17、紧接着查看红色框处 ActivityStack 的 resumeTopActivityInnerLocked 方法:

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

18、resumeTopActivityInnerLocked 方法代码非常多,我们只需要关注调用了 ActivityStackSupervisor 的 startSpecificActivityLocked 方法,代码如下所示。

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

19、在黄色框处获取即将启动的 Activity 所在的应用程序进程;

在绿色框 处判断要启动的 Activity 所在的应用程序进程如果已经运行的话;

就会调用红色框 处的 realStartActivityLocked 方法,这个方法的第二个参数是代表要启动的 Activity 所在的应用程序进程 ProcessRecord。

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

20、这里的 app.thread 指的是 IApplicationThread,它的实现是 ActivityThread 的内部类 ApplicationThread,其中 ApplicationThread 继承了 IApplicationThread.Stub。

app 指的是传入的要启动的 Activity 所在的应用程序进程,因此,这段代码指的就是要在目标应用程序进程启动 Activity。当前代码逻辑运行在 AMS 所在的进程(SystemServer 进程)中,通过 ApplicationThread 来与应用程序进程进行 Binder 通信,换句话说,ApplicationThread 是 AMS 所在进程(SystemServer 进程)和应用程序进程的通信桥梁,如图所示:

4、ActivityThread 启动 Activity 的过程

通过上面的讲解,我们知道目前的代码逻辑已经运行在应用程序进程中。先来查看 ActivityThread 启动 Activity 过程的时序图,如图所示:

21、接着查看 ApplicationThread 的 scheduleLaunchActivity 方法,其中 ApplicationThread 是 ActivityThread 的内部类,应用程序进程创建后会运行代表主线程的实例 ActivityThread,它管理着当前应用程序进程的主线程。

ApplicationThread 的 scheduleLaunchActivity 方法如下所示:

frameworks/base/core/java/android/app/ActivityThread.java

22、scheduleLaunchActivity 方法将启动 Activity 的参数封装成 ActivityClientRecord,sendMessage 方法向 H 类发送类型为 LAUNCH_ACTIVITY 的消息,并将 ActivityClientRecord 传递过去,sendMessage 方法有多个重载方法,最终调用的 sendMessage 方法如下所示:

frameworks/base/core/java/android/app/ActivityThread.java

23、这里的 mH 指的是 H,它是 ActivityThread 的内部类并继承自 Handler,是应用程序进程中主线程的消息管理类。

因为 ApplicationThread 是一个 Binder,它的调用逻辑运行在 Binder 线程池中,所以这里需要用 H 将代码的逻辑切换到主线程中。

H 的代码如下所示:

frameworks/base/core/java/android/app/ActivityThread.java

24、查看 H 的 handleMessage 方法中对 LAUNCH_ACTIVITY 的处理;

在注释 1 处将传过来的 msg 的成员变量 obj 转换为 ActivityClientRecord;

在 注释 2 处通过 getPackageInfoNoCheck 方法获得 LoadedApk 类型的对象并赋值给 ActivityClientRecord 的成员变量 packageInfo。应用程序进程要启动 Activity 时需要将该 Activity 所属的 APK 加载进来,而 LoadApk 就是用来描述已加载的 APK 文件的。

在注释 3 处调用 handleLaunchActivity 方法,代码如下所示:

frameworks/base/core/java/android/app/ActivityThread.java

25、注释 1 处的 performLaunchActivity 方法用来启动 Activity;

注释 2 处的代码用来将 Activity 的状态设置为 Resume。

如果该 Activity 为 null 则会通知 AMS 停止启动 Activity。

下面来查看 performLaunchActivity 方法做了什么:

frameworks/base/core/java/android/app/ActivityThread.java

26、注释 1 处用来获取 ActivityInfo,用于储存代码以及 AndroidManifes 设置的 Activity 和 Receiver 节点信息,比如 Activity 的 theme 和 launchMode。

在注释 2 处获取 APK 文件的描述类 LoadedApk。

在注释 3 处获取要启动的 Activity 的 ComponentName 类,在 ComponentName 类中保存了该 Activity 的包名和类名。

在注释 4 处用来创建要启动 Activity 的上下文环境。

在注释 5 处根据 ComponentName 中储存的 Activity 类名,用类加载器来创建该 Activity 的实例。

在注释 6 处用来创建 Application,makeApplication 方法内部会调用 Application 的 onCreate 方法。

在注释 7 处调用 Activity 的 attach 方法初始化 Activity,在 attach 方法中会创建 Window 对象(PhoneWindow)并与 Activity 自身进行关联。

在注释 8 处调用 Instrumentation 的 callActivityOnCreate 方法来启动 Activity,如下所示:

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

27、注释 1 处调用了 Activity 的 performCreate 方法,代码如下所示:

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

28、在 performCreate 方法中调用 Activity 的 onCreate 方法,讲到这里,根 Activity 就启动了,即应用程序就启动了。根 Activity 启动过程就讲到这里,下面我们来学习根 Activity 启动过程中涉及的进程。

5、根 Activity 启动过程中涉及的进程

根 Activity 启动过程中会涉及 4 个进程,分别是 Zygote 进程、Launcher 进程、AMS 所在的进程(SystemServer进程)、应用程序进程。它们之间的关系如图所示:

首先 Launcher 进程向 AMS 请求创建根进程 Activity,AMS 会判断根 Activity 所需的应用程序进程是否存在并启动,如果不存在就会请求 Zygote 进程创建应用程序进程。

应用程序进程启动后,AMS 会请求创建应用程序进程并启动根 Activity。

其中步骤 2 采用的是 Socket 通信,步骤 1 和步骤 4 采用的是 Binder 通信。

为了更好理解,下面给出这个 4 个进程调用的时序图,如图所示:

 

 

 

                                                                                 学习资料主要来源于《Android进阶解密》 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值