【Android】Task ActivityStack Activity 三者关系

2021.11.10更新:

最近android升级为S版本,阅读Framework代码时,ActivityStack已经被删掉,源码中只有Task,因此在此做记录。

同R版本一样,Task依然在ActivityStart.startActivityInner中创造,依然采用reuseOrCreate方式创造,但代码更加简洁了,核心方法如下,先判断是否可重用Task,否则直接创建一个,Task创建过程变为构造者模式。值得注意的是,ActivityStackSupervisor同样改为ActivityTaskSupervisor。

Task reuseOrCreateTask(ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession,
            IVoiceInteractor voiceInteractor, boolean toTop, ActivityRecord activity,
            ActivityRecord source, ActivityOptions options) {

        Task task;
        if (canReuseAsLeafTask()) {
            // This root task will only contain one task, so just return itself since all root
            // tasks ara now tasks and all tasks are now root tasks.
            task = reuseAsLeafTask(voiceSession, voiceInteractor, intent, info, activity);
        } else {
            // Create child task since this root task can contain multiple tasks.
            final int taskId = activity != null
                    ? mTaskSupervisor.getNextTaskIdForUser(activity.mUserId)
                    : mTaskSupervisor.getNextTaskIdForUser();
            task = new Task.Builder(mAtmService)
                    .setTaskId(taskId)
                    .setActivityInfo(info)
                    .setActivityOptions(options)
                    .setIntent(intent)
                    .setVoiceSession(voiceSession)
                    .setVoiceInteractor(voiceInteractor)
                    .setOnTop(toTop)
                    .setParent(this)
                    .build();
        }

        int displayId = getDisplayId();
        if (displayId == INVALID_DISPLAY) displayId = DEFAULT_DISPLAY;
        final boolean isLockscreenShown = mAtmService.mTaskSupervisor.getKeyguardController()
                .isKeyguardOrAodShowing(displayId);
        if (!mTaskSupervisor.getLaunchParamsController()
                .layoutTask(task, info.windowLayout, activity, source, options)
                && !getRequestedOverrideBounds().isEmpty()
                && task.isResizeable() && !isLockscreenShown) {
            task.setBounds(getRequestedOverrideBounds());
        }

        return task;
    }

-------------------------------------------------------------------------------------------------------------------------

原文:

关于三者关系,可以用如下图来说明,一般一个包名对应一个Task,可是如果某Activity启动模式设置为SingleInstance,则会为其单独创建一个Task,其中的ActivityStack中只有单独的Activity;

ActivityStack用来记录Activity历史,以便Back回退时仿佛在同一个应用中(事实也如此),直到回退到HomeActivity;

如果多个Activity的TaskAffinity相同,则认为是同一个任务,共享一个Task;

ActivityStack继承自Task,所以实际Task就是ActivityStack;

如果Activity的TaskAffinity不同,系统会新创建一个Task,在PcMode下就表现为创建了两个窗口;

TaskAffinity意为任务相关性,一般默认包名;

如果是不同进程,那么就会有不同Task。注意同一进程可以有多个Task(比如singleInstance这一特殊启动模式或者FLAG_NEW_TASK flag);

另外一个重要概念是Display,可以理解为手机屏幕进行划分,每个Display就拥有独立的多个Task,彼此没有联系;

【Android】Task ActivityStack Activity 三者关系_第1张图片

 咱们进入源码查看细节,

在ActivityStart的startActivityInner函数中,涉及了Stack、Task相关描述,

if (mTargetStack == null) {

           //一个新启动的Activity,如果是MainActivity,此处mTargetStack就为null,此时就去创建一个堆栈

           mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, targetTask, mOptions);

 }

委托给RootWindowContainer创建

private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, Task task,

           ActivityOptions aOptions) {

       // We are reusing a task, keep the stack!

       if (mReuseTask != null) {

           return mReuseTask.getStack();

       }

       final boolean onTop =

               (aOptions == null || !aOptions.getAvoidMoveToFront()) && !mLaunchTaskBehind;

       return mRootWindowContainer.getLaunchStack(r, aOptions, task, onTop, mLaunchParams,

               mRequest.realCallingPid, mRequest.realCallingUid);

   }

咱们具体进入RootWindowContainer中查看

ActivityStack getLaunchStack(@Nullable ActivityRecord r,

           @Nullable ActivityOptions options, @Nullable Task candidateTask, boolean onTop,

           @Nullable LaunchParamsController.LaunchParams launchParams, int realCallingPid,

           int realCallingUid) {

       int taskId = INVALID_TASK_ID;

       int displayId = INVALID_DISPLAY;

       TaskDisplayArea taskDisplayArea = null;

       // We give preference to the launch preference in activity options.

       if (options != null) {

           taskId = options.getLaunchTaskId();//这是设置的启动Task,手动管理,如果一个正常启动的MainActivity,假设不走此处

           displayId = options.getLaunchDisplayId();

           final WindowContainerToken daToken = options.getLaunchTaskDisplayArea();

           taskDisplayArea = daToken != null

                   ? (TaskDisplayArea) WindowContainer.fromBinder(daToken.asBinder()) : null;

       }

       // First preference for stack goes to the task Id set in the activity options. Use the stack

       // associated with that if possible.

       if (taskId != INVALID_TASK_ID) {

           // Temporarily set the task id to invalid in case in re-entry.

           options.setLaunchTaskId(INVALID_TASK_ID);

           final Task task = anyTaskForId(taskId,

                   MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, options, onTop);

           options.setLaunchTaskId(taskId);

           if (task != null) {

               return task.getStack(); // 返回已经存在Task的Stack

           }

       }

        

       //解析Activity启动模式,默认ACTIVITY_TYPE_STANDARD

       final int activityType = resolveActivityType(r, options, candidateTask);

       ActivityStack stack = null;

       // Next preference for stack goes to the taskDisplayArea candidate.

       if (launchParams != null && launchParams.mPreferredTaskDisplayArea != null) {

           taskDisplayArea = launchParams.mPreferredTaskDisplayArea;

       }

       if (taskDisplayArea == null && displayId != INVALID_DISPLAY) {

           final DisplayContent displayContent = getDisplayContent(displayId); //如果显示区域为null,还得创建一个display,该概念后面再分析

           if (displayContent != null) {

               taskDisplayArea = displayContent.getDefaultTaskDisplayArea();

           }

       }

       if (taskDisplayArea != null) {

           //一般新启动的MainActivity不走此处

           final int tdaDisplayId = taskDisplayArea.getDisplayId();

           final boolean canLaunchOnDisplayFromStartRequest =

                   realCallingPid != 0 && realCallingUid > 0 && r != null

                           && mStackSupervisor.canPlaceEntityOnDisplay(tdaDisplayId,

                           realCallingPid, realCallingUid, r.info);

           if (canLaunchOnDisplayFromStartRequest || canLaunchOnDisplay(r, tdaDisplayId)) {

               if (r != null) {

                   // 获得一个Stack,就可以正常返回了;返回的是显示区域的topStack,如果没有则新创建一个Stack

                   final ActivityStack result = getValidLaunchStackInTaskDisplayArea(

                           taskDisplayArea, r, candidateTask, options, launchParams);

                   if (result != null) {

                       return result;

                   }

               }

               // Falling back to default task container

               taskDisplayArea = taskDisplayArea.mDisplayContent.getDefaultTaskDisplayArea();

               stack = taskDisplayArea.getOrCreateStack(r, options, candidateTask, activityType,

                       onTop);

               if (stack != null) {

                   return stack;

               }

           }

       }

       // Give preference to the stack and display of the input task and activity if they match the

       // mode we want to launch into.

       TaskDisplayArea container = null;

       if (candidateTask != null) {

           stack = candidateTask.getStack();

       }

       if (stack == null && r != null) {

           stack = r.getRootTask();

       }

       int windowingMode = launchParams != null ? launchParams.mWindowingMode

               : WindowConfiguration.WINDOWING_MODE_UNDEFINED;

       if (stack != null) {

           container = stack.getDisplayArea();

           if (container != null && canLaunchOnDisplay(r, container.mDisplayContent.mDisplayId)) {

               if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {

                   windowingMode = container.resolveWindowingMode(r, options, candidateTask,

                           activityType);

               }

               // Always allow organized tasks that created by organizer since the activity type

               // of an organized task is decided by the activity type of its top child, which

               // could be incompatible with the given windowing mode and activity type.

               if (stack.isCompatible(windowingMode, activityType) || stack.mCreatedByOrganizer) {

                   return stack;

               }

               if (windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY

                       && container.getRootSplitScreenPrimaryTask() == stack

                       && candidateTask == stack.getTopMostTask()) {

                   // This is a special case when we try to launch an activity that is currently on

                   // top of split-screen primary stack, but is targeting split-screen secondary.

                   // In this case we don't want to move it to another stack.

                   // TODO(b/78788972): Remove after differentiating between preferred and required

                   // launch options.

                   return stack;

               }

           }

       }

       if (container == null

               || !canLaunchOnDisplay(r, container.mDisplayContent.mDisplayId)) {

           container = getDefaultTaskDisplayArea(); // 赋值默认显示区域

           if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {

               windowingMode = container.resolveWindowingMode(r, options, candidateTask,

                       activityType);

           }

       }

       //进入此处继续查看

       return container.getOrCreateStack(r, options, candidateTask, activityType, onTop);

   }

进入TaskDisplayArea

ActivityStack getOrCreateStack(@Nullable ActivityRecord r,

            @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType,

            boolean onTop) {

        // First preference is the windowing mode in the activity options if set.

        int windowingMode = (options != null)

                ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;

        // Validate that our desired windowingMode will work under the current conditions.

        // UNDEFINED windowing mode is a valid result and means that the new stack will inherit

        // it's display's windowing mode.

        windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);

        return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */,

                candidateTask);

    }

//最终层层调用到createStack,直接进入查看

ActivityStack createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info,

            Intent intent, boolean createdByOrganizer) {

        if (mDisplayContent.mSingleTaskInstance && getStackCount() > 0) {

            // Create stack on default display instead since this display can only contain 1 stack.

            // TODO: Kinda a hack, but better that having the decision at each call point. Hoping

            // this goes away once ActivityView is no longer using virtual displays.

            return mRootWindowContainer.getDefaultTaskDisplayArea().createStack(

                    windowingMode, activityType, onTop, info, intent, createdByOrganizer);

        }

        if (activityType == ACTIVITY_TYPE_UNDEFINED && !createdByOrganizer) {

            // Can't have an undefined stack type yet...so re-map to standard. Anyone that wants

            // anything else should be passing it in anyways...except for the task organizer.

            activityType = ACTIVITY_TYPE_STANDARD;

        }

        if (activityType != ACTIVITY_TYPE_STANDARD && activityType != ACTIVITY_TYPE_UNDEFINED) {

            // For now there can be only one stack of a particular non-standard activity type on a

            // display. So, get that ignoring whatever windowing mode it is currently in.

            ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);

            if (stack != null) {

                throw new IllegalArgumentException("Stack=" + stack + " of activityType="

                        + activityType + " already on display=" this ". Can't have multiple.");

            }

        }

        if (!isWindowingModeSupported(windowingMode, mAtmService.mSupportsMultiWindow,

                mAtmService.mSupportsSplitScreenMultiWindow,

                mAtmService.mSupportsFreeformWindowManagement,

                mAtmService.mSupportsPictureInPicture, activityType)) {

            throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="

                    + windowingMode);

        }

        if (windowingMode == WINDOWING_MODE_PINNED && getRootPinnedTask() != null) {

            // Only 1 stack can be PINNED at a time, so dismiss the existing one

            getRootPinnedTask().dismissPip();

        }

        final int stackId = getNextStackId();

        

        return createStackUnchecked(windowingMode, activityType, stackId, onTop, info, intent,

                createdByOrganizer);

    }

@VisibleForTesting

ActivityStack createStackUnchecked(int windowingMode, int activityType, int stackId,

            boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer) {

        if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {

            throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "

                    "activity type.");

        }

        if (info == null) {

            info = new ActivityInfo();

            info.applicationInfo = new ApplicationInfo();

        }

        // Task created by organizer are added as root.

        Task launchRootTask = createdByOrganizer ? null : updateLaunchRootTask(windowingMode);

        if (launchRootTask != null) {

            // Since this stack will be put into a root task, its windowingMode will be inherited.

            windowingMode = WINDOWING_MODE_UNDEFINED;

        }

        //这就new了一个Stack了

        final ActivityStack stack = new ActivityStack(mAtmService, stackId, activityType,

                info, intent, createdByOrganizer);

        if (launchRootTask != null) {

            launchRootTask.addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);

            if (onTop) {

                positionStackAtTop((ActivityStack) launchRootTask, false /* includingParents */);

            }

        else {

            addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);

            stack.setWindowingMode(windowingMode, true /* creating */);

        }

        return stack;

    }

----------------------------------------------------------------------------------------------------------------------------

Task的创建同在StartActivityInner函数中,

if (newTask) {

            final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)

                    ? mSourceRecord.getTask() : null;

            String packageName= mService.mContext.getPackageName();

            if (mPerf != null) {

                mStartActivity.perfActivityBoostHandler =

                    mPerf.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST,

                                        packageName, -1, BoostFramework.Launch.BOOST_V1);

            }

            setNewTask(taskToAffiliate); //根据TaskAffinity创建任务或者返回已有任务

            if (mService.getLockTaskController().isLockTaskModeViolation(

                    mStartActivity.getTask())) {

                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);

                return START_RETURN_LOCK_TASK_MODE_VIOLATION;

            }

        }

进入setNewTask中查看吧,

private void setNewTask(Task taskToAffiliate) {

        final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;

        // 根据前面已经创建好的Stack,去创建一个新的Task

        final Task task = mTargetStack.reuseOrCreateTask(

                mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,

                mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,

                mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);

        addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");

        if (true) {

            Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity

                    " in new task " + mStartActivity.getTask());

        }

        if (taskToAffiliate != null) {

            mStartActivity.setTaskToAffiliateWith(taskToAffiliate);

        }

    }

进入ActivityStack中,

Task reuseOrCreateTask(ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession,

            IVoiceInteractor voiceInteractor, boolean toTop, ActivityRecord activity,

            ActivityRecord source, ActivityOptions options) {

        Task task;

        if (DisplayContent.alwaysCreateStack(getWindowingMode(), getActivityType())) {

            // This stack will only contain one task, so just return itself since all stacks ara now

            // tasks and all tasks are now stacks.

            // 重用已有Task,返回的是this,其中设置applicationInfo、Intent等消息

            task = reuseAsLeafTask(voiceSession, voiceInteractor, intent, info, activity);

        else {

            // Create child task since this stack can contain multiple tasks.

            final int taskId = activity != null

                    ? mStackSupervisor.getNextTaskIdForUser(activity.mUserId)

                    : mStackSupervisor.getNextTaskIdForUser();

            //创建一个Task,ActivityStack继承自Task哦,

            task = new ActivityStack(mAtmService, taskId, info, intent, voiceSession,

                    voiceInteractor, null /* taskDescription */this);

            // add the task to stack first, mTaskPositioner might need the stack association

            addChild(task, toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);

        }

        int displayId = getDisplayId();

        if (displayId == INVALID_DISPLAY) displayId = DEFAULT_DISPLAY;

        final boolean isLockscreenShown = mAtmService.mStackSupervisor.getKeyguardController()

                .isKeyguardOrAodShowing(displayId);

        if (!mStackSupervisor.getLaunchParamsController()

                .layoutTask(task, info.windowLayout, activity, source, options)

                && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {

            task.setBounds(getRequestedOverrideBounds());

        }

        return task;

    }

可以看到,只有ACTIVITY_TYPE_STANDARD才会一直去Create Task,对于Home或者Recent则不那么做。

static boolean alwaysCreateStack(int windowingMode, int activityType) {

        // Always create a stack for fullscreen, freeform, and split-screen-secondary windowing

        // modes so that we can manage visual ordering and return types correctly.

        return activityType == ACTIVITY_TYPE_STANDARD

                && (windowingMode == WINDOWING_MODE_FULLSCREEN

                || windowingMode == WINDOWING_MODE_FREEFORM

                || windowingMode == WINDOWING_MODE_PINNED

                || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY

                || windowingMode == WINDOWING_MODE_MULTI_WINDOW);

    }

你可能感兴趣的:(android)