ActivityRecord、TaskRecord、ActivityStack

原创 2016年12月19日 19:59:17

本文基于Android 7.0

每一个ActivityRecord都会有一个Activity与之对应,一个Activity可能会有多个ActivityRecord,因为Activity可以被多次实例化,取决于其launchmode。一系列相关的ActivityRecord组成了一个TaskRecord,TaskRecord是存在于ActivityStack中,ActivityStackSupervisor是用来管理这些ActivityStack的。

下面是一个简单的关系图


可以看到一个ActivityStack可以包含很多个TaskRecord,一个TaskRecord又可以包含很多个ActivityRecord。

下面看下ActivityRecord、TaskRecord、ActivityStack数据结构

一、ActivityRecord

ActivityRecord包含了一个Activity的所有信息,比较重要的对象主要有

frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java

    //ams的引用
    final ActivityManagerService service; // owner
    //token用来和wms交互
    final IApplicationToken.Stub appToken; // window manager token
    final ActivityInfo info; // all about me
    final ApplicationInfo appInfo; // information about activity's app
    ...

    //Activity资源信息
    CharSequence nonLocalizedLabel;  // the label information from the package mgr.
    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.
	
    //ActivityRecord所在的TaskRecord
    TaskRecord task;        // the task this is in.
    ...
    //ActivityRecord所在进程
    ProcessRecord app;      // if non-null, hosting application
    ActivityState state;    // current state we are in
    ...

其中task对象标识了所在的其所在的TaskRecord,这样ActivityRecord和TaskRecord就联系起来了。

ActivityRecord中还定义了activity的类型,一共有三种

    static final int APPLICATION_ACTIVITY_TYPE = 0;
    static final int HOME_ACTIVITY_TYPE = 1;
    static final int RECENTS_ACTIVITY_TYPE = 2;
如何区分这三种类型的Activity呢?

frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java

private void setActivityType(boolean componentSpecified,
            int launchedFromUid, Intent intent, ActivityRecord sourceRecord) {
        if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord))
                && isHomeIntent(intent) && !isResolverActivity()) {
            // This sure looks like a home activity!
            mActivityType = HOME_ACTIVITY_TYPE;
        } else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) {
            mActivityType = RECENTS_ACTIVITY_TYPE;
        } else {
            mActivityType = APPLICATION_ACTIVITY_TYPE;
        }
    }

如果是launcher activity或者ResolverActivity(这是一个系统Activity,弹出的让用户选择app的界面,例如分享文件时弹出让用户选择分享到哪个应用),只有这两种Activity会设置为HOME_ACTIVITY_TYPE。RECENTS_ACTIVITY_TYPE是systemui里的RecentsActivity,除了这三个activity之外,其他的都属于APPLICATION_ACTIVITY_TYPE。

ActivityRecord是在startActivity时创建的

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

    final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask) {
        ...

        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
                options, sourceRecord);
        ...
    }

二、TaskRecord

frameworks/base/services/core/java/com/android/server/am/TaskRecord.java

    //TaskRecord的唯一标识
    final int taskId;       // Unique identifier for this task.
    ...

    // This represents the last resolved activity values for this task
    // NOTE: This value needs to be persisted with each task
    TaskDescription lastTaskDescription = new TaskDescription();

	//TaskRecord里所有的ActivityRecord信息
    /** List of all activities in the task arranged in history order */
    final ArrayList<ActivityRecord> mActivities;

	//TaskRecord所在的stack
    /** Current stack */
    ActivityStack stack;
mActivities保存了该TaskRecord的所有ActivityRecord信息,同时每一个ActivityRecord都有其所在TaskRecord的引用。

在startActivity时,也会创建TaskRecord

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
        mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
                mOptions);

        if (mReuseTask == null) {
            final TaskRecord task = mTargetStack.createTaskRecord(
                    mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
                    mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                    mNewTaskIntent != null ? mNewTaskIntent : mIntent,
                    mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
            mStartActivity.setTask(task, taskToAffiliate);
            ...
        } else {
            mStartActivity.setTask(mReuseTask, taskToAffiliate);
        }
    }
frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
   TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            boolean toTop) {
        TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
                voiceInteractor);
        // add the task to stack first, mTaskPositioner might need the stack association
        addTask(task, toTop, "createTaskRecord");
        ...
        return task;
    }


当没有可复用的TaskRecord时(假如第一次跑进来,肯定是没有的,必须要创建),就会创建一个TaskRecord,mStartActivity是要启动的Activity的ActivityRecord,通过其setTask就把ActivityRecord绑定到了一个TaskRecord上

三、ActivityStack

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
    /**
     * The back history of all previous (and possibly still
     * running) activities.  It contains #TaskRecord objects.
     */
    private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();

   ...

    final int mStackId;
   ...
    /** Run all ActivityStacks through this */
    final ActivityStackSupervisor mStackSupervisor;

ActivityStack管理了一系列的TaskRecord,通过mStackId来唯一标识,持有ActivityStackSupervisor的引用。

ActivityStack的种类一共有5种

frameworks/base/core/java/android/app/ActivityManager.java
public static class StackId {
        /** Invalid stack ID. */
        public static final int INVALID_STACK_ID = -1;

        /** First static stack ID. */
        public static final int FIRST_STATIC_STACK_ID = 0;

        /** Home activity stack ID. */
        public static final int HOME_STACK_ID = FIRST_STATIC_STACK_ID;

        /** ID of stack where fullscreen activities are normally launched into. */
        public static final int FULLSCREEN_WORKSPACE_STACK_ID = 1;

        /** ID of stack where freeform/resized activities are normally launched into. */
        public static final int FREEFORM_WORKSPACE_STACK_ID = FULLSCREEN_WORKSPACE_STACK_ID + 1;

        /** ID of stack that occupies a dedicated region of the screen. */
        public static final int DOCKED_STACK_ID = FREEFORM_WORKSPACE_STACK_ID + 1;

        /** ID of stack that always on top (always visible) when it exist. */
        public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;

        /** Last static stack stack ID. */
        public static final int LAST_STATIC_STACK_ID = PINNED_STACK_ID;
		...
}

HOME_STACK_ID标识的ActivityStack主要维护了launcheractivity和recentactivity所在的TaskRecord,FREEFORM_WORKSPACE_STACK_ID标识的ActivityStack主要维护了FREEFORM模式下的TaskRecord,分屏的应用进入分屏模式后会在DOCKED_STACK_ID标识的ActivityStack中,进入画中画模式之后会在PINNED_STACK_ID标识的ActivityStack中。一般情况下,我们接触到的绝大部分都是在FULLSCREEN_WORKSPACE_STACK_ID(全屏显示)标识的ActivityStack中。

ActivityStack并不是开机就创建的,而是在需要时才创建。

android面试题-ActivityRecord TaskRecord和ProcessRecord之间的关系

ActivityRecord TaskRecord和ProcessRecord之间的关系
  • mwq384807683
  • mwq384807683
  • 2017年05月19日 15:04
  • 1772

Activity的代表ActivityRecord

ActivityRecord
  • u010479969
  • u010479969
  • 2015年08月28日 09:25
  • 4755

ActivityRecord、TaskRecord、ActivityStack

ActivityRecord
  • kebelzc24
  • kebelzc24
  • 2016年12月19日 19:59
  • 2865

TaskRecord、ActivityRecord 和 ActivityStack的关系

分析 TaskRecord、ActivityRecord 和 ActivityStack的关系
  • qugename
  • qugename
  • 2017年06月25日 16:59
  • 654

深入理解Activity——Token之旅

Token是ActivityRecord的内部静态类,我们先来看下Token的继承关系,Token extends IApplicationToken.Stub,从IApplicationToken....
  • guoqifa29
  • guoqifa29
  • 2015年07月09日 17:15
  • 8572

Android 之ActivityThead、ActivityManagerService 与activity的管理和创建

 在android中,Activity是四大组件中比较重要的一个(当然其他的也比较重要),那么android中是怎样管理这些activity的?应用的进程和主线程是怎么创建的,应用的消息循环又是在什么...
  • xieqibao
  • xieqibao
  • 2011年06月27日 13:56
  • 29852

TaskRecord ActivityRecord ActivityStack之间的关系

ActivityRecord
  • u010479969
  • u010479969
  • 2015年08月28日 09:24
  • 3803

Android 堆栈式管理Activity

基本上每一个项目都会需要用到,总体把控每一个activity的状态。网上搜了一下,使用了一下,感觉写的有问题,重写了一下,测试可行。栈:也就是stack,学过java的应该也了解,栈(stack)与堆...
  • qq_24956515
  • qq_24956515
  • 2016年12月02日 16:59
  • 1289

Android6.0 AMS启动Activity(四) AMS内部一些成员变量

之前在分析AMS和ActivityStackSupervisor和ActivityStack对一些成员变量比较模糊,这篇博客主要讲下这些成员变量 一、AMS成员变量的初始化 我们先来看看AMS在s...
  • kc58236582
  • kc58236582
  • 2016年09月09日 14:10
  • 2547

ActivityStack 详解

http://android.xsoftlab.net/guide/components/tasks-and-back-stack.html 我花了不少时间看了些,资料和书籍。 结论是吊用没有啊,...
  • ivolianer
  • ivolianer
  • 2016年03月24日 13:42
  • 1277
收藏助手
不良信息举报
您举报文章:ActivityRecord、TaskRecord、ActivityStack
举报原因:
原因补充:

(最多只允许输入30个字)