最近在阅读Activity启动过程时接触到了这几个概念:ActivityRecord、TaskRecord、ActivityStack、ActivityDisplay、ActivityStackSupervisor
。它们是什么?可以用来干什么?以及怎么干的?网络上,常见的回答就是ActivityStackSupervisor管理ActivityDisplay,ActivityDisplay管理ActivityStack、ActivityStack管理TaskRecord、TaskRecord管理ActivityRecord。但是到底怎么管理的?为什么要管理啊?哎,没讲明白~~。
今天就由我来介绍下这几个概念。
ActivityRecord
ActivityRecord
是Activity在system_server进程中的镜像,Activity实例与ActivityRecord实例一一对应。ActivityRecord
用来存储Activity的信息,如所在的进程名称,应用的包名,所在的任务栈的taskAffinity
等。
/**
* An entry in the history stack, representing an activity.
*/
final class ActivityRecord {
final ComponentName realActivity; // the intent component, or target of an alias.
final String shortComponentName; // the short component name of the intent
final String packageName; // the package implementing intent's component
final String processName; // process where this component wants to run
final String taskAffinity; // as per ActivityInfo.taskAffinity
boolean fullscreen; // covers the full screen?
}
TaskRecord
TaskRecord
表示任务栈,用于记录activity开启的先后顺序。其所存放的Activity是不支持重新排序的,只能根据压栈和出栈操作更改Activity的顺序。有了TaskRecord,Android系统才能知道当一个Activity退出时,接下来该显示哪一个Activity。
final class TaskRecord {
/** List of all activities in the task arranged in history order */
final ArrayList<ActivityRecord> mActivities;
}
ActivityStack
ActivityStack
这个类在名字上给人很大的误解,Stack
是栈的意思(Heap
是堆的意思),那ActivityStack
就表示“Activity的栈”?其实不是。从下面的代码中可以看出ActivityStack
维护的是TaskRecord的列表。而且该列表也不是栈结构,列表中的TaskRecord可以重排顺序。
final class ActivityStack {
/**
* The back history of all previous (and possibly still
* running) activities. It contains #TaskRecord objects.
*/
private ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
}
也有人说是一个APP对应一个ActivityStack
。其实也不是。
接下来就用命令行——adb shell dumpsys activity
,来验证以下2个问题:
1. ActivityStack维护的TaskRecord列表是否可以重排顺序
2. APP与ActivityStack的关系
先准备2个APP。app1和app2各自都有两个页面,各自的启动页都是普通常见的,然后各自的都有另外一个其他页面,这分属于两个app的其他页面我们都给他们指定同一个任务栈名(这个任务栈名不跟任意一个app包名相同)。
也就是说app1里面有MainActivity和OtherActivity1。app2里面有MainActivity和OtherActivity2。两个应用的MainActivity都是普通的Standard启动模式,而OtherActivity1和OtherActivity2都在清单文件指定了同一个自定义的任务栈名称和singelTask启动模式。
我们这样操作:
第一阶段:先打开app1,再打开OtherActivity1页面。
第二阶段:按下HOME键,然后打开app2,再打开app2的OtherActivity2页面。
先贴上相关图片和代码:
app1的manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.a_task.application">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name="com.a_task.application.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.a_task.application.OtherActivity1"
android:launchMode="singleTask"
android:taskAffinity="com.task.other.independent"/>
<activity android:name="com.a_task.application.StandActivity" />
</application>
</manifest>
app2的manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.b_task.application2">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name="com.b_task.application2.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.b_task.application2.OtherActivity2"
android:launchMode="singleTask"
android:taskAffinity="com.task.other.independent"/>
</application>
</manifest>
- 第一阶段:先打开app1,再打开OtherActivity1页面。
在cmd窗口中输入adb shell dumpsys activity
。查看任务栈信息。搜索ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)部分的内容。
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
Stack #1:
Task id #3
TaskRecord{1dc0c488 #3 A=com.task.other.independent U=0 sz=1}
Hist #0: ActivityRecord{2e69f0af u0 com.a_task.application/.OtherActivity1 t3}
Task id #2
TaskRecord{30254e21 #2 A=com.a_task.application U=0 sz=1}
Hist #0: ActivityRecord{3f983660 u0 com.a_task.application/.MainActivity t2}
Running activities (most recent first):
TaskRecord{1dc0c488 #3 A=com.task.other.independent U=0 sz=1}
Run #1: ActivityRecord{2e69f0af u0 com.a_task.application/.OtherActivity1 t3}
TaskRecord{30254e21 #2 A=com.a_task.application U=0 sz=1}
Run #0: ActivityRecord{3f983660 u0 com.a_task.application/.MainActivity t2}
mResumedActivity: ActivityRecord{2e69f0af u0 com.a_task.application/.OtherActivity1 t3}
Stack #0:
Task id #1
TaskRecord{2c368246 #1 A=com.android.launcher3 U=0 sz=1}
Hist #0: ActivityRecord{3f94d55b u0 com.android.launcher3/.Launcher t1}
Running activities (most recent first):
TaskRecord{2c368246 #1 A=com.android.launcher3 U=0 sz=1}
Run #0: ActivityRecord{3f94d55b u0 com.android.launcher3/.Launcher t1}
上面的栈信息是来自Android5.1.1。可以看到目前机器中有2个ActivityStack(Stack #0和Stack #1)。Stack #0中含有TaskRecord #1,TaskRecord #1含有一个代表Launcher的ActivityRecord。Stack #1中含有TaskRecord #3 和TaskRecord #2,TaskRecord #3含有一个代表com.a_task.application/.OtherActivity1的ActivityRecord,TaskRecord #2含有一个代表com.a_task.application/.MainActivity的ActivityRecord。
从Display #0 (activities from top to bottom):
这句话可以看出,ActivityRecord出现的顺序正是机器目前所有Activity的排列顺序。OtherActivity1位于顶部,Launcher位于底部。
- 第二阶段:按下HOME键,然后打开app2,再打开app2的OtherActivity2页面。
- 按下HOME键,打开app2
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
Stack #1:
Task id #4
TaskRecord{1f030017 #4 A=com.b_task.application2 U=0 sz=1}
Hist #0: ActivityRecord{135a258e u0 com.b_task.application2/.MainActivity t4}
Task id #3
TaskRecord{16b2f5ed #3 A=com.task.other.independent U=0 sz=1}
Hist #0: ActivityRecord{1952693a u0 com.a_task.application/.OtherActivity1 t3}
Task id #2
TaskRecord{136f1c22 #2 A=com.a_task.application U=0 sz=1}
Hist #0: ActivityRecord{210d00df u0 com.a_task.application/.MainActivity t2}
Running activities (most recent first):
TaskRecord{1f030017 #4 A=com.b_task.application2 U=0 sz=1}
Run #2: ActivityRecord{135a258e u0 com.b_task.application2/.MainActivity t4}
TaskRecord{16b2f5ed #3 A=com.task.other.independent U=0 sz=1}
Run #1: ActivityRecord{1952693a u0 com.a_task.application/.OtherActivity1 t3}
TaskRecord{136f1c22 #2 A=com.a_task.application U=0 sz=1}
Run #0: ActivityRecord{210d00df u0 com.a_task.application/.MainActivity t2}
mResumedActivity: ActivityRecord{135a258e u0 com.b_task.application2/.MainActivity t4}
Stack #0:
Task id #1
TaskRecord{7183c04 #1 A=com.android.launcher3 U=0 sz=1}
Hist #0: ActivityRecord{25eace7b u0 com.android.launcher3/.Launcher t1}
Running activities (most recent first):
TaskRecord{7183c04 #1 A=com.android.launcher3 U=0 sz=1}
Run #0: ActivityRecord{25eace7b u0 com.android.launcher3/.Launcher t1}
- 再打开app2的OtherActivity2页面。
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
Stack #1:
Task id #3
TaskRecord{1dc0c488 #3 A=com.task.other.independent U=0 sz=2}
Hist #1: ActivityRecord{182ecc32 u0 com.b_task.application2/.OtherActivity2 t3}
Hist #0: ActivityRecord{2e69f0af u0 com.a_task.application/.OtherActivity1 t3}
Task id #4
TaskRecord{3d4399bb #4 A=com.b_task.application2 U=0 sz=1}
Hist #0: ActivityRecord{3f04f4f7 u0 com.b_task.application2/.MainActivity t4}
Task id #2
TaskRecord{30254e21 #2 A=com.a_task.application U=0 sz=1}
Hist #0: ActivityRecord{3f983660 u0 com.a_task.application/.MainActivity t2}
Running activities (most recent first):
TaskRecord{1dc0c488 #3 A=com.task.other.independent U=0 sz=2}
Run #3: ActivityRecord{182ecc32 u0 com.b_task.application2/.OtherActivity2 t3}
TaskRecord{3d4399bb #4 A=com.b_task.application2 U=0 sz=1}
Run #2: ActivityRecord{3f04f4f7 u0 com.b_task.application2/.MainActivity t4}
TaskRecord{1dc0c488 #3 A=com.task.other.independent U=0 sz=2}
Run #1: ActivityRecord{2e69f0af u0 com.a_task.application/.OtherActivity1 t3}
TaskRecord{30254e21 #2 A=com.a_task.application U=0 sz=1}
Run #0: ActivityRecord{3f983660 u0 com.a_task.application/.MainActivity t2}
mResumedActivity: ActivityRecord{182ecc32 u0 com.b_task.application2/.OtherActivity2 t3}
Stack #0:
Task id #1
TaskRecord{2c368246 #1 A=com.android.launcher3 U=0 sz=1}
Hist #0: ActivityRecord{3f94d55b u0 com.android.launcher3/.Launcher t1}
Running activities (most recent first):
TaskRecord{2c368246 #1 A=com.android.launcher3 U=0 sz=1}
Run #0: ActivityRecord{3f94d55b u0 com.android.launcher3/.Launcher t1}
从上面的栈信息中我们可以看到当打开app2时,Task #4位于Task #3的上方。但是当我们打开app2的OtherActivity2页面时,Task #3就被移动到了Task #4的上方。这说明ActivityStack #1中的TaskRecord重排了顺序。而且app1和app2对应的ActivityStack都是Stack #1。
我们再来看看在Android9的机器上重复上面的操作,栈信息是怎样的。
- 第一阶段:先打开app1,再打开OtherActivity1页面。
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
Stack #761: type=standard mode=fullscreen
Task id #11652
* TaskRecord{dfc4117 #11652 A=com.task.other.independent U=0 StackId=761 sz=1}
Hist #0: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}
Running activities (most recent first):
TaskRecord{dfc4117 #11652 A=com.task.other.independent U=0 StackId=761 sz=1}
Run #0: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}
mResumedActivity: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}
Stack #760: type=standard mode=fullscreen
Task id #11651
* TaskRecord{f06e904 #11651 A=com.a_task.application U=0 StackId=760 sz=1}
Hist #0: ActivityRecord{2035f77 u0 com.a_task.application/.MainActivity t11651}
Running activities (most recent first):
TaskRecord{f06e904 #11651 A=com.a_task.application U=0 StackId=760 sz=1}
Run #0: ActivityRecord{2035f77 u0 com.a_task.application/.MainActivity t11651}
Stack #0: type=home mode=fullscreen
Task id #1
* TaskRecord{a611787 #1 A=com.huawei.android.launcher U=0 StackId=0 sz=1}
Hist #0: ActivityRecord{a99c328 u0 com.huawei.android.launcher/.unihome.UniHomeLauncher t1}
Running activities (most recent first):
TaskRecord{a611787 #1 A=com.huawei.android.launcher U=0 StackId=0 sz=1}
Run #0: ActivityRecord{a99c328 u0 com.huawei.android.launcher/.unihome.UniHomeLauncher t1}
- 第二阶段:按下HOME键,然后打开app2,再打开app2的OtherActivity2页面。
- 按下HOME键,打开app2
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
Stack #762: type=standard mode=fullscreen
Task id #11653
* TaskRecord{c7e67ab #11653 A=com.b_task.application2 U=0 StackId=762 sz=1}
Hist #0: ActivityRecord{b8c7cd2 u0 com.b_task.application2/.MainActivity t11653}
Running activities (most recent first):
TaskRecord{c7e67ab #11653 A=com.b_task.application2 U=0 StackId=762 sz=1}
Run #0: ActivityRecord{b8c7cd2 u0 com.b_task.application2/.MainActivity t11653}
mResumedActivity: ActivityRecord{b8c7cd2 u0 com.b_task.application2/.MainActivity t11653}
Stack #0: type=home mode=fullscreen
Task id #1
* TaskRecord{a611787 #1 A=com.huawei.android.launcher U=0 StackId=0 sz=1}
Hist #0: ActivityRecord{a99c328 u0 com.huawei.android.launcher/.unihome.UniHomeLauncher t1}
Running activities (most recent first):
TaskRecord{a611787 #1 A=com.huawei.android.launcher U=0 StackId=0 sz=1}
Run #0: ActivityRecord{a99c328 u0 com.huawei.android.launcher/.unihome.UniHomeLauncher t1}
Stack #761: type=standard mode=fullscreen
Task id #11652
* TaskRecord{dfc4117 #11652 A=com.task.other.independent U=0 StackId=761 sz=1}
Hist #0: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}
Running activities (most recent first):
TaskRecord{dfc4117 #11652 A=com.task.other.independent U=0 StackId=761 sz=1}
Run #0: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}
Stack #760: type=standard mode=fullscreen
Task id #11651
* TaskRecord{f06e904 #11651 A=com.a_task.application U=0 StackId=760 sz=1}
Hist #0: ActivityRecord{2035f77 u0 com.a_task.application/.MainActivity t11651}
Running activities (most recent first):
TaskRecord{f06e904 #11651 A=com.a_task.application U=0 StackId=760 sz=1}
Run #0: ActivityRecord{2035f77 u0 com.a_task.application/.MainActivity t11651}
- 再打开app2的OtherActivity2页面。
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
Stack #761: type=standard mode=fullscreen
Task id #11652
* TaskRecord{dfc4117 #11652 A=com.task.other.independent U=0 StackId=761 sz=2}
Hist #1: ActivityRecord{32435ec u0 com.b_task.application2/.OtherActivity2 t11652}
Hist #0: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}
Running activities (most recent first):
TaskRecord{dfc4117 #11652 A=com.task.other.independent U=0 StackId=761 sz=2}
Run #1: ActivityRecord{32435ec u0 com.b_task.application2/.OtherActivity2 t11652}
Run #0: ActivityRecord{2a95a74 u0 com.a_task.application/.OtherActivity1 t11652}
mResumedActivity: ActivityRecord{32435ec u0 com.b_task.application2/.OtherActivity2 t11652}
Stack #762: type=standard mode=fullscreen
Task id #11653
* TaskRecord{c7e67ab #11653 A=com.b_task.application2 U=0 StackId=762 sz=1}
Hist #0: ActivityRecord{b8c7cd2 u0 com.b_task.application2/.MainActivity t11653}
Running activities (most recent first):
TaskRecord{c7e67ab #11653 A=com.b_task.application2 U=0 StackId=762 sz=1}
Run #0: ActivityRecord{b8c7cd2 u0 com.b_task.application2/.MainActivity t11653}
Stack #0: type=home mode=fullscreen
Task id #1
* TaskRecord{a611787 #1 A=com.huawei.android.launcher U=0 StackId=0 sz=1}
Hist #0: ActivityRecord{a99c328 u0 com.huawei.android.launcher/.unihome.UniHomeLauncher t1}
Running activities (most recent first):
TaskRecord{a611787 #1 A=com.huawei.android.launcher U=0 StackId=0 sz=1}
Run #0: ActivityRecord{a99c328 u0 com.huawei.android.launcher/.unihome.UniHomeLauncher t1}
Stack #760: type=standard mode=fullscreen
Task id #11651
* TaskRecord{f06e904 #11651 A=com.a_task.application U=0 StackId=760 sz=1}
Hist #0: ActivityRecord{2035f77 u0 com.a_task.application/.MainActivity t11651}
Running activities (most recent first):
TaskRecord{f06e904 #11651 A=com.a_task.application U=0 StackId=760 sz=1}
Run #0: ActivityRecord{2035f77 u0 com.a_task.application/.MainActivity t11651}
从上面的栈信息可以看出来,在第一阶段时,app1有2个ActivityStack,分别是Stack #760和Stack #761,第二阶段时app2有属于自己的ActivityStack,即Stack #762,也有和app1共享的ActivityStack,即Stack #761。由此可见,在不同的Android版本下,APP与ActivityStack的对应关系不同。APP与ActivityStack之间并无必然的联系。有可能是一个APP对应一个ActivityStack,有可能是一个APP对应多个ActivityStack,也有可能是多个APP共用一个ActivityStack。
ActivityStack的作用
那么ActivityStack是用来做什么的?这个问题我在网上找了好久,也没有答案。以下说说我的理解。
不知道大家有没有想过为什么要用这么多的ActivityStack来管理TaskRecord列表,而不是用一个ActivityStack管理全部的TaskRecord。下面假设只用一个ActivityStack管理全部的TaskRecord,那么在Android5.1.1的机器中执行了第二阶段后,栈信息会变成什么样?
现在按下HOME键,我们来看下栈信息会怎么变。
Android5.1.1的原栈中只需要将Stack #0移至列表头即可,需要3个步骤:
- 移除Stack #0并保存于临时变量中
- Stack #1移至列表底部
- 将Stack #0移至列表顶部
此时的栈信息如下:
Stack #0:
Task id #1
TaskRecord{20b66655 #1 A=com.android.launcher3 U=0 sz=1}
Hist #0: ActivityRecord{1f09fcbb u0 com.android.launcher3/.Launcher t1}
Running activities (most recent first):
TaskRecord{20b66655 #1 A=com.android.launcher3 U=0 sz=1}
Run #0: ActivityRecord{1f09fcbb u0 com.android.launcher3/.Launcher t1}
mResumedActivity: ActivityRecord{1f09fcbb u0 com.android.launcher3/.Launcher t1}
Stack #1:
Task id #3
TaskRecord{3b95a86a #3 A=com.task.other.independent U=0 sz=2}
Hist #1: ActivityRecord{22bb8f8a u0 com.b_task.application2/.OtherActivity2 t3}
Hist #0: ActivityRecord{6fc682b u0 com.a_task.application/.OtherActivity1 t3}
Task id #4
TaskRecord{2405315b #4 A=com.b_task.application2 U=0 sz=1}
Hist #0: ActivityRecord{92febef u0 com.b_task.application2/.MainActivity t4}
Task id #2
TaskRecord{32a1edf8 #2 A=com.a_task.application U=0 sz=1}
Hist #0: ActivityRecord{3915bebe u0 com.a_task.application/.MainActivity t2}
Running activities (most recent first):
TaskRecord{3b95a86a #3 A=com.task.other.independent U=0 sz=2}
Run #3: ActivityRecord{22bb8f8a u0 com.b_task.application2/.OtherActivity2 t3}
TaskRecord{2405315b #4 A=com.b_task.application2 U=0 sz=1}
Run #2: ActivityRecord{92febef u0 com.b_task.application2/.MainActivity t4}
TaskRecord{3b95a86a #3 A=com.task.other.independent U=0 sz=2}
Run #1: ActivityRecord{6fc682b u0 com.a_task.application/.OtherActivity1 t3}
TaskRecord{32a1edf8 #2 A=com.a_task.application U=0 sz=1}
Run #0: ActivityRecord{3915bebe u0 com.a_task.application/.MainActivity t2}
如果只用一个ActivityStack管理所有的TaskRecord的话:
我们可以看到需要5个步骤:
- 移除Task #1,并保存于临时变量
- Task #2向前移一位
- Task #4向前移一位
- Task #3向前移一位
- 将Task #1移至列表顶部
显然效率低了很多。所以我得出一个结论:ActivityStack的作用是更快捷地将任务栈从后台调至前台。
由于app1的OtherActivity1的启动模式是singleTask,且单独为它指定了一个任务栈名。Android9.0就把OtherActivity1单独放在了一个ActivityStack中,之所以这么做,也是为了更快地调度任务栈。
上图中,假设Task #2中含有启动模式为singleTask的Activity,现要启动该Activity,就需要把Task #2移至队列顶部(即前台)。
Android5.1.1需要4个步骤:
- 移除Task #2,并保存于临时变量中
- Task #3向前移一位
- Task #4向前移一位
- 将Task #2移至Stack #1中的
List<TaskRecord>
的顶部
Android9.0只需要3个步骤:
- 移除Stack #1,并保存于临时变量中
- Stack #2向前移一位
- 将Stack #1移至列表顶部
显然Android9.0的效率更高。
ActivityDisplay
ActivityDisplay表示一个屏幕,Android支持三种屏幕:主屏幕,外接屏幕(HDMI等),虚拟屏幕(投屏)。一般情况下,即只有主屏幕时,ActivityStackSupervisor与ActivityDisplay都是系统唯一;
ActivityDisplay是ActivityStackSupervisor的内部类,它相当于一个工具类,封装了移除和添加ActivityStack的方法。
class ActivityDisplay {
final ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
void attachActivities(ActivityStack stack) {
if (DEBUG_STACK) Slog.v(TAG_STACK,
"attachActivities: attaching " + stack + " to displayId=" + mDisplayId);
mStacks.add(stack);
}
void detachActivitiesLocked(ActivityStack stack) {
if (DEBUG_STACK) Slog.v(TAG_STACK, "detachActivitiesLocked: detaching " + stack
+ " from displayId=" + mDisplayId);
mStacks.remove(stack);
}
}
ActivityStackSupervisor
ActivityStackSupervisor是ActivityStack的管理者,内部管理了mHomeStack、mFocusedStack和mLastFocusedStack三个ActivityStack。其中,mHomeStack管理的是Launcher相关的Activity栈, stackId为0;mFocusedStack管理的是当前显示在前台Activity的Activity栈;mLastFocusedStack管理的是上一次显示在前台Activity的Activity栈。
public final class ActivityStackSupervisor implements DisplayListener {
/** The stack containing the launcher app. Assumed to always be attached to
* Display.DEFAULT_DISPLAY. */
private ActivityStack mHomeStack;
/** The stack currently receiving input or launching the next activity. */
private ActivityStack mFocusedStack;
/** If this is the same as mFocusedStack then the activity on the top of the focused stack has
* been resumed. If stacks are changing position this will hold the old stack until the new
* stack becomes resumed after which it will be set to mFocusedStack. */
private ActivityStack mLastFocusedStack;
/** Mapping from (ActivityStack/TaskStack).mStackId to their current state */
private SparseArray<ActivityContainer> mActivityContainers = new SparseArray<>();
ActivityStack createStackOnDisplay(int stackId, int displayId) {
……
ActivityContainer activityContainer = new ActivityContainer(stackId);
mActivityContainers.put(stackId, activityContainer);
activityContainer.attachToDisplayLocked(activityDisplay);
return activityContainer.mStack;
}
class ActivityContainer extends android.app.IActivityContainer.Stub {
final ActivityStack mStack;
ActivityDisplay mActivityDisplay;
ActivityContainer(int stackId) {
synchronized (mService) {
mStackId = stackId;
mStack = new ActivityStack(this, mRecentTasks);
}
}
void attachToDisplayLocked(ActivityDisplay activityDisplay) {
……
mActivityDisplay = activityDisplay;
activityDisplay.attachActivities(mStack);
}
protected void detachLocked() {
……
if (mActivityDisplay != null) {
mActivityDisplay.detachActivitiesLocked(mStack);
}
}
}
}
ActivityDisplay的添加和移除ActivityStack的方法又被封装进了ActivityContainer类中,ActivityStackSupervisor调用ActivityContainer的attachToDisplayLocked
与detachLocked
对ActivityStack列表进行重排序,将任务栈从后台切换至前台。
前台任务栈与后台任务栈
如上图所示,只有Task #5才是前台任务栈,其余的都是后台任务栈。后台任务栈里面的Activity全部处于onStop状态。