深入理解ActivityRecord、TaskRecord、ActivityStack的作用及关系

7,698 阅读21分钟

ActivityManagerService

ActivityManagerService(简称AMS)是Android系统最核心的Binder服务之一,从名称上看好像它只是Activity的管理者,但实际上AMS管理和维护着系统四大组件(Activity,Service,Broadcast,ContentProvider)的相关工作,这个任务非常重要而且异常复杂,在KK中单是AMS一个类的源码行数就高达一万六千多行,可见其内部的任务有多庞大。在这之中,AMS对于Activity的管理任务最为复杂,这可能也是它为什么叫ActivityManagerService的原因吧。AMS对于activity的管理实际上通过三个类来体现,它们分别是ActivityRecord,TaskRecord以及ActivityStack,把握和理解它们之间的关系对于我们理解AMS的工作将会有很大的帮助。因此本篇将会介绍这三者在AMS中的联系和作用。

ActivityRecord

ActivityRecord是应用层Activity组件在AMS中的代表,每一个在应用中启动的Activity,在AMS中都有一个ActivityRecord实例来与之对应,这个ActivityRecord伴随着Activity的启动而创建,也伴随着Activity的终止而销毁。

类结构说明

关于ActivityRecord类,它只是一个简单的类,并没有继承任何其他父类,在它内部存储的都是一些关于Activity组件的相关信息,所以类结构比较简单,下面我将列出它的一些成员进行介绍:

/**
 * An entry in the history stack, representing an activity.
 */
final class ActivityRecord {
    final ActivityManagerService service; // owner
    final IApplicationToken.Stub appToken; // window manager token
    final ActivityInfo info; // all about me
    final int launchedFromUid; // always the uid who started the activity.
    final String launchedFromPackage; // always the package who started the activity.
    final int userId;          // Which user is this running for?
    final Intent intent;    // the original intent that generated us
    final ComponentName realActivity;  // the intent component, or target of an alias.
    final String shortComponentName; // the short component name of the intent
    final String resolvedType; // as per original caller;
    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
    ...
    int labelRes;           // the label information from the package mgr.
    int icon;               // resource identifier of activity's icon.
    int logo;               // resource identifier of activity's logo.
    int theme;              // resource identifier of activity's theme.
    int realTheme;          // actual theme resource we will use, never 0.
    int windowFlags;        // custom window flags for preview window.
    TaskRecord task;        // the task this is in.
    Configuration configuration; // configuration activity was last running in
    CompatibilityInfo compat;// last used compatibility mode
    ActivityRecord resultTo; // who started this entry, so will get our reply
    final String resultWho; // additional identifier for use by resultTo.
    final int requestCode;  // code given by requester (resultTo)
    HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
    ArrayList<Intent> newIntents; // any pending new intents for single-top mode
    ActivityOptions pendingOptions; // most recently given options
    HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
    UriPermissionOwner uriPermissions; // current special URI access perms.
    ProcessRecord app;      // if non-null, hosting application
    ActivityState state;    // current state we are in
    ...
    int launchMode;         // the launch mode activity attribute.

}

可以看出ActivityRecord包含了很多信息,我们简单描述下:

  1. appToken :这是一个Binder,而且是Server端的实体,Token即令牌,它一般作为一个标识使用,这个appToken用来在WindowManagerService端标识这个AcitvityRecord,token的实现如下
static class Token extends IApplicationToken.Stub {
        final WeakReference<ActivityRecord> weakActivity;

        Token(ActivityRecord activity) {
            weakActivity = new WeakReference<ActivityRecord>(activity);
        }

        @Override public void windowsDrawn() {
            ActivityRecord activity = weakActivity.get();
            if (activity != null) {
                activity.windowsDrawn();
            }
        }

        @Override public void windowsVisible() {
            ActivityRecord activity = weakActivity.get();
            if (activity != null) {
                activity.windowsVisible();
            }
        }

        @Override public void windowsGone() {
            ActivityRecord activity = weakActivity.get();
            if (activity != null) {
                activity.windowsGone();
            }
        }
    ...        
}

可以看到它实际上是一个Token,实现了自IApplicationToken.Stub的方法,内部有个弱引用指向包含它的ActivityRecord实例,从实现来看,appkToken实际上有两个作用,在WMS端标记一个ActivityRecord,同时可以通过该token和AMS进行通信。

  1. launchedFromUid和launchedFromPackage 启动该activity的应用uid和包名,比如我们从launcher启动的应用activity,这个对应的就是launcher的uid和包名
  2. intent 和 ComponentName intent是启动时候传递的意图对象,ComponentName标记了启动的acitivity组件。
  3. packageName和processName 分别代表了activity所属应用的包名和进程名
  4. taskAffinity 标记了activity的亲属性,默认情况下为包名,这个成员和该activity所属TaskRecord有关,后面我们具体介绍。
  5. logo 和 theme 这些是activity所使用的logo和theme资源标记。
  6. task 应用所属TaskRecord,后面介绍。
  7. resultTo和requestCode,resultTo也是一个ActivityRecord,它是当前ActivityRecord对应的activity要返回和恢复的activity,我们通过startActivityForResult启动一个activity时,往往需要接受来自于启动的activity的返回值,这个resultTo就是负责处理返回值的activity对应的ActivityRecord
  8. app 它是一个ProcessRecord,用于描述当前activity所在应用的进程
  9. state 它是一个AcitivityState枚举,用于描述当前activity的状态,这些状态被AMS内部使用,ActivityState的定义如下:
enum ActivityState {
        INITIALIZING,
        RESUMED,
        PAUSING,
        PAUSED,
        STOPPING,
        STOPPED,
        FINISHING,
        DESTROYING,
        DESTROYED
}
  1. launchMode activity的启动模式

ActivityRecord的创建

final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
            String resultWho, int requestCode,
            int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
            boolean componentSpecified, ActivityRecord[] outActivity) {
          ...
          //为activity创建ActivityRecord
          ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration,
                resultRecord, resultWho, requestCode, componentSpecified, this);
          ...      
}

AcitivtyRecord是在启动activity时候创建的,这里具体是在ActivityStackSupervisor中,关于ActivityStackSupervisor后面再介绍。我们看看ActivityRecord的构造方法中

ActivityRecord(ActivityManagerService _service, ProcessRecord _caller,
            int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
            ActivityInfo aInfo, Configuration _configuration,
            ActivityRecord _resultTo, String _resultWho, int _reqCode,
            boolean _componentSpecified, ActivityStackSupervisor supervisor) {
        service = _service;
        appToken = new Token(this);//创建了appToken 这个token用来标记activity,token内部持有该ActivityRecord的弱引用
        info = aInfo;
        launchedFromUid = _launchedFromUid;
        launchedFromPackage = _launchedFromPackage;
        userId = UserHandle.getUserId(aInfo.applicationInfo.uid);
        intent = _intent;
        shortComponentName = _intent.getComponent().flattenToShortString();
        resolvedType = _resolvedType;
        componentSpecified = _componentSpecified;
        configuration = _configuration;
        resultTo = _resultTo;
        resultWho = _resultWho;
        requestCode = _reqCode;
        state = ActivityState.INITIALIZING;
        frontOfTask = false;
        launchFailed = false;
        stopped = false;
        delayedResume = false;
        finishing = false;
        configDestroy = false;
        keysPaused = false;
        inHistory = false;
        visible = true;
        waitingVisible = false;
        nowVisible = false;
        thumbnailNeeded = false;
        idle = false;
        hasBeenLaunched = false;
        mStackSupervisor = supervisor;

        ...
}

在构造方法中创建了ActivityRecord的appToken,关于appToken我们前面已经做了介绍。初始的activity状态为ActivityState.INITIALIZING,这里的visible标记的是activity在WMS端对应的window是否需要显示,在构造ActivityRecord时表示我们要启动activity了,这时候也就需要WMS为我们显示窗口,置true。nowVisible表示的是activity当前的窗口显示状态,这时候activity还在创建过程中,还未显示出来,置false。

TaskRecord

TaskRecord即任务栈,或者叫返回栈(back Stack),Task实际上是指执行一个特定任务时和用户进行交互的一组activity,什么意思呢?比如我们为了完成用微信发送消息这个任务,而需要打开首页的联系人列表,然后选择一个联系人进入聊天界面发送消息,这两个activity就可以说是一个Task,但如果我们说要发送图片,那么还会去打开选择照片的activity,这时候Task就是三个activity,所以说Task是一个动态的概念,但不管怎么样,我们总成为它是一组activity的集合,这个集合在AMS中就是TaskRecord,它和数据结构中的Stack结构类似,也是先进后出,当我们打开App中的一个activity1时,它对应的ActivityRecord被添加到TaskRecord中,再在activit1中打开第二个页面activity2,在activity2中打开activity3,同样它们的ActivityRecord也会被添加到TaskRecord,当我们按下返回键,activity3先从TaskRecord中弹出来,依次类推,当task中所有的activity被弹出后,这个task也就销毁了。最终它的结构如下图所示:

Task切换

一般情况下,我们可以将打开的一个app看做是一个TaskRecord,当我们先后打开app A的两个页面A和B,这时候在其对应的TaskRecord中就有两个ActivityRecord的记录,当我们按下home键后,然后打开另一个app B的C和D页面,这时候app A的TaskRecord就到了后台中,它内部的两个activity此时都处于停止状态,而app B的TaskRecord此时处于前台和用户交互的状态,它的TaskRecord中也有两个ActivityRecord的记录,如果我们再按下home键,点击app A,这时候我们发现app A停留在B页面,也就是说app A的TaskRecord又作为一个整体从后台切换到了前台,它的状态和之前是一样的。系统可以同时管理多个后台的TaskRecord,但是如果用户打开的太多app在后台中,系统可能会回收一部分。

打开多个app时,AMS中就存在了多个TaskRecord,我们可以在这些TaskRecord之间进行切换,当我打开Email应用后可以在编辑Email的过程中打开相册应用来选择图片,选择完成后可以继续回到Email中编辑邮件。这个是Task切换带来的便利。

启动模式launchMode

Android管理activity的方式是在同一个Task中使用先进后出的栈管理方式,默认情况下,我们创建一个Activity就会在TaskRecord中有一个实例,但有些时候我们可能希望当启动一个activity的时候使用TaskRecord中已经存在的实例或者当我们启动一个activity时需要将它放置在单独的一个TaskRecord之中,这时候就需要我们为启动的activity设置启动模式(launchMode)了,所以说launchMode是和TaskRecord相关联的。

有四种不同的启动模式:

  1. standard,这个即是Android默认的启动模式,每打开一个Activity就创建一个实例到Task中,同一个Activity在Task中可以有多个实例。
  2. singleTop,如果一个activity的实例已经在Task栈的顶部,那么当再次打开这个activity时会复用这个实例而不再创建一个新的实例,同时通过onNewIntent传递给这个实例Intent。比如Task已经有四个activityA->B->C->D,D在Task顶部,那么再次打开D页面时,Task依然是A->B->C->D,而在Standard模式下将会是A->B->C-D->D
  3. singleTask,这个是说一个activity的实例在Task只能有一个实例,如果一个activity实例已经在Task中存在,Android系统会直接把Intent路由到Task中存在的Activity实例对象上,会通过调用onNewIntent()方法处理,而非创建一个新的Activity实例对象。并且会把在它之上的其它Activity清理掉。但是如果实例不存在Task中,此时系统将会为比较调用方activity和被调用方activity的taskAffnity,如果一致就将该activity创建一个实例,并加入到已存在的Task中,如果不一致,就为该activity创建一个新的Task,此时activity是作为Task的root activity的。事实上,Task的taskAffinity正是由Task的root activity决定的。
  4. singleInstance,如果设置了该模式,那么在Task中只能有一个该activity的实例。

启动模式不仅可以在AndroidManifest中进行设定,同样的我们可以使用Intent Flags进行设定,一些常见的Flags可以更方便和灵活的处理activity和Task的关系:

  1. FLAG_ACTIVITY_NEW_TASK ,这个标记同singleTask的处理方式
  2. FLAG_ACTIVITY_SINGLE_TOP,这个标记同singleTop的处理方式
  3. FLAG_ACTIVITY_CLEAR_TOP,如果activity的实例已经在当前Task中,那么再启动时,将会将其之上的activity实例都销毁掉。比如Task A->B->C->D,如果在D中启动B添加了该标记,那么会将C和D都从Task销毁掉,如果此时B是默认的启动模式,那么会将B的实例也销毁,并重新创建一个实例添加到Task顶部,如果我们不想它重新创建,可以配合FLAG_ACTIVITY_SINGLE_TOP使用,这样复用顶部的B实例并触发onNewIntent。
  4. FLAG_ACTIVITY_REORDER_TO_FRONT,新启动的Activity将会被放到它所属task的顶部,例如,当Task A->B->C->D,如果D启动B使用了这个标记,B将会排在这个task的最上面,也即现在Task的顺序变成了A,C,D,B。
  5. FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET 这个标记将会在TASK重置时清理对应的Activity,比如Task当前为A->B,A启动B添加了该标记,那么当切换到Home再打开该应用后Task变为A,B被清理。这个其实是在Task中设置了一个还原点,当Task重置时将Task恢复到指定的还原点。

另外在 AndroidManifest的中也可以设置和Task相关属性,下面我们看看几种:

  1. android:allowTaskReparenting 这个属性定义的是activity具有reparent Task的能力,即标记一个Activity实例在当前应用退居后台后,是否能从启动它的那个Task移动到有共同TaskAffinity的Task,“true”表示可以移动,“false”表示它必须呆在当前应用的task中,默认值为false。下面通过一个例子说明这种情况: 比如App A 有一个Activity:MainActivity,App B有两个Activity:BMainActivity和SecondActivity,其中SecondActivity定义了该属性为true,当我们在App A中的MainActivity中启动App B的SecondActivity后,此时A的Task为MainActivity->SecondActivity,注意此时MainActivity和SecondActivity的TaskAffinity并不是相同的,他们为各自的包名。如果此时按Home键回到Launcher,再启动App B后,会发现此时的页面是SecondActivity,也就是说SecondActivity从原来App A的Task移动到了和他TaskAffinity相同的Task中即App B的Task。

  2. android:clearTaskOnLaunch 如果设置了这个属性为true,每次用户重新启动这个应用时,都只会看到Root Activity,task中的其他Activity都会被清除出栈。这个属性也只对Root Activity有效。

  3. android:alwaysRetainTaskState 这个属性是让Task保持原来的状态,true表示保持,false不能够保持,此属性也只对Root Activity有效,一般情况下,如果Task切换到后台后太久系统会对Task进行清理,除了Root Activity其他Activity都会被清理。但如果设置了该属性为true,则可以保持上次操作的界面。

  4. android:noHistory 这个属性设置为true后,则Activity将不会被记录到Task的history列表中,那么就是说,这个Activity不可见,那么它实际上就和销毁了一样,因为AMS没有它的相关信息。

TaskRecord的实现

了解了Task的相关知识,接下来我们看看它是如何在AMS中实现的。

final class TaskRecord extends ThumbnailHolder {
    final int taskId;       // Unique identifier for this task. //Task栈的比唯一标志
    final String affinity;  // The affinity name for this task, or null.
    Intent intent;          // The original intent that started the task.
    Intent affinityIntent;  // Intent of affinity-moved activity that started this task.
    ComponentName origActivity; // The non-alias activity component of the intent.
    ComponentName realActivity; // The actual activity component that started the task.
    int numActivities;      // Current number of activities in this task.
    long lastActiveTime;    // Last time this task was active, including sleep.
    boolean rootWasReset;   // True if the intent at the root of the task had
                            // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
    boolean askedCompatMode;// Have asked the user about compat mode for this task.

    String stringName;      // caching of toString() result.
    int userId;             // user for which this task was created

    int numFullscreen;      // Number of fullscreen activities.

    /** List of all activities in the task arranged in history order */
    final ArrayList<ActivityRecord> mActivities = new ArrayList<ActivityRecord>();//以历史序排列的所有activities

    /** Current stack */
    ActivityStack stack;

    /** Takes on same set of values as ActivityRecord.mActivityType */
    private int mTaskType;

    /** Launch the home activity when leaving this task. */
    boolean mOnTopOfHome = false;

    TaskRecord(int _taskId, ActivityInfo info, Intent _intent) {
        taskId = _taskId;
        affinity = info.taskAffinity;
        setIntent(_intent, info);
    }
    ...
}

在AMS中,Task是通过TaskRecord类来描述的,它的成员相对ActivityRecord要少很多,这里我们介绍下:

  1. taskId,这个是TaskRecord的一个唯一标记
  2. affnity,亲属性的名称,同一个Task的ativity有相同的taskAffinity,它是由Task的Root Activity的taskAffinity决定的。
  3. Intent,启动这个Task的源activity对应的Intent,也即是启动root activity的Intent。
  4. numActivities,这个是当前Task中的activity数目。
  5. numFullscreen 全屏activity的个数
  6. mActivities 维护的ActivityRecord实例,这个代表的就是Activity,可见TaskRecord栈结构是通过ArrayList来体现的。
  7. stack ,所属的ActivityStack,关于ActivityStack我们后面介绍

TaskRecord的创建

一般情况下,在启动App的第一个activity时,AMS为其创建一个TaskRecord任务栈,当然启动后也可能创建新的TaskRecord,比如我们启动singleTask的Activity,而且为该Activity指定了和包名不同的taskAffinity,这时候也会为该activity创建一个新的TaskRecord,所有一个App是可能有多个TaskRecord存在的,这取决于应用的使用场景和需求。

我们按照分析的逻辑看看AMS中是如何实现为TaskRecord创建的。

final int startActivityUncheckedLocked(ActivityRecord r,
            ActivityRecord sourceRecord, int startFlags, boolean doResume,
            Bundle options) {
    if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
            
            boolean addingToTask = false;
            TaskRecord reuseTask = null;
            ...        
            ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
                                ? findTaskLocked(r)
                                : findActivityLocked(intent, r.info);
            ...
            if (r.resultTo == null && !addingToTask
                && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
                ...
                if (reuseTask == null) {
                    r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                            newTaskInfo != null ? newTaskInfo : r.info,
                            newTaskIntent != null ? newTaskIntent : intent,
                            true), null, true);//创建新的taskRecord
                }        
            }
    }

}

当启动模式设定为singleTask后我们通过findTaskLocked来为启动的Activity寻找TaskRecord,如果找到则返回它顶部的Activity对应的ActivityRecord。

ActivityRecord findTaskLocked(ActivityRecord r) {
    if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + r);
    for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
        final ActivityStack stack = mStacks.get(stackNdx);
        if (!r.isApplicationActivity() && !stack.isHomeStack()) {
            if (DEBUG_TASKS) Slog.d(TAG, "Skipping stack: " + stack);
            continue;
        }
        final ActivityRecord ar = stack.findTaskLocked(r);
        if (ar != null) {
            return ar;
        }
    }
    if (DEBUG_TASKS) Slog.d(TAG, "No task found");
    return null;
}

/**
    * Returns the top activity in any existing task matching the given
    * Intent.  Returns null if no such task is found.
    */
ActivityRecord findTaskLocked(ActivityRecord target) {
    Intent intent = target.intent;//要启动Activity的Intent
    ActivityInfo info = target.info;
    ComponentName cls = intent.getComponent();
    if (info.targetActivity != null) {
        cls = new ComponentName(info.packageName, info.targetActivity);
    }
    final int userId = UserHandle.getUserId(info.applicationInfo.uid);

    if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + target + " in " + this);
    for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {//遍历TaskRecord
        final TaskRecord task = mTaskHistory.get(taskNdx);
        if (task.userId != userId) {
            // Looking for a different task.
            if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": different user");
            continue;
        }
        final ActivityRecord r = task.getTopActivity();//获取taskRecord顶部的activity
        if (r == null || r.finishing || r.userId != userId ||
                r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
            if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": mismatch root " + r);
            continue;
        }

        if (DEBUG_TASKS) Slog.d(TAG, "Comparing existing cls="
                + r.task.intent.getComponent().flattenToShortString()
                + "/aff=" + r.task.affinity + " to new cls="
                + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
        if (task.affinity != null) {//首先根据亲属性taskAffinity匹配,相等的就是匹配的
            if (task.affinity.equals(info.taskAffinity)) {
                if (DEBUG_TASKS) Slog.d(TAG, "Found matching affinity!");
                return r;
            }
        } else if (task.intent != null && task.intent.getComponent().equals(cls)) {//否则启动的就是栈顶activity
            if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
            //dump();
            if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
                    + r.intent);
            return r;
        } else if (task.affinityIntent != null
                && task.affinityIntent.getComponent().equals(cls)) {
            if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
            //dump();
            if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
                    + r.intent);
            return r;
        } else if (DEBUG_TASKS) {
            Slog.d(TAG, "Not a match: " + task);
        }
    }

    return null;//未找到就返回null
}

在findTaskLocked中,我们会比较要启动的Activity和Task的affinity,如果匹配就返回TaskRecord顶部的ActivityRecord,如果最终没找到则返回null。如果返回值intentActivity为null,那么 addingToTask和reuseTask都不会设置,这时候会通过createTaskRecord创建TaskRecord并设置到ActivityRecord之中。

TaskRecord的复用

事实上大多数情况,Activity都会复用TaskRecord,也就是说Activity会添加到相同的TaskRecord之中,除了应用第一次启动或者taskAffinity不同之外。如果上一步中通过findTaskLocked返回的intentActivity不为null,这表示我们为启动模式为singleTask的activity找到了一个可复用的TaskRecord。

final int startActivityUncheckedLocked(ActivityRecord r,
            ActivityRecord sourceRecord, int startFlags, boolean doResume,
            Bundle options) {
    if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
                ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
                                        ? findTaskLocked(r)
                                        : findActivityLocked(intent, r.info);
                if (intentActivity != null) {//找到对应TaskRecord栈顶的ActivityRecord
                    if (r.task == null) {
                        r.task = intentActivity.task;//设置r的TaskRecord为该Task
                    }
                }
    }

    if (r.resultTo == null && !addingToTask
                && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        ...
    } else if (sourceRecord != null) {//针对其他启动模式的复用TaskRecord
        TaskRecord sourceTask = sourceRecord.task;
        targetStack = sourceTask.stack;
        ...
        r.setTask(sourceTask, sourceRecord.thumbHolder, false);
    }
}            

ActivityStack

ActivityStack的说法听起来很容易和我们常说的任务栈混淆,很多人可能看到它的第一个反应是它就是我们的任务栈,然而并非如此,我们知道系统中可能同时有多个Task,一般前台就一个Task和用户进行交互,而后台中可能有多个Task存在,前后台的Task可以进行切换,AMS为了方便的管理这些Task而引入了ActivityStack,在ActivityStack内部通过ArrayList维护了一组TaskRecord。一般来说Launcher的Task属于单独的一个ActivityStack,称为Home Activity Stack,System UI如rencentActivity的Task属于一个单独ActivityStack,其他App的Task属于另一个ActivityStack。

结构

下面我们看看ActivityStack的结构

final class ActivityStack {
    ...
    final ActivityManagerService mService;//AMS引用
    final WindowManagerService mWindowManager;//WMS引用

    /**
     * The back history of all previous (and possibly still
     * running) activities.  It contains #TaskRecord objects.
     */
    private ArrayList<TaskRecord> mTaskHistory = new ArrayList<TaskRecord>();

    /**
     * List of running activities, sorted by recent usage.
     * The first entry in the list is the least recently used.
     * It contains HistoryRecord objects.
     */
    final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<ActivityRecord>();

    ...

    /**
     * This is the last activity that we put into the paused state.  This is
     * used to determine if we need to do an activity transition while sleeping,
     * when we normally hold the top activity paused.
     */
    ActivityRecord mLastPausedActivity = null;//记录了上次切换ActivityStack后被暂停的Activity

    /**
     * Current activity that is resumed, or null if there is none.
     */
    ActivityRecord mResumedActivity = null;//当前正在运行的activity,可以为null表示当前运行的activity不在该ActivityStack中

    final int mStackId;

    /** Run all ActivityStacks through this */
    final ActivityStackSupervisor mStackSupervisor;//ActivityStack的管家

    ...

}

从其成员中我们可以看出ActivityStack维护了一组TaskRecord,以及一组最近使用的Activities,还有上次切换ActivityStack被暂停的Activity,和TaskRecord类似,多个ActivityStack同样是可以进行切换的,比如我们从桌面Launcher点击app后,会从Launcher所在的ActivityStack切换到app所在的ActivityStack,mResumedActivity表示正在运行的activity,它也可以是null,当为null时表示当前运行的Activity不在该ActivityStack。同样的,在ActivityStack中通过mStackId来唯一的标识一个ActivityStack。

明白了ActivityStack的概念和用途,我们看看ASM是如何管理它的。在AMS中通过ActivityStackSupervisor来管理这些ActivityStack,从而间接的管理着TaskRecord,在ActivityStackSupervisor内部通过mHomeStack和mStacks管理着所有ActivityStack,其中mHomeStack是Launcher的TaskRecord所在的ActivityStack,而mStacks是其他的ActivityStack,它是一个ArrayList。

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ...
    /** Run all ActivityStacks through this */
    ActivityStackSupervisor mStackSupervisor;
    ...
     //在SystemServer启动时候 调用该main方法
    public static final Context main(int factoryTest) {
        ...
        ActivityManagerService m = thr.mService;
        mSelf = m;
        ActivityThread at = ActivityThread.systemMain();
        mSystemThread = at;//创建AMS的ActivityThread
        Context context = at.getSystemContext();
        context.setTheme(android.R.style.Theme_Holo);//系统默认的context主题
        m.mContext = context;
        m.mFactoryTest = factoryTest;
        m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface());

        m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper);//创建ActivityStack管家

        m.mBatteryStatsService.publish(context);
        m.mUsageStatsService.publish(context);
        m.mAppOpsService.publish(context);

        ...
        return context;
    }
}            
public final class ActivityStackSupervisor {
    final ActivityManagerService mService;
    /** Identifier counter for all ActivityStacks */
    private int mLastStackId = HOME_STACK_ID;
    /** Task identifier that activities are currently being started in.  Incremented each time a
     * new task is created. */
    private int mCurTaskId = 0;

    /** The current user */
    private int mCurrentUser;

    /** The stack containing the launcher app */
    private ActivityStack mHomeStack;

    /** The non-home stack currently receiving input or launching the next activity. If home is
     * in front then mHomeStack overrides mFocusedStack.
     * DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */
    private ActivityStack mFocusedStack;

    /** All the non-launcher stacks */
    private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();

        /** List of activities that are waiting for a new activity to become visible before completing
     * whatever operation they are supposed to do. */
    final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();

    /** List of activities that are ready to be stopped, but waiting for the next activity to
     * settle down before doing so. */
    final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();

    /** List of activities that are ready to be finished, but waiting for the previous activity to
     * settle down before doing so.  It contains ActivityRecord objects. */
    final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();

    /** List of activities that are in the process of going to sleep. */
    final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>();

    ...
}
  1. mLastStackId是所有ActivityStack的计数,这个在创建ActivityStack使用来计算stackId
  2. mCurTaskId 指当前前台的ActivityStatck对应的stackId
  3. mHomeStack 这个是launcher的TaskRecord所在的ActivityStack。
  4. mStacks 所有非Launcher的ActivityStack。这是一个ArrayList,因为非Launcher的ActivityStack可能有多个。
  5. 除了以上成员,ActivityStackSupervisor还维护着多组ActivityRecord的集合,这些分别用来记录那些等待显示,或者正在停止或销毁的Activity。

创建过程

同样的ActivityStack也是按需创建的

final int startActivityUncheckedLocked(ActivityRecord r,
            ActivityRecord sourceRecord, int startFlags, boolean doResume,
            Bundle options) {
    ...
    if (r.resultTo == null && !addingToTask
                && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
            targetStack = adjustStackFocus(r);

    }
    ...            
}

实际上ActivityStack的创建时在Launcher启动时候进行的,而且是在系统启动后启动的第一个app,这个app在启动第一个Activity的时候在AMS还未有非Launcher的ActivityStack,所以需要创建一个。后面的App启动时就会找到这个ActivityStack。创建时通过ActivityStackSupervisor的adjustStackFocus方法,这个方法为要启动的Acitivity寻找前台的ActivityStack,即mFocusedStack。

//frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java
ActivityStack adjustStackFocus(ActivityRecord r) {
        final TaskRecord task = r.task;
        if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
            if (task != null) {
                final ActivityStack taskStack = task.stack;
                if (mFocusedStack != taskStack) {
                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
                            "adjustStackFocus: Setting focused stack to r=" + r + " task=" + task);
                    mFocusedStack = taskStack.isHomeStack() ? null : taskStack;
                } else {
                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
                        "adjustStackFocus: Focused stack already=" + mFocusedStack);
                }
                return taskStack;
            }
            //如果已经有一个Focused stack直接返回即可    
            if (mFocusedStack != null) {
                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
                        "adjustStackFocus: Have a focused stack=" + mFocusedStack);
                return mFocusedStack;
            }

            for (int stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
                ActivityStack stack = mStacks.get(stackNdx);
                if (!stack.isHomeStack()) {
                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
                            "adjustStackFocus: Setting focused stack=" + stack);
                    mFocusedStack = stack;
                    return mFocusedStack;
                }
            }
            //如果没有Focused Stack就创建一个    
            // Time to create the first app stack for this user.
            int stackId =
                    mService.createStack(-1, HOME_STACK_ID, StackBox.TASK_STACK_GOES_OVER, 1.0f);
            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
                    " stackId=" + stackId);
            mFocusedStack = getStack(stackId);
            return mFocusedStack;
        }
        return mHomeStack;
}

在adjustStackFocus方法中,对于应用Task,如果ActivityRecord对应的TaskRecord所属的ActivityStack不是当前的mFocusedStack,则将其所属的ActivityStack作为mFoucnedStack返回则直接返回,否则如果此时TaskRecord还未创建,如果mFocusedStack已经不为null,则直接返回,否则会从当前的mStacks找到一个非Home Stack作为mFocusedStack返回,如果以上都不满足,则为当前系统创建一个ActivityStack作为mFocusedStack返回。这是通过调用AMS的createStack方法来完成的结果返回stackId。

 @Override
public int createStack(int taskId, int relativeStackBoxId, int position, float weight) {
    enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
            "createStack()");
    if (DEBUG_STACK) Slog.d(TAG, "createStack: taskId=" + taskId + " relStackBoxId=" +
            relativeStackBoxId + " position=" + position + " weight=" + weight);
    synchronized (this) {
        long ident = Binder.clearCallingIdentity();
        try {
            int stackId = mStackSupervisor.createStack();
            mWindowManager.createStack(stackId, relativeStackBoxId, position, weight);
            if (taskId > 0) {
                moveTaskToStack(taskId, stackId, true);
            }
            return stackId;
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
}

createStack是作为AMS的Binder接口提供给使用者的,这里会进一步通过ActivityStackSupervisor的createStack方法创建。

int createStack() {
    while (true) {
        if (++mLastStackId <= HOME_STACK_ID) {
            mLastStackId = HOME_STACK_ID + 1;
        }
        if (getStack(mLastStackId) == null) {
            break;
        }
    }
    mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
    return mLastStackId;
}

通过mLaskStackId来计算要创建的ActivityStack对应的id,然后将新创建的实例添加到mStacks中。

Task切换

final int startActivityUncheckedLocked(ActivityRecord r,
            ActivityRecord sourceRecord, int startFlags, boolean doResume,
            Bundle options) {
    ...
    if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
            // If bring to front is requested, and no result is requested, and
            // we can find a task that was started with this same
            // component, then instead of launching bring that one to the front.
            if (r.resultTo == null) {
                // See if there is a task to bring to the front.  If this is
                // a SINGLE_INSTANCE activity, there can be one and only one
                // instance of it in the history, and it is always in its own
                // unique task, so we do a special search.
                ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
                        ? findTaskLocked(r)
                        : findActivityLocked(intent, r.info);
                if (intentActivity != null) {//找到对应TaskRecord栈顶的ActivityRecord
                    if (r.task == null) {
                        r.task = intentActivity.task;//设置r的TaskRecord为该Task
                    }
                    targetStack = intentActivity.task.stack;//设置ActivityStack为该Stack
                    ...
                    // If the target task is not in the front, then we need
                    // to bring it to the front...  except...  well, with
                    // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
                    // to have the same behavior as if a new instance was
                    // being started, which means not bringing it to the front
                    // if the caller is not itself in the front.
                    final ActivityStack lastStack = getLastStack();
                    ActivityRecord curTop = lastStack == null?
                            null : lastStack.topRunningNonDelayedActivityLocked(notTop);//取到它顶部的ActivityRecord
                    if (curTop != null && (curTop.task != intentActivity.task ||
                            curTop.task != lastStack.topTask())) {//比较当前的task和复用的task 如果不是同一个就需要将复用的task移动到前端
                        r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
                        if (sourceRecord == null || (sourceStack.topActivity() != null &&
                                sourceStack.topActivity().task == sourceRecord.task)) {
                            // We really do want to push this one into the
                            // user's face, right now.
                            movedHome = true;
                            targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
                            ...
                        }
                    }
                    
                }
            }
        }
    ...
}                

Task的切换同样是在startActivityUncheckedLocked中进行的,首先我们通过findTaskLocked为要启动的activity寻找一个合适的TaskRecord,通过initActivity标识,找到后这个TaskRecord就是要切换到前台的Task,通过getLastStack取到上次切换的ActivityStack,然后取到它顶部的ActivityRecord,对于Launcher启动来说,这个就是非Launcher Stack,它顶部的Task可能不是initAcitivty标识的那个,因为可能之前我们启动的app的TaskRecord和它是不同的,即curTop.task != intentActivity.task,那么这时候我们需要为r设置Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT,同时通过moveTaskToFrontLocked将Task移动到ActivityStack的顶部。

final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
    
    final int numTasks = mTaskHistory.size();//task的数目
    final int index = mTaskHistory.indexOf(tr);//当前tr在Stack中的位置
    ...
    mStackSupervisor.moveHomeStack(isHomeStack());

    // Shift all activities with this task up to the top
    // of the stack, keeping them in the same internal order.
    insertTaskAtTop(tr);//移动Task到Stack顶部

    ...

    mWindowManager.moveTaskToTop(tr.taskId);

    mStackSupervisor.resumeTopActivitiesLocked();
    ...
}

moveTaskToFrontLocked通过insertTaskAtTop将TaskRecord移动到顶部

private void insertTaskAtTop(TaskRecord task) {
    // If this is being moved to the top by another activity or being launched from the home
    // activity, set mOnTopOfHome accordingly.
    ActivityStack lastStack = mStackSupervisor.getLastStack();
    final boolean fromHome = lastStack == null ? true : lastStack.isHomeStack();
    if (!isHomeStack() && (fromHome || topTask() != task)) {
        task.mOnTopOfHome = fromHome;
    }

    mTaskHistory.remove(task);//先删除
    // Now put task at top.
    int stackNdx = mTaskHistory.size();
    if (task.userId != mCurrentUser) {//push非当前用户task到当前task的后面
        // Put non-current user tasks below current user tasks.
        while (--stackNdx >= 0) {
            if (mTaskHistory.get(stackNdx).userId != mCurrentUser) {
                break;
            }
        }
        ++stackNdx;
    }
    mTaskHistory.add(stackNdx, task);
}

insertTaskAtTop先从mTaskHistory中删除该TaskRecord,然后计算添加的位置stackNdx,最后添加到mTaskHistory中,这里最顶部的Task一般存放在最末尾。

总结

从以上的分析中,我们知道了ActivityRecord、TaskRecord以及ActivityStack之间的关系及作用,它们之间的组织关系实际上是包含的关系,即AcitivtyStack包含了TaskRecord的集合,TaskRecord包含着ActivityRecord的集合,同时反向的,ActivityRecord中记录了它所属的TaskRecord,TaskRecord记录着它所属的ActivityStack。他们三者贯穿AMS管理Activity的整个逻辑处理,其中ActivityRecord是Activity组件在AMS中的存在的形式,它和Activity实例是一一对应的关系(注意这里描述的是实例),TaskRecord用于描述Task,即一组Activity,这组Activity以栈的形式组织起来,每个启动的Activity即ActivityRecord都应该要有所属的TaskRecord。ActivityStack是系统中用于管理TaskRecord的,系统中可能有多组ActivityStack,大体可以分为Launcher ActivityStack和非Launcher ActivityStack,我们启动的App对应的TaskRecord由非Launcher ActivityStack管理,它是在系统启动第一个app时创建的。

以上都是个人的理解,有描述不当的地方,烦请不吝赐教~