本篇文章是基于android-9.0.0_r8分支的代码进行分析的,想要看framwork层源码的笔者推荐以下两种方式:
- github:https://github.com/aosp-mirror/platform_frameworks_base
- Android社区:https://www.androidos.net.cn/sourcecode
从桌面图标的点击 Luancher——AMS
Launcher简介
在系统启动的最后一步会启动一个应用程序来显示系统中已经安装的应用程序,这个应用程序就叫做Launcher。Launcher在启动的过程中会请求PackageManagerService返回系统中已经安装的应用程序的信息,并将这些信息封装成一个快捷图标列表在系统桌面上,这样用户点击这些快捷方式图标来启动应用程序。
简而言之:作为Android系统中应用程序或其他桌面组件的管理者,负责显示、管理以及程序启动入口
当我们点击桌面图标到app开始启动,这个过程是从Luancher类开始的,Luancher继承于activity,他也实现了onClick方法,我们很容易想到在这个onClick方法里就有桌面图标点击事件的监听,即启动的入口:
public void onClick(View v) { |
我们看从快捷方式启动的onClickAppShortcut方法的实现:
/** |
这里调用了startAppShortcutOrInfoActivity方法,之后的调用分别为startAppShortcutOrInfoActivity到startActivitySafely方法,在startActivitySafely方法里的实现如下:
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) { |
Activity启动入口
Launcher继承于Activity类,而Activity类实现了startActivity函数,因此,这里就调用了Activity.startActivity函数,而这个startActivity方法又是我们开发中经常使用的方法,所以这里我将它做为了Activity的入口。看看startActivity干了什么:
public class Activity extends ContextThemeWrapper |
我们看到在startActivity方法里,直接调用了startActivityForResult方法,传入的-1表示不需要这个Actvity结束后的返回结果,再接着看startActivityForResult方法,这里有一个mParent字段,他其实是一个Activity对象。因为是第一次启动,也就是启动的应用程序的根Activity,所以这个mParent肯定为空,然后执行了Instrumentation.ActivityResult的execStartActivity方法,即使mParent不为空,调用的startActivityFromChild方法内也调用的是Instrumentation.ActivityResult的execStartActivity方法。ActivityResult是Instrumentation的内部类,代表着Activity的启动结果数据,而Instrumentation的作用则是监控整个APP运行流程、交互流程。这一点可以通过源码上的注释发现:
/** |
那么这个execStartActivity方法里又做了什么呢,再看:
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { |
我们看第一句,contextThread是一个IBinder对象,实际上它也是IApplicationThread 的实现类,IApplicationThread 继承了IInterface,简单看看:
/** |
看到这些方法,例如schedulePauseActivity,scheduleResumeActivity等,我们不难发现这个IApplicationThread好像与Activity的生命周期相关,而scheduleBindService、scheduleUnbindService等方法由于service的绑定等操作相关,所以IApplicationThread的实现类ApplicationThread主要完成Activity、service的创建等相关操作的。
然后再看 ActivityManager.getService().startActivity这一块,首先看看ActivityManager.getService()方法:
|
通过源码我们看到返回的是一个IActivitryManager,首先需要从ServiceManager中通过Context.ACTIVITY_SERVICE的一个字符串作为Key去查询(在ServiceManager中注册过的service会通过一个Map保存),然后返回了一个IBinder,然后又通过AIDL的方式,调用了IActivityManager.Stub.asInterface(b)方法返回一个IActivitryManager。需要注意的是,这里返回的代理对象并不是原来版本的ActivityManagerProxy对象,因为在API26之后就不再有ActivityManagerProxy这个类了,并且ActivityManagerNative也将被废弃,现在的AMN已经没有多少代码了,这里返回的应该是IActivityManager.Stub的内部类对象IActivityManager.Stub.Proxy,通过AIDL的方式在编译时会产生IActivityManager.java文件。那么这里最终是由谁去执行startActivity方法的呢,显然他应该是IActivityManager的实现类,没错就是ActivityManagerService。这样,IActivityManager.Stub与相当于一个Binder的客户端而ActivityManagerService相当于Binder的服务端,这样当IActivityManager.Stub.Proxy调用接口方法的时候底层通过Binder driver就会将请求数据与请求传递给server端,并在server端执行具体的接口逻辑。
在看AMS的startActivity之前,我们还要看看这个checkStartActivityResult方法:
public static void checkStartActivityResult(int res, Object intent) { |
顾名思义这个方法就是用来检查启动Activity的,代码中也可以很清晰的发现,这里会抛出各种比如异常,比如我们没有在AndroidManifest中声明activity就会抛出这个ActivityNotFoundException,提示have you declared this activity in your AndroidManifest.xml。
小结
所谓一图胜千言,我们看看第一部分的时序图
AMS——zygote过程
获取了ActivityManager的服务(AMS)来启动Activity后,我们就要来看他的实现类AMS的startActivity方法:
public class ActivityManagerService extends IActivityManager.Stub |
首先在startActivity方法中又直接调用了父类的startActivityAsUser,最后调用自己的startActivityAsUser方法,注释3处会检查该进程是否被隔离了,然后检查启动activity的userId是否合法,最后进行了一长串的链式调用,我们看最后的execute方法。
/** |
这里有一个判断,他会返回true,为什么呢,在之前链式调用setMayWait方法时:
ActivityStarter setMayWait(int userId) { |
可见,下一步会调用startActivityMayWait方法,内部调用了startActivityLocked方法,然后进入startActivity方法,之后又调用了startActivityUnchecked方法,然后调用了ActivityStackSupervisor#resumeFocusedStackTopActivityLocked,这个时候启动过程就从ActivityStarter 转移到ActivityStackSupervisor,源码调用过程如下:
//这里传进来的参数中比之前多了一个TaskRecord对象,代表着启动的activity所在的栈 |
之后进入了startActivivty方法中,这里有三个重载方法,比较长,我们一点点来看:
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent, |
这里来到了ActivityStackSupervisor这个类,上面简单提过一点ActivityStack的作用,而它主要是来管理ActivityStack的,继续看resumeFocusedStackTopActivityLocked方法又是如何运作的:
boolean resumeFocusedStackTopActivityLocked( |
这个方法又调用了自身的resumeTopActivityInnerLocked方法,这个方法特别长,我们仔细看看:
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { |
这个方法比较长,但是也可以清楚的发现些比较关键的地方:
- 如果mResumedActivity不为空,则需要先暂停这个Activity。mResumedActivity代表当前已经存在于界面的Activity。当需要启动一个新的Activity时,需要先停止当前的Activity。这部分工作由startPausingLocked函数来完成。当前的Activity被中断后,将重新启动新的Activity。
- 当mResumedActivity为空时,若待启动的Activity对应的进程已经存在,那么仅需要重新启动该Activity;否则,需要调用ActivityStackSupervisor的startSpecificActivityLocked函数,启动整个进程:
void startSpecificActivityLocked(ActivityRecord r, |
这个方法的内部实现可以发现它的作用是根据app进程是否存在来调用不同的方法,当app进程已经存在就直接调用了realStartActivityLocked方法,否则调用startProcessLocked方法,顾名思义这个方法将用于app进程的创建,当然真正的创建工作并不是他完成的,想知道他是在哪实现的,还需要知道mService是什么,通过构造方法我们发现,其实就是AMS:
public ActivityStackSupervisor(ActivityManagerService service, Looper looper) { |
所以我们需要到AMS里去看看是如何实现的(4个重载方法,代码很长):
final ProcessRecord startProcessLocked(String processName, |
这里出现了Process的start方法,那是不是说进程的创建就是它完成的呢,我们继续:
public static final ProcessStartResult start(final String processClass, |
可以看到两种方式都不是在这里创建进程的,而是分别交给了ZygoteProcess和WebViewZygote来完成。注释中我写到zygoteProcess是一个ZygoteProcess对象是从何而来呢,先来看看:
public static final ZygoteProcess zygoteProcess = |
我们发现这里似乎用到了Socket的方式来实现跨进程通信,至于后面具体怎么实现,慢慢往后看。先来看看WebViewZygote.getProcess()方法做了什么,是不是拿到的也是一个ZygoteProcess对象呢:
private static ChildZygoteProcess sZygote; |
这里的sZygote是一个ChildZygoteProcess对象,实际上我们的才想也并没有错误,因为这个ChildZygoteProcess是ZygoteProcess的子类,其构造方法就是调用的ZygoteProcess的构造方法。那么现在就要看看ZygoteProcess的start方法又是如何实现的了:
public final Process.ProcessStartResult start(final String processClass, |
因为Zygote所在进程与AMS所在进程不同,根据方法被调用时可以发现这个zygoteState是通过openZygoteSocketIfNeeded(abi)创建的,再看看这个方法:
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { |
先看注释1处,这里调用ZygoteState的connect函数与mSocket的Socket建立连接,还记得之前在ZygoteProcess构造方法里传入的ZYGOTE_SOCKET和SECONDARY_ZYGOTE_SOCKET,它们的值分别对应的是”zygote”和”zygote_secondary”,这是因为Zygote进程启动过程时,在Zygote的main函数中会创建name为“zygote”的Server端Socket,如果连接name为“zygote”的Socket返回的primaryZygoteState与当前的abi不匹配,则会在注释2处连接name为“zygote_secondary”的Socket。这两个Socket区别就是:name为”zygote”的Socket是运行在64位Zygote进程中的,而name为“zygote_secondary”的Socket则运行在32位Zygote进程中。既然应用程序进程是通过Zygote进程fock产生的,当要连接Zygote中的Socket时,也需要保证位数的一致。
Socket进行连接成功并匹配abi后会返回ZygoteState类型对象,我们在分析zygoteSendArgsAndGetResult函数中讲过,会将应用进程的启动参数argsForZygote写入到ZygoteState中,这样Zygote进程就会收到一个创建新的应用程序进程的请求,我们回到ZygoteInit的main函数,如下所示:
public static void main(String argv[]) { |
注释1处通过registerZygoteSocket函数来创建一个Server端的Socket,这个name为”zygote”的Socket用来等待ActivityManagerService来请求Zygote来创建新的应用程序进程
注释2处用来预加载类和资源。
注释3处用来启动SystemServer进程,这样系统的关键服务也会由SystemServer进程启动起来。
注释4处调用runSelectLoop函数来等待ActivityManagerService的请求,我们就来查看runSelectLoop:
Runnable runSelectLoop(String abiList) { |
这里要返回的Runnable对象又到了ZygoteConnection的processOneCommand方法里:
Runnable processOneCommand(ZygoteServer zygoteServer) { |
再看handleChildProc方法:
private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, |
再看ZygoteInit.childZygoteInit方法,这里传进去了目标SDK版本和相关参数:
static final Runnable childZygoteInit( |
这个方法就比较简单了,直接传到了RuntimeInit.findStaticMain方法里:
protected static Runnable findStaticMain(String className, String[] argv, |
最终这里返回了一个MethodAndArgsCaller对象,根据方法的返回值可以很容易知道这是一个Runnable对象,其实它是RuntimeInit的内部类:
static class MethodAndArgsCaller implements Runnable { |
所以看到这里就知道上文caller就是这里的MethodAndArgsCaller对象,调用run方法执行的就是通过反射执行传进来的方法。这个方法在findStaticMain方法里知道了是main方法,那么是哪一个类呢,是ActivityThread类,这是在findStaticMain方法里通过反射找到的。
ActivityThread#main——App#onCreate
现在程序就执行到了ActivityThread.main方法了:
public static void main(String[] args) { |
这里主要的三件事:
- 调用Looper.prepareMainLooper 创建并赋值(这个looper的MessageQueue不能quit)静态变量 sMainLooper ,这样应用可以在任何地方拿到主线程的Looper对象
- 创建ActivityThread实例,并调用attach,这两步很关键,首先,ActivityThread对象创建时,会创建ResourcesManager的单例对象。在thread.attach(false, startSeq)中还会创建 IActivityManager 对象即AMS,并为app绑定一个Application对象:
private void attach(boolean system, long startSeq) { |
前面已经知道了这里的IActivityManager就是一个ActivityManagerService对象,看它的attachApplication方法:
public final void attachApplication(IApplicationThread thread, long startSeq) { |
这里又跳转到了ActivityStackSupervisor的attachApplicationLocked方法:
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException { |
这里出现了一个之前提到但没有看过的方法,realStartActivityLocked方法,之前分析过程中说过如果应用进程已经启动的情况下去启动Activity所调用的方法,那么现在来看看:
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, |
这里我们看到最后一行,mService.getLifecycleManager:
ClientLifecycleManager getLifecycleManager() { |
再到ClientLifecycleManager 里看scheduleTransaction方法:
void scheduleTransaction(ClientTransaction transaction) throws RemoteException { |
那么这里的mClint是什么呢,他其实就是上面调用clientTransaction.obtain方法时传入的IApplicationThread实例,是一个ApplicationThread对象,那么现在再看scheduleTransaction方法:
private class ApplicationThread extends IApplicationThread.Stub { |
由于继承自IApplicationThread.Stub,所以这里的Application就是一个Binder,然后在scheduleTransaction调用了ActivityThread的scheduleTransaction方法,这就又回到了app,但是由于ActivityThread并没有重写该方法,所以调用的实际上是它的父类ClientTransactionHandler的方法:
void scheduleTransaction(ClientTransaction transaction) { |
H继承自Handler,是ActivityThread的内部类,再看H的sendMessage方法:
public void handleMessage(Message msg){ |
为节省篇幅这里只截取了源码中的EXECUTE_TRANSACTION一个消息,实际上源代码里还有很多,比如BIND_SERVICE,DISPATCH_PACKAGE_BROADCAST;可以看出四大组件的生命周期回调入口都在这里,具体就不在谈了。又看TransactionExecutor的execute方法:
public void execute(ClientTransaction transaction) { |
在executeLifecycleState方法里面,会调用TransactionExecutor的cycleToPath函数执行当前Activity的生命周期,第二个参数lifecycleItem.getTargetState确定了我们将要执行哪些声明周期函数,由于我们在realStartActivity函数中创建的是ResumeActivityItem对象,所以这里调用的是ResumeActivityItem的getTargetState函数:
public int getTargetState() { |
这里只是单纯的返回了ON_RESUME,ON_RESUME保存在他的父类ActivityLifecycleItem中:
public static final int UNDEFINED = -1; |
下面我们来看TransactionExecutor的cycleToPath函数
private void cycleToPath(ActivityClientRecord r, int finish, |
在该函数中创建了一个IntArray类型的对象path,该path确定了我们将要执行哪些生命周期函数,之后调用了performLifecycleSequence函数:
private void performLifecycleSequence(ActivityClientRecord r, IntArray path) { |
performLifecycleSequence会根据path执行Activity相应的生命周期函数。整个流程还是比较简单的,由于是Android9新增的机制,所以得着重看一看。由于是app的启动所以activity还没有创建,所以ActivityThread的handleLaunchActivity会最先被调用:
public Activity handleLaunchActivity(ActivityClientRecord r, |
handleLaunchActivity函数会调用performLaunchActivity返回一个Activity对象,接下来我们看performLaunchActivity函数:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { |
函数performLaunchActivity首先利用反射机制创建了Activity对象,然后调用Activity的attach函数初始化新建的Activity,最后调用activity的onCreat函数。我们先看一下Activity.attach函数内部都做了什么。
final void attach(Context context, ActivityThread aThread, |
Activity的attach函数内部初始化Activity的成员变量,创建了PhoneWindow对象并为PhoneWindow和Activity创建了WindowManagerImpl对象,getWindow函数返回了Activity类中的mWindow对象,在Activity.attach函数中创建了PhoneWindow对象并保存为mWindow。关于attach方法的细节留到后面再谈,现在继续看mInstrumentation.callActivityOnCreate方法:
public void callActivityOnCreate(Activity activity, Bundle icicle) { |
最终activity的创建来到了它的performCreate方法:
final void performCreate(Bundle icicle) { |
随着那熟悉的onCreate方法的出现,整个启动流程就
记一道面试题
我在头条一面的时候,面试官问完activity的生命周期后,又问道我刚才回答的这些方法比如onCreate,他是由谁调用的呢?
当然这些方法是activity自身的方法,也没有严格的说能由谁调用,但是既然面试官要问,就一定有他的道理,这里我们也已经看完了这个启动流程,那么你觉得是由谁调用的呢。当时我并没有答上来,而是答了是由LifecycleOwner调用,在那里回调的。面试结束之后,我又才恍然大悟,其实就是由Instrumentation这个类的callActivityOnCreate方法调用的。就这么一个小问题就会反映出很多问题,面试不会直白的问源码中怎么实现,而是会进行一些变种,所以在看源码的过程中应该理清楚各个流程做了些什么,多思考多提问,而不是记住甚至是背下流程。
全文总结
不得不说整个流程还是比较复杂的,但在用户使用的时候就是点击一下然后app就启动到眼前一瞬间的事。拉完整个流程对笔者的帮助真的很大,不仅收获了很多源码阅读的经验,还能了解系统的工作原理。随着反复看的次数增加,笔者也逐渐能够对启动流程有个一知半解,也慢慢开始理解和体会到它的意义与设计上的巧妙。最后向大家推荐一本书《Android进阶解密》,对阅读FramWork层源码比较有帮助,也比较系统。
一张大图来总结一下吧