![Android进阶解密](https://wfqqreader-1252317822.image.myqcloud.com/cover/331/31186331/b_31186331.jpg)
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所示。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer826.jpg?sign=1738995438-y6g2WHVvHWfyzI5wVKXizt24iVrP8fem-0-27d96701e9de1946ab5924cd5bab5f1e)
图4-1 Launcher请求AMS的时序图
当我们点击应用程序的快捷图标时,就会调用Launcher的startActivitySafely方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer827.jpg?sign=1738995438-h7M4vaVoD9qZm4CmjqUorYhqLaT8Ttan-0-a07a01731e777af92dcdb989d4354d4e)
在注释1处将Flag设置为Intent.FLAG_ACTIVITY_NEW_TASK①,这样根Activity会在新的任务栈中启动。在注释2处会调用startActivity方法,这个startActivity方法在Activity中实现,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer828.jpg?sign=1738995438-l59IR15MRtiObksxSuKF25aOUneOcY8n-0-b7baafbce563aa0fc74a3f118dfd9e1c)
在startActivity 方法中会调用startActivityForResult 方法,它的第二个参数为-1,表示Launcher不需要知道Activity启动的结果,startActivityForResult方法的代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer829.jpg?sign=1738995438-ZHYpyqudJAovfHM4HNIfxUJYp5G5GRTG-0-72421632cfdeb67ea3d483e5aa50cc70)
注释1处的mParent是Activity类型的,表示当前Activity的父类。因为目前根Activity还没有创建出来,因此,mParent==null成立。接着调用Instrumentation的execStartActivity方法,Instrumentation 主要用来监控应用程序和系统的交互,execStartActivity 方法的代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer830.jpg?sign=1738995438-f5x8MRzhbxwozUVcYXcdkgtOUV403mGL-0-e3674222ae3a608a79692bd2b27035ae)
首先调用ActivityManager的getService方法来获取AMS的代理对象,接着调用它的startActivity方法。这里与Android 8.0之前代码的逻辑有些不同,Android 8.0之前是通过ActivityManagerNative的getDefault来获取AMS的代理对象的,现在这个逻辑封装到了ActivityManager 中而不是ActivityManagerNative中。首先我们来查看ActivityManager的getService方法做了什么:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer01.jpg?sign=1738995438-2ZLAKe3hwPsRuHUA38lrwU9jWAeLV04u-0-0dee6deb375b1b40bf8f5db0bda6e60c)
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所示。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer02.jpg?sign=1738995438-3VCFSTSo3qvKJeKvkwSw2YuXRUwQ4Uel-0-2ca876e5fe352a790bba95f09575cf72)
图4-2 AMS到ApplicationThread的调用过程的时序图
AMS的startActivity方法如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer03.jpg?sign=1738995438-SMG8fAvR28DCeGambwk5x04g12M4NSMt-0-eadd1138a19c6820eb40713be477b46a)
在AMS的startActivity方法中返回了startActivityAsUser方法,可以发现startActivityAsUser方法比startActivity方法多了一个参数UserHandle.getCallingUserId(),这个方法会获得调用者的UserId,AMS根据这个UserId来确定调用者的权限。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer04.jpg?sign=1738995438-YdHQPY1cyagTurYRjUWQOMRZ8yKRegjx-0-e709f41bb4107615f28248ef049fd1ec)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer05.jpg?sign=1738995438-DGA5vQBmhuS0DHPcRQKG5zMwApCWkwpY-0-83d9dc2624df8438e1c7fb858cbd01f8)
在注释1处判断调用者进程是否被隔离,如果被隔离则抛出SecurityException异常,在注释2处检查调用者是否有权限,如果没有权限也会抛出SecurityException异常。最后调用了ActivityStarter的startActivityLocked 方法,startActivityLocked 方法的参数要比startActivityAsUser多几个,需要注意的是倒数第二个参数类型为TaskRecord,代表启动的Activity所在的栈。最后一个参数"startActivityAsUser"代表启动的理由。startActivityLocked方法的代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer06.jpg?sign=1738995438-bCMfxV3hGI2O0QpadcOe6X8vGkF8iarn-0-90f6893429768e024575a4ff6bf99457)
ActivityStarter是Android 7.0中新加入的类,它是加载Activity的控制类,会收集所有的逻辑来决定如何将Intent和Flags转换为Activity,并将Activity和Task以及Stack相关联。ActivityStarter的startActivityMayWait方法调用了startActivityLocked方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer07.jpg?sign=1738995438-js0glqQ4wvGEAKgcULwFwFjP0trskfoC-0-21eafa0ee54135c7c791d28259f8f317)
在注释1处判断启动的理由不为空,如果为空则抛出IllegalArgumentException异常。紧接着又调用了startActivity方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer08.jpg?sign=1738995438-vrJtqy7KBjD9jTBjwEaNy7YJxC0FlBQN-0-29c3dec5db044ec577deeb63260320ba)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer09.jpg?sign=1738995438-1bAzd8dtYlZeTuEJaHe6tqoSOoc5vPlI-0-e0ce4b36cc87e11f798eeaaade65a6da)
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方法的参数传递下去。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer10.jpg?sign=1738995438-s0F9LE4H56TCo1EG0qpcFd0FIe6vjfPW-0-ab69d2d8c607b99603b65be1aa7adba6)
startActivity方法紧接着调用了startActivityUnchecked方法:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer11.jpg?sign=1738995438-psnnUEvkCEWkzGgjUDtMFtTmOOdRJRBW-0-d3ac5eb727bb226ac2042f21854257bd)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer12.jpg?sign=1738995438-mxgGlt3MSdHMEQ0PkSg0nxEgNbalWeyH-0-3e623bcaafdbbc53db46c7540bf182b9)
startActivityUnchecked 方法主要处理与栈管理相关的逻辑。在标注①处我们得知,启动根Activity时会将Intent的Flag设置为FLAG_ACTIVITY_NEW_TASK,这样注释1处的条件判断就会满足,接着执行注释2处的setTaskFromReuseOrCreateNewTask方法,其内部会创建一个新的TaskRecord,用来描述一个Activity任务栈,也就是说setTaskFromReuseOrCreateNewTask方法内部会创建一个新的Activity任务栈。Activity任务栈其实是一个假想的模型,并不真实存在,关于Activity 任务栈会在第6章进行介绍。在注释3处会调用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer13.jpg?sign=1738995438-jrvNxnlhTYEuhdeM0KfZT6ETrEVR0Oiq-0-5bff79eb53cb9b0a78d6a16ff34f964d)
在注释1处调用ActivityStack的topRunningActivityLocked方法获取要启动的Activity所在栈的栈顶的不是处于停止状态的ActivityRecord。在注释2处,如果ActivityRecord不为null,或者要启动的Activity的状态不是RESUMED状态,就会调用注释3处的ActivityStack的resumeTopActivityUncheckedLocked方法,对于即将启动的Activity,注释2处的条件判断是肯定满足的,我们来查看ActivityStack的resumeTopActivityUncheckedLocked方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer14.jpg?sign=1738995438-1LEUXpDNgPfA4KYr8O6W7gx8w7N7UhHh-0-8495026e09eca42fe19a1d0c5ab6feea)
紧接着查看注释1处ActivityStack的resumeTopActivityInnerLocked方法:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer15.jpg?sign=1738995438-fXiXEQYShcJxcRzqXykntdJ3zdJMGM9l-0-ec64d890e51b0e96a30a6739d9dd4330)
resumeTopActivityInnerLocked 方法代码非常多,我们只需要关注调用了ActivityStackSupervisor的startSpecificActivityLocked方法即可,代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer16.jpg?sign=1738995438-SjcqxsnV9RdoS8c8T3D1xuK6InnYsUF6-0-5a3369d6336b24086b0f2fffd2b3b1c6)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer17.jpg?sign=1738995438-lUaIKwkDH4INaPGdQaBT3LeLfg9N83Jn-0-fd0a5d8a3c0805a2d0157cb821a11125)
在注释1处获取即将启动的Activity所在的应用程序进程,在注释2处判断要启动的Activity所在的应用程序进程如果已经运行的话,就会调用注释3处的realStartActivityLocked方法,这个方法的第二个参数是代表要启动的Activity所在的应用程序进程的ProcessRecord。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer18.jpg?sign=1738995438-BF12sQF46Jo1Tdw10ZF6kpuYqvtJrBuR-0-644a934f0a4444f5b760807e5380778d)
这里的app.thread指的是IApplicationThread,它的实现是ActivityThread 的内部类ApplicationThread,其中ApplicationThread继承了IApplicationThread.Stub。app指的是传入的要启动的Activity所在的应用程序进程,因此,这段代码指的就是要在目标应用程序进程启动Activity。当前代码逻辑运行在AMS 所在的进程(SystemServer 进程)中,通过ApplicationThread来与应用程序进程进行Binder通信,换句话说,ApplicationThread是AMS所在进程(SystemServer进程)和应用程序进程的通信桥梁,如图4-3所示。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer19.jpg?sign=1738995438-ltTK3YXcrY2RKpenS8APwHeqONIA4Hdh-0-534d154e7bf6f0b2f0c4a74f99c37c35)
图4-3 AMS与应用程序进程通信
4.1.3 ActivityThread启动Activity的过程
通过4.1.2节的知识,我们知道目前的代码逻辑运行在应用程序进程中。先来查看ActivityThread启动Activity过程的时序图,如图4-4所示。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer20.jpg?sign=1738995438-gtcPZX00CEPo83qjhNb6ioDsokgEbeQ9-0-1921739a5888f346512ad116e3603943)
图4-4 ActivityThread启动Activity过程的时序图
接着查看ApplicationThread的scheduleLaunchActivity方法,其中ApplicationThread是ActivityThread 的内部类,在3.2.2节中讲过应用程序进程创建后会运行代表主线程的实例ActivityThread,它管理着当前应用程序进程的主线程。ApplicationThread 的scheduleLaunchActivity方法如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer21.jpg?sign=1738995438-bkGBgBNOeTmz5LVJZKStfnCiB7Sv7hR3-0-f4fbb014d45a9f2d02edb8f25c17402b)
scheduleLaunchActivity方法将启动Activity的参数封装成ActivityClientRecord,sendMessage方法向H类发送类型为LAUNCH_ACTIVITY的消息,并将ActivityClientRecord传递过去,sendMessage方法有多个重载方法,最终调用的sendMessage方法如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer22.jpg?sign=1738995438-UfY4Kgr0qLLTexMiCSTNcsuD1F41qSaM-0-5f6635f8a3e820ea23006c8a82812e27)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer23.jpg?sign=1738995438-UmjOfl7aX8yu0RnRNHXj2lpRR78zFdI0-0-4dfd97e25f166eb923882f0cdbfba624)
这里mH指的是H,它是ActivityThread的内部类并继承自Handler,是应用程序进程中主线程的消息管理类。因为ApplicationThread是一个Binder,它的调用逻辑运行在Binder线程池中,所以这里需要用H将代码的逻辑切换到主线程中。H的代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer24.jpg?sign=1738995438-LoiH4zFQoaDAnymYbw5Rv1L29cXprhhI-0-fb812a60d9a18faa30a9435e95919341)
查看H的handleMessage方法中对LAUNCH_ACTIVITY的处理,在注释1处将传过来的msg的成员变量obj转换为ActivityClientRecord。在注释2处通过getPackageInfoNoCheck方法获得LoadedApk类型的对象并赋值给ActivityClientRecord 的成员变量packageInfo。应用程序进程要启动Activity时需要将该Activity所属的APK加载进来,而LoadedApk就是用来描述已加载的APK文件的。在注释3处调用handleLaunchActivity方法,代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer25.jpg?sign=1738995438-JnolNvFyl5BmSiru449QOp2zkRGbNeB8-0-e983a5d8cb51c24760115792e6175bae)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer26.jpg?sign=1738995438-TWZv70072NXa9NyplXPE1ZpQhtITOKU6-0-088d0683bce724db09f1ee83fc3f5b3c)
注释1处的performLaunchActivity方法用来启动Activity,注释2处的代码用来将Activity的状态设置为Resume。如果该Activity为null则会通知AMS停止启动Activity。下面来查看performLaunchActivity方法做了什么:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer27.jpg?sign=1738995438-F1y6v6Lj4OJKxjbS1LMt9HIwvMRKxJmv-0-af401d83403661e00cd2312372df4d03)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer28.jpg?sign=1738995438-b3EXMzGU7vhSWyGvUhnCnT9eIrQQPyA7-0-df19835032dd7c480f49cf1592fed1e5)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer29.jpg?sign=1738995438-rPjsD5WR8KvJECH7wGDC52aGz2kGFZSw-0-ba421fc973908dcd01d68a5af3a25986)
注释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,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer30.jpg?sign=1738995438-FbDtuktNczZZPe6K6qRkY1LhCPapNIvB-0-3973f6e7c356017433e0544acce35a47)
注释1处调用了Activity的performCreate方法,代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer31.jpg?sign=1738995438-tLFYWSsXEeKmTBRgdH3WjLBA6qJkTKBi-0-d3995a209bb01220a64af8eaeb3e9539)
在performCreate方法中会调用Activity的onCreate方法,讲到这里,根Activity就启动了,即应用程序就启动了。根Activity启动过程就讲到这里,下面我们来学习根Activity启动过程中涉及的进程。
4.1.4 根Activity启动过程中涉及的进程
根Activity启动过程中会涉及4个进程,分别是Zygote进程、Launcher进程、AMS所在进程(SystemServer进程)、应用程序进程。它们之间的关系如图4-5所示。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer32.jpg?sign=1738995438-HlKucDx3PJnCbbI1JO1xaikTWgkFrIDP-0-6da6ab38d4eb68d6ecad79cb10992b32)
图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所示。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer33.jpg?sign=1738995438-kRgFaxFcYlGXqmsI0VN5NjgoWvEGo8ZB-0-b26cbb3982e7de88522cd1a0be602e71)
图4-6 根Activity启动过程中进程调用时序图
如果是普通Activity启动过程会涉及几个进程呢?答案是两个,AMS所在进程和应用程序进程。实际上理解了根Activity的启动过程(根Activity的onCreate过程),根Activity和普通Activity其他生命周期状态(比如onStart、onResume等)过程也会很轻松掌握,这些知识点都是触类旁通的,想要具体了解这些知识点的读者可以自行阅读源码,由于篇幅有限这里就不再介绍了。