/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wm;

import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityTaskManagerService.TAG_ROOT_TASK;
import static com.android.server.wm.DisplayContent.alwaysCreateRootTask;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.annotation.ColorInt;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.res.Configuration;
import android.graphics.Color;
import android.os.UserHandle;
import android.util.IntArray;
import android.util.Slog;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.WindowManager;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.wm.LaunchParamsController.LaunchParams;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * {@link DisplayArea} that represents a section of a screen that contains app window containers.
 *
 * The children can be either {@link Task} or {@link TaskDisplayArea}.
 */
final class TaskDisplayArea extends DisplayArea<WindowContainer> {

    DisplayContent mDisplayContent;

    /**
     * Keeps track of the last set color layer so that it can be reset during surface migrations.
     */
    private @ColorInt int mBackgroundColor = 0;

    /**
     * This counter is used to make sure we don't prematurely clear the background color in the
     * case that background color animations are interleaved.
     * NOTE: The last set color will remain until the counter is reset to 0, which means that an
     * animation background color may sometime remain after the animation has finished through an
     * animation with a different background color if an animation starts after and ends before
     * another where both set different background colors. However, this is not a concern as
     * currently all task animation backgrounds are the same color.
     */
    private int mColorLayerCounter = 0;

    // Cached reference to some special tasks we tend to get a lot so we don't need to loop
    // through the list to find them.
    private Task mRootHomeTask;
    private Task mRootPinnedTask;

    private final ArrayList<WindowContainer> mTmpAlwaysOnTopChildren = new ArrayList<>();
    private final ArrayList<WindowContainer> mTmpNormalChildren = new ArrayList<>();
    private final ArrayList<WindowContainer> mTmpHomeChildren = new ArrayList<>();
    private final IntArray mTmpNeedsZBoostIndexes = new IntArray();

    private ArrayList<Task> mTmpTasks = new ArrayList<>();

    private ActivityTaskManagerService mAtmService;

    private RootWindowContainer mRootWindowContainer;

    // Launch root tasks by activityType then by windowingMode.
    static private class LaunchRootTaskDef {
        Task task;
        int[] windowingModes;
        int[] activityTypes;

        boolean contains(int windowingMode, int activityType) {
            return ArrayUtils.contains(windowingModes, windowingMode)
                    && ArrayUtils.contains(activityTypes, activityType);
        }
    }
    private final ArrayList<LaunchRootTaskDef> mLaunchRootTasks = new ArrayList<>();

    /**
     * A launch root task for activity launching with {@link FLAG_ACTIVITY_LAUNCH_ADJACENT} flag.
     */
    @VisibleForTesting
    Task mLaunchAdjacentFlagRootTask;

    /**
     * A focusable root task that is purposely to be positioned at the top. Although the root
     * task may not have the topmost index, it is used as a preferred candidate to prevent being
     * unable to resume target root task properly when there are other focusable always-on-top
     * root tasks.
     */
    @VisibleForTesting
    Task mPreferredTopFocusableRootTask;

    /**
     * If this is the same as {@link #getFocusedRootTask} then the activity on the top of the
     * focused root task has been resumed. If root tasks are changing position this will hold the
     * old root task until the new root task becomes resumed after which it will be set to
     * current focused root task.
     */
    Task mLastFocusedRootTask;
    /**
     * All of the root tasks on this display. Order matters, topmost root task is in front of all
     * other root tasks, bottommost behind. Accessed directly by ActivityManager package classes.
     * Any calls changing the list should also call {@link #onRootTaskOrderChanged(Task)}.
     */
    private ArrayList<OnRootTaskOrderChangedListener> mRootTaskOrderChangedCallbacks =
            new ArrayList<>();

    /**
     * The task display area is removed from the system and we are just waiting for all activities
     * on it to be finished before removing this object.
     */
    private boolean mRemoved;

    /**
     * The id of a leaf task that most recently being moved to front.
     */
    private int mLastLeafTaskToFrontId;

    /**
     * Whether this TaskDisplayArea was created by a {@link android.window.DisplayAreaOrganizer}.
     * If {@code true}, this will be removed when the organizer is unregistered.
     */
    final boolean mCreatedByOrganizer;

    /**
     * True if this TaskDisplayArea can have a home task
     * {@link WindowConfiguration#ACTIVITY_TYPE_HOME}
     */
    private final boolean mCanHostHomeTask;

    private final Configuration mTempConfiguration = new Configuration();

    TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name,
                    int displayAreaFeature) {
        this(displayContent, service, name, displayAreaFeature, false /* createdByOrganizer */,
                true /* canHostHomeTask */);
    }

    TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name,
                    int displayAreaFeature, boolean createdByOrganizer) {
        this(displayContent, service, name, displayAreaFeature, createdByOrganizer,
                true /* canHostHomeTask */);
    }

    TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name,
                    int displayAreaFeature, boolean createdByOrganizer,
                    boolean canHostHomeTask) {
        super(service, Type.ANY, name, displayAreaFeature);
        mDisplayContent = displayContent;
        mRootWindowContainer = service.mRoot;
        mAtmService = service.mAtmService;
        mCreatedByOrganizer = createdByOrganizer;
        mCanHostHomeTask = canHostHomeTask;
    }

    /**
     * Returns the topmost root task on the display that is compatible with the input windowing mode
     * and activity type. Null is no compatible root task on the display.
     */
    @Nullable
    Task getRootTask(int windowingMode, int activityType) {
        if (activityType == ACTIVITY_TYPE_HOME) {
            return mRootHomeTask;
        }
        if (windowingMode == WINDOWING_MODE_PINNED) {
            return mRootPinnedTask;
        }
        return getRootTask(rootTask -> {
            if (activityType == ACTIVITY_TYPE_UNDEFINED
                    && windowingMode == rootTask.getWindowingMode()) {
                // Passing in undefined type means we want to match the topmost root task with the
                // windowing mode.
                return true;
            }
            return rootTask.isCompatible(windowingMode, activityType);
        });
    }

    @VisibleForTesting
    Task getTopRootTask() {
        return getRootTask(t -> true);
    }

    @Nullable
    Task getRootHomeTask() {
        return mRootHomeTask;
    }

    Task getRootPinnedTask() {
        return mRootPinnedTask;
    }

    ArrayList<Task> getVisibleTasks() {
        final ArrayList<Task> visibleTasks = new ArrayList<>();
        forAllTasks(task -> {
            if (task.isLeafTask() && task.isVisible()) {
                visibleTasks.add(task);
            }
        });
        return visibleTasks;
    }

    void onRootTaskWindowingModeChanged(Task rootTask) {
        removeRootTaskReferenceIfNeeded(rootTask);
        addRootTaskReferenceIfNeeded(rootTask);
        if (rootTask == mRootPinnedTask && getTopRootTask() != rootTask) {
            // Looks like this root task changed windowing mode to pinned. Move it to the top.
            positionChildAt(POSITION_TOP, rootTask, false /* includingParents */);
        }
    }

    void addRootTaskReferenceIfNeeded(Task rootTask) {
        if (rootTask.isActivityTypeHome()) {
            if (mRootHomeTask != null) {
                if (!rootTask.isDescendantOf(mRootHomeTask)) {
                    throw new IllegalArgumentException("addRootTaskReferenceIfNeeded: root home"
                            + " task=" + mRootHomeTask + " already exist on display=" + this
                            + " rootTask=" + rootTask);
                }
            } else {
                mRootHomeTask = rootTask;
            }
        }

        if (!rootTask.isRootTask()) {
            return;
        }
        final int windowingMode = rootTask.getWindowingMode();
        if (windowingMode == WINDOWING_MODE_PINNED) {
            if (mRootPinnedTask != null) {
                throw new IllegalArgumentException(
                        "addRootTaskReferenceIfNeeded: root pinned task=" + mRootPinnedTask
                                + " already exist on display=" + this + " rootTask=" + rootTask);
            }
            mRootPinnedTask = rootTask;
        }
    }

    void removeRootTaskReferenceIfNeeded(Task rootTask) {
        if (rootTask == mRootHomeTask) {
            mRootHomeTask = null;
        } else if (rootTask == mRootPinnedTask) {
            mRootPinnedTask = null;
        }
    }

    @Override
    void setInitialSurfaceControlProperties(SurfaceControl.Builder b) {
        // We want an effect layer instead of the default container layer so that we can set a
        // background color on it for task animations.
        b.setEffectLayer();
        super.setInitialSurfaceControlProperties(b);
    }

    @Override
    void addChild(WindowContainer child, int position) {
        if (child.asTaskDisplayArea() != null) {
            if (DEBUG_ROOT_TASK) {
                Slog.d(TAG_WM, "Set TaskDisplayArea=" + child + " on taskDisplayArea=" + this);
            }
            super.addChild(child, position);
        } else if (child.asTask() != null) {
            addChildTask(child.asTask(), position);
        } else {
            throw new IllegalArgumentException(
                    "TaskDisplayArea can only add Task and TaskDisplayArea, but found "
                            + child);
        }
    }

    private void addChildTask(Task task, int position) {
        if (DEBUG_ROOT_TASK) Slog.d(TAG_WM, "Set task=" + task + " on taskDisplayArea=" + this);

        addRootTaskReferenceIfNeeded(task);
        position = findPositionForRootTask(position, task, true /* adding */);

        super.addChild(task, position);
        if (mPreferredTopFocusableRootTask != null
                && task.isFocusable()
                && mPreferredTopFocusableRootTask.compareTo(task) < 0) {
            // Clear preferred top because the adding focusable task has a higher z-order.
            mPreferredTopFocusableRootTask = null;
        }

        // Update the top resumed activity because the preferred top focusable task may be changed.
        mAtmService.mTaskSupervisor.updateTopResumedActivityIfNeeded("addChildTask");

        mAtmService.updateSleepIfNeededLocked();
        onRootTaskOrderChanged(task);
    }

    @Override
    protected void removeChild(WindowContainer child) {
        if (child.asTaskDisplayArea() != null) {
            super.removeChild(child);
        } else if (child.asTask() != null) {
            removeChildTask(child.asTask());
        } else {
            throw new IllegalArgumentException(
                    "TaskDisplayArea can only remove Task and TaskDisplayArea, but found "
                            + child);
        }
    }

    private void removeChildTask(Task task) {
        super.removeChild(task);
        onRootTaskRemoved(task);
        mAtmService.updateSleepIfNeededLocked();
        removeRootTaskReferenceIfNeeded(task);
    }

    @Override
    boolean isOnTop() {
        // Considered always on top
        return true;
    }

    @Override
    void positionChildAt(int position, WindowContainer child, boolean includingParents) {
        if (child.asTaskDisplayArea() != null) {
            super.positionChildAt(position, child, includingParents);
        } else if (child.asTask() != null) {
            positionChildTaskAt(position, child.asTask(), includingParents);
        } else {
            throw new IllegalArgumentException(
                    "TaskDisplayArea can only position Task and TaskDisplayArea, but found "
                            + child);
        }
    }

    private void positionChildTaskAt(int position, Task child, boolean includingParents) {
        final boolean moveToTop = position >= getChildCount() - 1;
        final boolean moveToBottom = position <= 0;

        final int oldPosition = mChildren.indexOf(child);
        if (child.isAlwaysOnTop() && !moveToTop) {
            // This root task is always-on-top, override the default behavior.
            Slog.w(TAG_WM, "Ignoring move of always-on-top root task=" + this + " to bottom");

            // Moving to its current position, as we must call super but we don't want to
            // perform any meaningful action.
            super.positionChildAt(oldPosition, child, false /* includingParents */);
            return;
        }
        // We don't allow untrusted display to top when root task moves to top,
        // until user tapping this display to change display position as top intentionally.
        //
        // Displays with {@code mDontMoveToTop} property set to {@code true} won't be
        // allowed to top neither.
        if ((!mDisplayContent.isTrusted() || mDisplayContent.mDontMoveToTop)
                && !getParent().isOnTop()) {
            includingParents = false;
        }
        final int targetPosition = findPositionForRootTask(position, child, false /* adding */);
        super.positionChildAt(targetPosition, child, false /* includingParents */);

        if (includingParents && getParent() != null && (moveToTop || moveToBottom)) {
            getParent().positionChildAt(moveToTop ? POSITION_TOP : POSITION_BOTTOM,
                    this /* child */, true /* includingParents */);
        }

        child.updateTaskMovement(moveToTop, moveToBottom, targetPosition);

        // The insert position may be adjusted to non-top when there is always-on-top root task.
        // Since the original position is preferred to be top, the root task should have higher
        // priority when we are looking for top focusable root task. The condition {@code
        // wasContained} restricts the preferred root task is set only when moving an existing
        // root task to top instead of adding a new root task that may be too early (e.g. in the
        // middle of launching or reparenting).
        final boolean isTopFocusableTask = moveToTop && child != mRootPinnedTask
                && child.isTopActivityFocusable();
        if (isTopFocusableTask) {
            mPreferredTopFocusableRootTask =
                    child.shouldBeVisible(null /* starting */) ? child : null;
        } else if (mPreferredTopFocusableRootTask == child) {
            mPreferredTopFocusableRootTask = null;
        }

        // Update the top resumed activity because the preferred top focusable task may be changed.
        mAtmService.mTaskSupervisor.updateTopResumedActivityIfNeeded("positionChildTaskAt");

        if (mChildren.indexOf(child) != oldPosition) {
            onRootTaskOrderChanged(child);
        }
    }

    void onLeafTaskRemoved(int taskId) {
        if (mLastLeafTaskToFrontId == taskId) {
            mLastLeafTaskToFrontId = INVALID_TASK_ID;
        }
    }

    void onLeafTaskMoved(Task t, boolean toTop, boolean toBottom) {
        if (toBottom) {
            mAtmService.getTaskChangeNotificationController().notifyTaskMovedToBack(
                    t.getTaskInfo());
        }

        if (!toTop) {
            if (t.mTaskId == mLastLeafTaskToFrontId) {
                mLastLeafTaskToFrontId = INVALID_TASK_ID;

                // If the previous front-most task is moved to the back, then notify of the new
                // front-most task.
                final ActivityRecord topMost = getTopMostActivity();
                if (topMost != null) {
                    mAtmService.getTaskChangeNotificationController().notifyTaskMovedToFront(
                            topMost.getTask().getTaskInfo());
                }
            }
            return;
        }
        if (t.mTaskId == mLastLeafTaskToFrontId || t.topRunningActivityLocked() == null) {
            return;
        }

        mLastLeafTaskToFrontId = t.mTaskId;
        EventLogTags.writeWmTaskToFront(t.mUserId, t.mTaskId, getDisplayId());
        // Notifying only when a leaf task moved to front. Or the listeners would be notified
        // couple times from the leaf task all the way up to the root task.
        mAtmService.getTaskChangeNotificationController().notifyTaskMovedToFront(t.getTaskInfo());
    }

    @Override
    void onChildPositionChanged(WindowContainer child) {
        super.onChildPositionChanged(child);
        mRootWindowContainer.invalidateTaskLayers();
    }

    @Override
    boolean forAllTaskDisplayAreas(Predicate<TaskDisplayArea> callback,
            boolean traverseTopToBottom) {
        // Apply the callback to all TDAs at or below this container. If the callback returns true,
        // stop early.
        if (traverseTopToBottom) {
            // When it is top to bottom, run on child TDA first as they are on top of the parent.
            return super.forAllTaskDisplayAreas(callback, traverseTopToBottom)
                    || callback.test(this);
        }
        return callback.test(this) || super.forAllTaskDisplayAreas(callback, traverseTopToBottom);
    }

    @Override
    void forAllTaskDisplayAreas(Consumer<TaskDisplayArea> callback, boolean traverseTopToBottom) {
        if (traverseTopToBottom) {
            super.forAllTaskDisplayAreas(callback, traverseTopToBottom);
            callback.accept(this);
        } else {
            callback.accept(this);
            super.forAllTaskDisplayAreas(callback, traverseTopToBottom);
        }
    }

    @Nullable
    @Override
    <R> R reduceOnAllTaskDisplayAreas(BiFunction<TaskDisplayArea, R, R> accumulator,
            @Nullable R initValue, boolean traverseTopToBottom) {
        if (traverseTopToBottom) {
            final R result =
                    super.reduceOnAllTaskDisplayAreas(accumulator, initValue, traverseTopToBottom);
            return accumulator.apply(this, result);
        } else {
            final R result = accumulator.apply(this, initValue);
            return super.reduceOnAllTaskDisplayAreas(accumulator, result, traverseTopToBottom);

        }
    }

    @Nullable
    @Override
    <R> R getItemFromTaskDisplayAreas(Function<TaskDisplayArea, R> callback,
            boolean traverseTopToBottom) {
        if (traverseTopToBottom) {
            final R item = super.getItemFromTaskDisplayAreas(callback, traverseTopToBottom);
            return item != null ? item : callback.apply(this);
        } else {
            final R item = callback.apply(this);
            return item != null
                    ? item
                    : super.getItemFromTaskDisplayAreas(callback, traverseTopToBottom);
        }
    }

    /**
     * Assigns a priority number to root task types. This priority defines an order between the
     * types of root task that are added to the task display area.
     *
     * Higher priority number indicates that the root task should have a higher z-order.
     *
     * For child {@link TaskDisplayArea}, it will be the priority of its top child.
     *
     * @return the priority of the root task
     */
    private int getPriority(WindowContainer child) {
        final TaskDisplayArea tda = child.asTaskDisplayArea();
        if (tda != null) {
            // Use the top child priority as the TaskDisplayArea priority.
            return tda.getPriority(tda.getTopChild());
        }
        final Task rootTask = child.asTask();
        if (mWmService.mAssistantOnTopOfDream && rootTask.isActivityTypeAssistant()) return 4;
        if (rootTask.isActivityTypeDream()) return 3;
        if (rootTask.inPinnedWindowingMode()) return 2;
        if (rootTask.isAlwaysOnTop()) return 1;
        return 0;
    }

    private int findMinPositionForRootTask(Task rootTask) {
        int minPosition = POSITION_BOTTOM;
        for (int i = 0; i < mChildren.size(); ++i) {
            if (getPriority(mChildren.get(i)) < getPriority(rootTask)) {
                minPosition = i;
            } else {
                break;
            }
        }

        if (rootTask.isAlwaysOnTop()) {
            // Since a root task could be repositioned while still being one of the children, we
            // check if this always-on-top root task already exists and if so, set the minPosition
            // to its previous position.
            // Use mChildren.indexOf instead of getTaskIndexOf because we need to place the rootTask
            // as a direct child.
            final int currentIndex = mChildren.indexOf(rootTask);
            if (currentIndex > minPosition) {
                minPosition = currentIndex;
            }
        }
        return minPosition;
    }

    private int findMaxPositionForRootTask(Task rootTask) {
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            final WindowContainer curr = mChildren.get(i);
            // Since a root task could be repositioned while still being one of the children, we
            // check if 'curr' is the same root task and skip it if so
            final boolean sameRootTask = curr == rootTask;
            if (getPriority(curr) <= getPriority(rootTask) && !sameRootTask) {
                return i;
            }
        }
        return 0;
    }

    /**
     * When root task is added or repositioned, find a proper position for it.
     *
     * The order is defined as:
     * - Dream is on top of everything
     * - PiP is directly below the Dream
     * - always-on-top root tasks are directly below PiP; new always-on-top root tasks are added
     * above existing ones
     * - other non-always-on-top root tasks come directly below always-on-top root tasks; new
     * non-always-on-top root tasks are added directly below always-on-top root tasks and above
     * existing non-always-on-top root tasks
     * - if {@link #mAssistantOnTopOfDream} is enabled, then Assistant is on top of everything
     * (including the Dream); otherwise, it is a normal non-always-on-top root task
     *
     * @param requestedPosition Position requested by caller.
     * @param rootTask          Root task to be added or positioned.
     * @param adding            Flag indicates whether we're adding a new root task or positioning
     *                          an existing.
     * @return The proper position for the root task.
     */
    private int findPositionForRootTask(int requestedPosition, Task rootTask, boolean adding) {
        // The max possible position we can insert the root task at.
        int maxPosition = findMaxPositionForRootTask(rootTask);
        // The min possible position we can insert the root task at.
        int minPosition = findMinPositionForRootTask(rootTask);

        // Cap the requested position to something reasonable for the previous position check
        // below.
        if (requestedPosition == POSITION_TOP) {
            requestedPosition = mChildren.size();
        } else if (requestedPosition == POSITION_BOTTOM) {
            requestedPosition = 0;
        }

        int targetPosition = requestedPosition;
        targetPosition = Math.min(targetPosition, maxPosition);
        targetPosition = Math.max(targetPosition, minPosition);

        int prevPosition = mChildren.indexOf(rootTask);
        // The positions we calculated above (maxPosition, minPosition) do not take into
        // consideration the following edge cases.
        // 1) We need to adjust the position depending on the value "adding".
        // 2) When we are moving a root task to another position, we also need to adjust the
        //    position depending on whether the root task is moving to a higher or lower position.
        if ((targetPosition != requestedPosition) && (adding || targetPosition < prevPosition)) {
            targetPosition++;
        }

        return targetPosition;
    }

    @Override
    @ScreenOrientation
    int getOrientation(@ScreenOrientation int candidate) {
        final int orientation = super.getOrientation(candidate);
        if (!canSpecifyOrientation(orientation)) {
            mLastOrientationSource = null;
            // We only respect orientation of the focused TDA, which can be a child of this TDA.
            return reduceOnAllTaskDisplayAreas((taskDisplayArea, taskOrientation) -> {
                if (taskDisplayArea == this || taskOrientation != SCREEN_ORIENTATION_UNSET) {
                    return taskOrientation;
                }
                return taskDisplayArea.getOrientation(candidate);
            }, SCREEN_ORIENTATION_UNSET);
        }

        if (orientation != SCREEN_ORIENTATION_UNSET
                && orientation != SCREEN_ORIENTATION_BEHIND) {
            ProtoLog.v(WM_DEBUG_ORIENTATION,
                    "App is requesting an orientation, return %d for display id=%d",
                    orientation, mDisplayContent.mDisplayId);
            return orientation;
        }

        ProtoLog.v(WM_DEBUG_ORIENTATION,
                "No app is requesting an orientation, return %d for display id=%d",
                mDisplayContent.getLastOrientation(), mDisplayContent.mDisplayId);
        // The next app has not been requested to be visible, so we keep the current orientation
        // to prevent freezing/unfreezing the display too early.
        return mDisplayContent.getLastOrientation();
    }

    @Override
    void assignChildLayers(SurfaceControl.Transaction t) {
        assignRootTaskOrdering(t);

        for (int i = 0; i < mChildren.size(); i++) {
            mChildren.get(i).assignChildLayers(t);
        }
    }

    void assignRootTaskOrdering(SurfaceControl.Transaction t) {
        if (getParent() == null) {
            return;
        }
        mTmpAlwaysOnTopChildren.clear();
        mTmpHomeChildren.clear();
        mTmpNormalChildren.clear();
        for (int i = 0; i < mChildren.size(); ++i) {
            final WindowContainer child = mChildren.get(i);
            final TaskDisplayArea childTda = child.asTaskDisplayArea();
            if (childTda != null) {
                final Task childTdaTopRootTask = childTda.getTopRootTask();
                if (childTdaTopRootTask == null) {
                    mTmpNormalChildren.add(childTda);
                } else if (childTdaTopRootTask.isAlwaysOnTop()) {
                    mTmpAlwaysOnTopChildren.add(childTda);
                } else if (childTdaTopRootTask.isActivityTypeHome()) {
                    mTmpHomeChildren.add(childTda);
                } else {
                    mTmpNormalChildren.add(childTda);
                }
                continue;
            }

            final Task childTask = child.asTask();
            if (childTask.isAlwaysOnTop()) {
                mTmpAlwaysOnTopChildren.add(childTask);
            } else if (childTask.isActivityTypeHome()) {
                mTmpHomeChildren.add(childTask);
            } else {
                mTmpNormalChildren.add(childTask);
            }
        }

        int layer = 0;
        // Place root home tasks to the bottom.
        layer = adjustRootTaskLayer(t, mTmpHomeChildren, layer);
        layer = adjustRootTaskLayer(t, mTmpNormalChildren, layer);
        adjustRootTaskLayer(t, mTmpAlwaysOnTopChildren, layer);
    }

    /**
     * Adjusts the layer of the root task which belongs to the same group.
     * Note that there are three root task groups: home rootTasks, always on top rootTasks, and
     * normal rootTasks.
     *
     * @param startLayer   The beginning layer of this group of rootTasks.
     * @return The adjusted layer value.
     */
    private int adjustRootTaskLayer(SurfaceControl.Transaction t,
            ArrayList<WindowContainer> children, int startLayer) {
        mTmpNeedsZBoostIndexes.clear();
        final int childCount = children.size();
        boolean hasAdjacentTask = false;
        for (int i = 0; i < childCount; i++) {
            final WindowContainer child = children.get(i);
            final TaskDisplayArea childTda = child.asTaskDisplayArea();
            final boolean childNeedsZBoost = childTda != null
                    ? childTda.childrenNeedZBoost()
                    : child.needsZBoost();

            if (childNeedsZBoost) {
                mTmpNeedsZBoostIndexes.add(i);
                continue;
            }

            child.assignLayer(t, startLayer++);
        }

        final int zBoostSize = mTmpNeedsZBoostIndexes.size();
        for (int i = 0; i < zBoostSize; i++) {
            final WindowContainer child = children.get(mTmpNeedsZBoostIndexes.get(i));
            child.assignLayer(t, startLayer++);
        }
        return startLayer;
    }

    private boolean childrenNeedZBoost() {
        final boolean[] needsZBoost = new boolean[1];
        forAllRootTasks(task -> {
            needsZBoost[0] |= task.needsZBoost();
        });
        return needsZBoost[0];
    }

    @Override
    RemoteAnimationTarget createRemoteAnimationTarget(
            RemoteAnimationController.RemoteAnimationRecord record) {
        final ActivityRecord activity = getTopMostActivity();
        return activity != null ? activity.createRemoteAnimationTarget(record) : null;
    }

    void setBackgroundColor(@ColorInt int colorInt) {
        setBackgroundColor(colorInt, false /* restore */);
    }

    void setBackgroundColor(@ColorInt int colorInt, boolean restore) {
        mBackgroundColor = colorInt;
        Color color = Color.valueOf(colorInt);

        // We don't want to increment the mColorLayerCounter if we are restoring the background
        // color after a surface migration because in that case the mColorLayerCounter already
        // accounts for setting that background color.
        if (!restore) {
            mColorLayerCounter++;
        }

        // Only apply the background color if the TDA is actually attached and has a valid surface
        // to set the background color on. We still want to keep track of the background color state
        // even if we are not showing it for when/if the TDA is reattached and gets a valid surface
        if (mSurfaceControl != null) {
            getPendingTransaction()
                    .setColor(mSurfaceControl,
                            new float[]{color.red(), color.green(), color.blue()});
            scheduleAnimation();
        }
    }

    void clearBackgroundColor() {
        mColorLayerCounter--;

        // Only clear the color layer if we have received the same amounts of clear as set
        // requests and TDA has a non null surface control (i.e. is attached)
        if (mColorLayerCounter == 0 && mSurfaceControl != null) {
            getPendingTransaction().unsetColor(mSurfaceControl);
            scheduleAnimation();
        }
    }

    @Override
    void migrateToNewSurfaceControl(SurfaceControl.Transaction t) {
        super.migrateToNewSurfaceControl(t);

        if (mColorLayerCounter > 0) {
            setBackgroundColor(mBackgroundColor, true /* restore */);
        }

        reassignLayer(t);
        scheduleAnimation();
    }

    void onRootTaskRemoved(Task rootTask) {
        if (ActivityTaskManagerDebugConfig.DEBUG_ROOT_TASK) {
            Slog.v(TAG_ROOT_TASK, "onRootTaskRemoved: detaching " + rootTask + " from displayId="
                    + mDisplayContent.mDisplayId);
        }
        if (mPreferredTopFocusableRootTask == rootTask) {
            mPreferredTopFocusableRootTask = null;
        }
        if (mLaunchAdjacentFlagRootTask == rootTask) {
            mLaunchAdjacentFlagRootTask = null;
        }
        mDisplayContent.releaseSelfIfNeeded();
        onRootTaskOrderChanged(rootTask);
    }

    /**
     * Moves/reparents `task` to the back of whatever container the root home task is in. This is
     * for when we just want to move a task to "the back" vs. a specific place. The primary use-case
     * is to make sure that moved-to-back apps go into secondary split when in split-screen mode.
     */
    void positionTaskBehindHome(Task task) {
        final Task home = getOrCreateRootHomeTask();
        final WindowContainer homeParent = home.getParent();
        final Task homeParentTask = homeParent != null ? homeParent.asTask() : null;
        if (homeParentTask == null) {
            // reparent throws if parent didn't change...
            if (task.getParent() == this) {
                positionChildAt(POSITION_BOTTOM, task, false /*includingParents*/);
            } else {
                task.reparent(this, false /* onTop */);
            }
        } else if (homeParentTask == task.getParent()) {
            // Apparently reparent early-outs if same root task, so we have to explicitly reorder.
            homeParentTask.positionChildAtBottom(task);
        } else {
            task.reparent(homeParentTask, false /* toTop */,
                    Task.REPARENT_LEAVE_ROOT_TASK_IN_PLACE, false /* animate */,
                    false /* deferResume */, "positionTaskBehindHome");
        }
    }

    /**
     * Returns an existing root task compatible with the windowing mode and activity type or
     * creates one if a compatible root task doesn't exist.
     *
     * @see #getOrCreateRootTask(int, int, boolean, Task, Task, ActivityOptions, int)
     */
    Task getOrCreateRootTask(int windowingMode, int activityType, boolean onTop) {
        return getOrCreateRootTask(windowingMode, activityType, onTop, null /* candidateTask */,
                null /* sourceTask */, null /* options */, 0 /* intent */);
    }

    /**
     * When two level tasks are required for given windowing mode and activity type, returns an
     * existing compatible root task or creates a new one.
     * For one level task, the candidate task would be reused to also be the root task or create
     * a new root task if no candidate task.
     *
     * @param windowingMode The windowing mode the root task should be created in.
     * @param activityType  The activityType the root task should be created in.
     * @param onTop         If true the root task will be created at the top of the display,
     *                      else at the bottom.
     * @param candidateTask The possible task the activity might be launched in. Can be null.
     * @param sourceTask    The task requesting to start activity. Used to determine which of the
     *                      adjacent roots should be launch root of the new task. Can be null.
     * @param options       The activity options used to the launch. Can be null.
     * @param launchFlags   The launch flags for this launch.
     * @return The root task to use for the launch.
     * @see #getRootTask(int, int)
     */
    Task getOrCreateRootTask(int windowingMode, int activityType, boolean onTop,
            @Nullable Task candidateTask, @Nullable Task sourceTask,
            @Nullable ActivityOptions options, int launchFlags) {
        final int resolvedWindowingMode =
                windowingMode == WINDOWING_MODE_UNDEFINED ? getWindowingMode() : windowingMode;
        // Need to pass in a determined windowing mode to see if a new root task should be created,
        // so use its parent's windowing mode if it is undefined.
        if (!alwaysCreateRootTask(resolvedWindowingMode, activityType)) {
            Task rootTask = getRootTask(resolvedWindowingMode, activityType);
            if (rootTask != null) {
                return rootTask;
            }
        } else if (candidateTask != null) {
            final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
            final Task launchParentTask = getLaunchRootTask(resolvedWindowingMode, activityType,
                    options, sourceTask, launchFlags, candidateTask);
            if (launchParentTask != null) {
                if (candidateTask.getParent() == null) {
                    launchParentTask.addChild(candidateTask, position);
                } else if (candidateTask.getParent() != launchParentTask) {
                    candidateTask.reparent(launchParentTask, position);
                }
            } else if (candidateTask.getDisplayArea() != this
                    || candidateTask.getRootTask().mReparentLeafTaskIfRelaunch) {
                if (candidateTask.getParent() == null) {
                    addChild(candidateTask, position);
                } else {
                    candidateTask.reparent(this, onTop);
                }
            }
            // Update windowing mode if necessary, e.g. launch into a different windowing mode.
            if (windowingMode != WINDOWING_MODE_UNDEFINED && candidateTask.isRootTask()
                    && candidateTask.getWindowingMode() != windowingMode) {
                candidateTask.mTransitionController.collect(candidateTask);
                candidateTask.setWindowingMode(windowingMode);
            }
            return candidateTask.getRootTask();
        }
        return new Task.Builder(mAtmService)
                .setWindowingMode(windowingMode)
                .setActivityType(activityType)
                .setOnTop(onTop)
                .setParent(this)
                .setSourceTask(sourceTask)
                .setActivityOptions(options)
                .setLaunchFlags(launchFlags)
                .build();
    }

    /**
     * Returns an existing root task compatible with the input params or creates one
     * if a compatible root task doesn't exist.
     *
     * @see #getOrCreateRootTask(int, int, boolean)
     */
    Task getOrCreateRootTask(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
            @Nullable Task candidateTask, @Nullable Task sourceTask,
            @Nullable LaunchParams launchParams, int launchFlags, int activityType, boolean onTop) {
        int windowingMode = WINDOWING_MODE_UNDEFINED;
        if (launchParams != null) {
            // If launchParams isn't null, windowing mode is already resolved.
            windowingMode = launchParams.mWindowingMode;
        } else if (options != null) {
            // If launchParams is null and options isn't let's use the windowing mode in the
            // options.
            windowingMode = options.getLaunchWindowingMode();
        }
        // Validate that our desired windowingMode will work under the current conditions.
        // UNDEFINED windowing mode is a valid result and means that the new root task will inherit
        // it's display's windowing mode.
        windowingMode = validateWindowingMode(windowingMode, r, candidateTask);
        return getOrCreateRootTask(windowingMode, activityType, onTop, candidateTask, sourceTask,
                options, launchFlags);
    }

    @VisibleForTesting
    int getNextRootTaskId() {
        return mAtmService.mTaskSupervisor.getNextTaskIdForUser();
    }

    Task createRootTask(int windowingMode, int activityType, boolean onTop) {
        return createRootTask(windowingMode, activityType, onTop, null /* activityOptions */);
    }

    /**
     * A convinenit method of creating a root task by providing windowing mode and activity type
     * on this display.
     *
     * @param windowingMode      The windowing mode the root task should be created in. If
     *                           {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the
     *                           root task will inherit its parent's windowing mode.
     * @param activityType       The activityType the root task should be created in. If
     *                           {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the
     *                           root task will be created in
     *                           {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
     * @param onTop              If true the root task will be created at the top of the display,
     *                           else at the bottom.
     * @param opts               The activity options.
     * @return The newly created root task.
     */
    Task createRootTask(int windowingMode, int activityType, boolean onTop, ActivityOptions opts) {
        return new Task.Builder(mAtmService)
                .setWindowingMode(windowingMode)
                .setActivityType(activityType)
                .setParent(this)
                .setOnTop(onTop)
                .setActivityOptions(opts)
                .build();
    }

    // TODO: Also clear when task is removed from system?
    void setLaunchRootTask(Task rootTask, int[] windowingModes, int[] activityTypes) {
        if (!rootTask.mCreatedByOrganizer) {
            throw new IllegalArgumentException(
                    "Can't set not mCreatedByOrganizer as launch root tr=" + rootTask);
        }

        LaunchRootTaskDef def = getLaunchRootTaskDef(rootTask);
        if (def != null) {
            // Remove so we add to the end of the list.
            mLaunchRootTasks.remove(def);
        } else {
            def = new LaunchRootTaskDef();
            def.task = rootTask;
        }

        def.activityTypes = activityTypes;
        def.windowingModes = windowingModes;
        if (!ArrayUtils.isEmpty(windowingModes) || !ArrayUtils.isEmpty(activityTypes)) {
            mLaunchRootTasks.add(def);
        }
    }

    void removeLaunchRootTask(Task rootTask) {
        LaunchRootTaskDef def = getLaunchRootTaskDef(rootTask);
        if (def != null) {
            mLaunchRootTasks.remove(def);
        }
    }

    void setLaunchAdjacentFlagRootTask(@Nullable Task adjacentFlagRootTask) {
        if (adjacentFlagRootTask != null) {
            if (!adjacentFlagRootTask.mCreatedByOrganizer) {
                throw new IllegalArgumentException(
                        "Can't set not mCreatedByOrganizer as launch adjacent flag root tr="
                                + adjacentFlagRootTask);
            }

            if (adjacentFlagRootTask.getAdjacentTaskFragment() == null) {
                throw new UnsupportedOperationException(
                        "Can't set non-adjacent root as launch adjacent flag root tr="
                                + adjacentFlagRootTask);
            }
        }

        mLaunchAdjacentFlagRootTask = adjacentFlagRootTask;
    }

    private @Nullable LaunchRootTaskDef getLaunchRootTaskDef(Task rootTask) {
        LaunchRootTaskDef def = null;
        for (int i = mLaunchRootTasks.size() - 1; i >= 0; --i) {
            if (mLaunchRootTasks.get(i).task.mTaskId != rootTask.mTaskId) continue;
            def = mLaunchRootTasks.get(i);
            break;
        }
        return def;
    }

    @Nullable
    Task getLaunchRootTask(int windowingMode, int activityType, @Nullable ActivityOptions options,
            @Nullable Task sourceTask, int launchFlags) {
        return getLaunchRootTask(windowingMode, activityType, options, sourceTask, launchFlags,
                null /* candidateTask */);
    }

    @Nullable
    Task getLaunchRootTask(int windowingMode, int activityType, @Nullable ActivityOptions options,
            @Nullable Task sourceTask, int launchFlags, @Nullable Task candidateTask) {
        // Try to use the launch root task in options if available.
        if (options != null) {
            final Task launchRootTask = Task.fromWindowContainerToken(options.getLaunchRootTask());
            // We only allow this for created by organizer tasks.
            if (launchRootTask != null && launchRootTask.mCreatedByOrganizer) {
                return launchRootTask;
            }
        }

        // Use launch-adjacent-flag-root if launching with launch-adjacent flag.
        if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0
                && mLaunchAdjacentFlagRootTask != null) {
            if (sourceTask != null && sourceTask == candidateTask) {
                // Do nothing when task that is getting opened is same as the source.
            } else if (sourceTask != null
                    && mLaunchAdjacentFlagRootTask.getAdjacentTask() != null
                    && (sourceTask == mLaunchAdjacentFlagRootTask
                    || sourceTask.isDescendantOf(mLaunchAdjacentFlagRootTask))) {
                // If the adjacent launch is coming from the same root, launch to
                // adjacent root instead.
                return mLaunchAdjacentFlagRootTask.getAdjacentTask();
            } else {
                return mLaunchAdjacentFlagRootTask;
            }
        }

        for (int i = mLaunchRootTasks.size() - 1; i >= 0; --i) {
            if (mLaunchRootTasks.get(i).contains(windowingMode, activityType)) {
                final Task launchRootTask = mLaunchRootTasks.get(i).task;
                final Task adjacentRootTask = launchRootTask != null
                        ? launchRootTask.getAdjacentTask() : null;
                if (sourceTask != null && adjacentRootTask != null
                        && (sourceTask == adjacentRootTask
                        || sourceTask.isDescendantOf(adjacentRootTask))) {
                    return adjacentRootTask;
                } else {
                    return launchRootTask;
                }
            }
        }

        // If a task is launching from a created-by-organizer task, it should be launched into the
        // same created-by-organizer task as well. Unless, the candidate task is already positioned
        // in the another adjacent task.
        if (sourceTask != null && (candidateTask == null
                // A pinned task relaunching should be handled by its task organizer. Skip fallback
                // launch target of a pinned task from source task.
                || candidateTask.getWindowingMode() != WINDOWING_MODE_PINNED)) {
            final Task adjacentTarget = sourceTask.getAdjacentTask();
            if (adjacentTarget != null) {
                if (candidateTask != null
                        && (candidateTask == adjacentTarget
                        || candidateTask.isDescendantOf(adjacentTarget))) {
                    return adjacentTarget;
                }
                return sourceTask.getCreatedByOrganizerTask();
            }
        }

        return null;
    }

    /**
     * Get the preferred focusable root task in priority. If the preferred root task does not exist,
     * find a focusable and visible root task from the top of root tasks in this display.
     */
    Task getFocusedRootTask() {
        if (mPreferredTopFocusableRootTask != null) {
            return mPreferredTopFocusableRootTask;
        }

        for (int i = mChildren.size() - 1; i >= 0; --i) {
            final WindowContainer child = mChildren.get(i);
            if (child.asTaskDisplayArea() != null) {
                final Task rootTask = child.asTaskDisplayArea().getFocusedRootTask();
                if (rootTask != null) {
                    return rootTask;
                }
                continue;
            }

            final Task rootTask = mChildren.get(i).asTask();
            if (rootTask.isFocusableAndVisible()) {
                return rootTask;
            }
        }

        return null;
    }

    Task getNextFocusableRootTask(Task currentFocus, boolean ignoreCurrent) {
        final int currentWindowingMode = currentFocus != null
                ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;

        Task candidate = null;
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            final WindowContainer child = mChildren.get(i);
            if (child.asTaskDisplayArea() != null) {
                final Task rootTask = child.asTaskDisplayArea()
                        .getNextFocusableRootTask(currentFocus, ignoreCurrent);
                if (rootTask != null) {
                    return rootTask;
                }
                continue;
            }

            final Task rootTask = mChildren.get(i).asTask();
            if (ignoreCurrent && rootTask == currentFocus) {
                continue;
            }
            if (!rootTask.isFocusableAndVisible()) {
                continue;
            }

            return rootTask;
        }
        return candidate;
    }

    ActivityRecord getFocusedActivity() {
        final Task focusedRootTask = getFocusedRootTask();
        if (focusedRootTask == null) {
            return null;
        }
        // TODO(b/111541062): Move this into Task#getResumedActivity()
        // Check if the focused root task has the resumed activity
        ActivityRecord resumedActivity = focusedRootTask.getTopResumedActivity();
        if (resumedActivity == null || resumedActivity.app == null) {
            // If there is no registered resumed activity in the root task or it is not running -
            // try to use previously resumed one.
            resumedActivity = focusedRootTask.getTopPausingActivity();
            if (resumedActivity == null || resumedActivity.app == null) {
                // If previously resumed activity doesn't work either - find the topmost running
                // activity that can be focused.
                resumedActivity = focusedRootTask.topRunningActivity(true /* focusableOnly */);
            }
        }
        return resumedActivity;
    }

    Task getLastFocusedRootTask() {
        return mLastFocusedRootTask;
    }

    void updateLastFocusedRootTask(Task prevFocusedTask, String updateLastFocusedTaskReason) {
        if (updateLastFocusedTaskReason == null) {
            return;
        }

        final Task currentFocusedTask = getFocusedRootTask();
        if (currentFocusedTask == prevFocusedTask) {
            return;
        }

        // Clear last paused activity if focused root task changed while sleeping, so that the
        // top activity of current focused task can be resumed.
        if (mDisplayContent.isSleeping() && currentFocusedTask != null) {
            currentFocusedTask.clearLastPausedActivity();
        }

        mLastFocusedRootTask = prevFocusedTask;
        EventLogTags.writeWmFocusedRootTask(mRootWindowContainer.mCurrentUser,
                mDisplayContent.mDisplayId,
                currentFocusedTask == null ? -1 : currentFocusedTask.getRootTaskId(),
                mLastFocusedRootTask == null ? -1 : mLastFocusedRootTask.getRootTaskId(),
                updateLastFocusedTaskReason);
    }

    boolean allResumedActivitiesComplete() {
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            final WindowContainer child = mChildren.get(i);
            if (child.asTaskDisplayArea() != null) {
                if (!child.asTaskDisplayArea().allResumedActivitiesComplete()) {
                    return false;
                }
                continue;
            }

            final ActivityRecord r = mChildren.get(i).asTask().getTopResumedActivity();
            if (r != null && !r.isState(RESUMED)) {
                return false;
            }
        }
        final Task currentFocusedRootTask = getFocusedRootTask();
        if (ActivityTaskManagerDebugConfig.DEBUG_ROOT_TASK) {
            Slog.d(TAG_ROOT_TASK, "allResumedActivitiesComplete: currentFocusedRootTask "
                    + "changing from=" + mLastFocusedRootTask + " to=" + currentFocusedRootTask);
        }
        mLastFocusedRootTask = currentFocusedRootTask;
        return true;
    }

    /**
     * Pause all activities in either all of the root tasks or just the back root tasks. This is
     * done before resuming a new activity and to make sure that previously active activities are
     * paused in root tasks that are no longer visible or in pinned windowing mode. This does not
     * pause activities in visible root tasks, so if an activity is launched within the same root
     * task, hen we should explicitly pause that root task's top activity.
     *
     * @param resuming    The resuming activity.
     * @return {@code true} if any activity was paused as a result of this call.
     */
    boolean pauseBackTasks(ActivityRecord resuming) {
        final int[] someActivityPaused = {0};
        forAllLeafTasks(leafTask -> {
            if (leafTask.pauseActivityIfNeeded(resuming, "pauseBackTasks")) {
                someActivityPaused[0]++;
            }
        }, true /* traverseTopToBottom */);
        return someActivityPaused[0] > 0;
    }


    /**
     * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
     *
     * @param windowingMode       The windowing mode we are checking support for.
     * @param supportsMultiWindow If we should consider support for multi-window mode in general.
     * @param supportsFreeform    If we should consider support for freeform multi-window.
     * @param supportsPip         If we should consider support for picture-in-picture mutli-window.
     * @return true if the windowing mode is supported.
     */
    static boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
            boolean supportsFreeform, boolean supportsPip) {

        if (windowingMode == WINDOWING_MODE_UNDEFINED
                || windowingMode == WINDOWING_MODE_FULLSCREEN) {
            return true;
        }
        if (!supportsMultiWindow) {
            return false;
        }

        if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
            return true;
        }

        if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
            return false;
        }

        if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) {
            return false;
        }
        return true;
    }

    /**
     * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this
     * display with the provided parameters.
     *
     * @param r            The ActivityRecord in question.
     * @param options      Options to start with.
     * @param task         The task within-which the activity would start.
     * @param activityType The type of activity to start.
     * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
     */
    int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
            @Nullable Task task) {

        // First preference if the windowing mode in the activity options if set.
        int windowingMode = (options != null)
                ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;

        // If windowing mode is unset, then next preference is the candidate task, then the
        // activity record.
        if (windowingMode == WINDOWING_MODE_UNDEFINED) {
            if (task != null) {
                windowingMode = task.getWindowingMode();
            }
            if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
                windowingMode = r.getWindowingMode();
            }
            if (windowingMode == WINDOWING_MODE_UNDEFINED) {
                // Use the display's windowing mode.
                windowingMode = getWindowingMode();
            }
        }
        windowingMode = validateWindowingMode(windowingMode, r, task);
        return windowingMode != WINDOWING_MODE_UNDEFINED
                ? windowingMode : WINDOWING_MODE_FULLSCREEN;
    }

    /**
     * Check if the requested windowing-mode is appropriate for the specified task and/or activity
     * on this display.
     *
     * @param windowingMode The windowing-mode to validate.
     * @param r             The {@link ActivityRecord} to check against.
     * @param task          The {@link Task} to check against.
     * @return {@code true} if windowingMode is valid, {@code false} otherwise.
     */
    boolean isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task
    ) {
        // Make sure the windowing mode we are trying to use makes sense for what is supported.
        boolean supportsMultiWindow = mAtmService.mSupportsMultiWindow;
        boolean supportsFreeform = mAtmService.mSupportsFreeformWindowManagement;
        boolean supportsPip = mAtmService.mSupportsPictureInPicture;
        if (supportsMultiWindow) {
            if (task != null) {
                supportsFreeform = task.supportsFreeformInDisplayArea(this);
                supportsMultiWindow = task.supportsMultiWindowInDisplayArea(this)
                        // When the activity needs to be moved to PIP while the Task is not in PIP,
                        // it can be moved to a new created PIP Task, so WINDOWING_MODE_PINNED is
                        // always valid for Task as long as the device supports it.
                        || (windowingMode == WINDOWING_MODE_PINNED && supportsPip);
            } else if (r != null) {
                supportsFreeform = r.supportsFreeformInDisplayArea(this);
                supportsPip = r.supportsPictureInPicture();
                supportsMultiWindow = r.supportsMultiWindowInDisplayArea(this);
            }
        }

        return windowingMode != WINDOWING_MODE_UNDEFINED
                && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsFreeform,
                supportsPip);
    }

    /**
     * Check that the requested windowing-mode is appropriate for the specified task and/or activity
     * on this display.
     *
     * @param windowingMode The windowing-mode to validate.
     * @param r             The {@link ActivityRecord} to check against.
     * @param task          The {@link Task} to check against.
     * @return The provided windowingMode or the closest valid mode which is appropriate.
     */
    int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task) {
        if (!isValidWindowingMode(windowingMode, r, task)) {
            return WINDOWING_MODE_UNDEFINED;
        }
        return windowingMode;
    }

    /**
     * Whether we can show non-resizable activities in multi window below this
     * {@link TaskDisplayArea}
     */
    boolean supportsNonResizableMultiWindow() {
        final int configSupportsNonResizableMultiWindow =
                mAtmService.mSupportsNonResizableMultiWindow;
        if (mAtmService.mDevEnableNonResizableMultiWindow
                || configSupportsNonResizableMultiWindow == 1) {
            // Device override to support.
            return true;
        }
        if (configSupportsNonResizableMultiWindow == -1) {
            // Device override to not support.
            return false;
        }
        // Support on large screen.
        return isLargeEnoughForMultiWindow();
    }

    /**
     * Whether we can show activity requesting the given min width/height in multi window below
     * this {@link TaskDisplayArea}.
     */
    boolean supportsActivityMinWidthHeightMultiWindow(int minWidth, int minHeight,
            @Nullable ActivityInfo activityInfo) {
        if (activityInfo != null && !activityInfo.shouldCheckMinWidthHeightForMultiWindow()) {
            return true;
        }
        if (minWidth <= 0 && minHeight <= 0) {
            // No request min width/height.
            return true;
        }
        final int configRespectsActivityMinWidthHeightMultiWindow =
                mAtmService.mRespectsActivityMinWidthHeightMultiWindow;
        if (configRespectsActivityMinWidthHeightMultiWindow == -1) {
            // Device override to ignore min width/height.
            return true;
        }
        if (configRespectsActivityMinWidthHeightMultiWindow == 0
                && isLargeEnoughForMultiWindow()) {
            // Ignore min width/height on large screen.
            return true;
        }
        // Check if the request min width/height is supported in multi window.
        final Configuration config = getConfiguration();
        final int orientation = config.orientation;
        if (orientation == ORIENTATION_LANDSCAPE) {
            final int maxSupportMinWidth = (int) (mAtmService.mMinPercentageMultiWindowSupportWidth
                    * config.screenWidthDp * mDisplayContent.getDisplayMetrics().density);
            return minWidth <= maxSupportMinWidth;
        } else {
            final int maxSupportMinHeight =
                    (int) (mAtmService.mMinPercentageMultiWindowSupportHeight
                            * config.screenHeightDp * mDisplayContent.getDisplayMetrics().density);
            return minHeight <= maxSupportMinHeight;
        }
    }

    /**
     * Whether this is large enough to support non-resizable, and activities with min width/height
     * in multi window.
     */
    private boolean isLargeEnoughForMultiWindow() {
        return getConfiguration().smallestScreenWidthDp
                >= WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
    }

    boolean isTopRootTask(Task rootTask) {
        return rootTask == getTopRootTask();
    }

    ActivityRecord topRunningActivity() {
        return topRunningActivity(false /* considerKeyguardState */);
    }

    /**
     * Returns the top running activity in the focused root task. In the case the focused root
     * task has no such activity, the next focusable root task on this display is returned.
     *
     * @param considerKeyguardState Indicates whether the locked state should be considered. if
     *                              {@code true} and the keyguard is locked, only activities that
     *                              can be shown on top of the keyguard will be considered.
     * @return The top running activity. {@code null} if none is available.
     */
    ActivityRecord topRunningActivity(boolean considerKeyguardState) {
        ActivityRecord topRunning = null;
        final Task focusedRootTask = getFocusedRootTask();
        if (focusedRootTask != null) {
            topRunning = focusedRootTask.topRunningActivity();
        }

        // Look in other focusable root tasks.
        if (topRunning == null) {
            for (int i = mChildren.size() - 1; i >= 0; --i) {
                final WindowContainer child = mChildren.get(i);
                if (child.asTaskDisplayArea() != null) {
                    topRunning =
                            child.asTaskDisplayArea().topRunningActivity(considerKeyguardState);
                    if (topRunning != null) {
                        break;
                    }
                    continue;
                }
                final Task rootTask = mChildren.get(i).asTask();
                // Only consider focusable root tasks other than the current focused one.
                if (rootTask == focusedRootTask || !rootTask.isTopActivityFocusable()) {
                    continue;
                }
                topRunning = rootTask.topRunningActivity();
                if (topRunning != null) {
                    break;
                }
            }
        }

        // This activity can be considered the top running activity if we are not considering
        // the locked state, the keyguard isn't locked, or we can show when locked.
        if (topRunning != null && considerKeyguardState
                && mRootWindowContainer.mTaskSupervisor.getKeyguardController()
                .isKeyguardLocked(topRunning.getDisplayId())
                && !topRunning.canShowWhenLocked()) {
            return null;
        }

        return topRunning;
    }

    protected int getRootTaskCount() {
        final int[] count = new int[1];
        forAllRootTasks(task -> {
            count[0]++;
        });
        return count[0];
    }

    @Nullable
    Task getOrCreateRootHomeTask() {
        return getOrCreateRootHomeTask(false /* onTop */);
    }

    /**
     * Returns the existing root home task or creates and returns a new one if it should exist
     * for the display.
     *
     * @param onTop Only be used when there is no existing root home task. If true the root home
     *              task will be created at the top of the display, else at the bottom.
     */
    @Nullable
    Task getOrCreateRootHomeTask(boolean onTop) {
        Task homeTask = getRootHomeTask();
        // Take into account if this TaskDisplayArea can have a home task before trying to
        // create the root task
        if (homeTask == null && canHostHomeTask()) {
            homeTask = createRootTask(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, onTop);
        }
        return homeTask;
    }

    /**
     * Returns the topmost root task on the display that is compatible with the input windowing
     * mode. Null is no compatible root task on the display.
     */
    Task getTopRootTaskInWindowingMode(int windowingMode) {
        return getRootTask(windowingMode, ACTIVITY_TYPE_UNDEFINED);
    }

    void moveHomeRootTaskToFront(String reason) {
        final Task homeRootTask = getOrCreateRootHomeTask();
        if (homeRootTask != null) {
            homeRootTask.moveToFront(reason);
        }
    }

    /**
     * Moves the focusable home activity to top. If there is no such activity, the root home task
     * will still move to top.
     */
    void moveHomeActivityToTop(String reason) {
        final ActivityRecord top = getHomeActivity();
        if (top == null) {
            moveHomeRootTaskToFront(reason);
            return;
        }
        top.moveFocusableActivityToTop(reason);
    }

    @Nullable
    ActivityRecord getHomeActivity() {
        return getHomeActivityForUser(mRootWindowContainer.mCurrentUser);
    }

    @Nullable
    ActivityRecord getHomeActivityForUser(int userId) {
        final Task rootHomeTask = getRootHomeTask();
        if (rootHomeTask == null) {
            return null;
        }

        final PooledPredicate p = PooledLambda.obtainPredicate(
                TaskDisplayArea::isHomeActivityForUser, PooledLambda.__(ActivityRecord.class),
                userId);
        final ActivityRecord r = rootHomeTask.getActivity(p);
        p.recycle();
        return r;
    }

    private static boolean isHomeActivityForUser(ActivityRecord r, int userId) {
        return r.isActivityTypeHome() && (userId == UserHandle.USER_ALL || r.mUserId == userId);
    }

    /**
     * Adjusts the {@param rootTask} behind the last visible rootTask in the display if necessary.
     * Generally used in conjunction with {@link #moveRootTaskBehindRootTask}.
     */
    // TODO(b/151575894): Remove special root task movement methods.
    void moveRootTaskBehindBottomMostVisibleRootTask(Task rootTask) {
        if (rootTask.shouldBeVisible(null)) {
            // Skip if the root task is already visible
            return;
        }

        // Move the root task to the bottom to not affect the following visibility checks
        rootTask.getParent().positionChildAt(POSITION_BOTTOM, rootTask,
                false /* includingParents */);

        // Find the next position where the root task should be placed
        final boolean isRootTask = rootTask.isRootTask();
        final int numRootTasks =
                isRootTask ? mChildren.size() : rootTask.getParent().getChildCount();
        for (int rootTaskNdx = 0; rootTaskNdx < numRootTasks; rootTaskNdx++) {
            Task s;
            if (isRootTask) {
                final WindowContainer child = mChildren.get(rootTaskNdx);
                if (child.asTaskDisplayArea() != null) {
                    s = child.asTaskDisplayArea().getBottomMostVisibleRootTask(rootTask);
                } else {
                    s = child.asTask();
                }
            } else {
                s = rootTask.getParent().getChildAt(rootTaskNdx).asTask();
            }
            if (s == rootTask || s == null) {
                continue;
            }
            final int winMode = s.getWindowingMode();
            final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN;
            if (s.shouldBeVisible(null) && isValidWindowingMode) {
                // Move the provided root task to behind this root task
                final int position = Math.max(0, rootTaskNdx - 1);
                rootTask.getParent().positionChildAt(position, rootTask,
                        false /*includingParents */);
                break;
            }
        }
    }

    @Nullable
    private Task getBottomMostVisibleRootTask(Task excludeRootTask) {
        return getRootTask(task -> {
            final int winMode = task.getWindowingMode();
            final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN;
            return task.shouldBeVisible(null) && isValidWindowingMode;
        }, false /* traverseTopToBottom */);
    }

    /**
     * Moves the {@param rootTask} behind the given {@param behindRootTask} if possible. If
     * {@param behindRootTask} is not currently in the display, then then the root task is moved
     * to the back. Generally used in conjunction with
     * {@link #moveRootTaskBehindBottomMostVisibleRootTask}.
     */
    void moveRootTaskBehindRootTask(Task rootTask, Task behindRootTask) {
        if (behindRootTask == null || behindRootTask == rootTask) {
            return;
        }

        final WindowContainer parent = rootTask.getParent();
        if (parent == null || parent != behindRootTask.getParent()) {
            return;
        }

        // Note that positionChildAt will first remove the given root task before inserting into the
        // list, so we need to adjust the insertion index to account for the removed index
        // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the
        //       position internally
        final int rootTaskIndex = parent.mChildren.indexOf(rootTask);
        final int behindRootTaskIndex = parent.mChildren.indexOf(behindRootTask);
        final int insertIndex = rootTaskIndex <= behindRootTaskIndex
                ? behindRootTaskIndex - 1 : behindRootTaskIndex;
        final int position = Math.max(0, insertIndex);
        parent.positionChildAt(position, rootTask, false /* includingParents */);
    }

    boolean hasPinnedTask() {
        return getRootPinnedTask() != null;
    }

    /**
     * @return the root task currently above the {@param rootTask}. Can be null if the
     * {@param rootTask} is already top-most.
     */
    static Task getRootTaskAbove(Task rootTask) {
        final WindowContainer wc = rootTask.getParent();
        final int index = wc.mChildren.indexOf(rootTask) + 1;
        return (index < wc.mChildren.size()) ? (Task) wc.mChildren.get(index) : null;
    }

    /** Returns true if the root task in the windowing mode is visible. */
    boolean isRootTaskVisible(int windowingMode) {
        final Task rootTask = getTopRootTaskInWindowingMode(windowingMode);
        return rootTask != null && rootTask.isVisible();
    }

    void removeRootTask(Task rootTask) {
        removeChild(rootTask);
    }

    int getDisplayId() {
        return mDisplayContent.getDisplayId();
    }

    boolean isRemoved() {
        return mRemoved;
    }

    /**
     * Adds a listener to be notified whenever the root task order in the display changes. Currently
     * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the
     * current animation when the system state changes.
     */
    void registerRootTaskOrderChangedListener(OnRootTaskOrderChangedListener listener) {
        if (!mRootTaskOrderChangedCallbacks.contains(listener)) {
            mRootTaskOrderChangedCallbacks.add(listener);
        }
    }

    /**
     * Removes a previously registered root task order change listener.
     */
    void unregisterRootTaskOrderChangedListener(OnRootTaskOrderChangedListener listener) {
        mRootTaskOrderChangedCallbacks.remove(listener);
    }

    /**
     * Notifies of a root task order change
     *
     * @param rootTask The root task which triggered the order change
     */
    void onRootTaskOrderChanged(Task rootTask) {
        for (int i = mRootTaskOrderChangedCallbacks.size() - 1; i >= 0; i--) {
            mRootTaskOrderChangedCallbacks.get(i).onRootTaskOrderChanged(rootTask);
        }
    }

    @Override
    boolean canCreateRemoteAnimationTarget() {
        // In the legacy transition system, promoting animation target from TaskFragment to
        // TaskDisplayArea prevents running finish animation. See b/194649929.
        return WindowManagerService.sEnableShellTransitions;
    }

    /**
     * Exposes the home task capability of the TaskDisplayArea
     */
    boolean canHostHomeTask() {
        return mDisplayContent.isHomeSupported() && mCanHostHomeTask;
    }

    /**
     * Callback for when the order of the root tasks in the display changes.
     */
    interface OnRootTaskOrderChangedListener {
        void onRootTaskOrderChanged(Task rootTask);
    }

    void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
            boolean preserveWindows, boolean notifyClients) {
        mAtmService.mTaskSupervisor.beginActivityVisibilityUpdate();
        try {
            forAllRootTasks(rootTask -> {
                rootTask.ensureActivitiesVisible(starting, configChanges, preserveWindows,
                        notifyClients);
            });
        } finally {
            mAtmService.mTaskSupervisor.endActivityVisibilityUpdate();
        }
    }

    /**
     * Removes the root tasks in the node applying the content removal node from the display.
     *
     * @return last reparented root task, or {@code null} if the root tasks had to be destroyed.
     */
    Task remove() {
        mPreferredTopFocusableRootTask = null;
        // TODO(b/153090332): Allow setting content removal mode per task display area
        final boolean destroyContentOnRemoval = mDisplayContent.shouldDestroyContentOnRemove();
        final TaskDisplayArea toDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
        Task lastReparentedRootTask = null;

        // Root tasks could be reparented from the removed display area to other display area. After
        // reparenting the last root task of the removed display area, the display area becomes
        // ready to be released (no more root tasks). But, we cannot release it at that moment
        // or the related WindowContainer will also be removed. So, we set display area as removed
        // after reparenting root task finished.
        // Keep the order from bottom to top.
        int numRootTasks = mChildren.size();

        for (int i = 0; i < numRootTasks; i++) {
            final WindowContainer child = mChildren.get(i);
            if (child.asTaskDisplayArea() != null) {
                lastReparentedRootTask = child.asTaskDisplayArea().remove();
                continue;
            }
            final Task task = mChildren.get(i).asTask();
            // Always finish non-standard type root tasks and root tasks created by a organizer.
            // TODO: For root tasks created by organizer, consider reparenting children tasks if
            //       the use case arises in the future.
            if (destroyContentOnRemoval
                    || !task.isActivityTypeStandardOrUndefined()
                    || task.mCreatedByOrganizer) {
                task.remove(false /* withTransition */, "removeTaskDisplayArea");
            } else {
                // Reparent task to corresponding launch root or display area.
                final WindowContainer launchRoot = toDisplayArea.getLaunchRootTask(
                                        task.getWindowingMode(),
                                        task.getActivityType(),
                                        null /* options */,
                                        null /* sourceTask */,
                                        0 /* launchFlags */);
                task.reparent(launchRoot == null ? toDisplayArea : launchRoot, POSITION_TOP);

                // If the task is going to be reparented to the non-fullscreen root TDA and the task
                // is set to FULLSCREEN explicitly, we keep the windowing mode as is. Otherwise, the
                // task will inherit the display windowing mode unexpectedly.
                final boolean keepWindowingMode = launchRoot == null
                        && task.getRequestedOverrideWindowingMode() == WINDOWING_MODE_FULLSCREEN
                        && toDisplayArea.getWindowingMode() != WINDOWING_MODE_FULLSCREEN;
                if (!keepWindowingMode) {
                    // Set the windowing mode to undefined to let the root task inherited the
                    // windowing mode.
                    task.setWindowingMode(WINDOWING_MODE_UNDEFINED);
                }
                lastReparentedRootTask = task;
            }
            // Root task may be removed from this display. Ensure each root task will be processed
            // and the loop will end.
            i -= numRootTasks - mChildren.size();
            numRootTasks = mChildren.size();
        }

        if (lastReparentedRootTask != null && !lastReparentedRootTask.isRootTask()) {
            // Update focus when the last reparented root task is not a root task anymore.
            // (For example, if it has been reparented to a split screen root task, move the
            // focus to the split root task)
            lastReparentedRootTask.getRootTask().moveToFront("display-removed");
        }

        mRemoved = true;

        return lastReparentedRootTask;
    }

    /** Whether this task display area can request orientation. */
    boolean canSpecifyOrientation(@ScreenOrientation int orientation) {
        // Only allow to specify orientation if this TDA is the last focused one on this logical
        // display that can request orientation request.
        return mDisplayContent.getOrientationRequestingTaskDisplayArea() == this
                && !shouldIgnoreOrientationRequest(orientation);
    }

    void clearPreferredTopFocusableRootTask() {
        mPreferredTopFocusableRootTask = null;
    }

    @Override
    public void setWindowingMode(int windowingMode) {
        mTempConfiguration.setTo(getRequestedOverrideConfiguration());
        WindowConfiguration tempRequestWindowConfiguration = mTempConfiguration.windowConfiguration;
        tempRequestWindowConfiguration.setWindowingMode(windowingMode);
        tempRequestWindowConfiguration.setDisplayWindowingMode(windowingMode);
        onRequestedOverrideConfigurationChanged(mTempConfiguration);
    }

    @Override
    TaskDisplayArea getTaskDisplayArea() {
        return this;
    }

    @Override
    boolean isTaskDisplayArea() {
        return true;
    }

    @Override
    TaskDisplayArea asTaskDisplayArea() {
        return this;
    }

    @Override
    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
        pw.println(prefix + "TaskDisplayArea " + getName());
        final String doublePrefix = prefix + "  ";
        super.dump(pw, doublePrefix, dumpAll);
        if (mPreferredTopFocusableRootTask != null) {
            pw.println(doublePrefix + "mPreferredTopFocusableRootTask="
                    + mPreferredTopFocusableRootTask);
        }
        if (mLastFocusedRootTask != null) {
            pw.println(doublePrefix + "mLastFocusedRootTask=" + mLastFocusedRootTask);
        }

        final String triplePrefix = doublePrefix + "  ";

        if (mLaunchRootTasks.size() > 0) {
            pw.println(doublePrefix + "mLaunchRootTasks:");
            for (int i = mLaunchRootTasks.size() - 1; i >= 0; --i) {
                final LaunchRootTaskDef def = mLaunchRootTasks.get(i);
                pw.println(triplePrefix
                        + Arrays.toString(def.activityTypes) + " "
                        + Arrays.toString(def.windowingModes) + " "
                        + " task=" + def.task);
            }
        }

        pw.println(doublePrefix + "Application tokens in top down Z order:");
        for (int index = getChildCount() - 1; index >= 0; --index) {
            final WindowContainer child = getChildAt(index);
            if (child.asTaskDisplayArea() != null) {
                child.dump(pw, doublePrefix, dumpAll);
                continue;
            }
            final Task rootTask = child.asTask();
            pw.println(doublePrefix + "* " + rootTask.toFullString());
            rootTask.dump(pw, triplePrefix, dumpAll);
        }
    }
}
