引言
在知乎上看到一个问题,是关于Android中应用的入口到底在哪里,本文以点击Launcher中某个icon为启动,分析Android应用的启动过程。
1.点击Launcher中的icon
Launcher其实也就是一个特殊的Activity而已,点击icon时的执行逻辑如下:
|
|
显然,startActivitySafely()就是打开App的代码:
|
|
显然,这里只是做一个检查,看该activity是否能找到,startActivity()的代码如下:
|
|
代码虽然有点长,但是逻辑很简单,即区分是否使用launch动画,之后会调用到Activity中的startActivityForResult()方法:
|
|
启动App时mParent为null,故调用Instrumentation#execStartActivity()方法:
|
|
之后就是Binder通信的常用套路了,这里ActivityManagerNative.getDefault().startActivity()实际上调用的是ActivityManagerProxy的startActivity()方法:
|
|
这里最终会通过Binder通信调用到AMS中的startActivity():
|
|
startActivityAsUser()的代码如下:
|
|
而ActivityStackSupervisor#startActivityMayWait()的代码如下:
|
|
代码虽然很长,当时目前只要关注startActivityLocked()这一句:
|
|
参数resultTo是Launcher这个Activity里面的一个Binder对象,通过它可以获得Launcher这个Activity的相关信息,保存在sourceRecord变量中。之后进入到startActivityUncheckedLocked()中:
|
|
由于是新任务,并且传进来的参数doResume为true,于是调用resumeTopActivityLocked():
|
|
进入resumeTopActivityLocked()中:
|
|
真正执行是在resumeTopActivityInnerLocked()中:
|
|
这里mResumedActivity其实就是Launcher,因为Launcher是当前正被执行的Activity.从而会进入startPausingLocked()方法中:
|
|
注意其中的prev.app.thread.schedulePauseActivity(),这是典型的Binder通信,最终会调用到ApplicationThread的schedulePauseActivity()中,注意这里的ApplicationThread是与Launcher对应的,还不是与要启动的App对应的。
|
|
这里的H是ActivityThread的一个内部类,继承自Handler,跟踪H.PAUSE_ACTIVITY 消息的流动可以发现消息的处理在ActivityThread,注意这里的ActivityThread也是与Launcher(确切地说是与Launcher所在的App)对应的,其中ActivityThread的处理代码如下:
|
|
显然调用handlePauseActivity()进行处理:
|
|
注意其中的ActivityManagerNative.getDefault().activityPaused(token),这是在Launcher进入Paused状态后通知AMS.
进入performPauseActivity中:
|
|
可以看到,真正的执行是在Instrumentation的callActivityOnPause()中:
|
|
而Activity的performPause()如下:
|
|
可以看到,这里回调了Activity的onPause()方法,到这里为止Launcher就进入了Paused状态,结合前面的ActivityManagerNative.getDefault().activityPaused(token),可以发现之后会通过Binder调用AMS的activityPaused()方法:
|
|
进入activityPausedLocked()方法中:
|
|
再进入completePauseLocked()中,注意插入的resumeNext为true:
|
|
由于resumeNext为true,会执行到 mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);该方法如下:
|
|
isFrontStack()会返回true,从而执行result = targetStack.resumeTopActivityLocked(target, targetOptions);该方法如下:
|
|
再进入resumeTopActivityInnerLocked()中:
|
|
由于App还未启动,故执行到mStackSupervisor.startSpecificActivityLocked(next, true, true);该方法如下:
|
|
由于app为null,故执行startProcessLocked()方法:
|
|
进入startProcessLocked()方法中:
|
|
排除那些检查及log代码,发现其实真正执行的是重载的startProcessLocked()方法:
|
|
该方法的前面主要是参数解析和获取,核心代码是下面这一部分:
|
|
注意到entryPoint为”android.app.ActivityThread”,Process.start()实际上是调用Zygote来fork一个新的进程,并且在最后会调用ActivityThread的main()方法.AMS 所在的进程和 Zygote 所在的进程通过Socket通信,关于Socket的通信就不展开了。
ZygoteInit 中有如下代码:
|
|
显然,Zygote 进程在循环读取Socket通信信息,一旦accept到一个ZygoteConnection,就会通过runOnce()方法进行处理:
|
|
创建App进程的代码是Zygote.forkAndSpecialize()这个方法:
|
|
显然forkAndSpecialize()其实是调用nativeForkAndSpecialize()这个native方法来完成进程的fork过程,下面就不分析C/C++代码了。回到ZygoteConnection中的runOnce()方法中,注意下面这一段代码:
|
|
表示会在创建的App进程中执行handleChildProc()方法,该方法代码如下:
|
|
注意最后面的ZygoteInit.invokeStaticMain(cloader, className, mainArgs);显然,ActivityThread 的main()方法就是在这里通过反射调用的,而ActivityThread的main()方法如下:
|
|
从这里开始,准备号主线程的消息队列,并为App配置一个ActivityThread,在通过thread.attach()将ActivityThead与AMS关联起来,注意这里的ActivityThread才是属于App的,后续AMS通过Binder通知ActivityThread进行这个App中所有主线程的调度工作,ActivityThread 再通过Instrumentation来真正执行。