![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=1739299752-Fy7D165EdGFlf7K7rTkTqZtL46yBbc6i-0-39a2dc26e20faf1bc41ba2c96b8cfcd6)
图4-1 Launcher请求AMS的时序图
当我们点击应用程序的快捷图标时,就会调用Launcher的startActivitySafely方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer827.jpg?sign=1739299752-lK1JvmL17nf50WZ1l4VNM2LNwcKw9Mvi-0-86d9a4f34a9a2c75edd439843dfab2bb)
在注释1处将Flag设置为Intent.FLAG_ACTIVITY_NEW_TASK①,这样根Activity会在新的任务栈中启动。在注释2处会调用startActivity方法,这个startActivity方法在Activity中实现,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer828.jpg?sign=1739299752-TA4AObdUiP3ckrjTE3Uw5Laybti4FBFw-0-404d95718f85af293c724dd1928564d5)
在startActivity 方法中会调用startActivityForResult 方法,它的第二个参数为-1,表示Launcher不需要知道Activity启动的结果,startActivityForResult方法的代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer829.jpg?sign=1739299752-Hs3HR4Bt9d3KVOuIC3A0iqrqI9NfaBNA-0-b970090fe462d7102acca718b2024f31)
注释1处的mParent是Activity类型的,表示当前Activity的父类。因为目前根Activity还没有创建出来,因此,mParent==null成立。接着调用Instrumentation的execStartActivity方法,Instrumentation 主要用来监控应用程序和系统的交互,execStartActivity 方法的代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer830.jpg?sign=1739299752-cFyavpnbOomxgBO9OIUt5jSHi4WZOk3a-0-bdf8b12c2a385ed64bb44b1f3fd00745)
首先调用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=1739299752-fsyZUaA9cypOB7gK93N9JAAn9eKkvPoa-0-ac303c6680204ce4f56bce45541f6245)
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=1739299752-VrCoXcMbnfEy8AX3ETbdls9chJGok8dM-0-452339f619ee07181082a152f1e242ba)
图4-2 AMS到ApplicationThread的调用过程的时序图
AMS的startActivity方法如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer03.jpg?sign=1739299752-0ZuKtEUGn7L7QZgiXJKznJbk3HZJL9JL-0-2da9ae7710dd8899edc8e97744048022)
在AMS的startActivity方法中返回了startActivityAsUser方法,可以发现startActivityAsUser方法比startActivity方法多了一个参数UserHandle.getCallingUserId(),这个方法会获得调用者的UserId,AMS根据这个UserId来确定调用者的权限。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer04.jpg?sign=1739299752-RQ3tqVNHHHiESOTifZXWcwijXXcHMojD-0-c62e75600634fb3acbc014ca8c1e9069)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer05.jpg?sign=1739299752-rwZZJJtWGqXCuUy37g5q7jAGQbsAccDp-0-7b2f8532a46744854482fb0319a4c768)
在注释1处判断调用者进程是否被隔离,如果被隔离则抛出SecurityException异常,在注释2处检查调用者是否有权限,如果没有权限也会抛出SecurityException异常。最后调用了ActivityStarter的startActivityLocked 方法,startActivityLocked 方法的参数要比startActivityAsUser多几个,需要注意的是倒数第二个参数类型为TaskRecord,代表启动的Activity所在的栈。最后一个参数"startActivityAsUser"代表启动的理由。startActivityLocked方法的代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer06.jpg?sign=1739299752-3AatZkHOZhuRmob38yH9HDnR8iR8ZesJ-0-3574e68c0e37c1986725cfad776da124)
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=1739299752-ZoHtplLqQEEE0yKt8tbC51SL7Ld6x14w-0-4e664139312b0836305d75df978eb891)
在注释1处判断启动的理由不为空,如果为空则抛出IllegalArgumentException异常。紧接着又调用了startActivity方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer08.jpg?sign=1739299752-nspnIbdb6XudqaFKaAJDn6CrMutjKHkU-0-2071c4d5ecd301ae242bf6b3f2a34df4)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer09.jpg?sign=1739299752-Phn3KcAzb7PdRbzQ6byhXPqiQHSQ5L8l-0-9e6124fbc425f81d82c52e6b16eb69a2)
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=1739299752-yDSJv6m8QfbQohHvmuYoOb3oRqK9d6XK-0-08904a7aacaede95bba51d11e74fc3f9)
startActivity方法紧接着调用了startActivityUnchecked方法:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer11.jpg?sign=1739299752-5J16t7jhjailKf7LMbi7T62T3NlW4DQV-0-2a1c49f95a3bf273bf2e12528defaf8a)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer12.jpg?sign=1739299752-p4RY5WdYFqA6sU6fNkmmv2czACGJCyQk-0-67f3b96362196cbf3b10858e4385cfbb)
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=1739299752-TJqHfGhUzojQ4g2PqgPewJXNoyvDRf6y-0-0736e25938a7ccc2b30a25bf10ca2df6)
在注释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=1739299752-K9UnrMXFtpghJtnkSMqtPu0KnJmVl12I-0-8a445f83337bd5827278ae0fef86fb0f)
紧接着查看注释1处ActivityStack的resumeTopActivityInnerLocked方法:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer15.jpg?sign=1739299752-cyVRY9wgCo7CNEeSGR2zoVBWi3bJ48M9-0-1740daab025e46ffd86f21edb26a5f62)
resumeTopActivityInnerLocked 方法代码非常多,我们只需要关注调用了ActivityStackSupervisor的startSpecificActivityLocked方法即可,代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer16.jpg?sign=1739299752-OoPsUgCPGDscE0suahCYOYH99psvee5n-0-c753bc14fea622d5eb21438264f34e21)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer17.jpg?sign=1739299752-87MUxg7TPUzXgtPeqwKU4pgHrFwX86T9-0-24fc2905dc8f4ff40907fc98838ffc89)
在注释1处获取即将启动的Activity所在的应用程序进程,在注释2处判断要启动的Activity所在的应用程序进程如果已经运行的话,就会调用注释3处的realStartActivityLocked方法,这个方法的第二个参数是代表要启动的Activity所在的应用程序进程的ProcessRecord。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer18.jpg?sign=1739299752-xouxmmEdTUFcHo62MGvEEqWniVBtO5Np-0-3d967812e6e6336df5d1f9b6076899b8)
这里的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=1739299752-1sH5GS3AuJGoGBksFCvOcJmulbmpDmmM-0-fff1dfb0e7777c64c50b9d5064b24b05)
图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=1739299752-OiFvT4Z0kQ8pDeDvdTptN91nrqNEeYzn-0-486180afc60de4ebca8539878f625b17)
图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=1739299752-5elrHYfskiU8ZnOuv2Q5srn6Iwi3Cx9M-0-db97d3b0473d9f9441ecf293abeec821)
scheduleLaunchActivity方法将启动Activity的参数封装成ActivityClientRecord,sendMessage方法向H类发送类型为LAUNCH_ACTIVITY的消息,并将ActivityClientRecord传递过去,sendMessage方法有多个重载方法,最终调用的sendMessage方法如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer22.jpg?sign=1739299752-Rf3NYrdDDPhGabsFDJPni0AvkzASsjVx-0-b9e5d0337e0b7ddb7b7b0bb39a19becc)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer23.jpg?sign=1739299752-HJbeBmyIbkdCsRFzTZDqAIfKi5aUbtQJ-0-3596ba3d235a1835f1cd183cc9dc52ce)
这里mH指的是H,它是ActivityThread的内部类并继承自Handler,是应用程序进程中主线程的消息管理类。因为ApplicationThread是一个Binder,它的调用逻辑运行在Binder线程池中,所以这里需要用H将代码的逻辑切换到主线程中。H的代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer24.jpg?sign=1739299752-awqGVTqVVlS4WVz0Qgr4TO2ijXloIwS9-0-ef3a61d50a5a402b9167e4d847499fdd)
查看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=1739299752-b0TmKFj8hvVqUITrY3giPEfFRLPPLABk-0-6931761c35e9a5c4a29b42c44eda80c1)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer26.jpg?sign=1739299752-eXPKCmUTgVAxHftK2jznha8l73NIQ41W-0-f8aedd76e2ecf6c064f2563e55459491)
注释1处的performLaunchActivity方法用来启动Activity,注释2处的代码用来将Activity的状态设置为Resume。如果该Activity为null则会通知AMS停止启动Activity。下面来查看performLaunchActivity方法做了什么:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer27.jpg?sign=1739299752-XXLj3DHKJqhSauLf8qMyyYbJORiQnl10-0-44b02225bc3c63f5eebc01802473a848)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer28.jpg?sign=1739299752-UoS1EIjle3ROvUppYIaSFoHrqoAM3yUt-0-480a67be8ba69c7c143a56dd94e9e090)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer29.jpg?sign=1739299752-DfVe5CtDwWAk0qwC8qpapi0x4Jckdtxx-0-cd5fbd98de52f81f30e0a1a8bf59b52b)
注释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=1739299752-RuSopPkX7wZtG18rJf9UjcdpMgVGVpuM-0-5ecffd774b8dbdbe22b081275eeed739)
注释1处调用了Activity的performCreate方法,代码如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer31.jpg?sign=1739299752-R8dCLoXrokkmVoXrJ8UqGp1QJrOWZYWr-0-164270e7fcbccf9580956b16c7ac5882)
在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=1739299752-C1o8TUz0rkzHLqZYDj3RnsMugBKr9uXL-0-daed4600d1a3f068798af6a51ce53ae0)
图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=1739299752-LUm35bskcvJwwQOre0oGkxWQIqcx4z1W-0-766ccf05584f5a5f13ea24f937b09084)
图4-6 根Activity启动过程中进程调用时序图
如果是普通Activity启动过程会涉及几个进程呢?答案是两个,AMS所在进程和应用程序进程。实际上理解了根Activity的启动过程(根Activity的onCreate过程),根Activity和普通Activity其他生命周期状态(比如onStart、onResume等)过程也会很轻松掌握,这些知识点都是触类旁通的,想要具体了解这些知识点的读者可以自行阅读源码,由于篇幅有限这里就不再介绍了。