/*
 * 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 android.server.am;

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.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.server.am.ActivityAndWindowManagersState.dpToPx;
import static android.server.am.ActivityManagerState.STATE_RESUMED;
import static android.server.am.ComponentNameUtils.getWindowName;
import static android.server.am.Components.BROADCAST_RECEIVER_ACTIVITY;
import static android.server.am.Components.BroadcastReceiverActivity.ACTION_TRIGGER_BROADCAST;
import static android.server.am.Components.BroadcastReceiverActivity.EXTRA_BROADCAST_ORIENTATION;
import static android.server.am.Components.BroadcastReceiverActivity.EXTRA_MOVE_BROADCAST_TO_BACK;
import static android.server.am.Components.DIALOG_WHEN_LARGE_ACTIVITY;
import static android.server.am.Components.LANDSCAPE_ORIENTATION_ACTIVITY;
import static android.server.am.Components.LAUNCHING_ACTIVITY;
import static android.server.am.Components.NIGHT_MODE_ACTIVITY;
import static android.server.am.Components.PORTRAIT_ORIENTATION_ACTIVITY;
import static android.server.am.Components.RESIZEABLE_ACTIVITY;
import static android.server.am.Components.TEST_ACTIVITY;
import static android.server.am.StateLogger.log;
import static android.server.am.StateLogger.logE;
import static android.server.am.translucentapp.Components.TRANSLUCENT_LANDSCAPE_ACTIVITY;
import static android.server.am.translucentapp26.Components.SDK26_TRANSLUCENT_LANDSCAPE_ACTIVITY;
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.MatcherAssert.assertThat;
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.assertNull;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import static com.android.compatibility.common.util.PackageUtil.supportsRotation;

import android.content.ComponentName;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.FlakyTest;

import org.junit.Ignore;
import org.junit.Test;

import java.util.List;

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

    // TODO(b/70247058): Use {@link Context#sendBroadcast(Intent).
    // Shell command to move {@link #BROADCAST_RECEIVER_ACTIVITY} task to back.
    private static final String MOVE_TASK_TO_BACK_BROADCAST = "am broadcast -a "
            + ACTION_TRIGGER_BROADCAST + " --ez " + EXTRA_MOVE_BROADCAST_TO_BACK + " true";
    // Shell command to request portrait orientation to {@link #BROADCAST_RECEIVER_ACTIVITY}.
    private static final String REQUEST_PORTRAIT_BROADCAST = "am broadcast -a "
            + ACTION_TRIGGER_BROADCAST + " --ei " + EXTRA_BROADCAST_ORIENTATION + " 1";
    private static final String REQUEST_LANDSCAPE_BROADCAST = "am broadcast -a "
            + ACTION_TRIGGER_BROADCAST + " --ei " + EXTRA_BROADCAST_ORIENTATION + " 0";

    private static final int SMALL_WIDTH_DP = 426;
    private static final int SMALL_HEIGHT_DP = 320;

    /**
     * Tests that the WindowManager#getDefaultDisplay() and the Configuration of the Activity
     * has an updated size when the Activity is resized from fullscreen to docked state.
     *
     * The Activity handles configuration changes, so it will not be restarted between resizes.
     * On Configuration changes, the Activity logs the Display size and Configuration width
     * and heights. The values reported in fullscreen should be larger than those reported in
     * docked state.
     */
    @Test
    public void testConfigurationUpdatesWhenResizedFromFullscreen() {
        assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());

        LogSeparator logSeparator = separateLogs();
        launchActivity(RESIZEABLE_ACTIVITY, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
        final ReportedSizes fullscreenSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                logSeparator);

        logSeparator = separateLogs();
        setActivityTaskWindowingMode(RESIZEABLE_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        final ReportedSizes dockedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                logSeparator);

        assertSizesAreSane(fullscreenSizes, dockedSizes);
    }

    /**
     * Same as {@link #testConfigurationUpdatesWhenResizedFromFullscreen()} but resizing
     * from docked state to fullscreen (reverse).
     */
    @Presubmit
    @Test
    @FlakyTest(bugId = 71792393)
    public void testConfigurationUpdatesWhenResizedFromDockedStack() {
        assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());

        LogSeparator logSeparator = separateLogs();
        launchActivity(RESIZEABLE_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        final ReportedSizes dockedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                logSeparator);

        logSeparator = separateLogs();
        setActivityTaskWindowingMode(RESIZEABLE_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
        final ReportedSizes fullscreenSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                logSeparator);

        assertSizesAreSane(fullscreenSizes, dockedSizes);
    }

    /**
     * Tests whether the Display sizes change when rotating the device.
     */
    @Test
    public void testConfigurationUpdatesWhenRotatingWhileFullscreen() throws Exception {
        assumeTrue("Skipping test: no rotation support", supportsRotation());

        try (final RotationSession rotationSession = new RotationSession()) {
            rotationSession.set(ROTATION_0);

            final LogSeparator logSeparator = separateLogs();
            launchActivity(RESIZEABLE_ACTIVITY,
                    WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
            final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                    logSeparator);

            rotateAndCheckSizes(rotationSession, initialSizes);
        }
    }

    /**
     * Same as {@link #testConfigurationUpdatesWhenRotatingWhileFullscreen()} but when the Activity
     * is in the docked stack.
     */
    @Presubmit
    @Test
    public void testConfigurationUpdatesWhenRotatingWhileDocked() throws Exception {
        assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());

        try (final RotationSession rotationSession = new RotationSession()) {
            rotationSession.set(ROTATION_0);

            final LogSeparator logSeparator = separateLogs();
            // Launch our own activity to side in case Recents (or other activity to side) doesn't
            // support rotation.
            launchActivitiesInSplitScreen(
                    getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
                    getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
            // Launch target activity in docked stack.
            getLaunchActivityBuilder().setTargetActivity(RESIZEABLE_ACTIVITY).execute();
            final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                    logSeparator);

            rotateAndCheckSizes(rotationSession, initialSizes);
        }
    }

    /**
     * Same as {@link #testConfigurationUpdatesWhenRotatingWhileDocked()} but when the Activity
     * is launched to side from docked stack.
     */
    @Presubmit
    @Test
    public void testConfigurationUpdatesWhenRotatingToSideFromDocked() throws Exception {
        assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());

        try (final RotationSession rotationSession = new RotationSession()) {
            rotationSession.set(ROTATION_0);

            final LogSeparator logSeparator = separateLogs();
            launchActivitiesInSplitScreen(
                    getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
                    getLaunchActivityBuilder().setTargetActivity(RESIZEABLE_ACTIVITY));
            final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                    logSeparator);

            rotateAndCheckSizes(rotationSession, initialSizes);
        }
    }

    private void rotateAndCheckSizes(RotationSession rotationSession, ReportedSizes prevSizes)
            throws Exception {
        final ActivityManagerState.ActivityTask task =
                mAmWmState.getAmState().getTaskByActivity(RESIZEABLE_ACTIVITY);
        final int displayId = mAmWmState.getAmState().getStackById(task.mStackId).mDisplayId;

        assumeTrue(supportsLockedUserRotation(rotationSession, displayId));

        final int[] rotations = { ROTATION_270, ROTATION_180, ROTATION_90, ROTATION_0 };
        for (final int rotation : rotations) {
            final LogSeparator logSeparator = separateLogs();
            rotationSession.set(rotation);
            final int newDeviceRotation = getDeviceRotation(displayId);
            if (newDeviceRotation == INVALID_DEVICE_ROTATION) {
                logE("Got an invalid device rotation value. "
                        + "Continuing the test despite of that, but it is likely to fail.");
            }

            final ReportedSizes rotatedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                    logSeparator);
            assertSizesRotate(prevSizes, rotatedSizes,
                    // Skip orientation checks if we are not in fullscreen mode.
                    task.getWindowingMode() != WINDOWING_MODE_FULLSCREEN);
            prevSizes = rotatedSizes;
        }
    }

    /**
     * Tests when activity moved from fullscreen stack to docked and back. Activity will be
     * relaunched twice and it should have same config as initial one.
     */
    @Test
    public void testSameConfigurationFullSplitFullRelaunch() {
        moveActivityFullSplitFull(TEST_ACTIVITY);
    }

    /**
     * Same as {@link #testSameConfigurationFullSplitFullRelaunch} but without relaunch.
     */
    @Presubmit
    @Test
    public void testSameConfigurationFullSplitFullNoRelaunch() {
        moveActivityFullSplitFull(RESIZEABLE_ACTIVITY);
    }

    /**
     * Launches activity in fullscreen stack, moves to docked stack and back to fullscreen stack.
     * Last operation is done in a way which simulates split-screen divider movement maximizing
     * docked stack size and then moving task to fullscreen stack - the same way it is done when
     * user long-presses overview/recents button to exit split-screen.
     * Asserts that initial and final reported sizes in fullscreen stack are the same.
     */
    private void moveActivityFullSplitFull(ComponentName activityName) {
        assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());

        // Launch to fullscreen stack and record size.
        LogSeparator logSeparator = separateLogs();
        launchActivity(activityName, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
        final ReportedSizes initialFullscreenSizes = getActivityDisplaySize(activityName,
                logSeparator);
        final Rect displayRect = getDisplayRect(activityName);

        // Move to docked stack.
        logSeparator = separateLogs();
        setActivityTaskWindowingMode(activityName, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        final ReportedSizes dockedSizes = getActivityDisplaySize(activityName, logSeparator);
        assertSizesAreSane(initialFullscreenSizes, dockedSizes);
        // Make sure docked stack is focused. This way when we dismiss it later fullscreen stack
        // will come up.
        launchActivity(activityName, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        mAmWmState.computeState(false /* compareTaskAndStackBounds */,
                new WaitForValidActivityState.Builder(activityName).build());
        final ActivityManagerState.ActivityStack stack = mAmWmState.getAmState()
                .getStandardStackByWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);

        // Resize docked stack to fullscreen size. This will trigger activity relaunch with
        // non-empty override configuration corresponding to fullscreen size.
        logSeparator = separateLogs();
        mAm.resizeStack(stack.mStackId, displayRect);

        // Move activity back to fullscreen stack.
        setActivityTaskWindowingMode(activityName,
                WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
        final ReportedSizes finalFullscreenSizes = getActivityDisplaySize(activityName,
                logSeparator);

        // After activity configuration was changed twice it must report same size as original one.
        assertSizesAreSame(initialFullscreenSizes, finalFullscreenSizes);
    }

    /**
     * Tests when activity moved from docked stack to fullscreen and back. Activity will be
     * relaunched twice and it should have same config as initial one.
     */
    @Test
    public void testSameConfigurationSplitFullSplitRelaunch() {
        moveActivitySplitFullSplit(TEST_ACTIVITY);
    }

    /**
     * Same as {@link #testSameConfigurationSplitFullSplitRelaunch} but without relaunch.
     */
    @Test
    public void testSameConfigurationSplitFullSplitNoRelaunch() {
        moveActivitySplitFullSplit(RESIZEABLE_ACTIVITY);
    }

    /**
     * Tests that an activity with the DialogWhenLarge theme can transform properly when in split
     * screen.
     */
    @Presubmit
    @Test
    public void testDialogWhenLargeSplitSmall() {
        assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());

        launchActivity(DIALOG_WHEN_LARGE_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        final ActivityManagerState.ActivityStack stack = mAmWmState.getAmState()
                .getStandardStackByWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        final WindowManagerState.Display display =
                mAmWmState.getWmState().getDisplay(stack.mDisplayId);
        final int density = display.getDpi();
        final int smallWidthPx = dpToPx(SMALL_WIDTH_DP, density);
        final int smallHeightPx = dpToPx(SMALL_HEIGHT_DP, density);

        mAm.resizeStack(stack.mStackId, new Rect(0, 0, smallWidthPx, smallHeightPx));
        mAmWmState.waitForValidState(
                new WaitForValidActivityState.Builder(DIALOG_WHEN_LARGE_ACTIVITY)
                        .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
                        .setActivityType(ACTIVITY_TYPE_STANDARD)
                        .build());
    }

    /**
     * Test that device handles consequent requested orientations and displays the activities.
     */
    @Presubmit
    @Test
    @FlakyTest(bugId = 71875755)
    public void testFullscreenAppOrientationRequests() {
        assumeTrue("Skipping test: no rotation support", supportsRotation());

        LogSeparator logSeparator = separateLogs();
        launchActivity(PORTRAIT_ORIENTATION_ACTIVITY);
        mAmWmState.assertVisibility(PORTRAIT_ORIENTATION_ACTIVITY, true /* visible */);
        ReportedSizes reportedSizes =
                getLastReportedSizesForActivity(PORTRAIT_ORIENTATION_ACTIVITY, logSeparator);
        assertEquals("portrait activity should be in portrait",
                1 /* portrait */, reportedSizes.orientation);
        logSeparator = separateLogs();

        launchActivity(LANDSCAPE_ORIENTATION_ACTIVITY);
        mAmWmState.assertVisibility(LANDSCAPE_ORIENTATION_ACTIVITY, true /* visible */);
        reportedSizes =
                getLastReportedSizesForActivity(LANDSCAPE_ORIENTATION_ACTIVITY, logSeparator);
        assertEquals("landscape activity should be in landscape",
                2 /* landscape */, reportedSizes.orientation);
        logSeparator = separateLogs();

        launchActivity(PORTRAIT_ORIENTATION_ACTIVITY);
        mAmWmState.assertVisibility(PORTRAIT_ORIENTATION_ACTIVITY, true /* visible */);
        reportedSizes =
                getLastReportedSizesForActivity(PORTRAIT_ORIENTATION_ACTIVITY, logSeparator);
        assertEquals("portrait activity should be in portrait",
                1 /* portrait */, reportedSizes.orientation);
        logSeparator = separateLogs();
    }

    @Test
    public void testNonfullscreenAppOrientationRequests() {
        assumeTrue("Skipping test: no rotation support", supportsRotation());

        LogSeparator logSeparator = separateLogs();
        launchActivity(PORTRAIT_ORIENTATION_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
        final ReportedSizes initialReportedSizes =
                getLastReportedSizesForActivity(PORTRAIT_ORIENTATION_ACTIVITY, logSeparator);
        assertEquals("portrait activity should be in portrait",
                1 /* portrait */, initialReportedSizes.orientation);
        logSeparator = separateLogs();

        launchActivity(SDK26_TRANSLUCENT_LANDSCAPE_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
        assertEquals("Legacy non-fullscreen activity requested landscape orientation",
                0 /* landscape */, mAmWmState.getWmState().getLastOrientation());

        // TODO(b/36897968): uncomment once we can suppress unsupported configurations
        // final ReportedSizes updatedReportedSizes =
        //      getLastReportedSizesForActivity(PORTRAIT_ACTIVITY_NAME, logSeparator);
        // assertEquals("portrait activity should not have moved from portrait",
        //         1 /* portrait */, updatedReportedSizes.orientation);
    }

    /**
     * Test that device handles consequent requested orientations and will not report a config
     * change to an invisible activity.
     */
    @Test
    public void testAppOrientationRequestConfigChanges() {
        assumeTrue("Skipping test: no rotation support", supportsRotation());

        LogSeparator logSeparator = separateLogs();
        launchActivity(PORTRAIT_ORIENTATION_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
        mAmWmState.assertVisibility(PORTRAIT_ORIENTATION_ACTIVITY, true /* visible */);

        assertLifecycleCounts(PORTRAIT_ORIENTATION_ACTIVITY, logSeparator, 1 /* create */,
                1 /* start */, 1 /* resume */, 0 /* pause */, 0 /* stop */, 0 /* destroy */,
                0 /* config */);

        launchActivity(LANDSCAPE_ORIENTATION_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
        mAmWmState.assertVisibility(LANDSCAPE_ORIENTATION_ACTIVITY, true /* visible */);

        assertLifecycleCounts(PORTRAIT_ORIENTATION_ACTIVITY, logSeparator, 1 /* create */,
                1 /* start */, 1 /* resume */, 1 /* pause */, 1 /* stop */, 0 /* destroy */,
                0 /* config */);
        assertLifecycleCounts(LANDSCAPE_ORIENTATION_ACTIVITY, logSeparator, 1 /* create */,
                1 /* start */, 1 /* resume */, 0 /* pause */, 0 /* stop */, 0 /* destroy */,
                0 /* config */);

        launchActivity(PORTRAIT_ORIENTATION_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
        mAmWmState.assertVisibility(PORTRAIT_ORIENTATION_ACTIVITY, true /* visible */);

        assertLifecycleCounts(PORTRAIT_ORIENTATION_ACTIVITY, logSeparator, 2 /* create */,
                2 /* start */, 2 /* resume */, 1 /* pause */, 1 /* stop */, 0 /* destroy */,
                0 /* config */);
        assertLifecycleCounts(LANDSCAPE_ORIENTATION_ACTIVITY, logSeparator, 1 /* create */,
                1 /* start */, 1 /* resume */, 1 /* pause */, 1 /* stop */, 0 /* destroy */,
                0 /* config */);
    }

    /**
     * Test that device orientation is restored when an activity that requests it is no longer
     * visible.
     */
    @Test
    public void testAppOrientationRequestConfigClears() {
        assumeTrue("Skipping test: no rotation support", supportsRotation());

        LogSeparator logSeparator = separateLogs();
        launchActivity(TEST_ACTIVITY);
        mAmWmState.assertVisibility(TEST_ACTIVITY, true /* visible */);
        final ReportedSizes initialReportedSizes =
                getLastReportedSizesForActivity(TEST_ACTIVITY, logSeparator);
        final int  initialOrientation = initialReportedSizes.orientation;


        // Launch an activity that requests different orientation and check that it will be applied
        final boolean launchingPortrait;
        if (initialOrientation == 2 /* landscape */) {
            launchingPortrait = true;
        } else if (initialOrientation == 1 /* portrait */) {
            launchingPortrait = false;
        } else {
            fail("Unexpected orientation value: " + initialOrientation);
            return;
        }
        final ComponentName differentOrientationActivity = launchingPortrait
                ? PORTRAIT_ORIENTATION_ACTIVITY : LANDSCAPE_ORIENTATION_ACTIVITY;
        logSeparator = separateLogs();
        launchActivity(differentOrientationActivity);
        mAmWmState.assertVisibility(differentOrientationActivity, true /* visible */);
        final ReportedSizes rotatedReportedSizes =
                getLastReportedSizesForActivity(differentOrientationActivity, logSeparator);
        assertEquals("Applied orientation must correspond to activity request",
                launchingPortrait ? 1 : 2, rotatedReportedSizes.orientation);

        // Launch another activity on top and check that its orientation is not affected by previous
        // activity.
        logSeparator = separateLogs();
        launchActivity(RESIZEABLE_ACTIVITY);
        mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
        final ReportedSizes finalReportedSizes =
                getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY, logSeparator);
        assertEquals("Applied orientation must not be influenced by previously visible activity",
                initialOrientation, finalReportedSizes.orientation);
    }

    // TODO(b/70870253): This test seems malfunction.
    @Ignore("b/70870253")
    @Test
    public void testNonFullscreenActivityProhibited() {
        // We do not wait for the activity as it should not launch based on the restrictions around
        // specifying orientation. We instead start an activity known to launch immediately after
        // so that we can ensure processing the first activity occurred.
        launchActivityNoWait(TRANSLUCENT_LANDSCAPE_ACTIVITY);
        launchActivity(PORTRAIT_ORIENTATION_ACTIVITY);

        assertFalse("target SDK > 26 non-fullscreen activity should not reach onResume",
                mAmWmState.getAmState().containsActivity(TRANSLUCENT_LANDSCAPE_ACTIVITY));
    }

    @Test
    public void testNonFullscreenActivityPermitted() throws Exception {
        if(!supportsRotation()) {
            //cannot physically rotate the screen on automotive device, skip
            return;
        }
        try (final RotationSession rotationSession = new RotationSession()) {
            rotationSession.set(ROTATION_0);

            launchActivity(SDK26_TRANSLUCENT_LANDSCAPE_ACTIVITY);
            mAmWmState.assertResumedActivity(
                    "target SDK <= 26 non-fullscreen activity should be allowed to launch",
                    SDK26_TRANSLUCENT_LANDSCAPE_ACTIVITY);
            assertEquals("non-fullscreen activity requested landscape orientation",
                    0 /* landscape */, mAmWmState.getWmState().getLastOrientation());
        }
    }

    /**
     * Test that device handles moving between two tasks with different orientations.
     */
    @Test
    public void testTaskCloseRestoreFixedOrientation() {
        assumeTrue("Skipping test: no rotation support", supportsRotation());

        // Start landscape activity.
        launchActivity(LANDSCAPE_ORIENTATION_ACTIVITY);
        mAmWmState.assertVisibility(LANDSCAPE_ORIENTATION_ACTIVITY, true /* visible */);
        assertEquals("Fullscreen app requested landscape orientation",
                0 /* landscape */, mAmWmState.getWmState().getLastOrientation());

        // Start another activity in a different task.
        launchActivityInNewTask(BROADCAST_RECEIVER_ACTIVITY);

        // Request portrait
        executeShellCommand(REQUEST_PORTRAIT_BROADCAST);
        mAmWmState.waitForLastOrientation(SCREEN_ORIENTATION_PORTRAIT);
        waitForBroadcastActivityReady(SCREEN_ORIENTATION_PORTRAIT);

        // Finish activity
        executeShellCommand(FINISH_ACTIVITY_BROADCAST);

        // Verify that activity brought to front is in originally requested orientation.
        mAmWmState.computeState(LANDSCAPE_ORIENTATION_ACTIVITY);
        assertEquals("Should return to app in landscape orientation",
                0 /* landscape */, mAmWmState.getWmState().getLastOrientation());
    }

    /**
     * Test that device handles moving between two tasks with different orientations.
     */
    @Test
    public void testTaskCloseRestoreFreeOrientation() {
        assumeTrue("Skipping test: no rotation support", supportsRotation());

        // Start landscape activity.
        launchActivity(RESIZEABLE_ACTIVITY);
        mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
        final int initialServerOrientation = mAmWmState.getWmState().getLastOrientation();

        // Verify fixed-landscape
        LogSeparator logSeparator = separateLogs();
        launchActivityInNewTask(BROADCAST_RECEIVER_ACTIVITY);
        executeShellCommand(REQUEST_LANDSCAPE_BROADCAST);
        mAmWmState.waitForLastOrientation(SCREEN_ORIENTATION_LANDSCAPE);
        waitForBroadcastActivityReady(SCREEN_ORIENTATION_LANDSCAPE);
        executeShellCommand(FINISH_ACTIVITY_BROADCAST);

        // Verify that activity brought to front is in originally requested orientation.
        mAmWmState.waitForActivityState(RESIZEABLE_ACTIVITY, STATE_RESUMED);
        ReportedSizes reportedSizes = getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY,
                logSeparator);
        assertNull("Should come back in original orientation", reportedSizes);
        assertEquals("Should come back in original server orientation",
                initialServerOrientation, mAmWmState.getWmState().getLastOrientation());
        assertRelaunchOrConfigChanged(RESIZEABLE_ACTIVITY, 0 /* numRelaunch */,
                0 /* numConfigChange */, logSeparator);

        // Verify fixed-portrait
        logSeparator = separateLogs();
        launchActivityInNewTask(BROADCAST_RECEIVER_ACTIVITY);
        executeShellCommand(REQUEST_PORTRAIT_BROADCAST);
        mAmWmState.waitForLastOrientation(SCREEN_ORIENTATION_PORTRAIT);
        waitForBroadcastActivityReady(SCREEN_ORIENTATION_PORTRAIT);
        executeShellCommand(FINISH_ACTIVITY_BROADCAST);

        // Verify that activity brought to front is in originally requested orientation.
        mAmWmState.waitForActivityState(RESIZEABLE_ACTIVITY, STATE_RESUMED);
        reportedSizes = getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY, logSeparator);
        assertNull("Should come back in original orientation", reportedSizes);
        assertEquals("Should come back in original server orientation",
                initialServerOrientation, mAmWmState.getWmState().getLastOrientation());
        assertRelaunchOrConfigChanged(RESIZEABLE_ACTIVITY, 0 /* numRelaunch */,
                0 /* numConfigChange */, logSeparator);
    }

    /**
     * Test that activity orientation will change when device is rotated.
     * Also verify that occluded activity will not get config changes.
     */
    @Test
    public void testAppOrientationWhenRotating() throws Exception {
        assumeTrue("Skipping test: no rotation support", supportsRotation());

        // Start resizeable activity that handles configuration changes.
        LogSeparator logSeparator = separateLogs();
        launchActivity(TEST_ACTIVITY);
        launchActivity(RESIZEABLE_ACTIVITY);
        mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);

        final int displayId = mAmWmState.getAmState().getDisplayByActivity(RESIZEABLE_ACTIVITY);

        // Rotate the activity and check that it receives configuration changes with a different
        // orientation each time.
        try (final RotationSession rotationSession = new RotationSession()) {
            assumeTrue("Skipping test: no locked user rotation mode support.",
                    supportsLockedUserRotation(rotationSession, displayId));

            rotationSession.set(ROTATION_0);
            ReportedSizes reportedSizes =
                    getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY, logSeparator);
            int prevOrientation = reportedSizes.orientation;

            final int[] rotations = { ROTATION_270, ROTATION_180, ROTATION_90, ROTATION_0 };
            for (final int rotation : rotations) {
                logSeparator = separateLogs();
                rotationSession.set(rotation);

                // Verify lifecycle count and orientation changes.
                assertRelaunchOrConfigChanged(RESIZEABLE_ACTIVITY, 0 /* numRelaunch */,
                        1 /* numConfigChange */, logSeparator);
                reportedSizes =
                        getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY, logSeparator);
                assertNotEquals(prevOrientation, reportedSizes.orientation);
                assertRelaunchOrConfigChanged(TEST_ACTIVITY, 0 /* numRelaunch */,
                        0 /* numConfigChange */, logSeparator);

                prevOrientation = reportedSizes.orientation;
            }
        }
    }

    /**
     * Test that activity orientation will not change when trying to rotate fixed-orientation
     * activity.
     * Also verify that occluded activity will not get config changes.
     */
    @Test
    public void testFixedOrientationWhenRotating() throws Exception {
        assumeTrue("Skipping test: no rotation support", supportsRotation());
        // TODO(b/110533226): Fix test on devices with display cutout
        assumeFalse("Skipping test: display cutout present, can't predict exact lifecycle",
                hasDisplayCutout());

        // Start portrait-fixed activity
        LogSeparator logSeparator = separateLogs();
        launchActivity(RESIZEABLE_ACTIVITY);
        launchActivity(PORTRAIT_ORIENTATION_ACTIVITY);
        mAmWmState.assertVisibility(PORTRAIT_ORIENTATION_ACTIVITY, true /* visible */);

        final int displayId = mAmWmState.getAmState()
                .getDisplayByActivity(PORTRAIT_ORIENTATION_ACTIVITY);

        // Rotate the activity and check that the orientation doesn't change
        try (final RotationSession rotationSession = new RotationSession()) {
            assumeTrue("Skipping test: no user locked rotation support.",
                    supportsLockedUserRotation(rotationSession, displayId));

            rotationSession.set(ROTATION_0);

            final int[] rotations = { ROTATION_270, ROTATION_180, ROTATION_90, ROTATION_0 };
            for (final int rotation : rotations) {
                logSeparator = separateLogs();
                rotationSession.set(rotation);

                // Verify lifecycle count and orientation changes.
                assertRelaunchOrConfigChanged(PORTRAIT_ORIENTATION_ACTIVITY, 0 /* numRelaunch */,
                        0 /* numConfigChange */, logSeparator);
                final ReportedSizes reportedSizes = getLastReportedSizesForActivity(
                        PORTRAIT_ORIENTATION_ACTIVITY, logSeparator);
                assertNull("No new sizes must be reported", reportedSizes);
                assertRelaunchOrConfigChanged(RESIZEABLE_ACTIVITY, 0 /* numRelaunch */,
                        0 /* numConfigChange */, logSeparator);
            }
        }
    }

    /**
     * Test that device handles moving between two tasks with different orientations.
     */
    @Presubmit
    @Test
    @FlakyTest(bugId = 71792393)
    public void testTaskMoveToBackOrientation() {
        assumeTrue("Skipping test: no rotation support", supportsRotation());

        // Start landscape activity.
        launchActivity(LANDSCAPE_ORIENTATION_ACTIVITY);
        mAmWmState.assertVisibility(LANDSCAPE_ORIENTATION_ACTIVITY, true /* visible */);
        assertEquals("Fullscreen app requested landscape orientation",
                0 /* landscape */, mAmWmState.getWmState().getLastOrientation());

        // Start another activity in a different task.
        launchActivityInNewTask(BROADCAST_RECEIVER_ACTIVITY);

        // Request portrait
        executeShellCommand(REQUEST_PORTRAIT_BROADCAST);
        mAmWmState.waitForLastOrientation(SCREEN_ORIENTATION_PORTRAIT);
        waitForBroadcastActivityReady(SCREEN_ORIENTATION_PORTRAIT);

        // Finish activity
        executeShellCommand(MOVE_TASK_TO_BACK_BROADCAST);

        // Verify that activity brought to front is in originally requested orientation.
        mAmWmState.waitForValidState(LANDSCAPE_ORIENTATION_ACTIVITY);
        assertEquals("Should return to app in landscape orientation",
                0 /* landscape */, mAmWmState.getWmState().getLastOrientation());
    }

    /**
     * Test that device doesn't change device orientation by app request while in multi-window.
     */
    @Presubmit
    @FlakyTest(bugId = 71918731)
    @Test
    public void testSplitscreenPortraitAppOrientationRequests() throws Exception {
        assumeTrue("Skipping test: no rotation support", supportsRotation());
        assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());

        try (final RotationSession rotationSession = new RotationSession()) {
            requestOrientationInSplitScreen(rotationSession,
                    ROTATION_90 /* portrait */, LANDSCAPE_ORIENTATION_ACTIVITY);
        }
    }

    /**
     * Test that device doesn't change device orientation by app request while in multi-window.
     */
    @Presubmit
    @Test
    public void testSplitscreenLandscapeAppOrientationRequests() throws Exception {
        assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());

        try (final RotationSession rotationSession = new RotationSession()) {
            requestOrientationInSplitScreen(rotationSession,
                    ROTATION_0 /* landscape */, PORTRAIT_ORIENTATION_ACTIVITY);
        }
    }

    /**
     * Rotate the device and launch specified activity in split-screen, checking if orientation
     * didn't change.
     */
    private void requestOrientationInSplitScreen(RotationSession rotationSession, int orientation,
            ComponentName activity) throws Exception {
        assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());

        // Set initial orientation.
        rotationSession.set(orientation);

        // Launch activities that request orientations and check that device doesn't rotate.
        launchActivitiesInSplitScreen(
                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
                getLaunchActivityBuilder().setTargetActivity(activity).setMultipleTask(true));

        mAmWmState.assertVisibility(activity, true /* visible */);
        assertEquals("Split-screen apps shouldn't influence device orientation",
                orientation, mAmWmState.getWmState().getRotation());

        getLaunchActivityBuilder().setMultipleTask(true).setTargetActivity(activity).execute();
        mAmWmState.computeState(activity);
        mAmWmState.assertVisibility(activity, true /* visible */);
        assertEquals("Split-screen apps shouldn't influence device orientation",
                orientation, mAmWmState.getWmState().getRotation());
    }

    /**
     * Launches activity in docked stack, moves to fullscreen stack and back to docked stack.
     * Asserts that initial and final reported sizes in docked stack are the same.
     */
    private void moveActivitySplitFullSplit(ComponentName activityName) {
        assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());

        // Launch to docked stack and record size.
        LogSeparator logSeparator = separateLogs();
        launchActivityInSplitScreenWithRecents(activityName);
        final ReportedSizes initialDockedSizes = getActivityDisplaySize(activityName, logSeparator);
        // Make sure docked stack is focused. This way when we dismiss it later fullscreen stack
        // will come up.
        launchActivity(activityName, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        mAmWmState.computeState(false /* compareTaskAndStackBounds */,
                new WaitForValidActivityState.Builder(activityName).build());

        // Move to fullscreen stack.
        logSeparator = separateLogs();
        setActivityTaskWindowingMode(
                activityName, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
        final ReportedSizes fullscreenSizes = getActivityDisplaySize(activityName, logSeparator);
        assertSizesAreSane(fullscreenSizes, initialDockedSizes);

        // Move activity back to docked stack.
        logSeparator = separateLogs();
        setActivityTaskWindowingMode(activityName, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        final ReportedSizes finalDockedSizes = getActivityDisplaySize(activityName, logSeparator);

        // After activity configuration was changed twice it must report same size as original one.
        assertSizesAreSame(initialDockedSizes, finalDockedSizes);
    }

    /**
     * Asserts that after rotation, the aspect ratios of display size, metrics, and configuration
     * have flipped.
     */
    private static void assertSizesRotate(ReportedSizes rotationA, ReportedSizes rotationB,
            boolean skipOrientationCheck) {
        assertEquals(rotationA.displayWidth, rotationA.metricsWidth);
        assertEquals(rotationA.displayHeight, rotationA.metricsHeight);
        assertEquals(rotationB.displayWidth, rotationB.metricsWidth);
        assertEquals(rotationB.displayHeight, rotationB.metricsHeight);

        if (skipOrientationCheck) {
            // All done if we are not doing orientation check.
            return;
        }
        final boolean beforePortrait = rotationA.displayWidth < rotationA.displayHeight;
        final boolean afterPortrait = rotationB.displayWidth < rotationB.displayHeight;
        assertFalse(beforePortrait == afterPortrait);

        final boolean beforeConfigPortrait = rotationA.widthDp < rotationA.heightDp;
        final boolean afterConfigPortrait = rotationB.widthDp < rotationB.heightDp;
        assertEquals(beforePortrait, beforeConfigPortrait);
        assertEquals(afterPortrait, afterConfigPortrait);

        assertEquals(rotationA.smallestWidthDp, rotationB.smallestWidthDp);
    }

    /**
     * Throws an AssertionError if fullscreenSizes has widths/heights (depending on aspect ratio)
     * that are smaller than the dockedSizes.
     */
    private static void assertSizesAreSane(ReportedSizes fullscreenSizes, ReportedSizes dockedSizes)
    {
        final boolean portrait = fullscreenSizes.displayWidth < fullscreenSizes.displayHeight;
        if (portrait) {
            assertThat(dockedSizes.displayHeight, lessThan(fullscreenSizes.displayHeight));
            assertThat(dockedSizes.heightDp, lessThan(fullscreenSizes.heightDp));
            assertThat(dockedSizes.metricsHeight, lessThan(fullscreenSizes.metricsHeight));
        } else {
            assertThat(dockedSizes.displayWidth, lessThan(fullscreenSizes.displayWidth));
            assertThat(dockedSizes.widthDp, lessThan(fullscreenSizes.widthDp));
            assertThat(dockedSizes.metricsWidth, lessThan(fullscreenSizes.metricsWidth));
        }
    }

    /**
     * Throws an AssertionError if sizes are different.
     */
    private static void assertSizesAreSame(ReportedSizes firstSize, ReportedSizes secondSize) {
        assertEquals(firstSize.widthDp, secondSize.widthDp);
        assertEquals(firstSize.heightDp, secondSize.heightDp);
        assertEquals(firstSize.displayWidth, secondSize.displayWidth);
        assertEquals(firstSize.displayHeight, secondSize.displayHeight);
        assertEquals(firstSize.metricsWidth, secondSize.metricsWidth);
        assertEquals(firstSize.metricsHeight, secondSize.metricsHeight);
        assertEquals(firstSize.smallestWidthDp, secondSize.smallestWidthDp);
    }

    private ReportedSizes getActivityDisplaySize(ComponentName activityName,
            LogSeparator logSeparator) {
        mAmWmState.computeState(false /* compareTaskAndStackBounds */,
                new WaitForValidActivityState(activityName));
        final ReportedSizes details = getLastReportedSizesForActivity(activityName, logSeparator);
        assertNotNull(details);
        return details;
    }

    private Rect getDisplayRect(ComponentName activityName) {
        final String windowName = getWindowName(activityName);

        mAmWmState.computeState(activityName);
        mAmWmState.assertFocusedWindow("Test window must be the front window.", windowName);

        final List<WindowManagerState.WindowState> windowList =
                mAmWmState.getWmState().getMatchingVisibleWindowState(windowName);

        assertEquals("Should have exactly one window state for the activity.", 1,
                windowList.size());

        WindowManagerState.WindowState windowState = windowList.get(0);
        assertNotNull("Should have a valid window", windowState);

        WindowManagerState.Display display = mAmWmState.getWmState()
                .getDisplay(windowState.getDisplayId());
        assertNotNull("Should be on a display", display);

        return display.getDisplayRect();
    }

    private void waitForBroadcastActivityReady(int orientation) {
        mAmWmState.waitForActivityOrientation(BROADCAST_RECEIVER_ACTIVITY, orientation);
        mAmWmState.waitForActivityState(BROADCAST_RECEIVER_ACTIVITY, STATE_RESUMED);
    }

    /**
     * Test launching an activity which requests specific UI mode during creation.
     */
    @Test
    public void testLaunchWithUiModeChange() {
        // Launch activity that changes UI mode and handles this configuration change.
        launchActivity(NIGHT_MODE_ACTIVITY);
        mAmWmState.waitForActivityState(NIGHT_MODE_ACTIVITY, STATE_RESUMED);

        // Check if activity is launched successfully.
        mAmWmState.assertVisibility(NIGHT_MODE_ACTIVITY, true /* visible */);
        mAmWmState.assertFocusedActivity("Launched activity should be focused",
                NIGHT_MODE_ACTIVITY);
        mAmWmState.assertResumedActivity("Launched activity must be resumed", NIGHT_MODE_ACTIVITY);
    }
}
