/*
 * Copyright (C) 2015 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 android.server.am;

import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.server.am.Components.DOCKED_ACTIVITY;
import static android.server.am.Components.LAUNCHING_ACTIVITY;
import static android.server.am.Components.NON_RESIZEABLE_ACTIVITY;
import static android.server.am.Components.NO_RELAUNCH_ACTIVITY;
import static android.server.am.Components.RESIZEABLE_ACTIVITY;
import static android.server.am.Components.SINGLE_INSTANCE_ACTIVITY;
import static android.server.am.Components.SINGLE_TASK_ACTIVITY;
import static android.server.am.Components.TEST_ACTIVITY;
import static android.server.am.Components.TestActivity.TEST_ACTIVITY_ACTION_FINISH_SELF;
import static android.server.am.UiDeviceUtils.pressHomeButton;
import static android.server.am.WindowManagerState.TRANSIT_WALLPAPER_OPEN;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;

import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import android.content.ComponentName;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.server.am.CommandSession.ActivityCallback;
import android.support.test.filters.FlakyTest;

import org.junit.Before;
import org.junit.Test;

/**
 * Build/Install/Run:
 *     atest CtsActivityManagerDeviceTestCases:ActivityManagerSplitScreenTests
 */
public class ActivityManagerSplitScreenTests extends ActivityManagerTestBase {

    private static final int TASK_SIZE = 600;
    private static final int STACK_SIZE = 300;

    private boolean mIsHomeRecentsComponent;

    @Before
    @Override
    public void setUp() throws Exception {
        super.setUp();

        mIsHomeRecentsComponent = mAmWmState.getAmState().isHomeRecentsComponent();

        assumeTrue("Skipping test: no split multi-window support",
                supportsSplitScreenMultiWindow());
    }

    @Test
    public void testMinimumDeviceSize() throws Exception {
        mAmWmState.assertDeviceDefaultDisplaySize(
                "Devices supporting multi-window must be larger than the default minimum"
                        + " task size");
    }

    @Test
    @Presubmit
    @FlakyTest(bugId = 71792393)
    public void testStackList() throws Exception {
        launchActivity(TEST_ACTIVITY);
        mAmWmState.computeState(TEST_ACTIVITY);
        mAmWmState.assertContainsStack("Must contain home stack.",
                WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
        mAmWmState.assertContainsStack("Must contain fullscreen stack.",
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
        mAmWmState.assertDoesNotContainStack("Must not contain docked stack.",
                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
    }

    @Test
    @Presubmit
    public void testDockActivity() throws Exception {
        launchActivityInSplitScreenWithRecents(TEST_ACTIVITY);
        mAmWmState.assertContainsStack("Must contain home stack.",
                WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
        mAmWmState.assertContainsStack("Must contain docked stack.",
                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
    }

    @Test
    @Presubmit
    public void testNonResizeableNotDocked() throws Exception {
        launchActivityInSplitScreenWithRecents(NON_RESIZEABLE_ACTIVITY);

        mAmWmState.assertContainsStack("Must contain home stack.",
                WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
        mAmWmState.assertDoesNotContainStack("Must not contain docked stack.",
                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
        mAmWmState.assertFrontStack("Fullscreen stack must be front stack.",
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
    }

    @Test
    @Presubmit
    public void testLaunchToSide() throws Exception {
        launchActivitiesInSplitScreen(
                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
        mAmWmState.assertContainsStack("Must contain fullscreen stack.",
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
        mAmWmState.assertContainsStack("Must contain docked stack.",
                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
    }

    @Test
    @Presubmit
    public void testLaunchToSideMultiWindowCallbacks() throws Exception {
        // Launch two activities in split-screen mode.
        launchActivitiesInSplitScreen(
                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
        mAmWmState.assertContainsStack("Must contain fullscreen stack.",
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
        mAmWmState.assertContainsStack("Must contain docked stack.",
                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);

        // Exit split-screen mode and ensure we only get 1 multi-window mode changed callback.
        separateTestJournal();
        removeStacksInWindowingModes(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        final ActivityLifecycleCounts lifecycleCounts = waitForOnMultiWindowModeChanged(
                TEST_ACTIVITY);
        assertEquals(1, lifecycleCounts.getCount(ActivityCallback.ON_MULTI_WINDOW_MODE_CHANGED));
    }

    @Test
    @Presubmit
    @FlakyTest(bugId = 72956284)
    public void testNoUserLeaveHintOnMultiWindowModeChanged() throws Exception {
        launchActivity(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN);

        // Move to docked stack.
        separateTestJournal();
        setActivityTaskWindowingMode(TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        ActivityLifecycleCounts lifecycleCounts = waitForOnMultiWindowModeChanged(TEST_ACTIVITY);
        assertEquals("mMultiWindowModeChangedCount",
                1, lifecycleCounts.getCount(ActivityCallback.ON_MULTI_WINDOW_MODE_CHANGED));
        assertEquals("mUserLeaveHintCount",
                0, lifecycleCounts.getCount(ActivityCallback.ON_USER_LEAVE_HINT));

        // Make sure docked stack is focused. This way when we dismiss it later fullscreen stack
        // will come up.
        launchActivity(TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);

        // Move activity back to fullscreen stack.
        separateTestJournal();
        setActivityTaskWindowingMode(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
        lifecycleCounts = waitForOnMultiWindowModeChanged(TEST_ACTIVITY);
        assertEquals("mMultiWindowModeChangedCount",
                1, lifecycleCounts.getCount(ActivityCallback.ON_MULTI_WINDOW_MODE_CHANGED));
        assertEquals("mUserLeaveHintCount",
                0, lifecycleCounts.getCount(ActivityCallback.ON_USER_LEAVE_HINT));
    }

    @Test
    @Presubmit
    public void testLaunchToSideAndBringToFront() throws Exception {
        launchActivitiesInSplitScreen(
                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));

        int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
                TEST_ACTIVITY);

        // Launch another activity to side to cover first one.
        launchActivity(NO_RELAUNCH_ACTIVITY, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
        int taskNumberCovered = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        assertEquals("Fullscreen stack must have one task added.",
                taskNumberInitial + 1, taskNumberCovered);
        mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
                NO_RELAUNCH_ACTIVITY);

        // Launch activity that was first launched to side. It should be brought to front.
        getLaunchActivityBuilder()
                .setTargetActivity(TEST_ACTIVITY)
                .setToSide(true)
                .setWaitForLaunched(true)
                .execute();
        int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        assertEquals("Task number in fullscreen stack must remain the same.",
                taskNumberCovered, taskNumberFinal);
        mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
                TEST_ACTIVITY);
    }

    @Test
    @Presubmit
    @FlakyTest(bugId = 71792393)
    public void testLaunchToSideMultiple() throws Exception {
        launchActivitiesInSplitScreen(
                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));

        int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        assertNotNull("Launched to side activity must be in fullscreen stack.",
                mAmWmState.getAmState().getTaskByActivity(
                        TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));

        // Try to launch to side same activity again.
        getLaunchActivityBuilder().setToSide(true).execute();
        mAmWmState.computeState(TEST_ACTIVITY, LAUNCHING_ACTIVITY);
        int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        assertEquals("Task number mustn't change.", taskNumberInitial, taskNumberFinal);
        mAmWmState.assertFocusedActivity("Launched to side activity must remain in front.",
                TEST_ACTIVITY);
        assertNotNull("Launched to side activity must remain in fullscreen stack.",
                mAmWmState.getAmState().getTaskByActivity(
                        TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
    }

    @Test
    @Presubmit
    @FlakyTest(bugId = 73808815)
    public void testLaunchToSideSingleInstance() throws Exception {
        launchTargetToSide(SINGLE_INSTANCE_ACTIVITY, false);
    }

    @Test
    public void testLaunchToSideSingleTask() throws Exception {
        launchTargetToSide(SINGLE_TASK_ACTIVITY, false);
    }

    @Presubmit
    @FlakyTest(bugId = 71792393)
    @Test
    public void testLaunchToSideMultipleWithDifferentIntent() throws Exception {
        launchTargetToSide(TEST_ACTIVITY, true);
    }

    private void launchTargetToSide(ComponentName targetActivityName,
            boolean taskCountMustIncrement) throws Exception {
        // Launch in fullscreen first
        getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY)
                .setUseInstrumentation()
                .setWaitForLaunched(true)
                .execute();

        // Move to split-screen primary
        final int taskId = mAmWmState.getAmState().getTaskByActivity(LAUNCHING_ACTIVITY).mTaskId;
        moveTaskToPrimarySplitScreen(taskId, true /* showRecents */);

        // Launch target to side
        final LaunchActivityBuilder targetActivityLauncher = getLaunchActivityBuilder()
                .setTargetActivity(targetActivityName)
                .setToSide(true)
                .setRandomData(true)
                .setMultipleTask(false);
        targetActivityLauncher.execute();

        mAmWmState.computeState(targetActivityName, LAUNCHING_ACTIVITY);
        mAmWmState.assertContainsStack("Must contain secondary stack.",
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
        int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        assertNotNull("Launched to side activity must be in fullscreen stack.",
                mAmWmState.getAmState().getTaskByActivity(
                        targetActivityName, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));

        // Try to launch to side same activity again with different data.
        targetActivityLauncher.execute();
        mAmWmState.computeState(targetActivityName, LAUNCHING_ACTIVITY);
        int taskNumberSecondLaunch = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        if (taskCountMustIncrement) {
            assertEquals("Task number must be incremented.", taskNumberInitial + 1,
                    taskNumberSecondLaunch);
        } else {
            assertEquals("Task number must not change.", taskNumberInitial,
                    taskNumberSecondLaunch);
        }
        mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
                targetActivityName);
        assertNotNull("Launched to side activity must be launched in fullscreen stack.",
                mAmWmState.getAmState().getTaskByActivity(
                        targetActivityName, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));

        // Try to launch to side same activity again with different random data. Note that null
        // cannot be used here, since the first instance of TestActivity is launched with no data
        // in order to launch into split screen.
        targetActivityLauncher.execute();
        mAmWmState.computeState(targetActivityName, LAUNCHING_ACTIVITY);
        int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        if (taskCountMustIncrement) {
            assertEquals("Task number must be incremented.", taskNumberSecondLaunch + 1,
                    taskNumberFinal);
        } else {
            assertEquals("Task number must not change.", taskNumberSecondLaunch,
                    taskNumberFinal);
        }
        mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
                targetActivityName);
        assertNotNull("Launched to side activity must be launched in fullscreen stack.",
                mAmWmState.getAmState().getTaskByActivity(
                        targetActivityName, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
    }

    @Presubmit
    @Test
    public void testLaunchToSideMultipleWithFlag() throws Exception {
        launchActivitiesInSplitScreen(
                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
        int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        assertNotNull("Launched to side activity must be in fullscreen stack.",
                mAmWmState.getAmState().getTaskByActivity(
                        TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));

        // Try to launch to side same activity again, but with Intent#FLAG_ACTIVITY_MULTIPLE_TASK.
        getLaunchActivityBuilder().setToSide(true).setMultipleTask(true).execute();
        mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
        int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        assertEquals("Task number must be incremented.", taskNumberInitial + 1,
                taskNumberFinal);
        mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
                TEST_ACTIVITY);
        assertNotNull("Launched to side activity must remain in fullscreen stack.",
                mAmWmState.getAmState().getTaskByActivity(
                        TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
    }

    @Test
    public void testRotationWhenDocked() throws Exception {
        launchActivitiesInSplitScreen(
                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
        mAmWmState.assertContainsStack("Must contain fullscreen stack.",
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
        mAmWmState.assertContainsStack("Must contain docked stack.",
                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);

        // Rotate device single steps (90°) 0-1-2-3.
        // Each time we compute the state we implicitly assert valid bounds.
        try (final RotationSession rotationSession = new RotationSession()) {
            for (int i = 0; i < 4; i++) {
                rotationSession.set(i);
                mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
            }
            // Double steps (180°) We ended the single step at 3. So, we jump directly to 1 for
            // double step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side.
            rotationSession.set(ROTATION_90);
            mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
            rotationSession.set(ROTATION_270);
            mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
            rotationSession.set(ROTATION_0);
            mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
            rotationSession.set(ROTATION_180);
            mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
            rotationSession.set(ROTATION_0);
            mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
        }
    }

    @Test
    @Presubmit
    public void testRotationWhenDockedWhileLocked() throws Exception {
        launchActivitiesInSplitScreen(
                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
        mAmWmState.assertSanity();
        mAmWmState.assertContainsStack("Must contain fullscreen stack.",
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
        mAmWmState.assertContainsStack("Must contain docked stack.",
                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);

        try (final RotationSession rotationSession = new RotationSession();
             final LockScreenSession lockScreenSession = new LockScreenSession()) {
            for (int i = 0; i < 4; i++) {
                lockScreenSession.sleepDevice();
                rotationSession.set(i);
                lockScreenSession.wakeUpDevice()
                        .unlockDevice();
                mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
            }
        }
    }

    @Test
    public void testMinimizedFromEachDockedSide() throws Exception {
        try (final RotationSession rotationSession = new RotationSession()) {
            for (int i = 0; i < 2; i++) {
                rotationSession.set(i);
                launchActivityInDockStackAndMinimize(TEST_ACTIVITY);
                if (!mAmWmState.isScreenPortrait() && isTablet()) {
                    // Test minimize to the right only on tablets in landscape
                    removeStacksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
                    launchActivityInDockStackAndMinimize(TEST_ACTIVITY,
                            SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT);
                }
                removeStacksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
            }
        }
    }

    @Test
    @Presubmit
    public void testRotationWhileDockMinimized() throws Exception {
        launchActivityInDockStackAndMinimize(TEST_ACTIVITY);

        // Rotate device single steps (90°) 0-1-2-3.
        // Each time we compute the state we implicitly assert valid bounds in minimized mode.
        try (final RotationSession rotationSession = new RotationSession()) {
            for (int i = 0; i < 4; i++) {
                rotationSession.set(i);
                mAmWmState.computeState(TEST_ACTIVITY);
            }

            // Double steps (180°) We ended the single step at 3. So, we jump directly to 1 for
            // double step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side in
            // minimized mode.
            rotationSession.set(ROTATION_90);
            mAmWmState.computeState(TEST_ACTIVITY);
            rotationSession.set(ROTATION_270);
            mAmWmState.computeState(TEST_ACTIVITY);
            rotationSession.set(ROTATION_0);
            mAmWmState.computeState(TEST_ACTIVITY);
            rotationSession.set(ROTATION_180);
            mAmWmState.computeState(TEST_ACTIVITY);
            rotationSession.set(ROTATION_0);
            mAmWmState.computeState(TEST_ACTIVITY);
        }
    }

    @Test
    public void testMinimizeAndUnminimizeThenGoingHome() throws Exception {
        // Rotate the screen to check that minimize, unminimize, dismiss the docked stack and then
        // going home has the correct app transition
        try (final RotationSession rotationSession = new RotationSession()) {
            for (int rotation = ROTATION_0; rotation <= ROTATION_270; rotation++) {
                rotationSession.set(rotation);
                launchActivityInDockStackAndMinimize(DOCKED_ACTIVITY);

                if (mIsHomeRecentsComponent) {
                    launchActivity(TEST_ACTIVITY,
                            WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
                } else {
                    // Unminimize the docked stack
                    pressAppSwitchButtonAndWaitForRecents();
                    waitForDockNotMinimized();
                    assertDockNotMinimized();
                }

                // Dismiss the dock stack
                setActivityTaskWindowingMode(DOCKED_ACTIVITY,
                        WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
                mAmWmState.computeState(DOCKED_ACTIVITY);

                // Go home and check the app transition
                assertNotEquals(TRANSIT_WALLPAPER_OPEN,
                        mAmWmState.getWmState().getDefaultDisplayLastTransition());
                pressHomeButton();
                mAmWmState.waitForHomeActivityVisible();

                assertEquals(TRANSIT_WALLPAPER_OPEN,
                        mAmWmState.getWmState().getDefaultDisplayLastTransition());
            }
        }
    }

    @FlakyTest(bugId = 73813034)
    @Test
    @Presubmit
    public void testFinishDockActivityWhileMinimized() throws Exception {
        launchActivityInDockStackAndMinimize(TEST_ACTIVITY);

        mBroadcastActionTrigger.doAction(TEST_ACTIVITY_ACTION_FINISH_SELF);
        waitForDockNotMinimized();
        mAmWmState.assertNotExist(TEST_ACTIVITY);
        assertDockNotMinimized();
    }

    @Test
    @Presubmit
    public void testDockedStackToMinimizeWhenUnlocked() throws Exception {
        launchActivityInSplitScreenWithRecents(TEST_ACTIVITY);
        mAmWmState.computeState(TEST_ACTIVITY);
        try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
            lockScreenSession.sleepDevice()
                    .wakeUpDevice()
                    .unlockDevice();
            mAmWmState.computeState(TEST_ACTIVITY);
            assertDockMinimized();
        }
    }

    @Test
    public void testMinimizedStateWhenUnlockedAndUnMinimized() throws Exception {
        launchActivityInDockStackAndMinimize(TEST_ACTIVITY);

        try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
            lockScreenSession.sleepDevice()
                    .wakeUpDevice()
                    .unlockDevice();
            mAmWmState.computeState(TEST_ACTIVITY);

            // Unminimized back to splitscreen
            if (mIsHomeRecentsComponent) {
                launchActivity(RESIZEABLE_ACTIVITY,
                        WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
            } else {
                pressAppSwitchButtonAndWaitForRecents();
            }
            mAmWmState.computeState(TEST_ACTIVITY);
        }
    }

    /**
     * Verify split screen mode visibility after stack resize occurs.
     */
    @Test
    @Presubmit
    @FlakyTest(bugId = 110276714)
    public void testResizeDockedStack() throws Exception {
        launchActivitiesInSplitScreen(
                getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
        resizeDockedStack(STACK_SIZE, STACK_SIZE, TASK_SIZE, TASK_SIZE);
        mAmWmState.computeState(false /* compareTaskAndStackBounds */,
                new WaitForValidActivityState(TEST_ACTIVITY),
                new WaitForValidActivityState(DOCKED_ACTIVITY));
        mAmWmState.assertContainsStack("Must contain secondary split-screen stack.",
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
        mAmWmState.assertContainsStack("Must contain primary split-screen stack.",
                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
        mAmWmState.assertVisibility(DOCKED_ACTIVITY, true);
        mAmWmState.assertVisibility(TEST_ACTIVITY, true);
    }

    @Test
    public void testActivityLifeCycleOnResizeDockedStack() throws Exception {
        launchActivity(TEST_ACTIVITY);
        mAmWmState.computeState(TEST_ACTIVITY);
        final Rect fullScreenBounds = mAmWmState.getWmState().getStandardStackByWindowingMode(
                WINDOWING_MODE_FULLSCREEN).getBounds();

        setActivityTaskWindowingMode(TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        mAmWmState.computeState(TEST_ACTIVITY);
        launchActivity(NO_RELAUNCH_ACTIVITY, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);

        mAmWmState.computeState(TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY);
        final Rect initialDockBounds = mAmWmState.getWmState().getStandardStackByWindowingMode(
                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) .getBounds();

        separateTestJournal();

        Rect newBounds = computeNewDockBounds(fullScreenBounds, initialDockBounds, true);
        resizeDockedStack(
                newBounds.width(), newBounds.height(), newBounds.width(), newBounds.height());
        mAmWmState.computeState(TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY);

        // We resize twice to make sure we cross an orientation change threshold for both
        // activities.
        newBounds = computeNewDockBounds(fullScreenBounds, initialDockBounds, false);
        resizeDockedStack(
                newBounds.width(), newBounds.height(), newBounds.width(), newBounds.height());
        mAmWmState.computeState(TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY);
        assertActivityLifecycle(TEST_ACTIVITY, true /* relaunched */);
        assertActivityLifecycle(NO_RELAUNCH_ACTIVITY, false /* relaunched */);
    }

    private Rect computeNewDockBounds(
            Rect fullscreenBounds, Rect dockBounds, boolean reduceSize) {
        final boolean inLandscape = fullscreenBounds.width() > dockBounds.width();
        // We are either increasing size or reducing it.
        final float sizeChangeFactor = reduceSize ? 0.5f : 1.5f;
        final Rect newBounds = new Rect(dockBounds);
        if (inLandscape) {
            // In landscape we change the width.
            newBounds.right = (int) (newBounds.left + (newBounds.width() * sizeChangeFactor));
        } else {
            // In portrait we change the height
            newBounds.bottom = (int) (newBounds.top + (newBounds.height() * sizeChangeFactor));
        }

        return newBounds;
    }

    @Test
    @Presubmit
    public void testStackListOrderLaunchDockedActivity() throws Exception {
        assumeTrue(!mIsHomeRecentsComponent);

        launchActivityInSplitScreenWithRecents(TEST_ACTIVITY);

        final int homeStackIndex = mAmWmState.getStackIndexByActivityType(ACTIVITY_TYPE_HOME);
        final int recentsStackIndex = mAmWmState.getStackIndexByActivityType(ACTIVITY_TYPE_RECENTS);
        assertThat("Recents stack should be on top of home stack",
                recentsStackIndex, lessThan(homeStackIndex));
    }

    @Test
    @Presubmit
    public void testStackListOrderOnSplitScreenDismissed() throws Exception {
        launchActivitiesInSplitScreen(
                getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));

        setActivityTaskWindowingMode(DOCKED_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
        mAmWmState.computeState(new WaitForValidActivityState.Builder(DOCKED_ACTIVITY)
                .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
                .build());

        final int homeStackIndex = mAmWmState.getStackIndexByActivityType(ACTIVITY_TYPE_HOME);
        final int prevSplitScreenPrimaryIndex =
                mAmWmState.getAmState().getStackIndexByActivity(DOCKED_ACTIVITY);
        final int prevSplitScreenSecondaryIndex =
                mAmWmState.getAmState().getStackIndexByActivity(TEST_ACTIVITY);

        final int expectedHomeStackIndex =
                (prevSplitScreenPrimaryIndex > prevSplitScreenSecondaryIndex
                        ? prevSplitScreenPrimaryIndex : prevSplitScreenSecondaryIndex) - 1;
        assertEquals("Home stack needs to be directly behind the top stack",
                expectedHomeStackIndex, homeStackIndex);
    }

    private void launchActivityInDockStackAndMinimize(ComponentName activityName) throws Exception {
        launchActivityInDockStackAndMinimize(activityName, SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT);
    }

    private void launchActivityInDockStackAndMinimize(ComponentName activityName, int createMode)
            throws Exception {
        launchActivityInSplitScreenWithRecents(activityName, createMode);
        pressHomeButton();
        waitForAndAssertDockMinimized();
    }

    private void assertDockMinimized() {
        assertTrue(mAmWmState.getWmState().isDockedStackMinimized());
    }

    private void waitForAndAssertDockMinimized() throws Exception {
        waitForDockMinimized();
        assertDockMinimized();
        mAmWmState.computeState(TEST_ACTIVITY);
        mAmWmState.assertContainsStack("Must contain docked stack.",
                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
        mAmWmState.assertFocusedStack("Home activity should be focused in minimized mode",
                WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
    }

    private void assertDockNotMinimized() {
        assertFalse(mAmWmState.getWmState().isDockedStackMinimized());
    }

    private void waitForDockMinimized() throws Exception {
        mAmWmState.waitForWithWmState(state -> state.isDockedStackMinimized(),
                "***Waiting for Dock stack to be minimized");
    }

    private void waitForDockNotMinimized() throws Exception {
        mAmWmState.waitForWithWmState(state -> !state.isDockedStackMinimized(),
                "***Waiting for Dock stack to not be minimized");
    }
}
