/*
 * Copyright (C) 2021 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_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.ROTATION_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.pm.ActivityInfo.FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING;
import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.os.Process.INVALID_UID;
import static android.os.Process.SYSTEM_UID;
import static android.os.UserHandle.USER_NULL;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_OPEN;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
import static com.android.server.wm.ActivityRecord.State.PAUSED;
import static com.android.server.wm.ActivityRecord.State.PAUSING;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityRecord.State.STOPPING;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityTaskSupervisor.printThisActivity;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
import static com.android.server.wm.TaskFragmentProto.ACTIVITY_TYPE;
import static com.android.server.wm.TaskFragmentProto.DISPLAY_ID;
import static com.android.server.wm.TaskFragmentProto.MIN_HEIGHT;
import static com.android.server.wm.TaskFragmentProto.MIN_WIDTH;
import static com.android.server.wm.TaskFragmentProto.WINDOW_CONTAINER;
import static com.android.server.wm.WindowContainerChildProto.TASK_FRAGMENT;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.IApplicationThread;
import android.app.ResultInfo;
import android.app.WindowConfiguration;
import android.app.servertransaction.ActivityResultItem;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.NewIntentItem;
import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.ResumeActivityItem;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
import android.os.IBinder;
import android.os.UserHandle;
import android.util.DisplayMetrics;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.window.ITaskFragmentOrganizer;
import android.window.ScreenCapture;
import android.window.TaskFragmentAnimationParams;
import android.window.TaskFragmentInfo;
import android.window.TaskFragmentOrganizerToken;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.server.am.HostingRecord;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.window.flags.Flags;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * A basic container that can be used to contain activities or other {@link TaskFragment}, which
 * also able to manage the activity lifecycle and updates the visibilities of the activities in it.
 */
class TaskFragment extends WindowContainer<WindowContainer> {
    @IntDef(prefix = {"TASK_FRAGMENT_VISIBILITY"}, value = {
            TASK_FRAGMENT_VISIBILITY_VISIBLE,
            TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
            TASK_FRAGMENT_VISIBILITY_INVISIBLE,
    })
    @interface TaskFragmentVisibility {}

    /**
     * TaskFragment is visible. No other TaskFragment(s) on top that fully or partially occlude it.
     */
    static final int TASK_FRAGMENT_VISIBILITY_VISIBLE = 0;

    /** TaskFragment is partially occluded by other translucent TaskFragment(s) on top of it. */
    static final int TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT = 1;

    /** TaskFragment is completely invisible. */
    static final int TASK_FRAGMENT_VISIBILITY_INVISIBLE = 2;

    private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskFragment" : TAG_ATM;
    private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
    private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
    private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION;

    /** Set to false to disable the preview that is shown while a new activity is being started. */
    static final boolean SHOW_APP_STARTING_PREVIEW = true;

    /**
     * An embedding check result of {@link #isAllowedToEmbedActivity(ActivityRecord)} or
     * {@link ActivityStarter#canEmbedActivity(TaskFragment, ActivityRecord, Task)}:
     * indicate that an Activity can be embedded successfully.
     */
    static final int EMBEDDING_ALLOWED = 0;
    /**
     * An embedding check result of {@link #isAllowedToEmbedActivity(ActivityRecord)} or
     * {@link ActivityStarter#canEmbedActivity(TaskFragment, ActivityRecord, Task)}:
     * indicate that an Activity can't be embedded because either the Activity does not allow
     * untrusted embedding, and the embedding host app is not trusted.
     */
    static final int EMBEDDING_DISALLOWED_UNTRUSTED_HOST = 1;
    /**
     * An embedding check result of {@link #isAllowedToEmbedActivity(ActivityRecord)} or
     * {@link ActivityStarter#canEmbedActivity(TaskFragment, ActivityRecord, Task)}:
     * indicate that an Activity can't be embedded because this taskFragment's bounds are
     * {@link #smallerThanMinDimension(ActivityRecord)}.
     */
    static final int EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION = 2;
    /**
     * An embedding check result of
     * {@link ActivityStarter#canEmbedActivity(TaskFragment, ActivityRecord, Task)}:
     * indicate that an Activity can't be embedded because the Activity is started on a new task.
     */
    static final int EMBEDDING_DISALLOWED_NEW_TASK = 3;

    /**
     * Embedding check results of {@link #isAllowedToEmbedActivity(ActivityRecord)} or
     * {@link ActivityStarter#canEmbedActivity(TaskFragment, ActivityRecord, Task)}.
     */
    @IntDef(prefix = {"EMBEDDING_"}, value = {
            EMBEDDING_ALLOWED,
            EMBEDDING_DISALLOWED_UNTRUSTED_HOST,
            EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION,
            EMBEDDING_DISALLOWED_NEW_TASK,
    })
    @interface EmbeddingCheckResult {}

    /**
     * Indicate that the minimal width/height should use the default value.
     *
     * @see #mMinWidth
     * @see #mMinHeight
     */
    static final int INVALID_MIN_SIZE = -1;

    final ActivityTaskManagerService mAtmService;
    final ActivityTaskSupervisor mTaskSupervisor;
    final RootWindowContainer mRootWindowContainer;
    private final TaskFragmentOrganizerController mTaskFragmentOrganizerController;

    // TODO(b/233177466): Move mMinWidth and mMinHeight to Task and remove usages in TaskFragment
    /**
     * Minimal width of this task fragment when it's resizeable. {@link #INVALID_MIN_SIZE} means it
     * should use the default minimal width.
     */
    int mMinWidth;

    /**
     * Minimal height of this task fragment when it's resizeable. {@link #INVALID_MIN_SIZE} means it
     * should use the default minimal height.
     */
    int mMinHeight;

    Dimmer mDimmer = Dimmer.DIMMER_REFACTOR
            ? new SmoothDimmer(this) : new LegacyDimmer(this);

    /** Apply the dim layer on the embedded TaskFragment. */
    static final int EMBEDDED_DIM_AREA_TASK_FRAGMENT = 0;

    /** Apply the dim layer on the parent Task for an embedded TaskFragment. */
    static final int EMBEDDED_DIM_AREA_PARENT_TASK = 1;

    /**
     * The type of dim layer area for an embedded TaskFragment.
     */
    @IntDef(prefix = {"EMBEDDED_DIM_AREA_"}, value = {
            EMBEDDED_DIM_AREA_TASK_FRAGMENT,
            EMBEDDED_DIM_AREA_PARENT_TASK,
    })
    @interface EmbeddedDimArea {}

    @EmbeddedDimArea
    private int mEmbeddedDimArea = EMBEDDED_DIM_AREA_TASK_FRAGMENT;

    /** This task fragment will be removed when the cleanup of its children are done. */
    private boolean mIsRemovalRequested;

    /** The TaskFragment that is adjacent to this one. */
    @Nullable
    private TaskFragment mAdjacentTaskFragment;

    /**
     * Unlike the {@link mAdjacentTaskFragment}, the companion TaskFragment is not always visually
     * adjacent to this one, but this TaskFragment will be removed by the organizer if the
     * companion TaskFragment is removed.
     */
    @Nullable
    private TaskFragment mCompanionTaskFragment;

    /**
     * Prevents duplicate calls to onTaskFragmentAppeared.
     */
    boolean mTaskFragmentAppearedSent;

    /**
     * Prevents unnecessary callbacks after onTaskFragmentVanished.
     */
    boolean mTaskFragmentVanishedSent;

    /**
     * The last running activity of the TaskFragment was finished due to clear task while launching
     * an activity in the Task.
     */
    boolean mClearedTaskForReuse;

    /**
     * The last running activity of the TaskFragment was reparented to a different Task because it
     * is entering PiP.
     */
    boolean mClearedTaskFragmentForPip;

    /**
     * The last running activity of the TaskFragment was removed and added to the top-most of the
     * Task because it was launched with FLAG_ACTIVITY_REORDER_TO_FRONT.
     */
    boolean mClearedForReorderActivityToFront;

    /**
     * When we are in the process of pausing an activity, before starting the
     * next one, this variable holds the activity that is currently being paused.
     *
     * Only set at leaf task fragments.
     */
    @Nullable
    private ActivityRecord mPausingActivity = null;

    /**
     * This is the last activity that we put into the paused state.  This is
     * used to determine if we need to do an activity transition while sleeping,
     * when we normally hold the top activity paused.
     */
    ActivityRecord mLastPausedActivity = null;

    /**
     * Current activity that is resumed, or null if there is none.
     * Only set at leaf task fragments.
     */
    @Nullable
    private ActivityRecord mResumedActivity = null;

    /**
     * This TaskFragment was created by an organizer which has the following implementations.
     * <ul>
     *     <li>The TaskFragment won't be removed when it is empty. Removal has to be an explicit
     *     request from the organizer.</li>
     *     <li>If this fragment is a Task object then unlike other non-root tasks, it's direct
     *     children are visible to the organizer for ordering purposes.</li>
     *     <li>A TaskFragment can be created by {@link android.window.TaskFragmentOrganizer}, and
     *     a Task can be created by {@link android.window.TaskOrganizer}.</li>
     * </ul>
     */
    @VisibleForTesting
    boolean mCreatedByOrganizer;

    /** Whether this TaskFragment is embedded in a task. */
    private final boolean mIsEmbedded;

    /** Organizer that organizing this TaskFragment. */
    @Nullable
    private ITaskFragmentOrganizer mTaskFragmentOrganizer;
    @VisibleForTesting
    int mTaskFragmentOrganizerUid = INVALID_UID;
    private @Nullable String mTaskFragmentOrganizerProcessName;

    /** Client assigned unique token for this TaskFragment if this is created by an organizer. */
    @Nullable
    private final IBinder mFragmentToken;

    /** The animation override params for animation running on this TaskFragment. */
    @NonNull
    private TaskFragmentAnimationParams mAnimationParams = TaskFragmentAnimationParams.DEFAULT;

    /**
     * The organizer requested bounds of the embedded TaskFragment relative to the parent Task.
     * {@code null} if it is not {@link #mIsEmbedded}
     */
    @Nullable
    private final Rect mRelativeEmbeddedBounds;

    /**
     * Whether to delay the call to {@link #updateOrganizedTaskFragmentSurface()} when there is a
     * configuration change.
     */
    private boolean mDelayOrganizedTaskFragmentSurfaceUpdate;

    /**
     * Whether to delay the last activity of TaskFragment being immediately removed while finishing.
     * This should only be set on a embedded TaskFragment, where the organizer can have the
     * opportunity to perform animations and finishing the adjacent TaskFragment.
     */
    private boolean mDelayLastActivityRemoval;

    /**
     * Whether the activity navigation should be isolated. That is, Activities cannot be launched
     * on an isolated TaskFragment, unless the activity is launched from an Activity in the same
     * isolated TaskFragment, or explicitly requested to be launched to.
     * <p>
     * Note that only an embedded TaskFragment can be isolated.
     */
    private boolean mIsolatedNav;

    /** When set, will force the task to report as invisible. */
    static final int FLAG_FORCE_HIDDEN_FOR_PINNED_TASK = 1;
    static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1;
    static final int FLAG_FORCE_HIDDEN_FOR_TASK_FRAGMENT_ORG = 1 << 2;

    @IntDef(prefix = {"FLAG_FORCE_HIDDEN_"}, value = {
            FLAG_FORCE_HIDDEN_FOR_PINNED_TASK,
            FLAG_FORCE_HIDDEN_FOR_TASK_ORG,
            FLAG_FORCE_HIDDEN_FOR_TASK_FRAGMENT_ORG,
    }, flag = true)
    @interface FlagForceHidden {}
    protected int mForceHiddenFlags = 0;

    private boolean mForceTranslucent = false;

    final Point mLastSurfaceSize = new Point();

    private final Rect mTmpBounds = new Rect();
    private final Rect mTmpAbsBounds = new Rect();
    private final Rect mTmpFullBounds = new Rect();
    /** For calculating screenWidthDp and screenWidthDp, i.e. the area without the system bars. */
    private final Rect mTmpStableBounds = new Rect();
    /** For calculating app bounds, i.e. the area without the nav bar and display cutout. */
    private final Rect mTmpNonDecorBounds = new Rect();

    //TODO(b/207481538) Remove once the infrastructure to support per-activity screenshot is
    // implemented
    HashMap<String, ScreenCapture.ScreenshotHardwareBuffer> mBackScreenshots = new HashMap<>();

    private final EnsureActivitiesVisibleHelper mEnsureActivitiesVisibleHelper =
            new EnsureActivitiesVisibleHelper(this);

    /** Creates an embedded task fragment. */
    TaskFragment(ActivityTaskManagerService atmService, IBinder fragmentToken,
            boolean createdByOrganizer) {
        this(atmService, fragmentToken, createdByOrganizer, true /* isEmbedded */);
    }

    TaskFragment(ActivityTaskManagerService atmService, IBinder fragmentToken,
            boolean createdByOrganizer, boolean isEmbedded) {
        super(atmService.mWindowManager);

        mAtmService = atmService;
        mTaskSupervisor = mAtmService.mTaskSupervisor;
        mRootWindowContainer = mAtmService.mRootWindowContainer;
        mCreatedByOrganizer = createdByOrganizer;
        mIsEmbedded = isEmbedded;
        mRelativeEmbeddedBounds = isEmbedded ? new Rect() : null;
        mTaskFragmentOrganizerController =
                mAtmService.mWindowOrganizerController.mTaskFragmentOrganizerController;
        mFragmentToken = fragmentToken;
        mRemoteToken = new RemoteToken(this);
    }

    @NonNull
    static TaskFragment fromTaskFragmentToken(@Nullable IBinder token,
            @NonNull ActivityTaskManagerService service) {
        if (token == null) return null;
        return service.mWindowOrganizerController.getTaskFragment(token);
    }

    void setAdjacentTaskFragment(@Nullable TaskFragment taskFragment) {
        if (mAdjacentTaskFragment == taskFragment) {
            return;
        }
        resetAdjacentTaskFragment();
        if (taskFragment != null) {
            mAdjacentTaskFragment = taskFragment;
            taskFragment.setAdjacentTaskFragment(this);
        }
    }

    void setCompanionTaskFragment(@Nullable TaskFragment companionTaskFragment) {
        mCompanionTaskFragment = companionTaskFragment;
    }

    TaskFragment getCompanionTaskFragment() {
        return mCompanionTaskFragment;
    }

    void resetAdjacentTaskFragment() {
        // Reset the adjacent TaskFragment if its adjacent TaskFragment is also this TaskFragment.
        if (mAdjacentTaskFragment != null && mAdjacentTaskFragment.mAdjacentTaskFragment == this) {
            mAdjacentTaskFragment.mAdjacentTaskFragment = null;
            mAdjacentTaskFragment.mDelayLastActivityRemoval = false;
        }
        mAdjacentTaskFragment = null;
        mDelayLastActivityRemoval = false;
    }

    void setTaskFragmentOrganizer(@NonNull TaskFragmentOrganizerToken organizer, int uid,
            @NonNull String processName) {
        mTaskFragmentOrganizer = ITaskFragmentOrganizer.Stub.asInterface(organizer.asBinder());
        mTaskFragmentOrganizerUid = uid;
        mTaskFragmentOrganizerProcessName = processName;
    }

    void onTaskFragmentOrganizerRemoved() {
        mTaskFragmentOrganizer = null;
    }

    /** Whether this TaskFragment is organized by the given {@code organizer}. */
    boolean hasTaskFragmentOrganizer(ITaskFragmentOrganizer organizer) {
        return organizer != null && mTaskFragmentOrganizer != null
                && organizer.asBinder().equals(mTaskFragmentOrganizer.asBinder());
    }

    /**
     * Returns the process of organizer if this TaskFragment is organized and the activity lives in
     * a different process than the organizer.
     */
    @Nullable
    private WindowProcessController getOrganizerProcessIfDifferent(@Nullable ActivityRecord r) {
        if ((r == null || mTaskFragmentOrganizerProcessName == null)
                || (mTaskFragmentOrganizerProcessName.equals(r.processName)
                && mTaskFragmentOrganizerUid == r.getUid())) {
            // No organizer or the process is the same.
            return null;
        }
        return mAtmService.getProcessController(mTaskFragmentOrganizerProcessName,
                mTaskFragmentOrganizerUid);
    }

    void setAnimationParams(@NonNull TaskFragmentAnimationParams animationParams) {
        mAnimationParams = animationParams;
    }

    @NonNull
    TaskFragmentAnimationParams getAnimationParams() {
        return mAnimationParams;
    }

    /** @see #mIsolatedNav */
    void setIsolatedNav(boolean isolatedNav) {
        if (!isEmbedded()) {
            return;
        }
        mIsolatedNav = isolatedNav;
    }

    /** @see #mIsolatedNav */
    boolean isIsolatedNav() {
        return isEmbedded() && mIsolatedNav;
    }

    TaskFragment getAdjacentTaskFragment() {
        return mAdjacentTaskFragment;
    }

    /** Returns the currently topmost resumed activity. */
    @Nullable
    ActivityRecord getTopResumedActivity() {
        final ActivityRecord taskFragResumedActivity = getResumedActivity();
        for (int i = getChildCount() - 1; i >= 0; --i) {
            WindowContainer<?> child = getChildAt(i);
            ActivityRecord topResumedActivity = null;
            if (taskFragResumedActivity != null && child == taskFragResumedActivity) {
                topResumedActivity = child.asActivityRecord();
            } else if (child.asTaskFragment() != null) {
                topResumedActivity = child.asTaskFragment().getTopResumedActivity();
            }
            if (topResumedActivity != null) {
                return topResumedActivity;
            }
        }
        return null;
    }

    /**
     * Returns the currently resumed activity in this TaskFragment's
     * {@link #mChildren direct children}
     */
    ActivityRecord getResumedActivity() {
        return mResumedActivity;
    }

    void setResumedActivity(ActivityRecord r, String reason) {
        warnForNonLeafTaskFragment("setResumedActivity");
        if (mResumedActivity == r) {
            return;
        }

        if (ActivityTaskManagerDebugConfig.DEBUG_ROOT_TASK) {
            Slog.d(TAG, "setResumedActivity taskFrag:" + this + " + from: "
                    + mResumedActivity + " to:" + r + " reason:" + reason);
        }

        if (r != null && mResumedActivity == null) {
            // Task is becoming active.
            getTask().touchActiveTime();
        }

        final ActivityRecord prevR = mResumedActivity;
        mResumedActivity = r;
        mTaskSupervisor.updateTopResumedActivityIfNeeded(reason);
        if (r == null && prevR.mDisplayContent != null
                && prevR.mDisplayContent.getFocusedRootTask() == null) {
            // Only need to notify DWPC when no activity will resume.
            prevR.mDisplayContent.onRunningActivityChanged();
        } else if (r != null) {
            r.mDisplayContent.onRunningActivityChanged();
        }
    }

    @VisibleForTesting
    void setPausingActivity(ActivityRecord pausing) {
        mPausingActivity = pausing;
    }

    /** Returns the currently topmost pausing activity. */
    @Nullable
    ActivityRecord getTopPausingActivity() {
        final ActivityRecord taskFragPausingActivity = getPausingActivity();
        for (int i = getChildCount() - 1; i >= 0; --i) {
            WindowContainer<?> child = getChildAt(i);
            ActivityRecord topPausingActivity = null;
            if (taskFragPausingActivity != null && child == taskFragPausingActivity) {
                topPausingActivity = child.asActivityRecord();
            } else if (child.asTaskFragment() != null) {
                topPausingActivity = child.asTaskFragment().getTopPausingActivity();
            }
            if (topPausingActivity != null) {
                return topPausingActivity;
            }
        }
        return null;
    }

    ActivityRecord getPausingActivity() {
        return mPausingActivity;
    }

    int getDisplayId() {
        final DisplayContent dc = getDisplayContent();
        return dc != null ? dc.mDisplayId : INVALID_DISPLAY;
    }

    @Nullable
    Task getTask() {
        if (asTask() != null) {
            return asTask();
        }

        TaskFragment parent = getParent() != null ? getParent().asTaskFragment() : null;
        return parent != null ? parent.getTask() : null;
    }

    @Override
    @Nullable
    TaskDisplayArea getDisplayArea() {
        return (TaskDisplayArea) super.getDisplayArea();
    }

    @Override
    public boolean isAttached() {
        final TaskDisplayArea taskDisplayArea = getDisplayArea();
        return taskDisplayArea != null && !taskDisplayArea.isRemoved();
    }

    /**
     * Returns the root {@link TaskFragment}, which is usually also a {@link Task}.
     */
    @NonNull
    TaskFragment getRootTaskFragment() {
        final WindowContainer parent = getParent();
        if (parent == null) return this;

        final TaskFragment parentTaskFragment = parent.asTaskFragment();
        return parentTaskFragment == null ? this : parentTaskFragment.getRootTaskFragment();
    }

    @Nullable
    Task getRootTask() {
        return getRootTaskFragment().asTask();
    }

    @Override
    TaskFragment asTaskFragment() {
        return this;
    }

    @Override
    boolean isEmbedded() {
        return mIsEmbedded;
    }

    @EmbeddingCheckResult
    int isAllowedToEmbedActivity(@NonNull ActivityRecord a) {
        return isAllowedToEmbedActivity(a, mTaskFragmentOrganizerUid);
    }

    /**
     * Checks if the organized task fragment is allowed to have the specified activity, which is
     * allowed if an activity allows embedding in untrusted mode, if the trusted mode can be
     * enabled, or if the organized task fragment bounds are not
     * {@link #smallerThanMinDimension(ActivityRecord)}.
     *
     * @param uid   uid of the TaskFragment organizer.
     * @see #isAllowedToEmbedActivityInTrustedMode(ActivityRecord)
     */
    @EmbeddingCheckResult
    int isAllowedToEmbedActivity(@NonNull ActivityRecord a, int uid) {
        if (!isAllowedToEmbedActivityInUntrustedMode(a)
                && !isAllowedToEmbedActivityInTrustedMode(a, uid)) {
            return EMBEDDING_DISALLOWED_UNTRUSTED_HOST;
        }

        if (smallerThanMinDimension(a)) {
            return EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION;
        }

        return EMBEDDING_ALLOWED;
    }

    boolean smallerThanMinDimension(@NonNull ActivityRecord activity) {
        final Rect taskFragBounds = getBounds();
        final Task task = getTask();
        // Don't need to check if the bounds match parent Task bounds because the fallback mechanism
        // is to reparent the Activity to parent if minimum dimensions are not satisfied.
        if (task == null || taskFragBounds.equals(task.getBounds())) {
            return false;
        }
        final Point minDimensions = activity.getMinDimensions();
        if (minDimensions == null) {
            return false;
        }
        final int minWidth = minDimensions.x;
        final int minHeight = minDimensions.y;
        return taskFragBounds.width() < minWidth
                || taskFragBounds.height() < minHeight;
    }

    /**
     * Checks if the organized task fragment is allowed to embed activity in untrusted mode.
     */
    boolean isAllowedToEmbedActivityInUntrustedMode(@NonNull ActivityRecord a) {
        final WindowContainer parent = getParent();
        if (parent == null || !parent.getBounds().contains(getBounds())) {
            // Without full trust between the host and the embedded activity, we don't allow
            // TaskFragment to have bounds outside of the parent bounds.
            return false;
        }
        return (a.info.flags & FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING)
                == FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING;
    }

    boolean isAllowedToEmbedActivityInTrustedMode(@NonNull ActivityRecord a) {
        return isAllowedToEmbedActivityInTrustedMode(a, mTaskFragmentOrganizerUid);
    }

    /**
     * Checks if the organized task fragment is allowed to embed activity in fully trusted mode,
     * which means that all transactions are allowed. This is supported in the following cases:
     * <li>the activity belongs to the same app as the organizer host;</li>
     * <li>the activity has declared the organizer host as trusted explicitly via known
     * certificate.</li>
     * @param uid   uid of the TaskFragment organizer.
     */
    boolean isAllowedToEmbedActivityInTrustedMode(@NonNull ActivityRecord a, int uid) {
        if (isFullyTrustedEmbedding(a, uid)) {
            return true;
        }

        Set<String> knownActivityEmbeddingCerts = a.info.getKnownActivityEmbeddingCerts();
        if (knownActivityEmbeddingCerts.isEmpty()) {
            // An application must either declare that it allows untrusted embedding, or specify
            // a set of app certificates that are allowed to embed it in trusted mode.
            return false;
        }

        AndroidPackage hostPackage = mAtmService.getPackageManagerInternalLocked()
                .getPackage(uid);

        return hostPackage != null && hostPackage.getSigningDetails().hasAncestorOrSelfWithDigest(
                knownActivityEmbeddingCerts);
    }

    /**
     * It is fully trusted for embedding in the system app or embedding in the same app. This is
     * different from {@link #isAllowedToBeEmbeddedInTrustedMode()} since there may be a small
     * chance for a previous trusted app to start doing something bad.
     */
    private static boolean isFullyTrustedEmbedding(@NonNull ActivityRecord a, int uid) {
        // The system is trusted to embed other apps securely and for all users.
        return UserHandle.getAppId(uid) == SYSTEM_UID
                // Activities from the same UID can be embedded freely by the host.
                || a.isUid(uid);
    }

    /**
     * Checks if all activities in the task fragment are embedded as fully trusted.
     * @see #isFullyTrustedEmbedding(ActivityRecord, int)
     * @param uid   uid of the TaskFragment organizer.
     */
    boolean isFullyTrustedEmbedding(int uid) {
        // Traverse all activities to see if any of them are not fully trusted embedding.
        return !forAllActivities(r -> !isFullyTrustedEmbedding(r, uid));
    }

    /**
     * Checks if all activities in the task fragment are allowed to be embedded in trusted mode.
     * @see #isAllowedToEmbedActivityInTrustedMode(ActivityRecord)
     */
    boolean isAllowedToBeEmbeddedInTrustedMode() {
        // Traverse all activities to see if any of them are not in the trusted mode.
        return !forAllActivities(r -> !isAllowedToEmbedActivityInTrustedMode(r));
    }

    /**
     * Returns the TaskFragment that is being organized, which could be this or the ascendant
     * TaskFragment.
     */
    @Nullable
    TaskFragment getOrganizedTaskFragment() {
        if (mTaskFragmentOrganizer != null) {
            return this;
        }

        TaskFragment parentTaskFragment = getParent() != null ? getParent().asTaskFragment() : null;
        return parentTaskFragment != null ? parentTaskFragment.getOrganizedTaskFragment() : null;
    }

    /**
     * Simply check and give warning logs if this is not operated on leaf {@link TaskFragment}.
     */
    private void warnForNonLeafTaskFragment(String func) {
        if (!isLeafTaskFragment()) {
            Slog.w(TAG, func + " on non-leaf task fragment " + this);
        }
    }

    boolean hasDirectChildActivities() {
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            if (mChildren.get(i).asActivityRecord() != null) {
                return true;
            }
        }
        return false;
    }

    void cleanUpActivityReferences(@NonNull ActivityRecord r) {
        if (mPausingActivity != null && mPausingActivity == r) {
            mPausingActivity = null;
        }

        if (mResumedActivity != null && mResumedActivity == r) {
            setResumedActivity(null, "cleanUpActivityReferences");
        }
        r.removeTimeouts();
    }

    /**
     * Returns whether this TaskFragment is currently forced to be hidden for any reason.
     */
    protected boolean isForceHidden() {
        return mForceHiddenFlags != 0;
    }

    /**
     * Sets/unsets the forced-hidden state flag for this task depending on {@param set}.
     * @return Whether the force hidden state changed
     */
    boolean setForceHidden(@FlagForceHidden int flags, boolean set) {
        int newFlags = mForceHiddenFlags;
        if (set) {
            newFlags |= flags;
        } else {
            newFlags &= ~flags;
        }
        if (mForceHiddenFlags == newFlags) {
            return false;
        }
        mForceHiddenFlags = newFlags;
        return true;
    }

    boolean isForceTranslucent() {
        return mForceTranslucent;
    }

    void setForceTranslucent(boolean set) {
        mForceTranslucent = set;
    }

    boolean isLeafTaskFragment() {
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            if (mChildren.get(i).asTaskFragment() != null) {
                return false;
            }
        }
        return true;
    }

    /**
     * This should be called when an child activity changes state. This should only
     * be called from
     * {@link ActivityRecord#setState(ActivityRecord.State, String)} .
     * @param record The {@link ActivityRecord} whose state has changed.
     * @param state The new state.
     * @param reason The reason for the change.
     */
    void onActivityStateChanged(ActivityRecord record, ActivityRecord.State state,
            String reason) {
        warnForNonLeafTaskFragment("onActivityStateChanged");
        if (record == mResumedActivity && state != RESUMED) {
            setResumedActivity(null, reason + " - onActivityStateChanged");
        }

        if (state == RESUMED) {
            if (ActivityTaskManagerDebugConfig.DEBUG_ROOT_TASK) {
                Slog.v(TAG, "set resumed activity to:" + record + " reason:" + reason);
            }
            setResumedActivity(record, reason + " - onActivityStateChanged");
            mTaskSupervisor.mRecentTasks.add(record.getTask());
        }

        // Update the process state for the organizer process if the activity is in a different
        // process in case the organizer process may not have activity state change in its process.
        final WindowProcessController hostProcess = getOrganizerProcessIfDifferent(record);
        if (hostProcess != null) {
            mTaskSupervisor.onProcessActivityStateChanged(hostProcess, false /* forceBatch */);
            hostProcess.updateProcessInfo(false /* updateServiceConnectionActivities */,
                    true /* activityChange */, true /* updateOomAdj */,
                    false /* addPendingTopUid */);
        }
    }

    /**
     * Resets local parameters because an app's activity died.
     * @param app The app of the activity that died.
     * @return {@code true} if the process of the pausing activity is died.
     */
    boolean handleAppDied(WindowProcessController app) {
        warnForNonLeafTaskFragment("handleAppDied");
        boolean isPausingDied = false;
        if (mPausingActivity != null && mPausingActivity.app == app) {
            ProtoLog.v(WM_DEBUG_STATES, "App died while pausing: %s",
                    mPausingActivity);
            mPausingActivity = null;
            isPausingDied = true;
        }
        if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
            mLastPausedActivity = null;
        }
        return isPausingDied;
    }

    void awakeFromSleeping() {
        if (mPausingActivity != null) {
            Slog.d(TAG, "awakeFromSleeping: previously pausing activity didn't pause");
            mPausingActivity.activityPaused(true);
        }
    }

    /**
     * Tries to put the activities in the task fragment to sleep.
     *
     * If the task fragment is not in a state where its activities can be put to sleep, this
     * function will start any necessary actions to move the task fragment into such a state.
     * It is expected that this function get called again when those actions complete.
     *
     * @param shuttingDown {@code true} when the called because the device is shutting down.
     * @return true if the root task finished going to sleep, false if the root task only started
     * the process of going to sleep (checkReadyForSleep will be called when that process finishes).
     */
    boolean sleepIfPossible(boolean shuttingDown) {
        boolean shouldSleep = true;
        if (mResumedActivity != null) {
            // Still have something resumed; can't sleep until it is paused.
            ProtoLog.v(WM_DEBUG_STATES, "Sleep needs to pause %s", mResumedActivity);
            startPausing(false /* userLeaving */, true /* uiSleeping */, null /* resuming */,
                    "sleep");
            shouldSleep = false;
        } else if (mPausingActivity != null) {
            // Still waiting for something to pause; can't sleep yet.
            ProtoLog.v(WM_DEBUG_STATES, "Sleep still waiting to pause %s", mPausingActivity);
            shouldSleep = false;
        }

        if (!shuttingDown) {
            if (containsStoppingActivity()) {
                // Still need to tell some activities to stop; can't sleep yet.
                ProtoLog.v(WM_DEBUG_STATES, "Sleep still need to stop %d activities",
                        mTaskSupervisor.mStoppingActivities.size());

                mTaskSupervisor.scheduleIdle();
                shouldSleep = false;
            }
        }

        if (shouldSleep) {
            updateActivityVisibilities(null /* starting */, 0 /* configChanges */,
                    !PRESERVE_WINDOWS, true /* notifyClients */);
        }

        return shouldSleep;
    }

    private boolean containsStoppingActivity() {
        for (int i = mTaskSupervisor.mStoppingActivities.size() - 1; i >= 0; --i) {
            ActivityRecord r = mTaskSupervisor.mStoppingActivities.get(i);
            if (r.getTaskFragment() == this) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns true if the TaskFragment is translucent and can have other contents visible behind
     * it if needed. A TaskFragment is considered translucent if it don't contain a visible or
     * starting (about to be visible) activity that is fullscreen (opaque).
     * @param starting The currently starting activity or null if there is none.
     */
    boolean isTranslucent(@Nullable ActivityRecord starting) {
        if (!isAttached() || isForceHidden() || isForceTranslucent()) {
            return true;
        }
        // A TaskFragment isn't translucent if it has at least one visible activity that occludes
        // this TaskFragment.
        return mTaskSupervisor.mOpaqueActivityHelper.getVisibleOpaqueActivity(this,
                starting, true /* ignoringKeyguard */) == null;
    }

    /**
     * Whether the TaskFragment should be treated as translucent for the current transition.
     * This is different from {@link #isTranslucent(ActivityRecord)} as this function also checks
     * finishing activities when the TaskFragment itself is becoming invisible.
     */
    boolean isTranslucentForTransition() {
        if (!isAttached() || isForceHidden() || isForceTranslucent()) {
            return true;
        }
        // Including finishing Activity if the TaskFragment is becoming invisible in the transition.
        return mTaskSupervisor.mOpaqueActivityHelper.getOpaqueActivity(this,
                true /* ignoringKeyguard */) == null;
    }

    /**
     * Like {@link  #isTranslucent(ActivityRecord)} but evaluating the actual visibility of the
     * windows rather than their visibility ignoring keyguard.
     */
    boolean isTranslucentAndVisible() {
        if (!isAttached() || isForceHidden() || isForceTranslucent()) {
            return true;
        }
        return mTaskSupervisor.mOpaqueActivityHelper.getVisibleOpaqueActivity(this, null,
                false /* ignoringKeyguard */) == null;
    }

    ActivityRecord getTopNonFinishingActivity() {
        return getTopNonFinishingActivity(true /* includeOverlays */);
    }

    /**
     * Returns the top-most non-finishing activity, even if the activity is NOT ok to show to
     * the current user.
     * @param includeOverlays whether the task overlay activity should be included.
     * @see #topRunningActivity(boolean)
     */
    ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) {
        // Split into 2 to avoid object creation due to variable capture.
        if (includeOverlays) {
            return getActivity((r) -> !r.finishing);
        }
        return getActivity((r) -> !r.finishing && !r.isTaskOverlay());
    }

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

    /**
     * Returns the top-most running activity, which the activity is non-finishing and ok to show
     * to the current user.
     *
     * @see ActivityRecord#canBeTopRunning()
     */
    ActivityRecord topRunningActivity(boolean focusableOnly) {
        // Split into 2 to avoid object creation due to variable capture.
        if (focusableOnly) {
            return getActivity((r) -> r.canBeTopRunning() && r.isFocusable());
        }
        return getActivity(ActivityRecord::canBeTopRunning);
    }

    /**
     * Reports non-finishing activity count including this TaskFragment's child embedded
     * TaskFragments' children activities.
     */
    int getNonFinishingActivityCount() {
        final int[] runningActivityCount = new int[1];
        forAllActivities(a -> {
            if (!a.finishing) {
                runningActivityCount[0]++;
            }
        });
        return runningActivityCount[0];
    }

    /**
     * Returns {@code true} if there's any non-finishing direct children activity, which is not
     * embedded in TaskFragments
     */
    boolean hasNonFinishingDirectActivity() {
        for (int i = getChildCount() - 1; i >= 0; --i) {
            final ActivityRecord activity = getChildAt(i).asActivityRecord();
            if (activity != null && !activity.finishing) {
                return true;
            }
        }
        return false;
    }

    boolean isTopActivityFocusable() {
        final ActivityRecord r = topRunningActivity();
        return r != null ? r.isFocusable()
                : (isFocusable() && getWindowConfiguration().canReceiveKeys());
    }

    /**
     * Returns the visibility state of this TaskFragment.
     *
     * @param starting The currently starting activity or null if there is none.
     */
    @TaskFragmentVisibility
    int getVisibility(ActivityRecord starting) {
        if (!isAttached() || isForceHidden()) {
            return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
        }

        if (isTopActivityLaunchedBehind()) {
            return TASK_FRAGMENT_VISIBILITY_VISIBLE;
        }
        final WindowContainer<?> parent = getParent();
        final Task thisTask = asTask();
        if (thisTask != null && parent.asTask() == null
                && mTransitionController.isTransientVisible(thisTask)) {
            // Keep transient-hide root tasks visible. Non-root tasks still follow standard rule.
            return TASK_FRAGMENT_VISIBILITY_VISIBLE;
        }

        boolean gotTranslucentFullscreen = false;
        boolean gotTranslucentAdjacent = false;
        boolean shouldBeVisible = true;

        // This TaskFragment is only considered visible if all its parent TaskFragments are
        // considered visible, so check the visibility of all ancestor TaskFragment first.
        if (parent.asTaskFragment() != null) {
            final int parentVisibility = parent.asTaskFragment().getVisibility(starting);
            if (parentVisibility == TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
                // Can't be visible if parent isn't visible
                return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
            } else if (parentVisibility == TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT) {
                // Parent is behind a translucent container so the highest visibility this container
                // can get is that.
                gotTranslucentFullscreen = true;
            }
        }

        final List<TaskFragment> adjacentTaskFragments = new ArrayList<>();
        for (int i = parent.getChildCount() - 1; i >= 0; --i) {
            final WindowContainer other = parent.getChildAt(i);
            if (other == null) continue;

            final boolean hasRunningActivities = hasRunningActivity(other);
            if (other == this) {
                if (!adjacentTaskFragments.isEmpty() && !gotTranslucentAdjacent) {
                    // The z-order of this TaskFragment is in middle of two adjacent TaskFragments
                    // and it cannot be visible if the TaskFragment on top is not translucent and
                    // is occluding this one.
                    mTmpRect.set(getBounds());
                    for (int j = adjacentTaskFragments.size() - 1; j >= 0; --j) {
                        final TaskFragment taskFragment = adjacentTaskFragments.get(j);
                        final TaskFragment adjacentTaskFragment =
                                taskFragment.mAdjacentTaskFragment;
                        if (adjacentTaskFragment == this) {
                            continue;
                        }
                        if (mTmpRect.intersect(taskFragment.getBounds())
                                || mTmpRect.intersect(adjacentTaskFragment.getBounds())) {
                            return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
                        }
                    }
                }
                // Should be visible if there is no other fragment occluding it, unless it doesn't
                // have any running activities, not starting one and not home stack.
                shouldBeVisible = hasRunningActivities
                        || (starting != null && starting.isDescendantOf(this))
                        || isActivityTypeHome();
                break;
            }

            if (!hasRunningActivities) {
                continue;
            }

            final int otherWindowingMode = other.getWindowingMode();
            if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN
                    || (otherWindowingMode != WINDOWING_MODE_PINNED && other.matchParentBounds())) {
                if (isTranslucent(other, starting)) {
                    // Can be visible behind a translucent TaskFragment.
                    gotTranslucentFullscreen = true;
                    continue;
                }
                return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
            }

            final TaskFragment otherTaskFrag = other.asTaskFragment();
            if (otherTaskFrag != null && otherTaskFrag.mAdjacentTaskFragment != null) {
                if (adjacentTaskFragments.contains(otherTaskFrag.mAdjacentTaskFragment)) {
                    if (otherTaskFrag.isTranslucent(starting)
                            || otherTaskFrag.mAdjacentTaskFragment.isTranslucent(starting)) {
                        // Can be visible behind a translucent adjacent TaskFragments.
                        gotTranslucentFullscreen = true;
                        gotTranslucentAdjacent = true;
                        continue;
                    }
                    // Can not be visible behind adjacent TaskFragments.
                    return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
                } else {
                    adjacentTaskFragments.add(otherTaskFrag);
                }
            }

        }

        if (!shouldBeVisible) {
            return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
        }

        // Lastly - check if there is a translucent fullscreen TaskFragment on top.
        return gotTranslucentFullscreen
                ? TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT
                : TASK_FRAGMENT_VISIBILITY_VISIBLE;
    }

    private static boolean hasRunningActivity(WindowContainer wc) {
        if (wc.asTaskFragment() != null) {
            return wc.asTaskFragment().topRunningActivity() != null;
        }
        return wc.asActivityRecord() != null && !wc.asActivityRecord().finishing;
    }

    private static boolean isTranslucent(WindowContainer wc, ActivityRecord starting) {
        if (wc.asTaskFragment() != null) {
            return wc.asTaskFragment().isTranslucent(starting);
        } else if (wc.asActivityRecord() != null) {
            return !wc.asActivityRecord().occludesParent();
        }
        return false;
    }


    private boolean isTopActivityLaunchedBehind() {
        final ActivityRecord top = topRunningActivity();
        return top != null && top.mLaunchTaskBehind;
    }

    final void updateActivityVisibilities(@Nullable ActivityRecord starting, int configChanges,
            boolean preserveWindows, boolean notifyClients) {
        mTaskSupervisor.beginActivityVisibilityUpdate();
        try {
            mEnsureActivitiesVisibleHelper.process(
                    starting, configChanges, preserveWindows, notifyClients);
        } finally {
            mTaskSupervisor.endActivityVisibilityUpdate();
        }
    }

    final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
            boolean skipPause) {
        ActivityRecord next = topRunningActivity(true /* focusableOnly */);
        if (next == null || !next.canResumeByCompat()) {
            return false;
        }

        next.delayedResume = false;

        if (!skipPause && !mRootWindowContainer.allPausedActivitiesComplete()) {
            // If we aren't skipping pause, then we have to wait for currently pausing activities.
            ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: Skip resume: some activity pausing.");
            return false;
        }

        final TaskDisplayArea taskDisplayArea = getDisplayArea();
        // If the top activity is the resumed one, nothing to do.
        if (mResumedActivity == next && next.isState(RESUMED)
                && taskDisplayArea.allResumedActivitiesComplete()) {
            // Ensure the visibility gets updated before execute app transition.
            taskDisplayArea.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
                    false /* preserveWindows */, true /* notifyClients */);
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            executeAppTransition(options);

            // In a multi-resumed environment, like in a freeform device, the top
            // activity can be resumed, but it might not be the focused app.
            // Set focused app when top activity is resumed. However, we shouldn't do it for a
            // same task because it can break focused state. (e.g. activity embedding)
            if (taskDisplayArea.inMultiWindowMode() && taskDisplayArea.mDisplayContent != null) {
                final ActivityRecord focusedApp = taskDisplayArea.mDisplayContent.mFocusedApp;
                if (focusedApp == null || focusedApp.getTask() != next.getTask()) {
                    taskDisplayArea.mDisplayContent.setFocusedApp(next);
                }
            }
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity "
                    + "resumed %s", next);
            return false;
        }

        // If we are sleeping, and there is no resumed activity, and the top activity is paused,
        // well that is the state we want.
        if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            executeAppTransition(options);
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Going to sleep and"
                    + " all paused");
            return false;
        }

        // Make sure that the user who owns this activity is started.  If not,
        // we will just leave it as is because someone should be bringing
        // another user's activities to the top of the stack.
        if (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) {
            Slog.w(TAG, "Skipping resume of top activity " + next
                    + ": user " + next.mUserId + " is stopped");
            return false;
        }

        // The activity may be waiting for stop, but that is no longer
        // appropriate for it.
        mTaskSupervisor.mStoppingActivities.remove(next);

        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);

        mTaskSupervisor.setLaunchSource(next.info.applicationInfo.uid);

        ActivityRecord lastResumed = null;
        final Task lastFocusedRootTask = taskDisplayArea.getLastFocusedRootTask();
        if (lastFocusedRootTask != null && lastFocusedRootTask != getRootTaskFragment().asTask()) {
            // So, why aren't we using prev here??? See the param comment on the method. prev
            // doesn't represent the last resumed activity. However, the last focus stack does if
            // it isn't null.
            lastResumed = lastFocusedRootTask.getTopResumedActivity();
        }

        boolean pausing = !skipPause && taskDisplayArea.pauseBackTasks(next);
        if (mResumedActivity != null) {
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Pausing %s", mResumedActivity);
            pausing |= startPausing(mTaskSupervisor.mUserLeaving, false /* uiSleeping */,
                    next, "resumeTopActivity");
        }
        if (pausing) {
            ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: Skip resume: need to"
                    + " start pausing");
            // At this point we want to put the upcoming activity's process
            // at the top of the LRU list, since we know we will be needing it
            // very soon and it would be a waste to let it get killed if it
            // happens to be sitting towards the end.
            if (next.attachedToProcess()) {
                next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
                        true /* activityChange */, false /* updateOomAdj */,
                        false /* addPendingTopUid */);
            } else if (!next.isProcessRunning()) {
                // Since the start-process is asynchronous, if we already know the process of next
                // activity isn't running, we can start the process earlier to save the time to wait
                // for the current activity to be paused.
                final boolean isTop = this == taskDisplayArea.getFocusedRootTask();
                mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
                        isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY
                                : HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);
            }
            if (lastResumed != null) {
                lastResumed.setWillCloseOrEnterPip(true);
            }
            return true;
        } else if (mResumedActivity == next && next.isState(RESUMED)
                && taskDisplayArea.allResumedActivitiesComplete()) {
            // It is possible for the activity to be resumed when we paused back stacks above if the
            // next activity doesn't have to wait for pause to complete.
            // So, nothing else to-do except:
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            executeAppTransition(options);
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity resumed "
                    + "(dontWaitForPause) %s", next);
            return true;
        }

        // If the most recent activity was noHistory but was only stopped rather
        // than stopped+finished because the device went to sleep, we need to make
        // sure to finish it as we're making a new activity topmost.
        if (shouldSleepActivities()) {
            mTaskSupervisor.finishNoHistoryActivitiesIfNeeded(next);
        }

        if (prev != null && prev != next && next.nowVisible) {
            // The next activity is already visible, so hide the previous
            // activity's windows right now so we can show the new one ASAP.
            // We only do this if the previous is finishing, which should mean
            // it is on top of the one being resumed so hiding it quickly
            // is good.  Otherwise, we want to do the normal route of allowing
            // the resumed activity to be shown so we can decide if the
            // previous should actually be hidden depending on whether the
            // new one is found to be full-screen or not.
            if (prev.finishing) {
                prev.setVisibility(false);
                if (DEBUG_SWITCH) {
                    Slog.v(TAG_SWITCH, "Not waiting for visible to hide: " + prev
                            + ", nowVisible=" + next.nowVisible);
                }
            } else {
                if (DEBUG_SWITCH) {
                    Slog.v(TAG_SWITCH, "Previous already visible but still waiting to hide: " + prev
                            + ", nowVisible=" + next.nowVisible);
                }
            }
        }

        try {
            mTaskSupervisor.getActivityMetricsLogger()
                    .notifyBeforePackageUnstopped(next.packageName);
            mAtmService.getPackageManagerInternalLocked().notifyComponentUsed(
                    next.packageName, next.mUserId,
                    next.packageName, next.toString()); /* TODO: Verify if correct userid */
        } catch (IllegalArgumentException e) {
            Slog.w(TAG, "Failed trying to unstop package "
                    + next.packageName + ": " + e);
        }

        // We are starting up the next activity, so tell the window manager
        // that the previous one will be hidden soon.  This way it can know
        // to ignore it when computing the desired screen orientation.
        boolean anim = true;
        final DisplayContent dc = taskDisplayArea.mDisplayContent;
        if (prev != null) {
            if (prev.finishing) {
                if (DEBUG_TRANSITION) {
                    Slog.v(TAG_TRANSITION, "Prepare close transition: prev=" + prev);
                }
                if (mTaskSupervisor.mNoAnimActivities.contains(prev)) {
                    anim = false;
                    dc.prepareAppTransition(TRANSIT_NONE);
                } else {
                    dc.prepareAppTransition(TRANSIT_CLOSE);
                }
                prev.setVisibility(false);
            } else {
                if (DEBUG_TRANSITION) {
                    Slog.v(TAG_TRANSITION, "Prepare open transition: prev=" + prev);
                }
                if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
                    anim = false;
                    dc.prepareAppTransition(TRANSIT_NONE);
                } else {
                    dc.prepareAppTransition(TRANSIT_OPEN,
                            next.mLaunchTaskBehind ? TRANSIT_FLAG_OPEN_BEHIND : 0);
                }
            }
        } else {
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
            if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
                anim = false;
                dc.prepareAppTransition(TRANSIT_NONE);
            } else {
                dc.prepareAppTransition(TRANSIT_OPEN);
            }
        }

        if (anim) {
            next.applyOptionsAnimation();
        } else {
            next.abortAndClearOptionsAnimation();
        }

        mTaskSupervisor.mNoAnimActivities.clear();

        if (next.attachedToProcess()) {
            if (DEBUG_SWITCH) {
                Slog.v(TAG_SWITCH, "Resume running: " + next + " stopped=" + next.mAppStopped
                        + " visibleRequested=" + next.isVisibleRequested());
            }

            // If the previous activity is translucent, force a visibility update of
            // the next activity, so that it's added to WM's opening app list, and
            // transition animation can be set up properly.
            // For example, pressing Home button with a translucent activity in focus.
            // Launcher is already visible in this case. If we don't add it to opening
            // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
            // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
            final boolean lastActivityTranslucent = inMultiWindowMode()
                    || mLastPausedActivity != null && !mLastPausedActivity.occludesParent();

            // This activity is now becoming visible.
            if (!next.isVisibleRequested() || next.mAppStopped || lastActivityTranslucent) {
                next.app.addToPendingTop();
                next.setVisibility(true);
            }

            // schedule launch ticks to collect information about slow apps.
            next.startLaunchTickingLocked();

            ActivityRecord lastResumedActivity =
                    lastFocusedRootTask == null ? null
                            : lastFocusedRootTask.getTopResumedActivity();
            final ActivityRecord.State lastState = next.getState();

            mAtmService.updateCpuStats();

            ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (in existing)", next);

            next.setState(RESUMED, "resumeTopActivity");

            // Have the window manager re-evaluate the orientation of
            // the screen based on the new activity order.
            boolean notUpdated = true;

            // Activity should also be visible if set mLaunchTaskBehind to true (see
            // ActivityRecord#shouldBeVisibleIgnoringKeyguard()).
            if (shouldBeVisible(next)) {
                // We have special rotation behavior when here is some active activity that
                // requests specific orientation or Keyguard is locked. Make sure all activity
                // visibilities are set correctly as well as the transition is updated if needed
                // to get the correct rotation behavior. Otherwise the following call to update
                // the orientation may cause incorrect configurations delivered to client as a
                // result of invisible window resize.
                // TODO: Remove this once visibilities are set correctly immediately when
                // starting an activity.
                notUpdated = !mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),
                        false /* deferResume */);
            }

            if (notUpdated) {
                // The configuration update wasn't able to keep the existing
                // instance of the activity, and instead started a new one.
                // We should be all done, but let's just make sure our activity
                // is still at the top and schedule another run if something
                // weird happened.
                ActivityRecord nextNext = topRunningActivity();
                ProtoLog.i(WM_DEBUG_STATES, "Activity config changed during resume: "
                        + "%s, new next: %s", next, nextNext);
                if (nextNext != next) {
                    // Do over!
                    mTaskSupervisor.scheduleResumeTopActivities();
                }
                if (!next.isVisibleRequested() || next.mAppStopped) {
                    next.setVisibility(true);
                }
                next.completeResumeLocked();
                return true;
            }

            try {
                final IApplicationThread appThread = next.app.getThread();
                final ClientTransaction transaction = Flags.bundleClientTransactionFlag()
                        ? null
                        : ClientTransaction.obtain(appThread);
                // Deliver all pending results.
                final ArrayList<ResultInfo> a = next.results;
                if (a != null) {
                    final int size = a.size();
                    if (!next.finishing && size > 0) {
                        if (DEBUG_RESULTS) {
                            Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a);
                        }
                        final ActivityResultItem activityResultItem = ActivityResultItem.obtain(
                                next.token, a);
                        if (transaction == null) {
                            mAtmService.getLifecycleManager().scheduleTransactionItem(
                                    appThread, activityResultItem);
                        } else {
                            transaction.addCallback(activityResultItem);
                        }
                    }
                }

                if (next.newIntents != null) {
                    final NewIntentItem newIntentItem = NewIntentItem.obtain(
                            next.token, next.newIntents, true /* resume */);
                    if (transaction == null) {
                        mAtmService.getLifecycleManager().scheduleTransactionItem(
                                appThread, newIntentItem);
                    } else {
                        transaction.addCallback(newIntentItem);
                    }
                }

                // Well the app will no longer be stopped.
                // Clear app token stopped state in window manager if needed.
                next.notifyAppResumed();

                EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),
                        next.getTask().mTaskId, next.shortComponentName);

                mAtmService.getAppWarningsLocked().onResumeActivity(next);
                final int topProcessState = mAtmService.mTopProcessState;
                next.app.setPendingUiCleanAndForceProcessStateUpTo(topProcessState);
                next.abortAndClearOptionsAnimation();
                final ResumeActivityItem resumeActivityItem = ResumeActivityItem.obtain(
                        next.token, topProcessState, dc.isNextTransitionForward(),
                        next.shouldSendCompatFakeFocus());
                if (transaction == null) {
                    mAtmService.getLifecycleManager().scheduleTransactionItem(
                            appThread, resumeActivityItem);
                } else {
                    transaction.setLifecycleStateRequest(resumeActivityItem);
                    mAtmService.getLifecycleManager().scheduleTransaction(transaction);
                }

                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Resumed %s", next);
            } catch (Exception e) {
                // Whoops, need to restart this activity!
                ProtoLog.v(WM_DEBUG_STATES, "Resume failed; resetting state to %s: "
                        + "%s", lastState, next);
                next.setState(lastState, "resumeTopActivityInnerLocked");

                // lastResumedActivity being non-null implies there is a lastStack present.
                if (lastResumedActivity != null) {
                    lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
                }

                Slog.i(TAG, "Restarting because process died: " + next);
                if (!next.hasBeenLaunched) {
                    next.hasBeenLaunched = true;
                } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedRootTask != null
                        && lastFocusedRootTask.isTopRootTaskInDisplayArea()) {
                    next.showStartingWindow(false /* taskSwitch */);
                }
                mTaskSupervisor.startSpecificActivity(next, true, false);
                return true;
            }

            // From this point on, if something goes wrong there is no way
            // to recover the activity.
            try {
                next.completeResumeLocked();
            } catch (Exception e) {
                // If any exception gets thrown, toss away this
                // activity and try the next one.
                Slog.w(TAG, "Exception thrown during resume of " + next, e);
                next.finishIfPossible("resume-exception", true /* oomAdj */);
                return true;
            }
        } else {
            // Whoops, need to restart this activity!
            if (!next.hasBeenLaunched) {
                next.hasBeenLaunched = true;
            } else {
                if (SHOW_APP_STARTING_PREVIEW) {
                    next.showStartingWindow(false /* taskSwich */);
                }
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
            }
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Restarting %s", next);
            mTaskSupervisor.startSpecificActivity(next, true, true);
        }

        return true;
    }

    boolean shouldSleepOrShutDownActivities() {
        return shouldSleepActivities() || mAtmService.mShuttingDown;
    }

    /**
     * Returns true if the TaskFragment should be visible.
     *
     * @param starting The currently starting activity or null if there is none.
     */
    boolean shouldBeVisible(ActivityRecord starting) {
        return getVisibility(starting) != TASK_FRAGMENT_VISIBILITY_INVISIBLE;
    }

    /**
     * Returns {@code true} is the activity in this TaskFragment can be resumed.
     *
     * @param starting The currently starting activity or {@code null} if there is none.
     */
    boolean canBeResumed(@Nullable ActivityRecord starting) {
        // No need to resume activity in TaskFragment that is not visible.
        return isTopActivityFocusable()
                && getVisibility(starting) == TASK_FRAGMENT_VISIBILITY_VISIBLE;
    }

    boolean isFocusableAndVisible() {
        return isTopActivityFocusable() && shouldBeVisible(null /* starting */);
    }

    final boolean startPausing(boolean uiSleeping, ActivityRecord resuming, String reason) {
        return startPausing(mTaskSupervisor.mUserLeaving, uiSleeping, resuming, reason);
    }

    /**
     * Start pausing the currently resumed activity.  It is an error to call this if there
     * is already an activity being paused or there is no resumed activity.
     *
     * @param userLeaving True if this should result in an onUserLeaving to the current activity.
     * @param uiSleeping True if this is happening with the user interface going to sleep (the
     * screen turning off).
     * @param resuming The activity we are currently trying to resume or null if this is not being
     *                 called as part of resuming the top activity, so we shouldn't try to instigate
     *                 a resume here if not null.
     * @param reason The reason of pausing the activity.
     * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
     * it to tell us when it is done.
     */
    boolean startPausing(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming,
            String reason) {
        if (!hasDirectChildActivities()) {
            return false;
        }

        ProtoLog.d(WM_DEBUG_STATES, "startPausing: taskFrag =%s " + "mResumedActivity=%s", this,
                mResumedActivity);

        if (mPausingActivity != null) {
            Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
                    + " state=" + mPausingActivity.getState());
            if (!shouldSleepActivities()) {
                // Avoid recursion among check for sleep and complete pause during sleeping.
                // Because activity will be paused immediately after resume, just let pause
                // be completed by the order of activity paused from clients.
                completePause(false, resuming);
            }
        }
        ActivityRecord prev = mResumedActivity;

        if (prev == null) {
            if (resuming == null) {
                Slog.wtf(TAG, "Trying to pause when nothing is resumed");
                mRootWindowContainer.resumeFocusedTasksTopActivities();
            }
            return false;
        }

        if (prev == resuming) {
            Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
            return false;
        }

        ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSING: %s", prev);
        mPausingActivity = prev;
        mLastPausedActivity = prev;
        if (!prev.finishing && prev.isNoHistory()
                && !mTaskSupervisor.mNoHistoryActivities.contains(prev)) {
            mTaskSupervisor.mNoHistoryActivities.add(prev);
        }
        prev.setState(PAUSING, "startPausingLocked");
        prev.getTask().touchActiveTime();

        mAtmService.updateCpuStats();

        boolean pauseImmediately = false;
        boolean shouldAutoPip = false;
        if (resuming != null) {
            // We do not want to trigger auto-PiP upon launch of a translucent activity.
            final boolean resumingOccludesParent = resuming.occludesParent();
            // Resuming the new resume activity only if the previous activity can't go into Pip
            // since we want to give Pip activities a chance to enter Pip before resuming the
            // next activity.
            final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState(
                    "shouldAutoPipWhilePausing", userLeaving);

            if (ActivityTaskManagerService.isPip2ExperimentEnabled()) {
                // If a new task is being launched, then mark the existing top activity as
                // supporting picture-in-picture while pausing only if the starting activity
                // would not be considered an overlay on top of the current activity
                // (eg. not fullscreen, or the assistant)
                Task.enableEnterPipOnTaskSwitch(prev, resuming.getTask(),
                        resuming, resuming.getOptions());
            }
            if (prev.supportsEnterPipOnTaskSwitch && userLeaving
                    && resumingOccludesParent && lastResumedCanPip
                    && prev.pictureInPictureArgs.isAutoEnterEnabled()) {
                shouldAutoPip = true;
            } else if (!lastResumedCanPip) {
                // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous
                // activity to be paused.
                pauseImmediately = (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
            } else {
                // The previous activity may still enter PIP even though it did not allow auto-PIP.
            }
        }

        if (prev.attachedToProcess()) {
            if (shouldAutoPip && ActivityTaskManagerService.isPip2ExperimentEnabled()) {
                prev.mPauseSchedulePendingForPip = true;
                boolean willAutoPip = mAtmService.prepareAutoEnterPictureAndPictureMode(prev);
                ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, requesting PIP mode "
                        + "via requestStartTransition(): %s, willAutoPip: %b", prev, willAutoPip);
            } else if (shouldAutoPip) {
                prev.mPauseSchedulePendingForPip = true;
                boolean didAutoPip = mAtmService.enterPictureInPictureMode(
                        prev, prev.pictureInPictureArgs, false /* fromClient */);
                ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode "
                        + "directly: %s, didAutoPip: %b", prev, didAutoPip);
            } else {
                schedulePauseActivity(prev, userLeaving, pauseImmediately,
                        false /* autoEnteringPip */, reason);
            }
        } else {
            mPausingActivity = null;
            mLastPausedActivity = null;
            mTaskSupervisor.mNoHistoryActivities.remove(prev);
        }

        // If we are not going to sleep, we want to ensure the device is
        // awake until the next activity is started.
        if (!uiSleeping && !mAtmService.isSleepingOrShuttingDownLocked()) {
            mTaskSupervisor.acquireLaunchWakelock();
        }

        // If already entered PIP mode, no need to keep pausing.
        if (mPausingActivity != null) {
            // Have the window manager pause its key dispatching until the new
            // activity has started.  If we're pausing the activity just because
            // the screen is being turned off and the UI is sleeping, don't interrupt
            // key dispatch; the same activity will pick it up again on wakeup.
            if (!uiSleeping) {
                prev.pauseKeyDispatchingLocked();
            } else {
                ProtoLog.v(WM_DEBUG_STATES, "Key dispatch not paused for screen off");
            }

            if (pauseImmediately) {
                // If the caller said they don't want to wait for the pause, then complete
                // the pause now.
                completePause(false, resuming);
                return false;

            } else {
                prev.schedulePauseTimeout();
                // All activities will be stopped when sleeping, don't need to wait for pause.
                if (!uiSleeping) {
                    // Unset readiness since we now need to wait until this pause is complete.
                    mTransitionController.setReady(this, false /* ready */);
                }
                return true;
            }

        } else {
            // This activity either failed to schedule the pause or it entered PIP mode,
            // so just treat it as being paused now.
            ProtoLog.v(WM_DEBUG_STATES, "Activity not running or entered PiP, resuming next.");
            if (resuming == null) {
                mRootWindowContainer.resumeFocusedTasksTopActivities();
            }
            return false;
        }
    }

    void schedulePauseActivity(ActivityRecord prev, boolean userLeaving,
            boolean pauseImmediately, boolean autoEnteringPip, String reason) {
        ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);
        try {
            prev.mPauseSchedulePendingForPip = false;
            EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
                    prev.shortComponentName, "userLeaving=" + userLeaving, reason);

            mAtmService.getLifecycleManager().scheduleTransactionItem(prev.app.getThread(),
                    PauseActivityItem.obtain(prev.token, prev.finishing, userLeaving,
                            prev.configChangeFlags, pauseImmediately, autoEnteringPip));
        } catch (Exception e) {
            // Ignore exception, if process died other code will cleanup.
            Slog.w(TAG, "Exception thrown during pause", e);
            mPausingActivity = null;
            mLastPausedActivity = null;
            mTaskSupervisor.mNoHistoryActivities.remove(prev);
        }
    }

    @VisibleForTesting
    void completePause(boolean resumeNext, ActivityRecord resuming) {
        // Complete the pausing process of a pausing activity, so it doesn't make sense to
        // operate on non-leaf tasks.
        // warnForNonLeafTask("completePauseLocked");

        ActivityRecord prev = mPausingActivity;
        ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev);

        if (prev != null) {
            prev.setWillCloseOrEnterPip(false);
            final boolean wasStopping = prev.isState(STOPPING);
            prev.setState(PAUSED, "completePausedLocked");
            if (prev.finishing) {
                // We will update the activity visibility later, no need to do in
                // completeFinishing(). Updating visibility here might also making the next
                // activities to be resumed, and could result in wrong app transition due to
                // lack of previous activity information.
                ProtoLog.v(WM_DEBUG_STATES, "Executing finish of activity: %s", prev);
                prev = prev.completeFinishing(false /* updateVisibility */,
                        "completePausedLocked");
            } else if (prev.attachedToProcess()) {
                ProtoLog.v(WM_DEBUG_STATES, "Enqueue pending stop if needed: %s "
                                + "wasStopping=%b visibleRequested=%b",  prev,  wasStopping,
                        prev.isVisibleRequested());
                if (prev.deferRelaunchUntilPaused) {
                    // Complete the deferred relaunch that was waiting for pause to complete.
                    ProtoLog.v(WM_DEBUG_STATES, "Re-launching after pause: %s", prev);
                    prev.relaunchActivityLocked(prev.preserveWindowOnDeferredRelaunch);
                } else if (wasStopping) {
                    // We are also stopping, the stop request must have gone soon after the pause.
                    // We can't clobber it, because the stop confirmation will not be handled.
                    // We don't need to schedule another stop, we only need to let it happen.
                    prev.setState(STOPPING, "completePausedLocked");
                } else if (!prev.isVisibleRequested() || shouldSleepOrShutDownActivities()) {
                    // Clear out any deferred client hide we might currently have.
                    prev.setDeferHidingClient(false);
                    // If we were visible then resumeTopActivities will release resources before
                    // stopping.
                    prev.addToStopping(true /* scheduleIdle */, false /* idleDelayed */,
                            "completePauseLocked");
                }
            } else {
                ProtoLog.v(WM_DEBUG_STATES, "App died during pause, not stopping: %s", prev);
                prev = null;
            }
            // It is possible the activity was freezing the screen before it was paused.
            // In that case go ahead and remove the freeze this activity has on the screen
            // since it is no longer visible.
            if (prev != null) {
                prev.stopFreezingScreen(true /* unfreezeNow */, true /* force */);
            }
            mPausingActivity = null;
        }

        if (resumeNext) {
            final Task topRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
            if (topRootTask != null && !topRootTask.shouldSleepOrShutDownActivities()) {
                mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev,
                        null /* targetOptions */);
            } else {
                // checkReadyForSleep();
                final ActivityRecord top =
                        topRootTask != null ? topRootTask.topRunningActivity() : null;
                if (top == null || (prev != null && top != prev)) {
                    // If there are no more activities available to run, do resume anyway to start
                    // something. Also if the top activity on the root task is not the just paused
                    // activity, we need to go ahead and resume it to ensure we complete an
                    // in-flight app switch.
                    mRootWindowContainer.resumeFocusedTasksTopActivities();
                }
            }
        }

        if (prev != null) {
            prev.resumeKeyDispatchingLocked();
        }

        mRootWindowContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);

        // Notify when the task stack has changed, but only if visibilities changed (not just
        // focus). Also if there is an active root pinned task - we always want to notify it about
        // task stack changes, because its positioning may depend on it.
        if (mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause
                || (getDisplayArea() != null && getDisplayArea().hasPinnedTask())) {
            mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
            mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
        }
    }

    @ActivityInfo.ScreenOrientation
    @Override
    int getOrientation(@ActivityInfo.ScreenOrientation int candidate) {
        if (shouldReportOrientationUnspecified()) {
            return SCREEN_ORIENTATION_UNSPECIFIED;
        }
        if (canSpecifyOrientation()) {
            return super.getOrientation(candidate);
        }
        return SCREEN_ORIENTATION_UNSET;
    }

    /**
     * Whether or not to allow this container to specify an app requested orientation.
     *
     * This is different from {@link #providesOrientation()} that
     * 1. The container may still provide an orientation even if it can't specify the app requested
     *    one, such as {@link #shouldReportOrientationUnspecified()}
     * 2. Even if the container can specify an app requested orientation, it may not be used by the
     *    parent container if it is {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}.
     */
    boolean canSpecifyOrientation() {
        final int windowingMode = getWindowingMode();
        final int activityType = getActivityType();
        return windowingMode == WINDOWING_MODE_FULLSCREEN
                || activityType == ACTIVITY_TYPE_HOME
                || activityType == ACTIVITY_TYPE_RECENTS
                || activityType == ACTIVITY_TYPE_ASSISTANT;
    }

    /**
     * Whether or not the parent container should use the orientation provided by this container
     * even if it is {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}.
     */
    @Override
    boolean providesOrientation() {
        return super.providesOrientation() || shouldReportOrientationUnspecified();
    }

    private boolean shouldReportOrientationUnspecified() {
        // Apps and their containers are not allowed to specify orientation from adjacent
        // TaskFragment.
        return getAdjacentTaskFragment() != null && isVisibleRequested();
    }

    @Override
    void forAllTaskFragments(Consumer<TaskFragment> callback, boolean traverseTopToBottom) {
        super.forAllTaskFragments(callback, traverseTopToBottom);
        callback.accept(this);
    }

    @Override
    void forAllLeafTaskFragments(Consumer<TaskFragment> callback, boolean traverseTopToBottom) {
        final int count = mChildren.size();
        boolean isLeafTaskFrag = true;
        if (traverseTopToBottom) {
            for (int i = count - 1; i >= 0; --i) {
                final TaskFragment child = mChildren.get(i).asTaskFragment();
                if (child != null) {
                    isLeafTaskFrag = false;
                    child.forAllLeafTaskFragments(callback, traverseTopToBottom);
                }
            }
        } else {
            for (int i = 0; i < count; i++) {
                final TaskFragment child = mChildren.get(i).asTaskFragment();
                if (child != null) {
                    isLeafTaskFrag = false;
                    child.forAllLeafTaskFragments(callback, traverseTopToBottom);
                }
            }
        }
        if (isLeafTaskFrag) callback.accept(this);
    }

    @Override
    boolean forAllLeafTaskFragments(Predicate<TaskFragment> callback) {
        boolean isLeafTaskFrag = true;
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            final TaskFragment child = mChildren.get(i).asTaskFragment();
            if (child != null) {
                isLeafTaskFrag = false;
                if (child.forAllLeafTaskFragments(callback)) {
                    return true;
                }
            }
        }
        if (isLeafTaskFrag) {
            return callback.test(this);
        }
        return false;
    }

    void addChild(ActivityRecord r) {
        addChild(r, POSITION_TOP);
    }

    @Override
    void addChild(WindowContainer child, int index) {
        ActivityRecord r = topRunningActivity();
        mClearedTaskForReuse = false;
        mClearedTaskFragmentForPip = false;
        mClearedForReorderActivityToFront = false;

        final ActivityRecord addingActivity = child.asActivityRecord();
        final boolean isAddingActivity = addingActivity != null;
        final Task task = isAddingActivity ? getTask() : null;

        // If this task had any activity before we added this one.
        boolean taskHadActivity = task != null && task.getTopMostActivity() != null;
        // getActivityType() looks at the top child, so we need to read the type before adding
        // a new child in case the new child is on top and UNDEFINED.
        final int activityType = task != null ? task.getActivityType() : ACTIVITY_TYPE_UNDEFINED;

        super.addChild(child, index);

        if (isAddingActivity && task != null) {
            // TODO(b/207481538): temporary per-activity screenshoting
            if (r != null && BackNavigationController.isScreenshotEnabled()) {
                ProtoLog.v(WM_DEBUG_BACK_PREVIEW, "Screenshotting Activity %s",
                        r.mActivityComponent.flattenToString());
                Rect outBounds = r.getBounds();
                ScreenCapture.ScreenshotHardwareBuffer backBuffer = ScreenCapture.captureLayers(
                        r.mSurfaceControl,
                        new Rect(0, 0, outBounds.width(), outBounds.height()),
                        1f);
                mBackScreenshots.put(r.mActivityComponent.flattenToString(), backBuffer);
            }
            addingActivity.inHistory = true;
            task.onDescendantActivityAdded(taskHadActivity, activityType, addingActivity);
        }

        final WindowProcessController hostProcess = getOrganizerProcessIfDifferent(addingActivity);
        if (hostProcess != null) {
            hostProcess.addEmbeddedActivity(addingActivity);
        }
    }

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

        sendTaskFragmentInfoChanged();
    }

    void executeAppTransition(ActivityOptions options) {
        // No app transition applied to the task fragment.
    }

    @Override
    RemoteAnimationTarget createRemoteAnimationTarget(
            RemoteAnimationController.RemoteAnimationRecord record) {
        final ActivityRecord activity = record.getMode() == RemoteAnimationTarget.MODE_OPENING
                // There may be a launching (e.g. trampoline or embedded) activity without a window
                // on top of the existing task which is moving to front. Exclude finishing activity
                // so the window of next activity can be chosen to create the animation target.
                ? getActivity(r -> !r.finishing && r.hasChild())
                : getTopMostActivity();
        return activity != null ? activity.createRemoteAnimationTarget(record) : null;
    }

    @Override
    boolean canCreateRemoteAnimationTarget() {
        return true;
    }

    boolean shouldSleepActivities() {
        final Task task = getRootTask();
        return task != null && task.shouldSleepActivities();
    }

    @Override
    void resolveOverrideConfiguration(Configuration newParentConfig) {
        mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
        super.resolveOverrideConfiguration(newParentConfig);
        final Configuration resolvedConfig = getResolvedOverrideConfiguration();

        if (mRelativeEmbeddedBounds != null && !mRelativeEmbeddedBounds.isEmpty()) {
            // For embedded TaskFragment, make sure the bounds is set based on the relative bounds.
            resolvedConfig.windowConfiguration.setBounds(translateRelativeBoundsToAbsoluteBounds(
                    mRelativeEmbeddedBounds, newParentConfig.windowConfiguration.getBounds()));
        }
        int windowingMode = resolvedConfig.windowConfiguration.getWindowingMode();
        final int parentWindowingMode = newParentConfig.windowConfiguration.getWindowingMode();

        // Resolve override windowing mode to fullscreen for home task (even on freeform
        // display), or split-screen if in split-screen mode.
        if (getActivityType() == ACTIVITY_TYPE_HOME && windowingMode == WINDOWING_MODE_UNDEFINED) {
            windowingMode = WINDOWING_MODE_FULLSCREEN;
            resolvedConfig.windowConfiguration.setWindowingMode(windowingMode);
        }

        // Do not allow tasks not support multi window to be in a multi-window mode, unless it is in
        // pinned windowing mode.
        if (!supportsMultiWindow()) {
            final int candidateWindowingMode =
                    windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : parentWindowingMode;
            if (WindowConfiguration.inMultiWindowMode(candidateWindowingMode)
                    && candidateWindowingMode != WINDOWING_MODE_PINNED) {
                resolvedConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
            }
        }

        final Task thisTask = asTask();
        if (thisTask != null) {
            thisTask.resolveLeafTaskOnlyOverrideConfigs(newParentConfig,
                    mTmpBounds /* previousBounds */);
        }
        computeConfigResourceOverrides(resolvedConfig, newParentConfig);
    }

    boolean supportsMultiWindow() {
        return supportsMultiWindowInDisplayArea(getDisplayArea());
    }

    /**
     * @return whether this task supports multi-window if it is in the given
     *         {@link TaskDisplayArea}.
     */
    boolean supportsMultiWindowInDisplayArea(@Nullable TaskDisplayArea tda) {
        if (!mAtmService.mSupportsMultiWindow) {
            return false;
        }
        if (tda == null) {
            return false;
        }
        final Task task = getTask();
        if (task == null) {
            return false;
        }
        if (!task.isResizeable() && !tda.supportsNonResizableMultiWindow()) {
            // Not support non-resizable in multi window.
            return false;
        }

        final ActivityRecord rootActivity = task.getRootActivity();
        return tda.supportsActivityMinWidthHeightMultiWindow(mMinWidth, mMinHeight,
                rootActivity != null ? rootActivity.info : null);
    }

    private int getTaskId() {
        return getTask() != null ? getTask().mTaskId : INVALID_TASK_ID;
    }

    void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
            @NonNull Configuration parentConfig) {
        computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
                null /* compatInsets */);
    }

    void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
            @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo) {
        if (overrideDisplayInfo != null) {
            // Make sure the screen related configs can be computed by the provided display info.
            inOutConfig.screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
            invalidateAppBoundsConfig(inOutConfig);
        }
        computeConfigResourceOverrides(inOutConfig, parentConfig, overrideDisplayInfo,
                null /* compatInsets */);
    }

    void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
            @NonNull Configuration parentConfig,
            @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
        if (compatInsets != null) {
            // Make sure the app bounds can be computed by the compat insets.
            invalidateAppBoundsConfig(inOutConfig);
        }
        computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
                compatInsets);
    }

    /**
     * Forces the app bounds related configuration can be computed by
     * {@link #computeConfigResourceOverrides(Configuration, Configuration, DisplayInfo,
     * ActivityRecord.CompatDisplayInsets)}.
     */
    private static void invalidateAppBoundsConfig(@NonNull Configuration inOutConfig) {
        final Rect appBounds = inOutConfig.windowConfiguration.getAppBounds();
        if (appBounds != null) {
            appBounds.setEmpty();
        }
        inOutConfig.screenWidthDp = Configuration.SCREEN_WIDTH_DP_UNDEFINED;
        inOutConfig.screenHeightDp = Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
    }

    /**
     * Calculates configuration values used by the client to get resources. This should be run
     * using app-facing bounds (bounds unmodified by animations or transient interactions).
     *
     * This assumes bounds are non-empty/null. For the null-bounds case, the caller is likely
     * configuring an "inherit-bounds" window which means that all configuration settings would
     * just be inherited from the parent configuration.
     **/
    void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
            @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo,
            @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
        int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
        if (windowingMode == WINDOWING_MODE_UNDEFINED) {
            windowingMode = parentConfig.windowConfiguration.getWindowingMode();
        }

        float density = inOutConfig.densityDpi;
        if (density == Configuration.DENSITY_DPI_UNDEFINED) {
            density = parentConfig.densityDpi;
        }
        density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;

        // The bounds may have been overridden at this level. If the parent cannot cover these
        // bounds, the configuration is still computed according to the override bounds.
        final boolean insideParentBounds;

        final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
        final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds();
        if (resolvedBounds.isEmpty()) {
            mTmpFullBounds.set(parentBounds);
            insideParentBounds = true;
        } else {
            mTmpFullBounds.set(resolvedBounds);
            insideParentBounds = parentBounds.contains(resolvedBounds);
        }

        // Non-null compatibility insets means the activity prefers to keep its original size, so
        // out bounds doesn't need to be restricted by the parent or current display
        final boolean customContainerPolicy = compatInsets != null;

        Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
        if (outAppBounds == null || outAppBounds.isEmpty()) {
            // App-bounds hasn't been overridden, so calculate a value for it.
            inOutConfig.windowConfiguration.setAppBounds(mTmpFullBounds);
            outAppBounds = inOutConfig.windowConfiguration.getAppBounds();

            if (!customContainerPolicy && windowingMode != WINDOWING_MODE_FREEFORM) {
                final Rect containingAppBounds;
                if (insideParentBounds) {
                    containingAppBounds = parentConfig.windowConfiguration.getAppBounds();
                } else {
                    // Restrict appBounds to display non-decor rather than parent because the
                    // override bounds are beyond the parent. Otherwise, it won't match the
                    // overridden bounds.
                    final TaskDisplayArea displayArea = getDisplayArea();
                    containingAppBounds = displayArea != null
                            ? displayArea.getWindowConfiguration().getAppBounds() : null;
                }
                if (containingAppBounds != null && !containingAppBounds.isEmpty()) {
                    outAppBounds.intersect(containingAppBounds);
                }
            }
        }

        if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
                || inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
            if (!customContainerPolicy && WindowConfiguration.isFloating(windowingMode)) {
                mTmpNonDecorBounds.set(mTmpFullBounds);
                mTmpStableBounds.set(mTmpFullBounds);
            } else if (!customContainerPolicy
                    && (overrideDisplayInfo != null || getDisplayContent() != null)) {
                final DisplayInfo di = overrideDisplayInfo != null
                        ? overrideDisplayInfo
                        : getDisplayContent().getDisplayInfo();

                // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
                // area, i.e. the screen area without the system bars.
                // The non decor inset are areas that could never be removed in Honeycomb. See
                // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
                calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, mTmpFullBounds, di);
            } else {
                // Apply the given non-decor and stable insets to calculate the corresponding bounds
                // for screen size of configuration.
                int rotation = inOutConfig.windowConfiguration.getRotation();
                if (rotation == ROTATION_UNDEFINED) {
                    rotation = parentConfig.windowConfiguration.getRotation();
                }
                if (rotation != ROTATION_UNDEFINED && customContainerPolicy) {
                    mTmpNonDecorBounds.set(mTmpFullBounds);
                    mTmpStableBounds.set(mTmpFullBounds);
                    compatInsets.getBoundsByRotation(mTmpBounds, rotation);
                    intersectWithInsetsIfFits(mTmpNonDecorBounds, mTmpBounds,
                            compatInsets.mNonDecorInsets[rotation]);
                    intersectWithInsetsIfFits(mTmpStableBounds, mTmpBounds,
                            compatInsets.mStableInsets[rotation]);
                    outAppBounds.set(mTmpNonDecorBounds);
                } else {
                    // Set to app bounds because it excludes decor insets.
                    mTmpNonDecorBounds.set(outAppBounds);
                    mTmpStableBounds.set(outAppBounds);
                }
            }

            if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
                final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density + 0.5f);
                inOutConfig.screenWidthDp = (insideParentBounds && !customContainerPolicy)
                        ? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp)
                        : overrideScreenWidthDp;
            }
            if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
                final int overrideScreenHeightDp =
                        (int) (mTmpStableBounds.height() / density + 0.5f);
                inOutConfig.screenHeightDp = (insideParentBounds && !customContainerPolicy)
                        ? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp)
                        : overrideScreenHeightDp;
            }

            // TODO(b/238331848): Consider simplifying logic that computes smallestScreenWidthDp.
            if (inOutConfig.smallestScreenWidthDp
                    == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
                // When entering to or exiting from Pip, the PipTaskOrganizer will set the
                // windowing mode of the activity in the task to WINDOWING_MODE_FULLSCREEN and
                // temporarily set the bounds of the task to fullscreen size for transitioning.
                // It will get the wrong value if the calculation is based on this temporary
                // fullscreen bounds.
                // We should just inherit the value from parent for this temporary state.
                final boolean inPipTransition = windowingMode == WINDOWING_MODE_PINNED
                        && !mTmpFullBounds.isEmpty() && mTmpFullBounds.equals(parentBounds);
                if (WindowConfiguration.isFloating(windowingMode) && !inPipTransition) {
                    // For floating tasks, calculate the smallest width from the bounds of the
                    // task, because they should not be affected by insets.
                    inOutConfig.smallestScreenWidthDp = (int) (0.5f
                            + Math.min(mTmpFullBounds.width(), mTmpFullBounds.height()) / density);
                } else if (windowingMode == WINDOWING_MODE_MULTI_WINDOW && mIsEmbedded
                        && insideParentBounds && !resolvedBounds.equals(parentBounds)) {
                    // For embedded TFs, the smallest width should be updated. Otherwise, inherit
                    // from the parent task would result in applications loaded wrong resource.
                    inOutConfig.smallestScreenWidthDp =
                            Math.min(inOutConfig.screenWidthDp, inOutConfig.screenHeightDp);
                }
                // otherwise, it will just inherit
            }
        }

        if (inOutConfig.orientation == ORIENTATION_UNDEFINED) {
            inOutConfig.orientation = (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
                    ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
        }
        if (inOutConfig.screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
            // For calculating screen layout, we need to use the non-decor inset screen area for the
            // calculation for compatibility reasons, i.e. screen area without system bars that
            // could never go away in Honeycomb.
            int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density + 0.5f);
            int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density + 0.5f);
            // Use overrides if provided. If both overrides are provided, mTmpNonDecorBounds is
            // undefined so it can't be used.
            if (inOutConfig.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
                compatScreenWidthDp = inOutConfig.screenWidthDp;
            }
            if (inOutConfig.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
                compatScreenHeightDp = inOutConfig.screenHeightDp;
            }
            // Reducing the screen layout starting from its parent config.
            inOutConfig.screenLayout = computeScreenLayout(parentConfig.screenLayout,
                    compatScreenWidthDp, compatScreenHeightDp);
        }
    }

    /**
     * Gets bounds with non-decor and stable insets applied respectively.
     *
     * If bounds overhangs the display, those edges will not get insets. See
     * {@link #intersectWithInsetsIfFits}
     *
     * @param outNonDecorBounds where to place bounds with non-decor insets applied.
     * @param outStableBounds where to place bounds with stable insets applied.
     * @param bounds the bounds to inset.
     */
    void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds,
            DisplayInfo displayInfo) {
        outNonDecorBounds.set(bounds);
        outStableBounds.set(bounds);
        if (mDisplayContent == null) {
            return;
        }
        mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);

        final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
        final DisplayPolicy.DecorInsets.Info info = policy.getDecorInsetsInfo(
                displayInfo.rotation, displayInfo.logicalWidth, displayInfo.logicalHeight);
        intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, info.mNonDecorInsets);
        intersectWithInsetsIfFits(outStableBounds, mTmpBounds, info.mConfigInsets);
    }

    /**
     * Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
     * intersectBounds on a side, then the respective side will not be intersected.
     *
     * The assumption is that if inOutBounds is initially larger than intersectBounds, then the
     * inset on that side is no-longer applicable. This scenario happens when a task's minimal
     * bounds are larger than the provided parent/display bounds.
     *
     * @param inOutBounds the bounds to intersect.
     * @param intersectBounds the bounds to intersect with.
     * @param intersectInsets insets to apply to intersectBounds before intersecting.
     */
    static void intersectWithInsetsIfFits(
            Rect inOutBounds, Rect intersectBounds, Rect intersectInsets) {
        if (inOutBounds.right <= intersectBounds.right) {
            inOutBounds.right =
                    Math.min(intersectBounds.right - intersectInsets.right, inOutBounds.right);
        }
        if (inOutBounds.bottom <= intersectBounds.bottom) {
            inOutBounds.bottom =
                    Math.min(intersectBounds.bottom - intersectInsets.bottom, inOutBounds.bottom);
        }
        if (inOutBounds.left >= intersectBounds.left) {
            inOutBounds.left =
                    Math.max(intersectBounds.left + intersectInsets.left, inOutBounds.left);
        }
        if (inOutBounds.top >= intersectBounds.top) {
            inOutBounds.top =
                    Math.max(intersectBounds.top + intersectInsets.top, inOutBounds.top);
        }
    }

    @Override
    public int getActivityType() {
        final int applicationType = super.getActivityType();
        if (applicationType != ACTIVITY_TYPE_UNDEFINED || !hasChild()) {
            return applicationType;
        }
        final ActivityRecord activity = getTopMostActivity();
        return activity != null ? activity.getActivityType() : getTopChild().getActivityType();
    }

    @Override
    public void onConfigurationChanged(Configuration newParentConfig) {
        super.onConfigurationChanged(newParentConfig);
        updateOrganizedTaskFragmentSurface();
        sendTaskFragmentInfoChanged();
    }

    void deferOrganizedTaskFragmentSurfaceUpdate() {
        mDelayOrganizedTaskFragmentSurfaceUpdate = true;
    }

    void continueOrganizedTaskFragmentSurfaceUpdate() {
        mDelayOrganizedTaskFragmentSurfaceUpdate = false;
        updateOrganizedTaskFragmentSurface();
    }

    /**
     * TaskFragmentOrganizer doesn't have access to the surface for security reasons, so we need to
     * update its surface on the server side if it is not collected for Shell or in pending
     * animation.
     */
    void updateOrganizedTaskFragmentSurface() {
        if (mDelayOrganizedTaskFragmentSurfaceUpdate || mTaskFragmentOrganizer == null) {
            return;
        }
        if (mTransitionController.isShellTransitionsEnabled()
                && !mTransitionController.isCollecting(this)) {
            // TaskFragmentOrganizer doesn't have access to the surface for security reasons, so
            // update the surface here if it is not collected by Shell transition.
            updateOrganizedTaskFragmentSurfaceUnchecked();
        } else if (!mTransitionController.isShellTransitionsEnabled() && !isAnimating()) {
            // Update the surface here instead of in the organizer so that we can make sure
            // it can be synced with the surface freezer for legacy app transition.
            updateOrganizedTaskFragmentSurfaceUnchecked();
        }
    }

    private void updateOrganizedTaskFragmentSurfaceUnchecked() {
        final SurfaceControl.Transaction t = getSyncTransaction();
        updateSurfacePosition(t);
        updateOrganizedTaskFragmentSurfaceSize(t, false /* forceUpdate */);
    }

    /** Updates the surface size so that the sub windows cannot be shown out of bounds. */
    private void updateOrganizedTaskFragmentSurfaceSize(SurfaceControl.Transaction t,
            boolean forceUpdate) {
        if (mTaskFragmentOrganizer == null) {
            // We only want to update for organized TaskFragment. Task will handle itself.
            return;
        }
        if (mSurfaceControl == null || mSurfaceAnimator.hasLeash() || mSurfaceFreezer.hasLeash()) {
            return;
        }

        // If this TaskFragment is closing while resizing, crop to the starting bounds instead.
        final Rect bounds = isClosingWhenResizing()
                ? mDisplayContent.mClosingChangingContainers.get(this)
                : getBounds();
        final int width = bounds.width();
        final int height = bounds.height();
        if (!forceUpdate && width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
            return;
        }
        t.setWindowCrop(mSurfaceControl, width, height);
        mLastSurfaceSize.set(width, height);
    }

    @Override
    public void onAnimationLeashCreated(SurfaceControl.Transaction t, SurfaceControl leash) {
        super.onAnimationLeashCreated(t, leash);
        // Reset surface bounds for animation. It will be taken care by the animation leash, and
        // reset again onAnimationLeashLost.
        if (mTaskFragmentOrganizer != null
                && (mLastSurfaceSize.x != 0 || mLastSurfaceSize.y != 0)) {
            t.setWindowCrop(mSurfaceControl, 0, 0);
            final SurfaceControl.Transaction syncTransaction = getSyncTransaction();
            if (t != syncTransaction) {
                // Avoid restoring to old window crop if the sync transaction is applied later.
                syncTransaction.setWindowCrop(mSurfaceControl, 0, 0);
            }
            mLastSurfaceSize.set(0, 0);
        }
    }

    @Override
    public void onAnimationLeashLost(SurfaceControl.Transaction t) {
        super.onAnimationLeashLost(t);
        // Update the surface bounds after animation.
        if (mTaskFragmentOrganizer != null) {
            updateOrganizedTaskFragmentSurfaceSize(t, true /* forceUpdate */);
        }
    }

    /**
     * Gets the relative bounds of this embedded TaskFragment. This should only be called on
     * embedded TaskFragment.
     */
    @NonNull
    Rect getRelativeEmbeddedBounds() {
        if (mRelativeEmbeddedBounds == null) {
            throw new IllegalStateException("The TaskFragment is not embedded");
        }
        return mRelativeEmbeddedBounds;
    }

    /**
     * Translates the given relative bounds to screen space based on the given parent bounds.
     * When the relative bounds is outside of the parent bounds, it will be adjusted to fit the Task
     * bounds.
     */
    Rect translateRelativeBoundsToAbsoluteBounds(@NonNull Rect relativeBounds,
            @NonNull Rect parentBounds) {
        if (relativeBounds.isEmpty()) {
            mTmpAbsBounds.setEmpty();
            return mTmpAbsBounds;
        }
        // Translate the relative bounds to absolute bounds.
        mTmpAbsBounds.set(relativeBounds);
        mTmpAbsBounds.offset(parentBounds.left, parentBounds.top);

        if (!isAllowedToBeEmbeddedInTrustedMode() && !parentBounds.contains(mTmpAbsBounds)) {
            // For untrusted embedding, we want to make sure the embedded bounds will never go
            // outside of the Task bounds.
            // We expect the organizer to update the bounds after receiving the Task bounds changed,
            // so skip trusted embedding to avoid unnecessary configuration change before organizer
            // requests a new bounds.
            // When the requested TaskFragment bounds is outside of Task bounds, try use the
            // intersection.
            // This can happen when the Task resized before the TaskFragmentOrganizer request.
            if (!mTmpAbsBounds.intersect(parentBounds)) {
                // Use empty bounds to fill Task if there is no intersection.
                mTmpAbsBounds.setEmpty();
            }
        }
        return mTmpAbsBounds;
    }

    void recomputeConfiguration() {
        onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
    }

    /**
     * Sets the relative bounds in parent coordinate for this embedded TaskFragment.
     * This will not override the requested bounds, and the actual bounds will be calculated in
     * {@link #resolveOverrideConfiguration}, so that it makes sure to record and use the relative
     * bounds that is set by the organizer until the organizer requests a new relative bounds.
     */
    void setRelativeEmbeddedBounds(@NonNull Rect relativeEmbeddedBounds) {
        if (mRelativeEmbeddedBounds == null) {
            throw new IllegalStateException("The TaskFragment is not embedded");
        }
        if (mRelativeEmbeddedBounds.equals(relativeEmbeddedBounds)) {
            return;
        }
        mRelativeEmbeddedBounds.set(relativeEmbeddedBounds);
    }

    /**
     * Updates the record of relative bounds of this embedded TaskFragment, and checks whether we
     * should prepare a transition for the bounds change.
     */
    boolean shouldStartChangeTransition(@NonNull Rect absStartBounds,
            @NonNull Rect relStartBounds) {
        if (mTaskFragmentOrganizer == null || !canStartChangeTransition()) {
            return false;
        }

        if (mTransitionController.isShellTransitionsEnabled()) {
            // For Shell transition, the change will be collected anyway, so only take snapshot when
            // the bounds are resized.
            final Rect endBounds = getConfiguration().windowConfiguration.getBounds();
            return endBounds.width() != absStartBounds.width()
                    || endBounds.height() != absStartBounds.height();
        } else {
            // For legacy transition, we need to trigger a change transition as long as the bounds
            // is changed, even if it is not resized.
            return !relStartBounds.equals(mRelativeEmbeddedBounds);
        }
    }

    @Override
    boolean canStartChangeTransition() {
        final Task task = getTask();
        // Skip change transition when the Task is drag resizing.
        return task != null && !task.isDragResizing() && super.canStartChangeTransition();
    }

    /**
     * Returns {@code true} if the starting bounds of the closing organized TaskFragment is
     * recorded. Otherwise, return {@code false}.
     */
    boolean setClosingChangingStartBoundsIfNeeded() {
        if (isOrganizedTaskFragment() && mDisplayContent != null
                && mDisplayContent.mChangingContainers.remove(this)) {
            mDisplayContent.mClosingChangingContainers.put(
                    this, new Rect(mSurfaceFreezer.mFreezeBounds));
            return true;
        }
        return false;
    }

    @Override
    boolean isSyncFinished(BLASTSyncEngine.SyncGroup group) {
        return super.isSyncFinished(group) && isReadyToTransit();
    }

    @Override
    void setSurfaceControl(SurfaceControl sc) {
        super.setSurfaceControl(sc);
        if (mTaskFragmentOrganizer != null) {
            updateOrganizedTaskFragmentSurfaceUnchecked();
            // If the TaskFragmentOrganizer was set before we created the SurfaceControl, we need to
            // emit the callbacks now.
            sendTaskFragmentAppeared();
        }
    }

    void sendTaskFragmentInfoChanged() {
        if (mTaskFragmentOrganizer != null) {
            mTaskFragmentOrganizerController
                    .onTaskFragmentInfoChanged(mTaskFragmentOrganizer, this);
        }
    }

    void sendTaskFragmentParentInfoChanged() {
        final Task parentTask = getParent().asTask();
        if (mTaskFragmentOrganizer != null && parentTask != null) {
            mTaskFragmentOrganizerController
                    .onTaskFragmentParentInfoChanged(mTaskFragmentOrganizer, parentTask);
        }
    }

    private void sendTaskFragmentAppeared() {
        if (mTaskFragmentOrganizer != null) {
            mTaskFragmentOrganizerController.onTaskFragmentAppeared(mTaskFragmentOrganizer, this);
        }
    }

    private void sendTaskFragmentVanished() {
        if (mTaskFragmentOrganizer != null) {
            mTaskFragmentOrganizerController.onTaskFragmentVanished(mTaskFragmentOrganizer, this);
        }
    }

    /**
     * Returns a {@link TaskFragmentInfo} with information from this TaskFragment. Should not be
     * called from {@link Task}.
     */
    TaskFragmentInfo getTaskFragmentInfo() {
        List<IBinder> childActivities = new ArrayList<>();
        List<IBinder> inRequestedTaskFragmentActivities = new ArrayList<>();
        for (int i = 0; i < getChildCount(); i++) {
            final WindowContainer<?> wc = getChildAt(i);
            final ActivityRecord ar = wc.asActivityRecord();
            if (mTaskFragmentOrganizerUid != INVALID_UID && ar != null
                    && ar.info.processName.equals(mTaskFragmentOrganizerProcessName)
                    && ar.getUid() == mTaskFragmentOrganizerUid && !ar.finishing) {
                // Only includes Activities that belong to the organizer process for security.
                childActivities.add(ar.token);
                if (ar.mRequestedLaunchingTaskFragmentToken == mFragmentToken) {
                    inRequestedTaskFragmentActivities.add(ar.token);
                }
            }
        }
        final Point positionInParent = new Point();
        getRelativePosition(positionInParent);
        return new TaskFragmentInfo(
                mFragmentToken,
                mRemoteToken.toWindowContainerToken(),
                getConfiguration(),
                getNonFinishingActivityCount(),
                shouldBeVisible(null /* starting */),
                childActivities,
                inRequestedTaskFragmentActivities,
                positionInParent,
                mClearedTaskForReuse,
                mClearedTaskFragmentForPip,
                mClearedForReorderActivityToFront,
                calculateMinDimension());
    }

    /**
     * Calculates the minimum dimensions that this TaskFragment can be resized.
     * @see TaskFragmentInfo#getMinimumWidth()
     * @see TaskFragmentInfo#getMinimumHeight()
     */
    Point calculateMinDimension() {
        final int[] maxMinWidth = new int[1];
        final int[] maxMinHeight = new int[1];

        forAllActivities(a -> {
            if (a.finishing) {
                return;
            }
            final Point minDimensions = a.getMinDimensions();
            if (minDimensions == null) {
                return;
            }
            maxMinWidth[0] = Math.max(maxMinWidth[0], minDimensions.x);
            maxMinHeight[0] = Math.max(maxMinHeight[0], minDimensions.y);
        });
        return new Point(maxMinWidth[0], maxMinHeight[0]);
    }

    @Nullable
    IBinder getFragmentToken() {
        return mFragmentToken;
    }

    @Nullable
    ITaskFragmentOrganizer getTaskFragmentOrganizer() {
        return mTaskFragmentOrganizer;
    }

    @Override
    boolean isOrganized() {
        return mTaskFragmentOrganizer != null;
    }

    /** Whether this is an organized {@link TaskFragment} and not a {@link Task}. */
    final boolean isOrganizedTaskFragment() {
        return mTaskFragmentOrganizer != null;
    }

    /**
     * Whether this is an embedded {@link TaskFragment} that does not fill the parent {@link Task}.
     */
    boolean isEmbeddedWithBoundsOverride() {
        if (!mIsEmbedded) {
            return false;
        }
        final Task task = getTask();
        if (task == null) {
            return false;
        }
        final Rect taskBounds = task.getBounds();
        final Rect taskFragBounds = getBounds();
        return !taskBounds.equals(taskFragBounds) && taskBounds.contains(taskFragBounds);
    }

    /** Whether the Task should be visible. */
    boolean isTaskVisibleRequested() {
        final Task task = getTask();
        return task != null && task.isVisibleRequested();
    }

    boolean isReadyToTransit() {
        // We only wait when this is organized to give the organizer a chance to update.
        if (!isOrganizedTaskFragment()) {
            return true;
        }
        // We don't want to start the transition if the organized TaskFragment is empty, unless
        // it is requested to be removed.
        if (getTopNonFinishingActivity() != null || mIsRemovalRequested) {
            return true;
        }
        // Organizer shouldn't change embedded TaskFragment in PiP.
        if (isEmbeddedTaskFragmentInPip()) {
            return true;
        }
        // The TaskFragment becomes empty because the last running activity enters PiP when the Task
        // is minimized.
        if (mClearedTaskFragmentForPip && !isTaskVisibleRequested()) {
            return true;
        }
        return false;
    }

    @Override
    boolean canCustomizeAppTransition() {
        // This is only called when the app transition is going to be played by system server. In
        // this case, we should allow custom app transition for fullscreen embedded TaskFragment
        // just like Activity.
        return isEmbedded() && matchParentBounds();
    }

    /** Clear {@link #mLastPausedActivity} for all {@link TaskFragment} children */
    void clearLastPausedActivity() {
        forAllTaskFragments(taskFragment -> taskFragment.mLastPausedActivity = null);
    }

    /**
     * Sets {@link #mMinWidth} and {@link #mMinWidth} to this TaskFragment.
     * It is usually set from the parent {@link Task} when adding the TaskFragment to the window
     * hierarchy.
     */
    void setMinDimensions(int minWidth, int minHeight) {
        if (asTask() != null) {
            throw new UnsupportedOperationException("This method must not be used to Task. The "
                    + " minimum dimension of Task should be passed from Task constructor.");
        }
        mMinWidth = minWidth;
        mMinHeight = minHeight;
    }

    /**
     * Whether this is an embedded TaskFragment in PIP Task. We don't allow any client config
     * override for such TaskFragment to prevent flight with PipTaskOrganizer.
     */
    boolean isEmbeddedTaskFragmentInPip() {
        return isOrganizedTaskFragment() && getTask() != null && getTask().inPinnedWindowingMode();
    }

    boolean shouldRemoveSelfOnLastChildRemoval() {
        return !mCreatedByOrganizer || mIsRemovalRequested;
    }

    @Nullable
    HardwareBuffer getSnapshotForActivityRecord(@Nullable ActivityRecord r) {
        if (!BackNavigationController.isScreenshotEnabled()) {
            return null;
        }
        if (r != null && r.mActivityComponent != null) {
            ScreenCapture.ScreenshotHardwareBuffer backBuffer =
                    mBackScreenshots.get(r.mActivityComponent.flattenToString());
            return backBuffer != null ? backBuffer.getHardwareBuffer() : null;
        }
        return null;
    }

    @Override
    void removeChild(WindowContainer child) {
        removeChild(child, true /* removeSelfIfPossible */);
    }

    void removeChild(WindowContainer child, boolean removeSelfIfPossible) {
        super.removeChild(child);
        final ActivityRecord r = child.asActivityRecord();
        if (BackNavigationController.isScreenshotEnabled()) {
            //TODO(b/207481538) Remove once the infrastructure to support per-activity screenshot is
            // implemented
            if (r != null) {
                mBackScreenshots.remove(r.mActivityComponent.flattenToString());
            }
        }
        final WindowProcessController hostProcess = getOrganizerProcessIfDifferent(r);
        if (hostProcess != null) {
            hostProcess.removeEmbeddedActivity(r);
        }
        if (removeSelfIfPossible && shouldRemoveSelfOnLastChildRemoval() && !hasChild()) {
            removeImmediately("removeLastChild " + child);
        }
    }

    /**
     * Requests to remove this task fragment. If it doesn't have children, it is removed
     * immediately. Otherwise it will be removed until all activities are destroyed.
     *
     * @param withTransition Whether to use transition animation when removing activities. Set to
     *                       {@code false} if this is invisible to user, e.g. display removal.
     */
    void remove(boolean withTransition, String reason) {
        if (!hasChild()) {
            removeImmediately(reason);
            return;
        }
        mIsRemovalRequested = true;
        // The task order may be changed by finishIfPossible() for adjusting focus if there are
        // nested tasks, so add all activities into a list to avoid missed removals.
        final ArrayList<ActivityRecord> removingActivities = new ArrayList<>();
        forAllActivities((Consumer<ActivityRecord>) removingActivities::add);
        for (int i = removingActivities.size() - 1; i >= 0; --i) {
            final ActivityRecord r = removingActivities.get(i);
            if (withTransition && r.isVisible()) {
                r.finishIfPossible(reason, false /* oomAdj */);
            } else {
                r.destroyIfPossible(reason);
            }
        }
    }

    void setDelayLastActivityRemoval(boolean delay) {
        if (!mIsEmbedded) {
            Slog.w(TAG, "Set delaying last activity removal on a non-embedded TF.");
        }
        mDelayLastActivityRemoval = delay;
    }

    boolean isDelayLastActivityRemoval() {
        return mDelayLastActivityRemoval;
    }

    boolean shouldDeferRemoval() {
        if (!hasChild()) {
            return false;
        }
        return isExitAnimationRunningSelfOrChild();
    }

    @Override
    boolean handleCompleteDeferredRemoval() {
        if (shouldDeferRemoval()) {
            return true;
        }
        return super.handleCompleteDeferredRemoval();
    }

    /** The overridden method must call {@link #removeImmediately()} instead of super. */
    void removeImmediately(String reason) {
        Slog.d(TAG, "Remove task fragment: " + reason);
        removeImmediately();
    }

    @Override
    void removeImmediately() {
        mIsRemovalRequested = false;
        resetAdjacentTaskFragment();
        cleanUpEmbeddedTaskFragment();
        final boolean shouldExecuteAppTransition =
                mClearedTaskFragmentForPip && isTaskVisibleRequested();
        super.removeImmediately();
        sendTaskFragmentVanished();
        if (shouldExecuteAppTransition && mDisplayContent != null) {
            // When the Task is still visible, and the TaskFragment is removed because the last
            // running activity is reparenting to PiP, it is possible that no activity is getting
            // paused or resumed (having an embedded activity in split), thus we need to relayout
            // and execute it explicitly.
            mAtmService.addWindowLayoutReasons(
                    ActivityTaskManagerService.LAYOUT_REASON_VISIBILITY_CHANGED);
            mDisplayContent.executeAppTransition();
        }
    }

    /** Called on remove to cleanup. */
    private void cleanUpEmbeddedTaskFragment() {
        if (!mIsEmbedded) {
            return;
        }
        mAtmService.mWindowOrganizerController.cleanUpEmbeddedTaskFragment(this);
        final Task task = getTask();
        if (task == null) {
            return;
        }
        task.forAllLeafTaskFragments(taskFragment -> {
            if (taskFragment.getCompanionTaskFragment() == this) {
                taskFragment.setCompanionTaskFragment(null /* companionTaskFragment */);
            }
        }, false /* traverseTopToBottom */);
    }

    @Override
    Dimmer getDimmer() {
        // If this is in an embedded TaskFragment and we want the dim applies on the TaskFragment.
        if (mIsEmbedded && mEmbeddedDimArea == EMBEDDED_DIM_AREA_TASK_FRAGMENT) {
            return mDimmer;
        }

        return super.getDimmer();
    }

    /** Bounds to be used for dimming, as well as touch related tests. */
    void getDimBounds(@NonNull Rect out) {
        if (mIsEmbedded && mEmbeddedDimArea == EMBEDDED_DIM_AREA_PARENT_TASK) {
            out.set(getTask().getBounds());
        } else {
            out.set(getBounds());
        }
    }

    void setEmbeddedDimArea(@EmbeddedDimArea int embeddedDimArea) {
        mEmbeddedDimArea = embeddedDimArea;
    }

    @Override
    void prepareSurfaces() {
        if (asTask() != null) {
            super.prepareSurfaces();
            return;
        }

        mDimmer.resetDimStates();
        super.prepareSurfaces();

        final Rect dimBounds = mDimmer.getDimBounds();
        if (dimBounds != null) {
            // Bounds need to be relative, as the dim layer is a child.
            dimBounds.offsetTo(0 /* newLeft */, 0 /* newTop */);
            if (mDimmer.updateDims(getSyncTransaction())) {
                scheduleAnimation();
            }
        }
    }

    @Override
    boolean fillsParent() {
        // From the perspective of policy, we still want to report that this task fills parent
        // in fullscreen windowing mode even it doesn't match parent bounds because there will be
        // letterbox around its real content.
        return getWindowingMode() == WINDOWING_MODE_FULLSCREEN || matchParentBounds();
    }

    @Override
    protected boolean onChildVisibleRequestedChanged(@Nullable WindowContainer child) {
        if (!super.onChildVisibleRequestedChanged(child)) return false;
        // Send the info changed to update the TaskFragment visibility.
        sendTaskFragmentInfoChanged();
        return true;
    }

    @Nullable
    @Override
    TaskFragment getTaskFragment(Predicate<TaskFragment> callback) {
        final TaskFragment taskFragment = super.getTaskFragment(callback);
        if (taskFragment != null) {
            return taskFragment;
        }
        return callback.test(this) ? this : null;
    }

    /**
     * Moves the passed child to front
     * @return whether it was actually moved (vs already being top).
     */
    boolean moveChildToFront(WindowContainer newTop) {
        int origDist = getDistanceFromTop(newTop);
        positionChildAt(POSITION_TOP, newTop, false /* includeParents */);
        return getDistanceFromTop(newTop) != origDist;
    }

    String toFullString() {
        final StringBuilder sb = new StringBuilder(128);
        sb.append(this);
        sb.setLength(sb.length() - 1); // Remove tail '}'.
        if (mTaskFragmentOrganizerUid != INVALID_UID) {
            sb.append(" organizerUid=");
            sb.append(mTaskFragmentOrganizerUid);
        }
        if (mTaskFragmentOrganizerProcessName != null) {
            sb.append(" organizerProc=");
            sb.append(mTaskFragmentOrganizerProcessName);
        }
        if (mAdjacentTaskFragment != null) {
            sb.append(" adjacent=");
            sb.append(mAdjacentTaskFragment);
        }
        sb.append('}');
        return sb.toString();
    }

    @Override
    public String toString() {
        return "TaskFragment{" + Integer.toHexString(System.identityHashCode(this))
                + " mode=" + WindowConfiguration.windowingModeToString(getWindowingMode()) + "}";
    }

    boolean dump(String prefix, FileDescriptor fd, PrintWriter pw, boolean dumpAll,
            boolean dumpClient, String dumpPackage, final boolean needSep, Runnable header) {
        boolean printed = false;
        Runnable headerPrinter = () -> {
            if (needSep) {
                pw.println();
            }
            if (header != null) {
                header.run();
            }

            dumpInner(prefix, pw, dumpAll, dumpPackage);
        };

        if (dumpPackage == null) {
            // If we are not filtering by package, we want to print absolutely everything,
            // so always print the header even if there are no tasks/activities inside.
            headerPrinter.run();
            headerPrinter = null;
            printed = true;
        }

        for (int i = mChildren.size() - 1; i >= 0; --i) {
            WindowContainer child = mChildren.get(i);
            if (child.asTaskFragment() != null) {
                printed |= child.asTaskFragment().dump(prefix + "  ", fd, pw, dumpAll,
                        dumpClient, dumpPackage, needSep, headerPrinter);
            } else if (child.asActivityRecord() != null) {
                ActivityRecord.dumpActivity(fd, pw, i, child.asActivityRecord(), prefix + "  ",
                        "Hist ", true, !dumpAll, dumpClient, dumpPackage, false, headerPrinter,
                        getTask());
            }
        }

        return printed;
    }

    void dumpInner(String prefix, PrintWriter pw, boolean dumpAll, String dumpPackage) {
        pw.print(prefix); pw.print("* "); pw.println(toFullString());
        final Rect bounds = getRequestedOverrideBounds();
        if (!bounds.isEmpty()) {
            pw.println(prefix + "  mBounds=" + bounds);
        }
        if (mIsRemovalRequested) {
            pw.println(prefix + "  mIsRemovalRequested=true");
        }
        if (dumpAll) {
            printThisActivity(pw, mLastPausedActivity, dumpPackage, false,
                    prefix + "  mLastPausedActivity: ", null);
        }
    }

    @Override
    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
        super.dump(pw, prefix, dumpAll);
        pw.println(prefix + "bounds=" + getBounds().toShortString()
                + (mIsolatedNav ? ", isolatedNav" : ""));
        final String doublePrefix = prefix + "  ";
        for (int i = mChildren.size() - 1; i >= 0; i--) {
            final WindowContainer<?> child = mChildren.get(i);
            final TaskFragment tf = child.asTaskFragment();
            pw.println(prefix + "* " + (tf != null ? tf.toFullString() : child));
            // Only dump non-activity because full activity info is already printed by
            // RootWindowContainer#dumpActivities.
            if (tf != null) {
                child.dump(pw, doublePrefix, dumpAll);
            }
        }
    }

    @Override
    void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
        final long token = proto.start(fieldId);
        proto.write(HASH_CODE, System.identityHashCode(this));
        final ActivityRecord topActivity = topRunningActivity();
        proto.write(USER_ID, topActivity != null ? topActivity.mUserId : USER_NULL);
        proto.write(TITLE, topActivity != null ? topActivity.intent.getComponent()
                .flattenToShortString() : "TaskFragment");
        proto.end(token);
    }

    @Override
    long getProtoFieldId() {
        return TASK_FRAGMENT;
    }

    @Override
    public void dumpDebug(ProtoOutputStream proto, long fieldId,
            @WindowTraceLogLevel int logLevel) {
        if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
            return;
        }

        final long token = proto.start(fieldId);

        super.dumpDebug(proto, WINDOW_CONTAINER, logLevel);

        proto.write(DISPLAY_ID, getDisplayId());
        proto.write(ACTIVITY_TYPE, getActivityType());
        proto.write(MIN_WIDTH, mMinWidth);
        proto.write(MIN_HEIGHT, mMinHeight);

        proto.end(token);
    }
}
