4.1 根Activity的启动过程

Activity的启动过程分为两种,一种是根Activity的启动过程,另一种是普通Activity的启动过程。根Activity指的是应用程序启动的第一个Activity,因此根Activity的启动过程一般情况下也可以理解为应用程序的启动过程。普通Activity指的是除应用程序启动的第一个Activity之外的其他Activity。这里介绍的是根Activity的启动过程,它和普通Activity的启动过程是有重叠部分的,只不过根Activity的启动过程一般情况下指的就是应用程序的启动过程,更具有指导性意义。想要了解普通Activity的启动过程,读者可以参考根Activity的启动过程,自行去阅读源码。

根Activity的启动过程比较复杂,因此这里分为3个部分来讲,分别是Launcher请求AMS过程、AMS到ApplicationThread的调用过程和ActivityThread启动Activity。

4.1.1 Launcher请求AMS过程

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

图4-1 Launcher请求AMS的时序图

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

在注释1处将Flag设置为Intent.FLAG_ACTIVITY_NEW_TASK①,这样根Activity会在新的任务栈中启动。在注释2处会调用startActivity方法,这个startActivity方法在Activity中实现,如下所示:

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

注释1处的mParent是Activity类型的,表示当前Activity的父类。因为目前根Activity还没有创建出来,因此,mParent==null成立。接着调用Instrumentation的execStartActivity方法,Instrumentation 主要用来监控应用程序和系统的交互,execStartActivity 方法的代码如下所示:

首先调用ActivityManager的getService方法来获取AMS的代理对象,接着调用它的startActivity方法。这里与Android 8.0之前代码的逻辑有些不同,Android 8.0之前是通过ActivityManagerNative的getDefault来获取AMS的代理对象的,现在这个逻辑封装到了ActivityManager 中而不是ActivityManagerNative中。首先我们来查看ActivityManager的getService方法做了什么:

getService 方法调用了IActivityManagerSingleton的get方法,我们接着往下看,IActivityManagerSingleton是一个Singleton类。在注释1处得到名为“activity”的Service引用,也就是IBinder类型的AMS的引用。接着在注释2处将它转换成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方法。

4.1.2 AMS 到ApplicationThread的调用过程

Launcher请求AMS后,代码逻辑已经进入AMS中,接着是AMS到ApplicationThread的调用流程,时序图如图4-2所示。

图4-2 AMS到ApplicationThread的调用过程的时序图

AMS的startActivity方法如下所示:

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

在注释1处判断调用者进程是否被隔离,如果被隔离则抛出SecurityException异常,在注释2处检查调用者是否有权限,如果没有权限也会抛出SecurityException异常。最后调用了ActivityStarter的startActivityLocked 方法,startActivityLocked 方法的参数要比startActivityAsUser多几个,需要注意的是倒数第二个参数类型为TaskRecord,代表启动的Activity所在的栈。最后一个参数"startActivityAsUser"代表启动的理由。startActivityLocked方法的代码如下所示:

ActivityStarter是Android 7.0中新加入的类,它是加载Activity的控制类,会收集所有的逻辑来决定如何将Intent和Flags转换为Activity,并将Activity和Task以及Stack相关联。ActivityStarter的startActivityMayWait方法调用了startActivityLocked方法,如下所示:

在注释1处判断启动的理由不为空,如果为空则抛出IllegalArgumentException异常。紧接着又调用了startActivity方法,如下所示:

ActivityStarter的startActivity方法逻辑比较多,这里列出部分我们需要关心的代码。在注释1处判断IApplicationThread类型的caller是否为null,这个caller是方法调用一路传过来的,指向的是Launcher所在的应用程序进程的ApplicationThread对象,在注释2处调用AMS的getRecordForAppLocked方法得到的是代表Launcher进程的callerApp对象,它是ProcessRecord类型的,ProcessRecord用于描述一个应用程序进程。同样地,ActivityRecord用于描述一个Activity,用来记录一个Activity 的所有信息。接下来创建ActivityRecord,用于描述将要启动的Activity,并在注释3处将创建的ActivityRecord赋值给ActivityRecord[]类型的outActivity,这个outActivity会作为注释4处的startActivity方法的参数传递下去。

startActivity方法紧接着调用了startActivityUnchecked方法:

startActivityUnchecked 方法主要处理与栈管理相关的逻辑。在标注①处我们得知,启动根Activity时会将Intent的Flag设置为FLAG_ACTIVITY_NEW_TASK,这样注释1处的条件判断就会满足,接着执行注释2处的setTaskFromReuseOrCreateNewTask方法,其内部会创建一个新的TaskRecord,用来描述一个Activity任务栈,也就是说setTaskFromReuseOrCreateNewTask方法内部会创建一个新的Activity任务栈。Activity任务栈其实是一个假想的模型,并不真实存在,关于Activity 任务栈会在第6章进行介绍。在注释3处会调用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法,如下所示:

在注释1处调用ActivityStack的topRunningActivityLocked方法获取要启动的Activity所在栈的栈顶的不是处于停止状态的ActivityRecord。在注释2处,如果ActivityRecord不为null,或者要启动的Activity的状态不是RESUMED状态,就会调用注释3处的ActivityStack的resumeTopActivityUncheckedLocked方法,对于即将启动的Activity,注释2处的条件判断是肯定满足的,我们来查看ActivityStack的resumeTopActivityUncheckedLocked方法,如下所示:

紧接着查看注释1处ActivityStack的resumeTopActivityInnerLocked方法:

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

在注释1处获取即将启动的Activity所在的应用程序进程,在注释2处判断要启动的Activity所在的应用程序进程如果已经运行的话,就会调用注释3处的realStartActivityLocked方法,这个方法的第二个参数是代表要启动的Activity所在的应用程序进程的ProcessRecord。

这里的app.thread指的是IApplicationThread,它的实现是ActivityThread 的内部类ApplicationThread,其中ApplicationThread继承了IApplicationThread.Stub。app指的是传入的要启动的Activity所在的应用程序进程,因此,这段代码指的就是要在目标应用程序进程启动Activity。当前代码逻辑运行在AMS 所在的进程(SystemServer 进程)中,通过ApplicationThread来与应用程序进程进行Binder通信,换句话说,ApplicationThread是AMS所在进程(SystemServer进程)和应用程序进程的通信桥梁,如图4-3所示。

图4-3 AMS与应用程序进程通信

4.1.3 ActivityThread启动Activity的过程

通过4.1.2节的知识,我们知道目前的代码逻辑运行在应用程序进程中。先来查看ActivityThread启动Activity过程的时序图,如图4-4所示。

图4-4 ActivityThread启动Activity过程的时序图

接着查看ApplicationThread的scheduleLaunchActivity方法,其中ApplicationThread是ActivityThread 的内部类,在3.2.2节中讲过应用程序进程创建后会运行代表主线程的实例ActivityThread,它管理着当前应用程序进程的主线程。ApplicationThread 的scheduleLaunchActivity方法如下所示:

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

这里mH指的是H,它是ActivityThread的内部类并继承自Handler,是应用程序进程中主线程的消息管理类。因为ApplicationThread是一个Binder,它的调用逻辑运行在Binder线程池中,所以这里需要用H将代码的逻辑切换到主线程中。H的代码如下所示:

查看H的handleMessage方法中对LAUNCH_ACTIVITY的处理,在注释1处将传过来的msg的成员变量obj转换为ActivityClientRecord。在注释2处通过getPackageInfoNoCheck方法获得LoadedApk类型的对象并赋值给ActivityClientRecord 的成员变量packageInfo。应用程序进程要启动Activity时需要将该Activity所属的APK加载进来,而LoadedApk就是用来描述已加载的APK文件的。在注释3处调用handleLaunchActivity方法,代码如下所示:

注释1处的performLaunchActivity方法用来启动Activity,注释2处的代码用来将Activity的状态设置为Resume。如果该Activity为null则会通知AMS停止启动Activity。下面来查看performLaunchActivity方法做了什么:

注释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,如下所示:

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

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

4.1.4 根Activity启动过程中涉及的进程

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

图4-5 根Activity启动过程中涉及的进程之间的关系

图4-5在图4-3基础上进行了修改,首先Launcher进程向AMS请求创建根Activity,AMS会判断根Activity所需的应用程序进程是否存在并启动,如果不存在就会请求Zygote进程创建应用程序进程。应用程序进程启动后,AMS 会请求创建应用程序进程并启动根Activity。图4-5中步骤2采用的是Socket通信,步骤1和步骤4采用的是Binder通信。图4-5可能并不是很直观,为了更好理解,下面给出这4个进程调用的时序图,如图4-6所示。

图4-6 根Activity启动过程中进程调用时序图

如果是普通Activity启动过程会涉及几个进程呢?答案是两个,AMS所在进程和应用程序进程。实际上理解了根Activity的启动过程(根Activity的onCreate过程),根Activity和普通Activity其他生命周期状态(比如onStart、onResume等)过程也会很轻松掌握,这些知识点都是触类旁通的,想要具体了解这些知识点的读者可以自行阅读源码,由于篇幅有限这里就不再介绍了。