activity的启动关闭最终都是由AMS控制的。从刷了rom到第一开机引导、launcher启动、点击启动特定app,这之间ams控制开机引导activity、launcher、app启动有什么不同吗?还是same流程?下面让我们一探究竟。
文章分三部分:第一部总体概述、第二部分流程图、第三部分讲解下具体一些细节点。
一、总体概述:
无所做什么,一定先是了解概况,然后在看细节,不然就是只见树木不见森林。
这里就会有区分,开机广告/开机引导类似(电视现在都是先播放广告,然后启动launcher)、launcher、其他app;
本文也从这个角度进行一下分析。
简单的说,启动一个activity,先看是否已经有activity是resume状态,没有则直接启动;有则先pause掉当前resume的,然后启动想启动的;这里也不关注activity如何调用到AMS的,只关注AMS内部如何调度最终启动相关的activity的。
除了开机广告,launcher和app启动都是两个阶段:一pause当前resume的activity;二resume需要启动的activity。(先finish后pause)
牢记,就这两个阶段,不过launcher和app启动在这两个阶段有些许的区别而已。
开机广告就不多说了,后面也会给出AMS添加的方案,从AMS直接启动广告Activity播放广告,然后主动finish;系统会启动Launcher;点击相关app,启动自己想打开的应用(顺序三个阶段)。
二、流程图
1.正常启动Launcher
这里先看下正常情况下的Luancher启动,即开机即启动Launcher。然后在看下先播放开机广告,然后在自动Launcher,看下异同点。
AMS被SystemServer启动之后,SystemServer会通过AMS调用startHomeActtivity启动Launcher,流程见上流程图。
其中有几个关键函数,需要关注一下:startHomeActivityLocked、startActivityLocked、addActivityToTop、resumeTopActivityLocked、realStartActivityLocked、attachApplicationLocked;几个点记住:ProcessLocked中有Process.start,最终会触发AMS的attachApplication。
从流程途中看到,起点可以算startHomeActivityLocked,终点是realStartActivityLocked;
第一阶段是startHomeActivity,触发activity的进程创建;第二阶段就是AMS的attachApplication在进程创建后被调用,最终执行realStartActivityLocked会回调Activity的onCreate函数。
这里第一阶段和上面说的不太一样,不过没关系,下面看下先播开机广告在启动launcher的流程。
2.开机广告之后启动Launcher
AMS启动广告的就不看了,看下广告finish之后,Launcher启动的流程:
先看下调用栈:
第一阶段:开机广告finish掉,触发paused:
06-28 18:07:14.098 4200 4391 W System.err: at com.android.server.am.ActivityStack.startPausingLocked(ActivityStack.java:825)
06-28 18:07:14.098 4200 4391 W System.err: at com.android.server.am.ActivityStack.finishActivityLocked(ActivityStack.java:2745)
06-28 18:07:14.098 4200 4391 W System.err: at com.android.server.am.ActivityStack.requestFinishActivityLocked(ActivityStack.java:2572)
06-28 18:07:14.098 4200 4391 W System.err: at com.android.server.am.ActivityManagerService.finishActivity(ActivityManagerService.java:4543)
06-28 18:07:14.098 4200 4391 W System.err: at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:325)
06-28 18:07:14.098 4200 4391 W System.err: at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2267)
06-28 18:07:14.098 4200 4391 W System.err: at android.os.Binder.execTransact(Binder.java:446)
第二阶段:paused并启动launcher
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.realStartActivityLocked(ActivityStackSupervisor.java:1182)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.startSpecificActivityLocked(ActivityStackSupervisor.java:1285)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.resumeTopActivityInnerLocked(ActivityStack.java:1898)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.resumeTopActivityLocked(ActivityStack.java:1459)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.resumeTopActivitiesLocked(ActivityStackSupervisor.java:2477)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.startActivityLocked(ActivityStack.java:2097)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.startActivityUncheckedLocked(ActivityStackSupervisor.java:2217)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.startActivityLocked(ActivityStackSupervisor.java:1519)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.startHomeActivity(ActivityStackSupervisor.java:833)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityManagerService.startHomeActivityLocked(ActivityManagerService.java:3248)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.resumeHomeStackTask(ActivityStackSupervisor.java:459)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.resumeTopActivityInnerLocked(ActivityStack.java:1504)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.resumeTopActivityLocked(ActivityStack.java:1459)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.resumeTopActivitiesLocked(ActivityStackSupervisor.java:2477)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.completePauseLocked(ActivityStack.java:998)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.activityPausedLocked(ActivityStack.java:896)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityManagerService.activityPaused(ActivityManagerService.java:6591)
06-29 15:18:57.860 4196 4213 W System.err: at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:512)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2267)
06-29 15:18:57.860 4196 4213 W System.err: at android.os.Binder.execTransact(Binder.java:446)
流程图:
直接启动launcher,通过进程创建,触发attach就起来了;而开机广告这种情况则复杂很多,先是finish掉开机广告,然后由pause流程触发startHomeActivity并递归调用了一次resume的流程之后才走到realStartActivityLocked,回调launcher的onCreate函数。
3.Launcher启动之后启动app
流程图:
正常启动:一阶段:先调用startActivityLocked,并调用pause,二阶段pause调用resume直接启动activity了。
正常启动activity,会走startActivity(这里会将ActivityRecord信息加入task顶,并也调用startPausingLocked);
在后续流程中,也不同,主要是2中launcher启动递归调用了resume得几个函数;而正常启动则不会递归,
原因就是正常启动在首次就将ActivityRecord信息入task顶了,而2中launcher则没有;
三、一些注意点
1.addActivityToTop这个函数比较重要,会将要启动的activity的AcitivityRecord加入TASK顶端;这个非常重要,决定着realStartActivityLocked会不会被调用,还是启动launcher;如果执行了,即加入了Task的栈顶则这里next!=null而是相关的ActivityRecord,否则为null(final ActivityRecord next = topRunningActivityLocked(null););
final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
// Find the first activity that is not finishing.
final ActivityRecord next = topRunningActivityLocked(null);
final TaskRecord prevTask = prev != null ? prev.task : null;
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
// Only resume home if on home display
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "noMoreActivities");
}
2.resumeTopActivityLocked这个函数比较坑(5.1~9.0都这样),函数里有个判断会导致2.2部分的launcher启动不起来,2.2中的调用逻辑是我将AOSP代码注释掉一行以后,启动的。
看下这个函数:注意标志位:inResumeTopActivity
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (mStackSupervisor.inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;//注释掉即可,既能如2.2中所示调用流程,否则嵌套调用就返回,launcher无法启动
if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
mService.updateSleepIfNeededLocked();
}
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
return result;
}
可以看到这个函数使用标志位inResumeTopActivity ,但是2.2中开机广告这种情况下,就会出现问题;
在2.2中,第一阶段只是进行finish处理和pause调用;第二阶段才会通过pause进行resume,但是先走到这个函数而后触发的startActivityLocked(调用addActivityToTop),随后又走到这里的时候就返回了,并没有继续执行,所以luancher就没有启动,会出现开机广告播放完成之后,一直黑屏的现象。
相关关键函数:
startHomeActivityLocked:调用启动Launcher;
startActivityLocked(ActivityStack中 ):调用触发addActivityToTop将ActivityRecord加入栈顶;
resumeTopActivityLocked:这个函数是3.1中说的函数,不修改会导致广告后launcher不启动;
realStartActivityLocked:触发app.thread.scheduleLaunchActivity,去回调mainactivity的onCreate函数;
attachApplicationLocked:由创建相关进程之后触发,此函数会触发realStartActivityLocked的调用。
总结:
整体上,这篇文章涉及较多,AMS管理task即生命周期都有涉及,如果之前没有接触过,基本看不懂,很头痛。
这里放上几篇基础文章,可以阅读后再来读本篇文章,应该会又更深刻的理解。
附上AMS关系图:
2.Android系统启动流程--从SystemServer启动Launcher--百度文库
3.Android源码解析之(十五)-->Activity销毁流程--刘超
4.四大组件之ActivityRecord--GitYuan
大组件之ActivityRecord