ActivityRecord、TaskRecord、ActivityStack

本文基于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并不是开机就创建的,而是在需要时才创建。

阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页