/*
 * Copyright (C) 2016 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.AppOpsManager.OP_NONE;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.os.Process.SYSTEM_UID;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.View.VISIBLE;
import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;

import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.mock;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.graphics.Insets;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
import android.hardware.display.DisplayManager;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IDisplayWindowInsetsController;
import android.view.IWindow;
import android.view.InsetsFrameProvider;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.InsetsVisibilities;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.DisplayImePolicy;
import android.window.ITransitionPlayer;
import android.window.StartingWindowInfo;
import android.window.StartingWindowRemovalInfo;
import android.window.TaskFragmentOrganizer;
import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;

import com.android.internal.policy.AttributeCache;
import com.android.internal.util.ArrayUtils;
import com.android.server.wm.DisplayWindowSettings.SettingsProvider.SettingsEntry;

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.runner.Description;
import org.mockito.Mockito;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.HashMap;

/** Common base class for window manager unit test classes. */
class WindowTestsBase extends SystemServiceTestsBase {
    final Context mContext = getInstrumentation().getTargetContext();

    // Default package name
    static final String DEFAULT_COMPONENT_PACKAGE_NAME = "com.foo";

    static final int DEFAULT_TASK_FRAGMENT_ORGANIZER_UID = 10000;
    static final String DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME = "Test:TaskFragmentOrganizer";

    // Default base activity name
    private static final String DEFAULT_COMPONENT_CLASS_NAME = ".BarActivity";

    // An id appended to the end of the component name to make it unique
    static int sCurrentActivityId = 0;

    ActivityTaskManagerService mAtm;
    RootWindowContainer mRootWindowContainer;
    ActivityTaskSupervisor mSupervisor;
    WindowManagerService mWm;
    private final IWindow mIWindow = new TestIWindow();
    private Session mMockSession;

    DisplayInfo mDisplayInfo = new DisplayInfo();
    DisplayContent mDefaultDisplay;

    static final int STATUS_BAR_HEIGHT = 10;
    static final int NAV_BAR_HEIGHT = 15;

    /**
     * It is {@link #mDefaultDisplay} by default. If the test class or method is annotated with
     * {@link UseTestDisplay}, it will be an additional display.
     */
    DisplayContent mDisplayContent;

    // The following fields are only available depending on the usage of annotation UseTestDisplay.
    WindowState mWallpaperWindow;
    WindowState mImeWindow;
    WindowState mImeDialogWindow;
    WindowState mStatusBarWindow;
    WindowState mNotificationShadeWindow;
    WindowState mDockedDividerWindow;
    WindowState mNavBarWindow;
    WindowState mAppWindow;
    WindowState mChildAppWindowAbove;
    WindowState mChildAppWindowBelow;

    /**
     * Spied {@link Transaction} class than can be used to verify calls.
     */
    Transaction mTransaction;

    /**
     * Whether device-specific global overrides have already been checked in
     * {@link WindowTestsBase#setUpBase()}.
     */
    private static boolean sGlobalOverridesChecked;
    /**
     * Whether device-specific overrides have already been checked in
     * {@link WindowTestsBase#setUpBase()} when the default display is used.
     */
    private static boolean sOverridesCheckedDefaultDisplay;
    /**
     * Whether device-specific overrides have already been checked in
     * {@link WindowTestsBase#setUpBase()} when a {@link TestDisplayContent} is used.
     */
    private static boolean sOverridesCheckedTestDisplay;

    @BeforeClass
    public static void setUpOnceBase() {
        AttributeCache.init(getInstrumentation().getTargetContext());
    }

    @Before
    public void setUpBase() {
        mAtm = mSystemServicesTestRule.getActivityTaskManagerService();
        mSupervisor = mAtm.mTaskSupervisor;
        mRootWindowContainer = mAtm.mRootWindowContainer;
        mWm = mSystemServicesTestRule.getWindowManagerService();
        SystemServicesTestRule.checkHoldsLock(mWm.mGlobalLock);

        mDefaultDisplay = mWm.mRoot.getDefaultDisplay();
        // Update the display policy to make the screen fully turned on so animation is allowed
        final DisplayPolicy displayPolicy = mDefaultDisplay.getDisplayPolicy();
        displayPolicy.screenTurnedOn(null /* screenOnListener */);
        displayPolicy.finishKeyguardDrawn();
        displayPolicy.finishWindowsDrawn();
        displayPolicy.finishScreenTurningOn();

        mTransaction = mSystemServicesTestRule.mTransaction;
        mMockSession = mock(Session.class);

        mContext.getSystemService(DisplayManager.class)
                .getDisplay(Display.DEFAULT_DISPLAY).getDisplayInfo(mDisplayInfo);

        // Only create an additional test display for annotated test class/method because it may
        // significantly increase the execution time.
        final Description description = mSystemServicesTestRule.getDescription();
        UseTestDisplay testDisplayAnnotation = description.getAnnotation(UseTestDisplay.class);
        if (testDisplayAnnotation == null) {
            testDisplayAnnotation = description.getTestClass().getAnnotation(UseTestDisplay.class);
        }
        if (testDisplayAnnotation != null) {
            createTestDisplay(testDisplayAnnotation);
        } else {
            mDisplayContent = mDefaultDisplay;
        }

        // Ensure letterbox aspect ratio is not overridden on any device target.
        // {@link com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio}, is set
        // on some device form factors.
        mAtm.mWindowManager.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(0);
        // Ensure letterbox horizontal position multiplier is not overridden on any device target.
        // {@link com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier},
        // may be set on some device form factors.
        mAtm.mWindowManager.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(0.5f);
        // Ensure letterbox vertical position multiplier is not overridden on any device target.
        // {@link com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier},
        // may be set on some device form factors.
        mAtm.mWindowManager.mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier(0.5f);
        // Ensure letterbox horizontal reachability treatment isn't overridden on any device target.
        // {@link com.android.internal.R.bool.config_letterboxIsHorizontalReachabilityEnabled},
        // may be set on some device form factors.
        mAtm.mWindowManager.mLetterboxConfiguration.setIsHorizontalReachabilityEnabled(false);
        // Ensure letterbox vertical reachability treatment isn't overridden on any device target.
        // {@link com.android.internal.R.bool.config_letterboxIsVerticalReachabilityEnabled},
        // may be set on some device form factors.
        mAtm.mWindowManager.mLetterboxConfiguration.setIsVerticalReachabilityEnabled(false);
        // Ensure aspect ratio for unresizable apps isn't overridden on any device target.
        // {@link com.android.internal.R.bool
        // .config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled}, may be set on some
        // device form factors.
        mAtm.mWindowManager.mLetterboxConfiguration
                .setIsSplitScreenAspectRatioForUnresizableAppsEnabled(false);

        checkDeviceSpecificOverridesNotApplied();
    }

    @After
    public void tearDown() throws Exception {
        // Revert back to device overrides.
        mAtm.mWindowManager.mLetterboxConfiguration.resetFixedOrientationLetterboxAspectRatio();
        mAtm.mWindowManager.mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier();
        mAtm.mWindowManager.mLetterboxConfiguration.resetLetterboxVerticalPositionMultiplier();
        mAtm.mWindowManager.mLetterboxConfiguration.resetIsHorizontalReachabilityEnabled();
        mAtm.mWindowManager.mLetterboxConfiguration.resetIsVerticalReachabilityEnabled();
        mAtm.mWindowManager.mLetterboxConfiguration
                .resetIsSplitScreenAspectRatioForUnresizableAppsEnabled();
    }

    /**
     * Check that device-specific overrides are not applied. Only need to check once during entire
     * test run for each case: global overrides, default display, and test display.
     */
    private void checkDeviceSpecificOverridesNotApplied() {
        // Check global overrides
        if (!sGlobalOverridesChecked) {
            assertEquals(0, mWm.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(),
                    0 /* delta */);
            sGlobalOverridesChecked = true;
        }
        // Check display-specific overrides
        if (!sOverridesCheckedDefaultDisplay && mDisplayContent == mDefaultDisplay) {
            assertFalse(mDisplayContent.getIgnoreOrientationRequest());
            sOverridesCheckedDefaultDisplay = true;
        } else if (!sOverridesCheckedTestDisplay && mDisplayContent instanceof TestDisplayContent) {
            assertFalse(mDisplayContent.getIgnoreOrientationRequest());
            sOverridesCheckedTestDisplay = true;
        }
    }

    private void createTestDisplay(UseTestDisplay annotation) {
        beforeCreateTestDisplay();
        mDisplayContent = createNewDisplayWithImeSupport(DISPLAY_IME_POLICY_LOCAL);

        final boolean addAll = annotation.addAllCommonWindows();
        final @CommonTypes int[] requestedWindows = annotation.addWindows();

        if (addAll || ArrayUtils.contains(requestedWindows, W_WALLPAPER)) {
            mWallpaperWindow = createCommonWindow(null, TYPE_WALLPAPER, "wallpaperWindow");
        }
        if (addAll || ArrayUtils.contains(requestedWindows, W_INPUT_METHOD)) {
            mImeWindow = createCommonWindow(null, TYPE_INPUT_METHOD, "mImeWindow");
            mDisplayContent.mInputMethodWindow = mImeWindow;
        }
        if (addAll || ArrayUtils.contains(requestedWindows, W_INPUT_METHOD_DIALOG)) {
            mImeDialogWindow = createCommonWindow(null, TYPE_INPUT_METHOD_DIALOG,
                    "mImeDialogWindow");
        }
        if (addAll || ArrayUtils.contains(requestedWindows, W_STATUS_BAR)) {
            mStatusBarWindow = createCommonWindow(null, TYPE_STATUS_BAR, "mStatusBarWindow");
            mStatusBarWindow.mAttrs.height = STATUS_BAR_HEIGHT;
            mStatusBarWindow.mAttrs.gravity = Gravity.TOP;
            mStatusBarWindow.mAttrs.layoutInDisplayCutoutMode =
                    LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
            mStatusBarWindow.mAttrs.setFitInsetsTypes(0);
        }
        if (addAll || ArrayUtils.contains(requestedWindows, W_NOTIFICATION_SHADE)) {
            mNotificationShadeWindow = createCommonWindow(null, TYPE_NOTIFICATION_SHADE,
                    "mNotificationShadeWindow");
        }
        if (addAll || ArrayUtils.contains(requestedWindows, W_NAVIGATION_BAR)) {
            mNavBarWindow = createCommonWindow(null, TYPE_NAVIGATION_BAR, "mNavBarWindow");
            mNavBarWindow.mAttrs.height = NAV_BAR_HEIGHT;
            mNavBarWindow.mAttrs.gravity = Gravity.BOTTOM;
            mNavBarWindow.mAttrs.paramsForRotation = new WindowManager.LayoutParams[4];
            mNavBarWindow.mAttrs.setFitInsetsTypes(0);
            mNavBarWindow.mAttrs.layoutInDisplayCutoutMode =
                    LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
            mNavBarWindow.mAttrs.privateFlags |=
                    WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
            for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
                mNavBarWindow.mAttrs.paramsForRotation[rot] =
                        getNavBarLayoutParamsForRotation(rot);
            }
        }
        if (addAll || ArrayUtils.contains(requestedWindows, W_DOCK_DIVIDER)) {
            mDockedDividerWindow = createCommonWindow(null, TYPE_DOCK_DIVIDER,
                    "mDockedDividerWindow");
        }
        final boolean addAboveApp = ArrayUtils.contains(requestedWindows, W_ABOVE_ACTIVITY);
        final boolean addBelowApp = ArrayUtils.contains(requestedWindows, W_BELOW_ACTIVITY);
        if (addAll || addAboveApp || addBelowApp
                || ArrayUtils.contains(requestedWindows, W_ACTIVITY)) {
            mAppWindow = createCommonWindow(null, TYPE_BASE_APPLICATION, "mAppWindow");
        }
        if (addAll || addAboveApp) {
            mChildAppWindowAbove = createCommonWindow(mAppWindow, TYPE_APPLICATION_ATTACHED_DIALOG,
                    "mChildAppWindowAbove");
        }
        if (addAll || addBelowApp) {
            mChildAppWindowBelow = createCommonWindow(mAppWindow, TYPE_APPLICATION_MEDIA_OVERLAY,
                    "mChildAppWindowBelow");
        }

        mDisplayContent.getInsetsPolicy().setRemoteInsetsControllerControlsSystemBars(false);

        // Adding a display will cause freezing the display. Make sure to wait until it's
        // unfrozen to not run into race conditions with the tests.
        waitUntilHandlersIdle();
    }

    private WindowManager.LayoutParams getNavBarLayoutParamsForRotation(int rotation) {
        int width = WindowManager.LayoutParams.MATCH_PARENT;
        int height = WindowManager.LayoutParams.MATCH_PARENT;
        int gravity = Gravity.BOTTOM;
        switch (rotation) {
            case ROTATION_UNDEFINED:
            case Surface.ROTATION_0:
            case Surface.ROTATION_180:
                height = NAV_BAR_HEIGHT;
                break;
            case Surface.ROTATION_90:
                gravity = Gravity.RIGHT;
                width = NAV_BAR_HEIGHT;
                break;
            case Surface.ROTATION_270:
                gravity = Gravity.LEFT;
                width = NAV_BAR_HEIGHT;
                break;
        }
        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR);
        lp.width = width;
        lp.height = height;
        lp.gravity = gravity;
        lp.setFitInsetsTypes(0);
        lp.privateFlags |=
                WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
        lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
        return lp;
    }

    void beforeCreateTestDisplay() {
        // Called before display is created.
    }

    private WindowState createCommonWindow(WindowState parent, int type, String name) {
        final WindowState win = createWindow(parent, type, name);
        // Prevent common windows from been IME targets.
        win.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
        return win;
    }

    private WindowToken createWindowToken(
            DisplayContent dc, int windowingMode, int activityType, int type) {
        if (type == TYPE_WALLPAPER) {
            return createWallpaperToken(dc);
        }
        if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) {
            return createTestWindowToken(type, dc);
        }

        return createActivityRecord(dc, windowingMode, activityType);
    }

    private WindowToken createWallpaperToken(DisplayContent dc) {
        return new WallpaperWindowToken(mWm, mock(IBinder.class), true /* explicit */, dc,
                true /* ownerCanManageAppTokens */);
    }

    WindowState createNavBarWithProvidedInsets(DisplayContent dc) {
        final WindowState navbar = createWindow(null, TYPE_NAVIGATION_BAR, dc, "navbar");
        navbar.mAttrs.providedInsets = new InsetsFrameProvider[] {
                new InsetsFrameProvider(ITYPE_NAVIGATION_BAR, Insets.of(0, 0, 0, NAV_BAR_HEIGHT))
        };
        dc.getDisplayPolicy().addWindowLw(navbar, navbar.mAttrs);
        return navbar;
    }

    WindowState createAppWindow(Task task, int type, String name) {
        final ActivityRecord activity = createNonAttachedActivityRecord(task.getDisplayContent());
        task.addChild(activity, 0);
        return createWindow(null, type, activity, name);
    }

    // TODO: Move these calls to a builder?
    WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name,
            IWindow iwindow) {
        final WindowToken token = createWindowToken(
                dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
        return createWindow(parent, type, token, name, 0 /* ownerId */,
                false /* ownerCanAddInternalSystemWindow */, iwindow);
    }

    WindowState createWindow(WindowState parent, int type, String name) {
        return (parent == null)
                ? createWindow(parent, type, mDisplayContent, name)
                : createWindow(parent, type, parent.mToken, name);
    }

    WindowState createWindow(WindowState parent, int type, String name, int ownerId) {
        return (parent == null)
                ? createWindow(parent, type, mDisplayContent, name, ownerId)
                : createWindow(parent, type, parent.mToken, name, ownerId);
    }

    WindowState createWindow(WindowState parent, int windowingMode, int activityType,
            int type, DisplayContent dc, String name) {
        final WindowToken token = createWindowToken(dc, windowingMode, activityType, type);
        return createWindow(parent, type, token, name);
    }

    WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name) {
        return createWindow(
                parent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type, dc, name);
    }

    WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name,
            int ownerId) {
        final WindowToken token = createWindowToken(
                dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
        return createWindow(parent, type, token, name, ownerId);
    }

    WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name,
            boolean ownerCanAddInternalSystemWindow) {
        final WindowToken token = createWindowToken(
                dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
        return createWindow(parent, type, token, name, 0 /* ownerId */,
                ownerCanAddInternalSystemWindow);
    }

    WindowState createWindow(WindowState parent, int type, WindowToken token, String name) {
        return createWindow(parent, type, token, name, 0 /* ownerId */,
                false /* ownerCanAddInternalSystemWindow */);
    }

    WindowState createWindow(WindowState parent, int type, WindowToken token, String name,
            int ownerId) {
        return createWindow(parent, type, token, name, ownerId,
                false /* ownerCanAddInternalSystemWindow */);
    }

    WindowState createWindow(WindowState parent, int type, WindowToken token, String name,
            int ownerId, boolean ownerCanAddInternalSystemWindow) {
        return createWindow(parent, type, token, name, ownerId, ownerCanAddInternalSystemWindow,
                mIWindow);
    }

    WindowState createWindow(WindowState parent, int type, WindowToken token, String name,
            int ownerId, boolean ownerCanAddInternalSystemWindow, IWindow iwindow) {
        return createWindow(parent, type, token, name, ownerId, UserHandle.getUserId(ownerId),
                ownerCanAddInternalSystemWindow, mWm, mMockSession, iwindow,
                mSystemServicesTestRule.getPowerManagerWrapper());
    }

    static WindowState createWindow(WindowState parent, int type, WindowToken token,
            String name, int ownerId, int userId, boolean ownerCanAddInternalSystemWindow,
            WindowManagerService service, Session session, IWindow iWindow,
            WindowState.PowerManagerWrapper powerManagerWrapper) {
        SystemServicesTestRule.checkHoldsLock(service.mGlobalLock);

        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
        attrs.setTitle(name);
        attrs.packageName = "test";

        final WindowState w = new WindowState(service, session, iWindow, token, parent,
                OP_NONE, attrs, VISIBLE, ownerId, userId,
                ownerCanAddInternalSystemWindow,
                powerManagerWrapper);
        // TODO: Probably better to make this call in the WindowState ctor to avoid errors with
        // adding it to the token...
        token.addWindow(w);
        return w;
    }

    static void makeWindowVisible(WindowState... windows) {
        for (WindowState win : windows) {
            win.mViewVisibility = View.VISIBLE;
            win.mRelayoutCalled = true;
            win.mHasSurface = true;
            win.mHidden = false;
            win.show(false /* doAnimation */, false /* requestAnim */);
        }
    }

    static void makeWindowVisibleAndDrawn(WindowState... windows) {
        makeWindowVisible(windows);
        for (WindowState win : windows) {
            win.mWinAnimator.mDrawState = HAS_DRAWN;
        }
    }

    /**
     * Gets the order of the given {@link Task} as its z-order in the hierarchy below this TDA.
     * The Task can be a direct child of a child TaskDisplayArea. {@code -1} if not found.
     */
    static int getTaskIndexOf(TaskDisplayArea taskDisplayArea, Task task) {
        int index = 0;
        final int childCount = taskDisplayArea.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final WindowContainer wc = taskDisplayArea.getChildAt(i);
            if (wc.asTask() != null) {
                if (wc.asTask() == task) {
                    return index;
                }
                index++;
            } else {
                final TaskDisplayArea tda = wc.asTaskDisplayArea();
                final int subIndex = getTaskIndexOf(tda, task);
                if (subIndex > -1) {
                    return index + subIndex;
                } else {
                    index += tda.getRootTaskCount();
                }
            }
        }
        return -1;
    }

    /** Creates a {@link TaskDisplayArea} right above the default one. */
    static TaskDisplayArea createTaskDisplayArea(DisplayContent displayContent,
            WindowManagerService service, String name, int displayAreaFeature) {
        final TaskDisplayArea newTaskDisplayArea = new TaskDisplayArea(
                displayContent, service, name, displayAreaFeature);
        final TaskDisplayArea defaultTaskDisplayArea = displayContent.getDefaultTaskDisplayArea();

        // Insert the new TDA to the correct position.
        defaultTaskDisplayArea.getParent().addChild(newTaskDisplayArea,
                defaultTaskDisplayArea.getParent().mChildren.indexOf(defaultTaskDisplayArea)
                        + 1);
        return newTaskDisplayArea;
    }

    /**
     *  Creates a {@link Task} with a simple {@link ActivityRecord} and adds to the given
     *  {@link TaskDisplayArea}.
     */
    Task createTaskWithActivity(TaskDisplayArea taskDisplayArea,
            int windowingMode, int activityType, boolean onTop, boolean twoLevelTask) {
        return createTask(taskDisplayArea, windowingMode, activityType,
                onTop, true /* createActivity */, twoLevelTask);
    }

    /** Creates a {@link Task} and adds to the given {@link DisplayContent}. */
    Task createTask(DisplayContent dc) {
        return createTask(dc.getDefaultTaskDisplayArea(),
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
    }

    Task createTask(DisplayContent dc, int windowingMode, int activityType) {
        return createTask(dc.getDefaultTaskDisplayArea(), windowingMode, activityType);
    }

    Task createTask(TaskDisplayArea taskDisplayArea, int windowingMode, int activityType) {
        return createTask(taskDisplayArea, windowingMode, activityType,
                true /* onTop */, false /* createActivity */, false /* twoLevelTask */);
    }

    /** Creates a {@link Task} and adds to the given {@link TaskDisplayArea}. */
    Task createTask(TaskDisplayArea taskDisplayArea, int windowingMode, int activityType,
            boolean onTop, boolean createActivity, boolean twoLevelTask) {
        final TaskBuilder builder = new TaskBuilder(mSupervisor)
                .setTaskDisplayArea(taskDisplayArea)
                .setWindowingMode(windowingMode)
                .setActivityType(activityType)
                .setOnTop(onTop)
                .setCreateActivity(createActivity);
        if (twoLevelTask) {
            return builder
                    .setCreateParentTask(true)
                    .build()
                    .getRootTask();
        } else {
            return builder.build();
        }
    }

    /** Creates a {@link Task} and adds to the given root {@link Task}. */
    Task createTaskInRootTask(Task rootTask, int userId) {
        final Task task = new TaskBuilder(rootTask.mTaskSupervisor)
                .setUserId(userId)
                .setParentTaskFragment(rootTask)
                .build();
        return task;
    }

    /** Creates an {@link ActivityRecord}. */
    static ActivityRecord createNonAttachedActivityRecord(DisplayContent dc) {
        final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService)
                .setOnTop(true)
                .build();
        postCreateActivitySetup(activity, dc);
        return activity;
    }

    /**
     * Creates an {@link ActivityRecord} and adds it to a new created {@link Task}.
     * [Task] - [ActivityRecord]
     */
    ActivityRecord createActivityRecord(DisplayContent dc) {
        return createActivityRecord(dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
    }

    /**
     * Creates an {@link ActivityRecord} and adds it to a new created {@link Task}.
     * [Task] - [ActivityRecord]
     */
    ActivityRecord createActivityRecord(DisplayContent dc, int windowingMode,
            int activityType) {
        final Task task = createTask(dc, windowingMode, activityType);
        return createActivityRecord(dc, task);
    }

    /**
     *  Creates an {@link ActivityRecord} and adds it to the specified {@link Task}.
     * [Task] - [ActivityRecord]
     */
    static ActivityRecord createActivityRecord(Task task) {
        return createActivityRecord(task.getDisplayContent(), task);
    }

    /**
     * Creates an {@link ActivityRecord} and adds it to the specified {@link Task}.
     * [Task] - [ActivityRecord]
     */
    static ActivityRecord createActivityRecord(DisplayContent dc, Task task) {
        final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService)
                .setTask(task)
                .setOnTop(true)
                .build();
        postCreateActivitySetup(activity, dc);
        return activity;
    }

    /**
     * Creates an {@link ActivityRecord} and adds it to a new created {@link Task}.
     * Then adds the new created {@link Task} to a new created parent {@link Task}
     * [Task1] - [Task2] - [ActivityRecord]
     */
    ActivityRecord createActivityRecordWithParentTask(DisplayContent dc, int windowingMode,
            int activityType) {
        final Task task = createTask(dc, windowingMode, activityType);
        return createActivityRecordWithParentTask(task);
    }

    /**
     * Creates an {@link ActivityRecord} and adds it to a new created {@link Task}.
     * Then adds the new created {@link Task} to the specified parent {@link Task}
     * [Task1] - [Task2] - [ActivityRecord]
     */
    static ActivityRecord createActivityRecordWithParentTask(Task parentTask) {
        final ActivityRecord activity = new ActivityBuilder(parentTask.mAtmService)
                .setParentTask(parentTask)
                .setCreateTask(true)
                .setOnTop(true)
                .build();
        postCreateActivitySetup(activity, parentTask.getDisplayContent());
        return activity;
    }

    private static void postCreateActivitySetup(ActivityRecord activity, DisplayContent dc) {
        activity.onDisplayChanged(dc);
        activity.setOccludesParent(true);
        activity.setVisible(true);
        activity.mVisibleRequested = true;
    }

    /**
     * Creates a {@link TaskFragment} and attach it to the {@code parentTask}.
     *
     * @param parentTask the {@link Task} this TaskFragment is going to be attached
     * @param createEmbeddedTask Sets to {@code true} to create an embedded Task for this
     *                           TaskFragment. Otherwise, create a {@link ActivityRecord}.
     * @return the created TaskFragment
     */
    static TaskFragment createTaskFragmentWithParentTask(@NonNull Task parentTask,
            boolean createEmbeddedTask) {
        final TaskFragmentBuilder builder = new TaskFragmentBuilder(parentTask.mAtmService)
                .setParentTask(parentTask);
        if (createEmbeddedTask) {
            builder.createEmbeddedTask();
        } else {
            builder.createActivityCount(1);
        }
        return builder.build();
    }

    static TaskFragment createTaskFragmentWithEmbeddedActivity(@NonNull Task parentTask,
            TaskFragmentOrganizer organizer) {
        return new TaskFragmentBuilder(parentTask.mAtmService)
                .setParentTask(parentTask)
                .createActivityCount(1)
                .setOrganizer(organizer)
                .build();
    }

    /** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
    DisplayContent createNewDisplay() {
        return createNewDisplayWithImeSupport(DISPLAY_IME_POLICY_LOCAL);
    }

    /** Creates a {@link DisplayContent} and adds it to the system. */
    private DisplayContent createNewDisplayWithImeSupport(@DisplayImePolicy int imePolicy) {
        return createNewDisplay(mDisplayInfo, imePolicy, /* overrideSettings */ null);
    }

    /** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
    DisplayContent createNewDisplay(DisplayInfo info) {
        return createNewDisplay(info, DISPLAY_IME_POLICY_LOCAL, /* overrideSettings */ null);
    }

    /** Creates a {@link DisplayContent} and adds it to the system. */
    private DisplayContent createNewDisplay(DisplayInfo info, @DisplayImePolicy int imePolicy,
            @Nullable SettingsEntry overrideSettings) {
        final DisplayContent display =
                new TestDisplayContent.Builder(mAtm, info)
                        .setOverrideSettings(overrideSettings)
                        .build();
        final DisplayContent dc = display.mDisplayContent;
        // this display can show IME.
        dc.mWmService.mDisplayWindowSettings.setDisplayImePolicy(dc, imePolicy);
        return dc;
    }

    /**
     * Creates a {@link DisplayContent} with given display state and adds it to the system.
     *
     * @param displayState For initializing the state of the display. See
     *                     {@link Display#getState()}.
     */
    DisplayContent createNewDisplay(int displayState) {
        // Leverage main display info & initialize it with display state for given displayId.
        DisplayInfo displayInfo = new DisplayInfo();
        displayInfo.copyFrom(mDisplayInfo);
        displayInfo.state = displayState;
        return createNewDisplay(displayInfo, DISPLAY_IME_POLICY_LOCAL, /* overrideSettings */ null);
    }

    /** Creates a {@link TestWindowState} */
    TestWindowState createWindowState(WindowManager.LayoutParams attrs, WindowToken token) {
        SystemServicesTestRule.checkHoldsLock(mWm.mGlobalLock);

        return new TestWindowState(mWm, mMockSession, mIWindow, attrs, token);
    }

    /** Creates a {@link DisplayContent} as parts of simulate display info for test. */
    DisplayContent createMockSimulatedDisplay() {
        return createMockSimulatedDisplay(/* overrideSettings */ null);
    }

    DisplayContent createMockSimulatedDisplay(@Nullable SettingsEntry overrideSettings) {
        DisplayInfo displayInfo = new DisplayInfo();
        displayInfo.copyFrom(mDisplayInfo);
        displayInfo.type = Display.TYPE_VIRTUAL;
        displayInfo.ownerUid = SYSTEM_UID;
        return createNewDisplay(displayInfo, DISPLAY_IME_POLICY_FALLBACK_DISPLAY, overrideSettings);
    }

    IDisplayWindowInsetsController createDisplayWindowInsetsController() {
        return new IDisplayWindowInsetsController.Stub() {

            @Override
            public void insetsChanged(InsetsState insetsState) throws RemoteException {
            }

            @Override
            public void insetsControlChanged(InsetsState insetsState,
                    InsetsSourceControl[] insetsSourceControls) throws RemoteException {
            }

            @Override
            public void showInsets(int i, boolean b) throws RemoteException {
            }

            @Override
            public void hideInsets(int i, boolean b) throws RemoteException {
            }

            @Override
            public void topFocusedWindowChanged(ComponentName component,
                    InsetsVisibilities requestedVisibilities) {
            }
        };
    }

    BLASTSyncEngine createTestBLASTSyncEngine() {
        return new BLASTSyncEngine(mWm) {
            @Override
            void scheduleTimeout(SyncGroup s, long timeoutMs) {
                // Disable timeout.
            }
        };
    }

    /** Sets up a simple implementation of transition player for shell transitions. */
    TestTransitionPlayer registerTestTransitionPlayer() {
        final TestTransitionPlayer testPlayer = new TestTransitionPlayer(
                mAtm.getTransitionController(), mAtm.mWindowOrganizerController);
        testPlayer.mController.registerTransitionPlayer(testPlayer, null /* playerProc */);
        return testPlayer;
    }

    /**
     * Avoids rotating screen disturbed by some conditions. It is usually used for the default
     * display that is not the instance of {@link TestDisplayContent} (it bypasses the conditions).
     *
     * @see DisplayRotation#updateRotationUnchecked
     */
    void unblockDisplayRotation(DisplayContent dc) {
        mWm.stopFreezingDisplayLocked();
        // The rotation animation won't actually play, it needs to be cleared manually.
        dc.setRotationAnimation(null);
    }

    // The window definition for UseTestDisplay#addWindows. The test can declare to add only
    // necessary windows, that avoids adding unnecessary overhead of unused windows.
    static final int W_NOTIFICATION_SHADE = TYPE_NOTIFICATION_SHADE;
    static final int W_STATUS_BAR = TYPE_STATUS_BAR;
    static final int W_NAVIGATION_BAR = TYPE_NAVIGATION_BAR;
    static final int W_INPUT_METHOD_DIALOG = TYPE_INPUT_METHOD_DIALOG;
    static final int W_INPUT_METHOD = TYPE_INPUT_METHOD;
    static final int W_DOCK_DIVIDER = TYPE_DOCK_DIVIDER;
    static final int W_ABOVE_ACTIVITY = TYPE_APPLICATION_ATTACHED_DIALOG;
    static final int W_ACTIVITY = TYPE_BASE_APPLICATION;
    static final int W_BELOW_ACTIVITY = TYPE_APPLICATION_MEDIA_OVERLAY;
    static final int W_WALLPAPER = TYPE_WALLPAPER;

    /** The common window types supported by {@link UseTestDisplay}. */
    @Retention(RetentionPolicy.RUNTIME)
    @IntDef(value = {
            W_NOTIFICATION_SHADE,
            W_STATUS_BAR,
            W_NAVIGATION_BAR,
            W_INPUT_METHOD_DIALOG,
            W_INPUT_METHOD,
            W_DOCK_DIVIDER,
            W_ABOVE_ACTIVITY,
            W_ACTIVITY,
            W_BELOW_ACTIVITY,
            W_WALLPAPER,
    })
    @interface CommonTypes {
    }

    /**
     * The annotation for class and method (higher priority) to create a non-default display that
     * will be assigned to {@link #mDisplayContent}. It is used if the test needs
     * <ul>
     * <li>Pure empty display.</li>
     * <li>Configured common windows.</li>
     * <li>Independent and customizable orientation.</li>
     * <li>Cross display operation.</li>
     * </ul>
     *
     * @see TestDisplayContent
     * @see #createTestDisplay
     **/
    @Target({ ElementType.METHOD, ElementType.TYPE })
    @Retention(RetentionPolicy.RUNTIME)
    @interface UseTestDisplay {
        boolean addAllCommonWindows() default false;
        @CommonTypes int[] addWindows() default {};
    }

    /** Creates and adds a {@link TestDisplayContent} to supervisor at the given position. */
    TestDisplayContent addNewDisplayContentAt(int position) {
        return new TestDisplayContent.Builder(mAtm, 1000, 1500).setPosition(position).build();
    }

    /** Sets the default minimum task size to 1 so that tests can use small task sizes */
    public void removeGlobalMinSizeRestriction() {
        mAtm.mRootWindowContainer.forAllDisplays(
                displayContent -> displayContent.mMinSizeOfResizeableTaskDp = 1);
    }

    /** Mocks the behavior of taking a snapshot. */
    void mockSurfaceFreezerSnapshot(SurfaceFreezer surfaceFreezer) {
        final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
                mock(SurfaceControl.ScreenshotHardwareBuffer.class);
        final HardwareBuffer hardwareBuffer = mock(HardwareBuffer.class);
        spyOn(surfaceFreezer);
        doReturn(screenshotBuffer).when(surfaceFreezer)
                .createSnapshotBufferInner(any(), any());
        doReturn(null).when(surfaceFreezer)
                .createFromHardwareBufferInner(any());
        doReturn(hardwareBuffer).when(screenshotBuffer).getHardwareBuffer();
        doReturn(100).when(hardwareBuffer).getWidth();
        doReturn(100).when(hardwareBuffer).getHeight();
    }

    static ComponentName getUniqueComponentName() {
        return ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME,
                DEFAULT_COMPONENT_CLASS_NAME + sCurrentActivityId++);
    }

    /**
     * Builder for creating new activities.
     */
    protected static class ActivityBuilder {
        static final int DEFAULT_FAKE_UID = 12345;
        static final String DEFAULT_PROCESS_NAME = "procName";
        static int sProcNameSeq;

        private final ActivityTaskManagerService mService;

        private ComponentName mComponent;
        private String mTargetActivity;
        private Task mTask;
        private String mProcessName = DEFAULT_PROCESS_NAME;
        private String mAffinity;
        private int mUid = DEFAULT_FAKE_UID;
        private boolean mCreateTask = false;
        private Task mParentTask;
        private int mActivityFlags;
        private int mLaunchMode;
        private int mResizeMode = RESIZE_MODE_RESIZEABLE;
        private float mMaxAspectRatio;
        private float mMinAspectRatio;
        private boolean mSupportsSizeChanges;
        private int mScreenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
        private boolean mLaunchTaskBehind = false;
        private int mConfigChanges;
        private int mLaunchedFromPid;
        private int mLaunchedFromUid;
        private String mLaunchedFromPackage;
        private WindowProcessController mWpc;
        private Bundle mIntentExtras;
        private boolean mOnTop = false;
        private ActivityInfo.WindowLayout mWindowLayout;
        private boolean mVisible = true;
        private ActivityOptions mLaunchIntoPipOpts;

        ActivityBuilder(ActivityTaskManagerService service) {
            mService = service;
        }

        ActivityBuilder setComponent(ComponentName component) {
            mComponent = component;
            return this;
        }

        ActivityBuilder setTargetActivity(String targetActivity) {
            mTargetActivity = targetActivity;
            return this;
        }

        ActivityBuilder setIntentExtras(Bundle extras) {
            mIntentExtras = extras;
            return this;
        }

        static ComponentName getDefaultComponent() {
            return ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME,
                    DEFAULT_COMPONENT_PACKAGE_NAME);
        }

        ActivityBuilder setTask(Task task) {
            mTask = task;
            return this;
        }

        ActivityBuilder setActivityFlags(int flags) {
            mActivityFlags = flags;
            return this;
        }

        ActivityBuilder setLaunchMode(int launchMode) {
            mLaunchMode = launchMode;
            return this;
        }

        ActivityBuilder setParentTask(Task parentTask) {
            mParentTask = parentTask;
            return this;
        }

        ActivityBuilder setCreateTask(boolean createTask) {
            mCreateTask = createTask;
            return this;
        }

        ActivityBuilder setProcessName(String name) {
            mProcessName = name;
            return this;
        }

        ActivityBuilder setUid(int uid) {
            mUid = uid;
            return this;
        }

        ActivityBuilder setResizeMode(int resizeMode) {
            mResizeMode = resizeMode;
            return this;
        }

        ActivityBuilder setMaxAspectRatio(float maxAspectRatio) {
            mMaxAspectRatio = maxAspectRatio;
            return this;
        }

        ActivityBuilder setMinAspectRatio(float minAspectRatio) {
            mMinAspectRatio = minAspectRatio;
            return this;
        }

        ActivityBuilder setSupportsSizeChanges(boolean supportsSizeChanges) {
            mSupportsSizeChanges = supportsSizeChanges;
            return this;
        }

        ActivityBuilder setScreenOrientation(int screenOrientation) {
            mScreenOrientation = screenOrientation;
            return this;
        }

        ActivityBuilder setLaunchTaskBehind(boolean launchTaskBehind) {
            mLaunchTaskBehind = launchTaskBehind;
            return this;
        }

        ActivityBuilder setConfigChanges(int configChanges) {
            mConfigChanges = configChanges;
            return this;
        }

        ActivityBuilder setLaunchedFromPid(int pid) {
            mLaunchedFromPid = pid;
            return this;
        }

        ActivityBuilder setLaunchedFromUid(int uid) {
            mLaunchedFromUid = uid;
            return this;
        }

        ActivityBuilder setLaunchedFromPackage(String packageName) {
            mLaunchedFromPackage = packageName;
            return this;
        }

        ActivityBuilder setUseProcess(WindowProcessController wpc) {
            mWpc = wpc;
            return this;
        }

        ActivityBuilder setAffinity(String affinity) {
            mAffinity = affinity;
            return this;
        }

        ActivityBuilder setOnTop(boolean onTop) {
            mOnTop = onTop;
            return this;
        }

        ActivityBuilder setWindowLayout(ActivityInfo.WindowLayout windowLayout) {
            mWindowLayout = windowLayout;
            return this;
        }

        ActivityBuilder setVisible(boolean visible) {
            mVisible = visible;
            return this;
        }

        ActivityBuilder setLaunchIntoPipActivityOptions(ActivityOptions opts) {
            mLaunchIntoPipOpts = opts;
            return this;
        }

        ActivityRecord build() {
            SystemServicesTestRule.checkHoldsLock(mService.mGlobalLock);
            try {
                mService.deferWindowLayout();
                return buildInner();
            } finally {
                mService.continueWindowLayout();
            }
        }

        ActivityRecord buildInner() {
            if (mComponent == null) {
                mComponent = getUniqueComponentName();
            }

            Intent intent = new Intent();
            intent.setComponent(mComponent);
            if (mIntentExtras != null) {
                intent.putExtras(mIntentExtras);
            }
            final ActivityInfo aInfo = new ActivityInfo();
            aInfo.applicationInfo = new ApplicationInfo();
            aInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
            aInfo.applicationInfo.packageName = mComponent.getPackageName();
            aInfo.applicationInfo.uid = mUid;
            if (DEFAULT_PROCESS_NAME.equals(mProcessName)) {
                mProcessName += ++sProcNameSeq;
            }
            aInfo.processName = mProcessName;
            aInfo.packageName = mComponent.getPackageName();
            aInfo.name = mComponent.getClassName();
            if (mTargetActivity != null) {
                aInfo.targetActivity = mTargetActivity;
            }
            aInfo.flags |= mActivityFlags;
            aInfo.launchMode = mLaunchMode;
            aInfo.resizeMode = mResizeMode;
            aInfo.setMaxAspectRatio(mMaxAspectRatio);
            aInfo.setMinAspectRatio(mMinAspectRatio);
            aInfo.supportsSizeChanges = mSupportsSizeChanges;
            aInfo.screenOrientation = mScreenOrientation;
            aInfo.configChanges |= mConfigChanges;
            aInfo.taskAffinity = mAffinity;
            aInfo.windowLayout = mWindowLayout;

            if (mCreateTask) {
                mTask = new TaskBuilder(mService.mTaskSupervisor)
                        .setComponent(mComponent)
                        // Apply the root activity info and intent
                        .setActivityInfo(aInfo)
                        .setIntent(intent)
                        .setParentTaskFragment(mParentTask).build();
            } else if (mTask == null && mParentTask != null && DisplayContent.alwaysCreateRootTask(
                    mParentTask.getWindowingMode(), mParentTask.getActivityType())) {
                // The parent task can be the task root.
                mTask = mParentTask;
            }

            ActivityOptions options = null;
            if (mLaunchIntoPipOpts != null) {
                options = mLaunchIntoPipOpts;
            } else if (mLaunchTaskBehind) {
                options = ActivityOptions.makeTaskLaunchBehind();
            }
            final ActivityRecord activity = new ActivityRecord.Builder(mService)
                    .setLaunchedFromPid(mLaunchedFromPid)
                    .setLaunchedFromUid(mLaunchedFromUid)
                    .setLaunchedFromPackage(mLaunchedFromPackage)
                    .setIntent(intent)
                    .setActivityInfo(aInfo)
                    .setActivityOptions(options)
                    .build();

            spyOn(activity);
            if (mTask != null) {
                mTask.addChild(activity);
                if (mOnTop) {
                    // Move the task to front after activity is added.
                    // Or {@link TaskDisplayArea#mPreferredTopFocusableRootTask} could be other
                    // root tasks (e.g. home root task).
                    mTask.moveToFront("createActivity");
                }
                if (mVisible) {
                    activity.mVisibleRequested = true;
                    activity.setVisible(true);
                }
            }

            final WindowProcessController wpc;
            if (mWpc != null) {
                wpc = mWpc;
            } else {
                final WindowProcessController p = mService.getProcessController(mProcessName, mUid);
                wpc = p != null ? p : SystemServicesTestRule.addProcess(
                        mService, aInfo.applicationInfo, mProcessName, 0 /* pid */);
            }
            activity.setProcess(wpc);

            // Resume top activities to make sure all other signals in the system are connected.
            mService.mRootWindowContainer.resumeFocusedTasksTopActivities();
            return activity;
        }
    }

    static class TaskFragmentBuilder {
        private final ActivityTaskManagerService mAtm;
        private Task mParentTask;
        private boolean mCreateParentTask;
        private boolean mCreateEmbeddedTask;
        private int mCreateActivityCount = 0;
        @Nullable
        private TaskFragmentOrganizer mOrganizer;
        private IBinder mFragmentToken;
        private Rect mBounds;

        TaskFragmentBuilder(ActivityTaskManagerService service) {
            mAtm = service;
        }

        TaskFragmentBuilder setCreateParentTask() {
            mCreateParentTask = true;
            return this;
        }

        TaskFragmentBuilder setParentTask(Task task) {
            mParentTask = task;
            return this;
        }

        /** Creates a child embedded Task and its Activity */
        TaskFragmentBuilder createEmbeddedTask() {
            mCreateEmbeddedTask = true;
            return this;
        }

        TaskFragmentBuilder createActivityCount(int count) {
            mCreateActivityCount = count;
            return this;
        }

        TaskFragmentBuilder setOrganizer(@Nullable TaskFragmentOrganizer organizer) {
            mOrganizer = organizer;
            return this;
        }

        TaskFragmentBuilder setFragmentToken(@Nullable IBinder fragmentToken) {
            mFragmentToken = fragmentToken;
            return this;
        }

        TaskFragmentBuilder setBounds(@Nullable Rect bounds) {
            mBounds = bounds;
            return this;
        }

        TaskFragment build() {
            SystemServicesTestRule.checkHoldsLock(mAtm.mGlobalLock);

            final TaskFragment taskFragment = new TaskFragment(mAtm, mFragmentToken,
                    mOrganizer != null);
            if (mParentTask == null && mCreateParentTask) {
                mParentTask = new TaskBuilder(mAtm.mTaskSupervisor).build();
            }
            if (mParentTask != null) {
                mParentTask.addChild(taskFragment, POSITION_TOP);
            }
            if (mCreateEmbeddedTask) {
                new TaskBuilder(mAtm.mTaskSupervisor)
                        .setParentTaskFragment(taskFragment)
                        .setCreateActivity(true)
                        .build();
            }
            while (mCreateActivityCount > 0) {
                final ActivityRecord activity = new ActivityBuilder(mAtm).build();
                taskFragment.addChild(activity);
                mCreateActivityCount--;
            }
            if (mOrganizer != null) {
                taskFragment.setTaskFragmentOrganizer(
                        mOrganizer.getOrganizerToken(), DEFAULT_TASK_FRAGMENT_ORGANIZER_UID,
                        DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME);
            }
            if (mBounds != null && !mBounds.isEmpty()) {
                taskFragment.setBounds(mBounds);
            }
            spyOn(taskFragment);
            return taskFragment;
        }
    }

    /**
     * Builder for creating new tasks.
     */
    protected static class TaskBuilder {
        private final ActivityTaskSupervisor mSupervisor;

        private TaskDisplayArea mTaskDisplayArea;
        private ComponentName mComponent;
        private String mPackage;
        private int mFlags = 0;
        private int mTaskId = -1;
        private int mUserId = 0;
        private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
        private int mActivityType = ACTIVITY_TYPE_STANDARD;
        private ActivityInfo mActivityInfo;
        private Intent mIntent;
        private boolean mOnTop = true;
        private IVoiceInteractionSession mVoiceSession;

        private boolean mCreateParentTask = false;
        private TaskFragment mParentTaskFragment;

        private boolean mCreateActivity = false;
        private boolean mCreatedByOrganizer = false;

        TaskBuilder(ActivityTaskSupervisor supervisor) {
            mSupervisor = supervisor;
            mTaskDisplayArea = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
        }

        /**
         * Set the parent {@link DisplayContent} and use the default task display area. Overrides
         * the task display area, if was set before.
         */
        TaskBuilder setDisplay(DisplayContent display) {
            mTaskDisplayArea = display.getDefaultTaskDisplayArea();
            return this;
        }

        /** Set the parent {@link TaskDisplayArea}. Overrides the display, if was set before. */
        TaskBuilder setTaskDisplayArea(TaskDisplayArea taskDisplayArea) {
            mTaskDisplayArea = taskDisplayArea;
            return this;
        }

        TaskBuilder setComponent(ComponentName component) {
            mComponent = component;
            return this;
        }

        TaskBuilder setPackage(String packageName) {
            mPackage = packageName;
            return this;
        }

        TaskBuilder setFlags(int flags) {
            mFlags = flags;
            return this;
        }

        TaskBuilder setTaskId(int taskId) {
            mTaskId = taskId;
            return this;
        }

        TaskBuilder setUserId(int userId) {
            mUserId = userId;
            return this;
        }

        TaskBuilder setWindowingMode(int windowingMode) {
            mWindowingMode = windowingMode;
            return this;
        }

        TaskBuilder setActivityType(int activityType) {
            mActivityType = activityType;
            return this;
        }

        TaskBuilder setActivityInfo(ActivityInfo info) {
            mActivityInfo = info;
            return this;
        }

        TaskBuilder setIntent(Intent intent) {
            mIntent = intent;
            return this;
        }

        TaskBuilder setOnTop(boolean onTop) {
            mOnTop = onTop;
            return this;
        }

        TaskBuilder setVoiceSession(IVoiceInteractionSession session) {
            mVoiceSession = session;
            return this;
        }

        TaskBuilder setCreateParentTask(boolean createParentTask) {
            mCreateParentTask = createParentTask;
            return this;
        }

        TaskBuilder setParentTaskFragment(TaskFragment parentTaskFragment) {
            mParentTaskFragment = parentTaskFragment;
            return this;
        }

        TaskBuilder setCreateActivity(boolean createActivity) {
            mCreateActivity = createActivity;
            return this;
        }

        TaskBuilder setCreatedByOrganizer(boolean createdByOrganizer) {
            mCreatedByOrganizer = createdByOrganizer;
            return this;
        }

        Task build() {
            SystemServicesTestRule.checkHoldsLock(mSupervisor.mService.mGlobalLock);

            // Create parent task.
            if (mParentTaskFragment == null && mCreateParentTask) {
                mParentTaskFragment = mTaskDisplayArea.createRootTask(
                        WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
            }
            if (mParentTaskFragment != null
                    && !Mockito.mockingDetails(mParentTaskFragment).isSpy()) {
                spyOn(mParentTaskFragment);
            }

            // Create task.
            if (mActivityInfo == null) {
                mActivityInfo = new ActivityInfo();
                mActivityInfo.applicationInfo = new ApplicationInfo();
                mActivityInfo.applicationInfo.packageName = mPackage;
            }

            if (mIntent == null) {
                mIntent = new Intent();
                if (mComponent == null) {
                    mComponent = getUniqueComponentName();
                }
                mIntent.setComponent(mComponent);
                mIntent.setFlags(mFlags);
            }

            final Task.Builder builder = new Task.Builder(mSupervisor.mService)
                    .setTaskId(mTaskId >= 0 ? mTaskId : mTaskDisplayArea.getNextRootTaskId())
                    .setWindowingMode(mWindowingMode)
                    .setActivityInfo(mActivityInfo)
                    .setIntent(mIntent)
                    .setOnTop(mOnTop)
                    .setVoiceSession(mVoiceSession)
                    .setCreatedByOrganizer(mCreatedByOrganizer);
            final Task task;
            if (mParentTaskFragment == null) {
                task = builder.setActivityType(mActivityType)
                        .setParent(mTaskDisplayArea)
                        .build();
            } else {
                task = builder.setParent(mParentTaskFragment).build();
                if (mParentTaskFragment.asTask() != null) {
                    mParentTaskFragment.asTask().moveToFront("build-task");
                }
            }
            spyOn(task);
            task.mUserId = mUserId;
            final Task rootTask = task.getRootTask();
            if (task != rootTask && !Mockito.mockingDetails(rootTask).isSpy()) {
                spyOn(rootTask);
            }
            doNothing().when(rootTask).startActivityLocked(
                    any(), any(), anyBoolean(), anyBoolean(), any(), any());

            // Create child activity.
            if (mCreateActivity) {
                new ActivityBuilder(mSupervisor.mService)
                        .setTask(task)
                        .setComponent(mComponent)
                        .build();
                if (mOnTop) {
                    // We move the task to front again in order to regain focus after activity
                    // is added. Or {@link TaskDisplayArea#mPreferredTopFocusableRootTask} could be
                    // other root tasks (e.g. home root task).
                    task.moveToFront("createActivityTask");
                } else {
                    task.moveToBack("createActivityTask", null);
                }
            }

            return task;
        }
    }

    static class TestStartingWindowOrganizer extends WindowOrganizerTests.StubOrganizer {
        private final ActivityTaskManagerService mAtm;
        private final WindowManagerService mWMService;
        private final WindowState.PowerManagerWrapper mPowerManagerWrapper;

        private Runnable mRunnableWhenAddingSplashScreen;
        private final SparseArray<IBinder> mTaskAppMap = new SparseArray<>();
        private final HashMap<IBinder, WindowState> mAppWindowMap = new HashMap<>();

        TestStartingWindowOrganizer(ActivityTaskManagerService service,
                WindowState.PowerManagerWrapper powerManagerWrapper) {
            mAtm = service;
            mWMService = mAtm.mWindowManager;
            mPowerManagerWrapper = powerManagerWrapper;
            mAtm.mTaskOrganizerController.setDeferTaskOrgCallbacksConsumer(Runnable::run);
            mAtm.mTaskOrganizerController.registerTaskOrganizer(this);
        }

        void setRunnableWhenAddingSplashScreen(Runnable r) {
            mRunnableWhenAddingSplashScreen = r;
        }

        @Override
        public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
            synchronized (mWMService.mGlobalLock) {
                final ActivityRecord activity = mWMService.mRoot.getActivityRecord(
                        appToken);
                IWindow iWindow = mock(IWindow.class);
                doReturn(mock(IBinder.class)).when(iWindow).asBinder();
                final WindowState window = WindowTestsBase.createWindow(null,
                        TYPE_APPLICATION_STARTING, activity,
                        "Starting window", 0 /* ownerId */, 0 /* userId*/,
                        false /* internalWindows */, mWMService, mock(Session.class),
                        iWindow,
                        mPowerManagerWrapper);
                activity.mStartingWindow = window;
                mAppWindowMap.put(appToken, window);
                mTaskAppMap.put(info.taskInfo.taskId, appToken);
            }
            if (mRunnableWhenAddingSplashScreen != null) {
                mRunnableWhenAddingSplashScreen.run();
                mRunnableWhenAddingSplashScreen = null;
            }
        }
        @Override
        public void removeStartingWindow(StartingWindowRemovalInfo removalInfo) {
            synchronized (mWMService.mGlobalLock) {
                final IBinder appToken = mTaskAppMap.get(removalInfo.taskId);
                if (appToken != null) {
                    mTaskAppMap.remove(removalInfo.taskId);
                    final ActivityRecord activity = mWMService.mRoot.getActivityRecord(
                            appToken);
                    WindowState win = mAppWindowMap.remove(appToken);
                    activity.removeChild(win);
                    activity.mStartingWindow = null;
                }
            }
        }
    }

    static class TestSplitOrganizer extends WindowOrganizerTests.StubOrganizer {
        final ActivityTaskManagerService mService;
        final TaskDisplayArea mDefaultTDA;
        Task mPrimary;
        Task mSecondary;
        int mDisplayId;

        TestSplitOrganizer(ActivityTaskManagerService service, DisplayContent display) {
            mService = service;
            mDefaultTDA = display.getDefaultTaskDisplayArea();
            mDisplayId = display.mDisplayId;
            mService.mTaskOrganizerController.registerTaskOrganizer(this);
            mPrimary = mService.mTaskOrganizerController.createRootTask(
                    display, WINDOWING_MODE_MULTI_WINDOW, null);
            mSecondary = mService.mTaskOrganizerController.createRootTask(
                    display, WINDOWING_MODE_MULTI_WINDOW, null);

            mPrimary.setAdjacentTaskFragment(mSecondary);
            display.getDefaultTaskDisplayArea().setLaunchAdjacentFlagRootTask(mSecondary);

            final Rect primaryBounds = new Rect();
            final Rect secondaryBounds = new Rect();
            if (display.getConfiguration().orientation == ORIENTATION_LANDSCAPE) {
                display.getBounds().splitVertically(primaryBounds, secondaryBounds);
            } else {
                display.getBounds().splitHorizontally(primaryBounds, secondaryBounds);
            }
            mPrimary.setBounds(primaryBounds);
            mSecondary.setBounds(secondaryBounds);

            spyOn(mPrimary);
            spyOn(mSecondary);
        }

        TestSplitOrganizer(ActivityTaskManagerService service) {
            this(service, service.mTaskSupervisor.mRootWindowContainer.getDefaultDisplay());
        }

        public Task createTaskToPrimary(boolean onTop) {
            final Task primaryTask = mDefaultTDA.createRootTask(
                    WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, onTop);
            putTaskToPrimary(primaryTask, onTop);
            return primaryTask;
        }

        public Task createTaskToSecondary(boolean onTop) {
            final Task secondaryTask = mDefaultTDA.createRootTask(
                    WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, onTop);
            putTaskToSecondary(secondaryTask, onTop);
            return secondaryTask;
        }

        public void putTaskToPrimary(Task task, boolean onTop) {
            task.reparent(mPrimary, onTop ? POSITION_TOP : POSITION_BOTTOM);
        }

        public void putTaskToSecondary(Task task, boolean onTop) {
            task.reparent(mSecondary, onTop ? POSITION_TOP : POSITION_BOTTOM);
        }
    }

    static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
        return createTestWindowToken(type, dc, false /* persistOnEmpty */);
    }

    static TestWindowToken createTestWindowToken(int type, DisplayContent dc,
            boolean persistOnEmpty) {
        SystemServicesTestRule.checkHoldsLock(dc.mWmService.mGlobalLock);

        return new TestWindowToken(type, dc, persistOnEmpty);
    }

    /** Used so we can gain access to some protected members of the {@link WindowToken} class */
    static class TestWindowToken extends WindowToken {

        private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
            super(dc.mWmService, mock(IBinder.class), type, persistOnEmpty, dc,
                    false /* ownerCanManageAppTokens */);
        }

        int getWindowsCount() {
            return mChildren.size();
        }

        boolean hasWindow(WindowState w) {
            return mChildren.contains(w);
        }
    }

    /** Used to track resize reports. */
    static class TestWindowState extends WindowState {
        boolean mResizeReported;

        TestWindowState(WindowManagerService service, Session session, IWindow window,
                WindowManager.LayoutParams attrs, WindowToken token) {
            super(service, session, window, token, null, OP_NONE, attrs, 0, 0, 0,
                    false /* ownerCanAddInternalSystemWindow */);
        }

        @Override
        void reportResized() {
            super.reportResized();
            mResizeReported = true;
        }

        @Override
        public boolean isGoneForLayout() {
            return false;
        }

        @Override
        void updateResizingWindowIfNeeded() {
            // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
            // the system that it can actually update the window.
            boolean hadSurface = mHasSurface;
            mHasSurface = true;

            super.updateResizingWindowIfNeeded();

            mHasSurface = hadSurface;
        }
    }

    static class TestTransitionPlayer extends ITransitionPlayer.Stub {
        final TransitionController mController;
        final WindowOrganizerController mOrganizer;
        Transition mLastTransit = null;
        TransitionRequestInfo mLastRequest = null;
        TransitionInfo mLastReady = null;

        TestTransitionPlayer(@NonNull TransitionController controller,
                @NonNull WindowOrganizerController organizer) {
            mController = controller;
            mOrganizer = organizer;
        }

        void clear() {
            mLastTransit = null;
            mLastReady = null;
            mLastRequest = null;
        }

        @Override
        public void onTransitionReady(IBinder transitToken, TransitionInfo transitionInfo,
                SurfaceControl.Transaction transaction, SurfaceControl.Transaction finishT)
                throws RemoteException {
            mLastTransit = Transition.fromBinder(transitToken);
            mLastReady = transitionInfo;
        }

        @Override
        public void requestStartTransition(IBinder transitToken,
                TransitionRequestInfo request) throws RemoteException {
            mLastTransit = Transition.fromBinder(transitToken);
            mLastRequest = request;
        }

        void startTransition() {
            mOrganizer.startTransition(mLastRequest.getType(), mLastTransit, null);
        }

        void onTransactionReady(SurfaceControl.Transaction t) {
            mLastTransit.onTransactionReady(mLastTransit.getSyncId(), t);
        }

        void start() {
            startTransition();
            onTransactionReady(mock(SurfaceControl.Transaction.class));
        }

        public void finish() {
            mController.finishTransition(mLastTransit);
        }
    }
}
