Jimmy Chen

A Programmer

(原创)ActivityRecord、TaskRecord和ActivityStack之间的关系

Advertisements
Advertisements
Advertisements

  很久没写博客了,是时候把写博客的习惯拾起来,今天就拿这一篇先做练练手了。

  原本想着一开始就想着分析Android应用的启动过程的,但是在这个过程中发现有很多类或者说知识点没有补齐,看着看着就感觉云里雾里的,所以就返回来看这些小的内容。这篇主要是想看下ActivityRecord、TaskRecord和ActivityStack这三个类分别代表什么以及有什么用。

  首先总体说一下这三个类:
– ActivityRecord:可以从它的类命名知道,这个记录Activity信息的类,主要记录一个Activity的所有信息。一个ActivityRecord只能对应一个Activity,但是一个Activity在系统中可以存在多份实例,所以一个Activity可以对应多个ActivityRecord记录
– TaskRecord:TaskRecord由一个或者多个ActivityRecord组成,TaskRecord就是常说的任务栈,用来记录一个task里面的调用Activity的相关信息
– ActivityStack:是用来管理TaskRecord的,一个ActivityStack会包含多个TaskRecord

  三个类的大小包含关系大致如下图:

《(原创)ActivityRecord、TaskRecord和ActivityStack之间的关系》

大概了解到这么多应该也可以了,下面是博主自己看代码的记录,没多少内容,要是看官们没时间就可以不看了:

ActivityRecord

// 如后半句注释,代表这一个Activity
/**
 * An entry in the history stack, representing an activity.
 */
final class ActivityRecord extends ConfigurationContainer implements AppWindowContainerListener {

    ...........................
    // 和WindowManager交互的Token
    final IApplicationToken.Stub appToken; // window manager token
    AppWindowContainerController mWindowContainerController;
    // 关于Activity的信息,这些信息主要是从应用AndroidManifest.xml中获得的
    final ActivityInfo info; // all about me
    // TODO: This is duplicated state already contained in info.applicationInfo - remove
    // Activity所在的Application信息
    ApplicationInfo appInfo; // information about activity's app
    // 启动这个Activity的PID和UID
    final int launchedFromPid; // always the pid who started the activity.
    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
    ....................................

    private CharSequence nonLocalizedLabel;  // the label information from the package mgr.
    // Activity所使用的一些资源信息
    private int labelRes;           // the label information from the package mgr.
    private int icon;               // resource identifier of activity's icon.
    private int logo;               // resource identifier of activity's logo.
    private int theme;              // resource identifier of activity's theme.
    private int realTheme;          // actual theme resource we will use, never 0.
    private int windowFlags;        // custom window flags for preview window.
    // 这里有个TaskRecord变量,之前也有提到TaskRecord是用来记录ActivityRecord记录的
    // 这里的TaskRecord变量就用来表示改Activity归属那个ActivityRecord管理的
    private TaskRecord task;        // the task this is in.
    ...........................

}

  上面代码中有很多ActivityRecord中的变量,这些变量从注释和变量名可以判断基本都是关于Activity的启动信息的。private TaskRecord task中,成员变量task是用来记录该ActivityRecord是归属于哪个TaskRecord的。在调用startActivity的过程中,会创建ActivityRecord来记录即将要启动的Activity的信息

// ActiviyStarter.java

private int startActivity(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,
        SafeActivityOptions options,
        boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
        TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup,
        PendingIntentRecord originatingPendingIntent) {
        ...........................
        
    ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
            callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
            resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
            mSupervisor, checkedOptions, sourceRecord);
        
        ...........................
        }

ActivityRecord的构造函数中主要就是对类内的一些成员变量进行初始化,这里就不进行分析了。

TaskRecord

  其他的一些类成员变量我们就省略了,直接看一些关键信息

class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
    // 下面摘录一些成员变量,篇幅问题就不全部贴出来了
    // 成员变量具体代表的意义可以看注释
    boolean inRecents;      // Actually in the recents list?
    long lastActiveTime;    // Last time this task was active in the current device session,
                            // including sleep. This time is initialized to the elapsed time when
                            // restored from disk.
    boolean isAvailable;    // Is the activity available to be launched?
    boolean rootWasReset;   // True if the intent at the root of the task had
                            // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
    boolean autoRemoveRecents;  // If true, we should automatically remove the task from
                                // recents when activity finishes
    boolean askedCompatMode;// Have asked the user about compat mode for this task.
    boolean hasBeenVisible; // Set if any activities in the task have been visible to the user.

    String stringName;      // caching of toString() result.
    int userId;             // user for which this task was created
    boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
                                // was changed.

    int numFullscreen;      // Number of fullscreen activities.

    int mResizeMode;        // The resize mode of this task and its activities.
                            // Based on the {@link ActivityInfo#resizeMode} of the root activity.

    
    // mActivities表示该TaskRecord中记录的所有ActivityRecord
    final ArrayList<ActivityRecord> mActivities;

    // mStack表示该TaskRecord由哪一个ActivityStack管理
    private ActivityStack mStack;
}

上面简单介绍了一下成员变量,主要关注的是mActivities变量,可以看到mActivities是一个ArrayList类型,用来记录当前TaskRe管理的Activity。其次和ActivityRecord类似,这里使用一个mStack记录当前TaskRecord归属哪个ActivityStack管理。下面在看看一些简单的成员方法,看看TaskRecord是如何管理自己使用到的ActivityRecord的。

void addActivityAtBottom(ActivityRecord r) {
    addActivityAtIndex(0, r);
}

void addActivityToTop(ActivityRecord r) {
    addActivityAtIndex(mActivities.size(), r);
}

void addActivityAtIndex(int index, ActivityRecord r) {
    TaskRecord task = r.getTask();
    if (task != null && task != this) {
        throw new IllegalArgumentException("Can not add r=" + " to task=" + this
                + " current parent=" + task);
    }

    // 将ActivityRecord中的task设置为当前TaskRecord
    r.setTask(this);

    ............................
    
    final int size = mActivities.size();

    ............................

    // 获取size和index中小的那个值
    index = Math.min(size, index);
    // 讲ActivityRecord添加到当前TaskRecord的mActivities中进行管理
    mActivities.add(index, r);

    .................
}

// 获取TaskRecord的工厂类
static TaskRecordFactory getTaskRecordFactory() {
    if (sTaskRecordFactory == null) {
        setTaskRecordFactory(new TaskRecordFactory());
    }
    return sTaskRecordFactory;
}

// 设置TaskRecord的工厂类
static void setTaskRecordFactory(TaskRecordFactory factory) {
    sTaskRecordFactory = factory;
}

// 创建一个TaskRecord
static TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
        Intent intent, IVoiceInteractionSession voiceSession,
        IVoiceInteractor voiceInteractor) {
    // 这里通过调用TaskRecord的工厂类进行创建,在工厂类内是直接通过new TaskRecord的方式调用
    return getTaskRecordFactory().create(
            service, taskId, info, intent, voiceSession, voiceInteractor);
}

static TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
        Intent intent, TaskDescription taskDescription) {
    return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription);
}

如果APP是冷启动的话,即在系统之前不存在这个task,那么在startActivity的过程中会创建相应的TaskRecord,这里只是粗略的过一下,startActivity详细的调用过程会在之后的文章再做分析

// 大体的调用过程
startActivity
-->startActivityUnchecked
---->setTaskFromReuseOrCreateNewTask

private int setTaskFromReuseOrCreateNewTask(
        TaskRecord taskToAffiliate, ActivityStack topStack) {
    mTargetStack = computeStackFocus(mStartActivity, true, mLaunchFlags, mOptions);
    
    // 创建对应的TaskRecord对象
    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, mSourceRecord,
                mOptions);
        addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
        updateBounds(mStartActivity.getTask(), mLaunchParams.mBounds);

        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
                + " in new task " + mStartActivity.getTask());
    } else {
        addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
    }

    if (taskToAffiliate != null) {
        mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
    }

    if (mService.getLockTaskController().isLockTaskModeViolation(mStartActivity.getTask())) {
        Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
        return START_RETURN_LOCK_TASK_MODE_VIOLATION;
    }

    if (mDoResume) {
        mTargetStack.moveToFront("reuseOrNewTask");
    }
    return START_SUCCESS;
}

ActivityStack

/**
 * State and management of a single stack of activities.
 */
class ActivityStack<T extends StackWindowController> extends ConfigurationContainer
        implements StackWindowListener {

    // 这里通过保存TaskRecord来获得之前运行过的Activity记录
    private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();

    // 这里保存正在运行的Activity信息,按照LRU方式排列
    final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();
    
    // 记录正在暂停的Activity
    ActivityRecord mPausingActivity = null;

    // 记录上次已经暂停的Activity
    ActivityRecord mLastPausedActivity = null;

    /**
     * Activities that specify No History must be removed once the user navigates away from them.
     * If the device goes to sleep with such an activity in the paused state then we save it here
     * and finish it later if another activity replaces it on wakeup.
     */
    // 用来标记那些指定不保存在最近任务中的Activity
    ActivityRecord mLastNoHistoryActivity = null;

    // 标记已经resumed的Activity
    ActivityRecord mResumedActivity = null;
}

老规则简单列出一些成员方法

// 可以通过改方法创建TaskRecord
TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        boolean toTop) {
    return createTaskRecord(taskId, info, intent, voiceSession, voiceInteractor, toTop,
            null /*activity*/, null /*source*/, null /*options*/);
}

TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        boolean toTop, ActivityRecord activity, ActivityRecord source,
        ActivityOptions options) {
    // 这里通过调用TaskRecord的crate方法进行创建
    final TaskRecord task = TaskRecord.create(
            mService, taskId, info, intent, voiceSession, voiceInteractor);
    // add the task to stack first, mTaskPositioner might need the stack association
    addTask(task, toTop, "createTaskRecord");
    final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
    final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController()
            .isKeyguardOrAodShowing(displayId);
    if (!mStackSupervisor.getLaunchParamsController()
            .layoutTask(task, info.windowLayout, activity, source, options)
            && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
        task.updateOverrideConfiguration(getOverrideBounds());
    }
    task.createWindowContainer(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
    return task;
}

// 已ArrayList方式返回所有的ActivityRecord记录
ArrayList<TaskRecord> getAllTasks() {
    return new ArrayList<>(mTaskHistory);
}

// 将一个TaskRecord记录添加到当前ActivityStack中
void addTask(final TaskRecord task, final boolean toTop, String reason) {
    addTask(task, toTop ? MAX_VALUE : 0, true /* schedulePictureInPictureModeChange */, reason);
    if (toTop) {
        // TODO: figure-out a way to remove this call.
        mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
                true /* includingParents */);
    }
}

// TODO: This shouldn't allow automatic reparenting. Remove the call to preAddTask and deal
// with the fall-out...
void addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange,
        String reason) {
    // TODO: Is this remove really needed? Need to look into the call path for the other addTask
    mTaskHistory.remove(task);
    position = getAdjustedPositionForTask(task, position, null /* starting */);
    final boolean toTop = position >= mTaskHistory.size();
    final ActivityStack prevStack = preAddTask(task, reason, toTop);

    mTaskHistory.add(position, task);
    task.setStack(this);

    updateTaskMovement(task, toTop);

    postAddTask(task, prevStack, schedulePictureInPictureModeChange);
}
Advertisements
Advertisements

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

%d 博主赞过: