android系统启动流程
3)ApplicationThread.handleLaunchActivity:
这里明确看到performLaunchActivity构造了一个activity实例,紧接着就调用了handleResumeActivity,到这里已经可以大胆猜测: handleResumeActivity就对应onResume,
performLaunchActivity不仅构造activity还调用onCreate,否则无法直接onResume.
4)ApplicationThread. performLaunchActivity
36 / 41
android系统启动流程
5) ApplicationThread. handleResumeActivity
6.2.2 ActivityThread.ApplicationThread.scheduleResumeActivity
1) ApplicationThread. scheduleResumeActivity
2) H.handleMessage:
同样进入了H内部H.handleMessage:
37 / 41
android系统启动流程
可以看到同样调用了handleResumeActivity。
到这里,launcher显示流程就结束了.
6.2.3 发出开机完成通知
发出开机广播:android.intent.ACTION_BOOT_COMPLETED 设置开机属性: sys.boot_completed为1
ApplicationThread. handleResumeActivity里面还有一句代码:
在当前thread的looper的消息队列中增加一个idlehandler: Idler
当该消息被发出的时候,Idler.queueIdle被调用,am.activityIdle被执行。 和前面关于attach的流程一样,这里也是一个binder通讯,这句代码最终执行到了ActivityManagerService. activityIdle:
38 / 41
android系统启动流程
继续进入到ActivityStackSupervisor.activityIdleInternalLocked
回到ActivityManagerService.finishBooting:
终于完成发出开机广播和设置开机属性为1.
39 / 41
android系统启动流程
7 总结
综合前面的分析,事实上,我们已经看到luancher的显示入口只有一个就是
ActivityThread.ApplicationThread下的各个schedule方法;但是拉起luancher进程和进入显示的过程的却有多个途径。
7.1 luancher启动流程总结
1)拉起launcher进程 途径1:
ActivityManagerService.systemready执行getPersistentApplications来主动拉起具有persistent属性的launcher. 途径2:
任何一个app进程启动,执行到ActivityStackSupervisor. attachApplicationLocked的时候,如果launcher已经进入栈顶,而当前attach回调的进程不是luancher,也会主动拉起launcher。 途径3:
launcher不具备persistent属性,也没有其他进程通过attachApplicationLocked来拉起launcher进程,则在进入ActivityStackSupervisor.startSpecificActivityLocked的流程后,拉起luancher进程
2)进入ActivityThread.ApplicationThread下的各个schedule显示的流程: 途径1:
进程并行拉起,resume launcher的流程进入ActivityStack.resumeTopActivityLocked
的if (next.app != null && next.app.thread != null) 这个分支,调用next.app.thread.scheduleResumeActivity显示 途径2:
进程并行拉起,resume launcher的流程进入ActivityStack.resumeTopActivityLocked
的if (next.app != null && next.app.thread != null) 时,进程没完全起来,条件不成立,进入mStackSupervisor.startSpecificActivityLocked---->realStartActivityLocked---> app.thread.scheduleLaunchActivity显示 途径3:
进程在attach回调的时候,activity栈顶已经准备好,直接调用ActivityStackSupervisor.realStartActivityLocked显示。
这个流程实际就是多种保险措施务必拉起launcher的进程并进行显示,但是这个流程应该存在优化的空间,如果能更直接底启动launcher,可能开机会更快。
40 / 41
android系统启动流程
7.2 luancher黑屏问题分析
当launcher具备persistent属性时,系统一开始就会拉起他;但这个并非完全是串行的,拉起进程的动作socket和zygote通讯,并不做任何等待就返回。
紧接着,开始启动调用launcher显示的动作,activity进入栈顶,会 执行将自身apptoken加入到windowmanager的动作,只有这个加进去了,activity的绘图才会被显示出来。
launcher进程起来后,开始attach回调,此时会出现一个时机问题: 1)如果这时形成栈顶activity信息和当前进程attach的进程信息一致,于是attachApplicationLocked调用realStartActivityLocked; 2)而这时如果mWindowManager.addAppToken还没完成的话,
realStartActivityLocked中的mWindowManager.setAppVisibility(r.appToken, true);就会失败。
3)realStartActivityLocked的写法是继续往下走,默认显示成功,调用scheduleLaunchActivity执行activity的create和resume动作,并调用
minimalResumeActivityLocked设置当前acitivity状态为resumed,这是实际只是绘图完成了,而windowmanger. setAppVisibility失败就类似于没有update,所以luancher不会显示。
4)调用launcher显示的流程继续走到ActivityStack .resumeTopActivityLocked.,但是此时activity的状态已经是resumed,于是什么都做不做,直接return,连这条补救的路径都没完成显示,最终导致黑屏。
简单解决该问题的办法就是在这个return之前再调用一次realStartActivityLocked。
如果launcher进程启动够快,则不会触发调用realStartActivityLocked,activity的状态就不会乱;或者launcher进程启动够慢或压根就由正常的流程自己去启动进程,则等于是个串行的流程,虽然慢,但是也不会出现状态乱。
尝试优化加快luancher显示:
是否可以在systemready函数中,直接找到launcherapk,第一个拉起他的进程,然后调用resumetopactivity,这样应该能引导luancher变成单一的流程,迅速显示。
41 / 41