/*
 * 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.cts;

import android.platform.test.annotations.Presubmit;

import com.android.tradefed.device.CollectingOutputReceiver;
import com.android.tradefed.device.DeviceNotAvailableException;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static android.server.cts.ActivityAndWindowManagersState.DEFAULT_DISPLAY_ID;
import static android.server.cts.ActivityManagerState.STATE_RESUMED;
import static android.server.cts.StateLogger.log;
import static android.server.cts.StateLogger.logE;

/**
 * Build: mmma -j32 cts/hostsidetests/services
 * Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsServicesHostTestCases android.server.cts.ActivityManagerDisplayTests
 */
public class ActivityManagerDisplayTests extends ActivityManagerDisplayTestBase {
    private static final String WM_SIZE = "wm size";
    private static final String WM_DENSITY = "wm density";

    private static final String TEST_ACTIVITY_NAME = "TestActivity";
    private static final String VIRTUAL_DISPLAY_ACTIVITY = "VirtualDisplayActivity";
    private static final String RESIZEABLE_ACTIVITY_NAME = "ResizeableActivity";
    private static final String NON_RESIZEABLE_ACTIVITY_NAME = "NonResizeableActivity";
    private static final String SECOND_ACTIVITY_NAME = "SecondActivity";
    private static final String THIRD_ACTIVITY_NAME = "ThirdActivity";
    private static final String VR_TEST_ACTIVITY_NAME = "VrTestActivity";
    private static final String SECOND_PACKAGE_NAME = "android.server.cts.second";
    private static final String THIRD_PACKAGE_NAME = "android.server.cts.third";
    private static final int VR_VIRTUAL_DISPLAY_WIDTH = 70;
    private static final int VR_VIRTUAL_DISPLAY_HEIGHT = 90;
    private static final int VR_VIRTUAL_DISPLAY_DPI = 320;

    /** Physical display metrics and overrides in the beginning of the test. */
    private ReportedDisplayMetrics mInitialDisplayMetrics;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mInitialDisplayMetrics = getDisplayMetrics();
    }

    @Override
    protected void tearDown() throws Exception {
        try {
            enablePersistentVrMode(false);
            restoreDisplayMetricsOverrides();
        } catch (DeviceNotAvailableException e) {
            logE(e.getMessage());
        }
        super.tearDown();
    }

    private void enablePersistentVrMode(boolean enabled) throws Exception {
        if (enabled) {
            executeShellCommand("setprop vr_virtualdisplay true");
            executeShellCommand("vr set-persistent-vr-mode-enabled true");
        } else {
            executeShellCommand("vr set-persistent-vr-mode-enabled false");
            executeShellCommand("setprop vr_virtualdisplay false");
        }
    }

    private void restoreDisplayMetricsOverrides() throws Exception {
        if (mInitialDisplayMetrics.sizeOverrideSet) {
            executeShellCommand(WM_SIZE + " " + mInitialDisplayMetrics.overrideWidth + "x"
                    + mInitialDisplayMetrics.overrideHeight);
        } else {
            executeShellCommand("wm size reset");
        }
        if (mInitialDisplayMetrics.densityOverrideSet) {
            executeShellCommand(WM_DENSITY + " " + mInitialDisplayMetrics.overrideDensity);
        } else {
            executeShellCommand("wm density reset");
        }
    }

    /**
     * Tests that the global configuration is equal to the default display's override configuration.
     */
    public void testDefaultDisplayOverrideConfiguration() throws Exception {
        final ReportedDisplays reportedDisplays = getDisplaysStates();
        assertNotNull("Global configuration must not be empty.", reportedDisplays.mGlobalConfig);
        final DisplayState primaryDisplay = reportedDisplays.getDisplayState(DEFAULT_DISPLAY_ID);
        assertEquals("Primary display's configuration should not be equal to global configuration.",
                reportedDisplays.mGlobalConfig, primaryDisplay.mOverrideConfig);
    }

    /**
     * Tests that secondary display has override configuration set.
     */
    public void testCreateVirtualDisplayWithCustomConfig() throws Exception {
        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();

        // Find the density of created display.
        final int newDensityDpi = newDisplay.getDpi();
        assertEquals(CUSTOM_DENSITY_DPI, newDensityDpi);
    }

    /**
     * Tests that launch on secondary display is not permitted if device has the feature disabled.
     * Activities requested to be launched on a secondary display in this case should land on the
     * default display.
     */
    public void testMultiDisplayDisabled() throws Exception {
        if (supportsMultiDisplay()) {
            // Only check devices with the feature disabled.
            return;
        }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();

        // Launch activity on new secondary display.
        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});

        mAmWmState.assertFocusedActivity("Launched activity must be focused", TEST_ACTIVITY_NAME);

        // Check that activity is on the right display.
        final int frontStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
        final ActivityManagerState.ActivityStack frontStack
                = mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Launched activity must be resumed",
                getActivityComponentName(TEST_ACTIVITY_NAME), frontStack.mResumedActivity);
        assertEquals("Front stack must be on the default display", DEFAULT_DISPLAY_ID,
                frontStack.mDisplayId);
        mAmWmState.assertFocusedStack("Focus must be on the default display", frontStackId);
    }

    /**
     * Tests that any new activity launch in Vr mode is in Vr display.
     */
    public void testVrActivityLaunch() throws Exception {
        if (!supportsVrMode() || !supportsMultiDisplay()) {
            // VR Mode is not supported on this device, bail from this test.
            return;
        }

        // Put the device in persistent vr mode.
        enablePersistentVrMode(true);

        // Launch the VR activity.
        launchActivity(VR_TEST_ACTIVITY_NAME);
        mAmWmState.computeState(mDevice, new String[] {VR_TEST_ACTIVITY_NAME});
        mAmWmState.assertVisibility(VR_TEST_ACTIVITY_NAME, true /* visible */);

        // Launch the non-VR 2D activity and check where it ends up.
        launchActivity(LAUNCHING_ACTIVITY);
        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});

        // Ensure that the subsequent activity is visible
        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);

        // Check that activity is launched in focused stack on primary display.
        mAmWmState.assertFocusedActivity("Launched activity must be focused", LAUNCHING_ACTIVITY);
        final int focusedStackId = mAmWmState.getAmState().getFocusedStackId();
        final ActivityManagerState.ActivityStack focusedStack
                = mAmWmState.getAmState().getStackById(focusedStackId);
        assertEquals("Launched activity must be resumed in focused stack",
            getActivityComponentName(LAUNCHING_ACTIVITY), focusedStack.mResumedActivity);

        // Check if the launch activity is in Vr virtual display id.
        final ReportedDisplays reportedDisplays = getDisplaysStates();
        assertNotNull("Global configuration must not be empty.", reportedDisplays.mGlobalConfig);
        final DisplayState vrDisplay = reportedDisplays.getDisplayState(VR_VIRTUAL_DISPLAY_WIDTH,
            VR_VIRTUAL_DISPLAY_HEIGHT, VR_VIRTUAL_DISPLAY_DPI);
        assertNotNull("Vr mode should have a virtual display", vrDisplay);

        // Check if the focused activity is on this virtual stack.
        assertEquals("Launch in Vr mode should be in virtual stack", vrDisplay.mDisplayId,
            focusedStack.mDisplayId);

        // Put the device out of persistent vr mode.
        enablePersistentVrMode(false);
    }

    /**
     * Tests that any activity already present is re-launched in Vr display in vr mode.
     */
    public void testVrActivityReLaunch() throws Exception {
        if (!supportsVrMode() || !supportsMultiDisplay()) {
            // VR Mode is not supported on this device, bail from this test.
            return;
        }

        // Launch a 2D activity.
        launchActivity(LAUNCHING_ACTIVITY);

        // Put the device in persistent vr mode.
        enablePersistentVrMode(true);

        // Launch the VR activity.
        launchActivity(VR_TEST_ACTIVITY_NAME);
        mAmWmState.computeState(mDevice, new String[] {VR_TEST_ACTIVITY_NAME});
        mAmWmState.assertVisibility(VR_TEST_ACTIVITY_NAME, true /* visible */);

        // Re-launch the non-VR 2D activity and check where it ends up.
        launchActivity(LAUNCHING_ACTIVITY);
        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});

        // Ensure that the subsequent activity is visible
        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);

        // Check that activity is launched in focused stack on primary display.
        mAmWmState.assertFocusedActivity("Launched activity must be focused", LAUNCHING_ACTIVITY);
        final int focusedStackId = mAmWmState.getAmState().getFocusedStackId();
        final ActivityManagerState.ActivityStack focusedStack
                = mAmWmState.getAmState().getStackById(focusedStackId);
        assertEquals("Launched activity must be resumed in focused stack",
            getActivityComponentName(LAUNCHING_ACTIVITY), focusedStack.mResumedActivity);

        // Check if the launch activity is in Vr virtual display id.
        final ReportedDisplays reportedDisplays = getDisplaysStates();
        assertNotNull("Global configuration must not be empty.", reportedDisplays.mGlobalConfig);
        final DisplayState vrDisplay = reportedDisplays.getDisplayState(VR_VIRTUAL_DISPLAY_WIDTH,
            VR_VIRTUAL_DISPLAY_HEIGHT, VR_VIRTUAL_DISPLAY_DPI);
        assertNotNull("Vr mode should have a virtual display", vrDisplay);

        // Check if the focused activity is on this virtual stack.
        assertEquals("Launch in Vr mode should be in virtual stack", vrDisplay.mDisplayId,
            focusedStack.mDisplayId);

        // Put the device out of persistent vr mode.
        enablePersistentVrMode(false);
    }

    /**
     * Tests that any new activity launch post Vr mode is in the main display.
     */
    public void testActivityLaunchPostVr() throws Exception {
        if (!supportsVrMode() || !supportsMultiDisplay()) {
            // VR Mode is not supported on this device, bail from this test.
            return;
        }

        // Put the device in persistent vr mode.
        enablePersistentVrMode(true);

        // Launch the VR activity.
        launchActivity(VR_TEST_ACTIVITY_NAME);
        mAmWmState.computeState(mDevice, new String[] {VR_TEST_ACTIVITY_NAME});
        mAmWmState.assertVisibility(VR_TEST_ACTIVITY_NAME, true /* visible */);

        // Launch the non-VR 2D activity and check where it ends up.
        launchActivity(ALT_LAUNCHING_ACTIVITY);
        mAmWmState.computeState(mDevice, new String[] {ALT_LAUNCHING_ACTIVITY});

        // Ensure that the subsequent activity is visible
        mAmWmState.assertVisibility(ALT_LAUNCHING_ACTIVITY, true /* visible */);

        // Check that activity is launched in focused stack on primary display.
        mAmWmState.assertFocusedActivity("Launched activity must be focused", ALT_LAUNCHING_ACTIVITY);
        final int focusedStackId = mAmWmState.getAmState().getFocusedStackId();
        final ActivityManagerState.ActivityStack focusedStack
                = mAmWmState.getAmState().getStackById(focusedStackId);
        assertEquals("Launched activity must be resumed in focused stack",
            getActivityComponentName(ALT_LAUNCHING_ACTIVITY), focusedStack.mResumedActivity);

        // Check if the launch activity is in Vr virtual display id.
        final ReportedDisplays reportedDisplays = getDisplaysStates();
        assertNotNull("Global configuration must not be empty.", reportedDisplays.mGlobalConfig);
        final DisplayState vrDisplay = reportedDisplays.getDisplayState(VR_VIRTUAL_DISPLAY_WIDTH,
            VR_VIRTUAL_DISPLAY_HEIGHT, VR_VIRTUAL_DISPLAY_DPI);
        assertNotNull("Vr mode should have a virtual display", vrDisplay);

        // Check if the focused activity is on this virtual stack.
        assertEquals("Launch in Vr mode should be in virtual stack", vrDisplay.mDisplayId,
            focusedStack.mDisplayId);

        // Put the device out of persistent vr mode.
        enablePersistentVrMode(false);

        // There isn't a direct launch of activity which can take an user out of persistent VR mode.
        // This sleep is to account for that delay and let device settle once it comes out of VR
        // mode.
        try {
            Thread.sleep(2000);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Launch the non-VR 2D activity and check where it ends up.
        launchActivity(RESIZEABLE_ACTIVITY_NAME);
        mAmWmState.computeState(mDevice, new String[] {RESIZEABLE_ACTIVITY_NAME});

        // Ensure that the subsequent activity is visible
        mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true /* visible */);

        // Check that activity is launched in focused stack on primary display.
        mAmWmState.assertFocusedActivity("Launched activity must be focused", RESIZEABLE_ACTIVITY_NAME);
        final int frontStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
        final ActivityManagerState.ActivityStack frontStack
                = mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Launched activity must be resumed in front stack",
                getActivityComponentName(RESIZEABLE_ACTIVITY_NAME), frontStack.mResumedActivity);
        assertEquals("Front stack must be on primary display",
                DEFAULT_DISPLAY_ID, frontStack.mDisplayId);
    }

    public void testCreateMultipleVirtualDisplays() throws Exception {
        // Create new virtual display.
        final List<DisplayState> newDisplays = new VirtualDisplayBuilder(this).build(3);
        destroyVirtualDisplays();
        getDisplayStateAfterChange(1);
    }

    /**
     * Tests launching an activity on virtual display.
     */
    @Presubmit
    public void testLaunchActivityOnSecondaryDisplay() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();

        // Launch activity on new secondary display.
        final String logSeparator = clearLogcat();
        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});

        mAmWmState.assertFocusedActivity("Activity launched on secondary display must be focused",
                TEST_ACTIVITY_NAME);

        // Check that activity is on the right display.
        final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mDisplayId);
        final ActivityManagerState.ActivityStack frontStack
                = mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Launched activity must be on the secondary display and resumed",
                getActivityComponentName(TEST_ACTIVITY_NAME), frontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);

        // Check that activity config corresponds to display config.
        final ReportedSizes reportedSizes = getLastReportedSizesForActivity(TEST_ACTIVITY_NAME,
                logSeparator);
        assertEquals("Activity launched on secondary display must have proper configuration",
                CUSTOM_DENSITY_DPI, reportedSizes.densityDpi);
    }

    /**
     * Tests launching a non-resizeable activity on virtual display. It should land on the
     * default display.
     */
    public void testLaunchNonResizeableActivityOnSecondaryDisplay() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();

        // Launch activity on new secondary display.
        launchActivityOnDisplay(NON_RESIZEABLE_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.computeState(mDevice, new String[] {NON_RESIZEABLE_ACTIVITY_NAME});

        mAmWmState.assertFocusedActivity("Activity launched on secondary display must be focused",
                NON_RESIZEABLE_ACTIVITY_NAME);

        // Check that activity is on the right display.
        final int frontStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
        final ActivityManagerState.ActivityStack frontStack =
                mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Launched activity must be on the primary display and resumed",
                getActivityComponentName(NON_RESIZEABLE_ACTIVITY_NAME),
                frontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on the primary display", frontStackId);
    }

    /**
     * Tests launching a non-resizeable activity on virtual display while split-screen is active
     * on the primary display. It should land on the primary display and dismiss docked stack.
     */
    public void testLaunchNonResizeableActivityWithSplitScreen() throws Exception {
        if (!supportsMultiDisplay() || !supportsSplitScreenMultiWindow()) { return; }

        // Start launching activity.
        launchActivityInDockStack(LAUNCHING_ACTIVITY);
        // Create new virtual display.
        final DisplayState newDisplay =
                new VirtualDisplayBuilder(this).setLaunchInSplitScreen(true).build();

        // Launch activity on new secondary display.
        launchActivityOnDisplay(NON_RESIZEABLE_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.computeState(mDevice, new String[] {NON_RESIZEABLE_ACTIVITY_NAME});

        mAmWmState.assertFocusedActivity("Activity launched on secondary display must be focused",
                NON_RESIZEABLE_ACTIVITY_NAME);

        // Check that activity is on the right display.
        final int frontStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
        final ActivityManagerState.ActivityStack frontStack =
                mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Launched activity must be on the primary display and resumed",
                getActivityComponentName(NON_RESIZEABLE_ACTIVITY_NAME),
                frontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on the primary display", frontStackId);
        mAmWmState.assertDoesNotContainStack("Must not contain docked stack.", DOCKED_STACK_ID);
    }

    /**
     * Tests moving a non-resizeable activity to a virtual display. It should land on the default
     * display.
     */
    public void testMoveNonResizeableActivityToSecondaryDisplay() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
        // Launch a non-resizeable activity on a primary display.
        launchActivityInNewTask(NON_RESIZEABLE_ACTIVITY_NAME);
        // Launch a resizeable activity on new secondary display to create a new stack there.
        launchActivityOnDisplay(RESIZEABLE_ACTIVITY_NAME, newDisplay.mDisplayId);
        int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mDisplayId);

        // Try to move the non-resizeable activity to new secondary display.
        moveActivityToStack(NON_RESIZEABLE_ACTIVITY_NAME, frontStackId);
        mAmWmState.computeState(mDevice, new String[] {NON_RESIZEABLE_ACTIVITY_NAME});

        mAmWmState.assertFocusedActivity("Activity launched on secondary display must be focused",
                NON_RESIZEABLE_ACTIVITY_NAME);

        // Check that activity is on the right display.
        frontStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
        final ActivityManagerState.ActivityStack frontStack =
                mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Launched activity must be on the primary display and resumed",
                getActivityComponentName(NON_RESIZEABLE_ACTIVITY_NAME),
                frontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on the primary display", frontStackId);
    }

    /**
     * Tests launching a non-resizeable activity on virtual display from activity there. It should
     * land on the secondary display based on the resizeability of the root activity of the task.
     */
    public void testLaunchNonResizeableActivityFromSecondaryDisplaySameTask() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();

        // Launch activity on new secondary display.
        launchActivityOnDisplay(LAUNCHING_ACTIVITY, newDisplay.mDisplayId);
        mAmWmState.assertFocusedActivity("Activity launched on secondary display must be focused",
                LAUNCHING_ACTIVITY);

        // Check that launching activity is on the secondary display.
        int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mDisplayId);
        ActivityManagerState.ActivityStack frontStack =
                mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Launched activity must be on the secondary display and resumed",
                getActivityComponentName(LAUNCHING_ACTIVITY),
                frontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on the secondary display", frontStackId);

        // Launch non-resizeable activity from secondary display.
        getLaunchActivityBuilder().setTargetActivityName(NON_RESIZEABLE_ACTIVITY_NAME).execute();

        // Check that non-resizeable activity is on the secondary display, because of the resizeable
        // root of the task.
        frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mDisplayId);
        frontStack = mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Launched activity must be on the primary display and resumed",
                getActivityComponentName(NON_RESIZEABLE_ACTIVITY_NAME),
                frontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on the primary display", frontStackId);
    }

    /**
     * Tests launching a non-resizeable activity on virtual display from activity there. It should
     * land on some different suitable display (usually - on the default one).
     */
    public void testLaunchNonResizeableActivityFromSecondaryDisplayNewTask() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();

        // Launch activity on new secondary display.
        launchActivityOnDisplay(LAUNCHING_ACTIVITY, newDisplay.mDisplayId);
        mAmWmState.assertFocusedActivity("Activity launched on secondary display must be focused",
                LAUNCHING_ACTIVITY);

        // Check that launching activity is on the secondary display.
        int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mDisplayId);
        ActivityManagerState.ActivityStack frontStack =
                mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Launched activity must be on the secondary display and resumed",
                getActivityComponentName(LAUNCHING_ACTIVITY),
                frontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on the secondary display", frontStackId);

        // Launch non-resizeable activity from secondary display.
        getLaunchActivityBuilder().setTargetActivityName(NON_RESIZEABLE_ACTIVITY_NAME)
                .setNewTask(true).setMultipleTask(true).execute();

        // Check that non-resizeable activity is on the primary display.
        frontStackId = mAmWmState.getAmState().getFocusedStackId();
        frontStack = mAmWmState.getAmState().getStackById(frontStackId);
        assertFalse("Launched activity must be on a different display",
                newDisplay.mDisplayId == frontStack.mDisplayId);
        assertEquals("Launched activity must be resumed",
                getActivityComponentName(NON_RESIZEABLE_ACTIVITY_NAME),
                frontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on a just launched activity", frontStackId);
    }

    /**
     * Tests launching a not embedded activity on virtual display. It should land on the
     * default display.
     */
    public void testLaunchNotEmbeddedOnVirtualDisplay() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();

        final String logSeparator = clearLogcat();

        // Launch other activity with different uid and check it is launched on primary display.
        final String broadcastAction = SECOND_PACKAGE_NAME + ".LAUNCH_BROADCAST_ACTION";
        final String includeStoppedPackagesFlag = " -f 0x00000020";
        executeShellCommand("am broadcast -a " + broadcastAction + " -p " + SECOND_PACKAGE_NAME
                + " --ei target_display " + newDisplay.mDisplayId + includeStoppedPackagesFlag
                + " --es package_name " + componentName
                + " --es target_activity " + TEST_ACTIVITY_NAME);

        int tries = 0;
        boolean match = false;
        final Pattern pattern = Pattern.compile(".*SecurityException launching activity.*");
        while (tries < 5 && !match) {
            String[] logs = getDeviceLogsForComponent("LaunchBroadcastReceiver", logSeparator);
            for (String line : logs) {
                Matcher m = pattern.matcher(line);
                if (m.matches()) {
                    match = true;
                    break;
                }
            }
            tries++;
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }

        assertTrue("Expected exception not found", match);

        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
        assertFalse("Restricted activity must not be launched",
                mAmWmState.getAmState().containsActivity(TEST_ACTIVITY_NAME));
    }

    /**
     * Tests launching an activity on virtual display and then launching another activity via shell
     * command and without specifying the display id - the second activity must appear on the
     * primary display.
     */
    @Presubmit
    public void testConsequentLaunchActivity() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();

        // Launch activity on new secondary display.
        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});

        mAmWmState.assertFocusedActivity("Activity launched on secondary display must be focused",
                TEST_ACTIVITY_NAME);

        // Launch second activity without specifying display.
        launchActivity(LAUNCHING_ACTIVITY);
        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});

        // Check that activity is launched in focused stack on primary display.
        mAmWmState.assertFocusedActivity("Launched activity must be focused", LAUNCHING_ACTIVITY);
        final int frontStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
        final ActivityManagerState.ActivityStack frontStack
                = mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Launched activity must be resumed in front stack",
                getActivityComponentName(LAUNCHING_ACTIVITY), frontStack.mResumedActivity);
        assertEquals("Front stack must be on primary display",
                DEFAULT_DISPLAY_ID, frontStack.mDisplayId);
    }

    /**
     * Tests launching an activity on virtual display and then launching another activity from the
     * first one - it must appear on the secondary display, because it was launched from there.
     */
    @Presubmit
    public void testConsequentLaunchActivityFromSecondaryDisplay() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();

        // Launch activity on new secondary display.
        launchActivityOnDisplay(LAUNCHING_ACTIVITY, newDisplay.mDisplayId);
        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});

        mAmWmState.assertFocusedActivity("Activity launched on secondary display must be resumed",
                LAUNCHING_ACTIVITY);

        // Launch second activity from app on secondary display without specifying display id.
        getLaunchActivityBuilder().setTargetActivityName(TEST_ACTIVITY_NAME).execute();
        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});

        // Check that activity is launched in focused stack on external display.
        mAmWmState.assertFocusedActivity("Launched activity must be focused", TEST_ACTIVITY_NAME);
        final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mDisplayId);
        final ActivityManagerState.ActivityStack frontStack
                = mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Launched activity must be resumed in front stack",
                getActivityComponentName(TEST_ACTIVITY_NAME), frontStack.mResumedActivity);
    }

    /**
     * Tests launching activities on secondary and then on primary display to see if the stack
     * visibility is not affected.
     */
    @Presubmit
    public void testLaunchActivitiesAffectsVisibility() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Start launching activity.
        launchActivity(LAUNCHING_ACTIVITY);
        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);

        // Launch activity on new secondary display.
        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);

        // Launch activity on primary display and check if it doesn't affect activity on secondary
        // display.
        getLaunchActivityBuilder().setTargetActivityName(RESIZEABLE_ACTIVITY_NAME).execute();
        mAmWmState.waitForValidState(mDevice, RESIZEABLE_ACTIVITY_NAME);
        mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
        mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true /* visible */);
    }

    /**
     * Test that move-task works when moving between displays.
     */
    @Presubmit
    public void testMoveTaskBetweenDisplays() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
        mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
                VIRTUAL_DISPLAY_ACTIVITY);
        final int defaultDisplayStackId = mAmWmState.getAmState().getFocusedStackId();
        ActivityManagerState.ActivityStack focusedStack
                = mAmWmState.getAmState().getStackById(defaultDisplayStackId);
        assertEquals("Focus must remain on primary display", DEFAULT_DISPLAY_ID,
                focusedStack.mDisplayId);

        // Launch activity on new secondary display.
        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.assertFocusedActivity("Focus must be on secondary display", TEST_ACTIVITY_NAME);
        int focusedStackId = mAmWmState.getAmState().getFocusedStackId();
        focusedStack = mAmWmState.getAmState().getStackById(focusedStackId);
        assertEquals("Focused stack must be on secondary display",
                newDisplay.mDisplayId, focusedStack.mDisplayId);

        // Move activity from secondary display to primary.
        moveActivityToStack(TEST_ACTIVITY_NAME, defaultDisplayStackId);
        mAmWmState.waitForFocusedStack(mDevice, defaultDisplayStackId);
        mAmWmState.assertFocusedActivity("Focus must be on moved activity", TEST_ACTIVITY_NAME);
        focusedStackId = mAmWmState.getAmState().getFocusedStackId();
        focusedStack = mAmWmState.getAmState().getStackById(focusedStackId);
        assertEquals("Focus must return to primary display", DEFAULT_DISPLAY_ID,
                focusedStack.mDisplayId);
    }

    /**
     * Tests launching activities on secondary display and then removing it to see if stack focus
     * is moved correctly.
     * This version launches virtual display creator to fullscreen stack in split-screen.
     */
    @Presubmit
    public void testStackFocusSwitchOnDisplayRemoved() throws Exception {
        if (!supportsMultiDisplay() || !supportsSplitScreenMultiWindow()) { return; }

        // Start launching activity into docked stack.
        launchActivityInDockStack(LAUNCHING_ACTIVITY);
        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);

        tryCreatingAndRemovingDisplayWithActivity(true /* splitScreen */,
                FULLSCREEN_WORKSPACE_STACK_ID);
    }

    /**
     * Tests launching activities on secondary display and then removing it to see if stack focus
     * is moved correctly.
     * This version launches virtual display creator to docked stack in split-screen.
     */
    public void testStackFocusSwitchOnDisplayRemoved2() throws Exception {
        if (!supportsMultiDisplay() || !supportsSplitScreenMultiWindow()) { return; }

        // Setup split-screen.
        launchActivityInDockStack(RESIZEABLE_ACTIVITY_NAME);

        // Start launching activity into fullscreen stack.
        launchActivityInStack(LAUNCHING_ACTIVITY, FULLSCREEN_WORKSPACE_STACK_ID);
        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);

        tryCreatingAndRemovingDisplayWithActivity(true /* splitScreen */,
                FULLSCREEN_WORKSPACE_STACK_ID);
    }

    /**
     * Tests launching activities on secondary display and then removing it to see if stack focus
     * is moved correctly.
     * This version works without split-screen.
     */
    public void testStackFocusSwitchOnDisplayRemoved3() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Start an activity on default display to determine default stack.
        launchActivity(BROADCAST_RECEIVER_ACTIVITY);
        final int focusedStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
        // Finish probing activity.
        executeShellCommand(FINISH_ACTIVITY_BROADCAST);


        tryCreatingAndRemovingDisplayWithActivity(false /* splitScreen */, focusedStackId);
    }

    /**
     * Create a virtual display, launch a test activity there, destroy the display and check if test
     * activity is moved to a stack on the default display.
     */
    private void tryCreatingAndRemovingDisplayWithActivity(boolean splitScreen, int defaultStackId)
            throws Exception {
        // Create new virtual display.
        final VirtualDisplayBuilder builder = new VirtualDisplayBuilder(this)
                .setPublicDisplay(true);
        if (splitScreen) {
            builder.setLaunchInSplitScreen(true);
        }
        final DisplayState newDisplay = builder.build();
        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
        if (splitScreen) {
            mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
        }

        // Launch activity on new secondary display.
        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.assertFocusedActivity("Focus must be on secondary display",
                TEST_ACTIVITY_NAME);
        final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mDisplayId);
        mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);

        // Destroy virtual display.
        destroyVirtualDisplays();
        mAmWmState.waitForValidState(mDevice, TEST_ACTIVITY_NAME, defaultStackId);
        mAmWmState.assertSanity();
        mAmWmState.assertValidBounds(true /* compareTaskAndStackBounds */);

        // Check if the focus is switched back to primary display.
        mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
        mAmWmState.assertFocusedStack(
                "Default stack on primary display must be focused after display removed",
                defaultStackId);
        mAmWmState.assertFocusedActivity(
                "Focus must be switched back to activity on primary display",
                TEST_ACTIVITY_NAME);
    }

    /**
     * Tests launching activities on secondary display and then removing it to see if stack focus
     * is moved correctly.
     */
    public void testStackFocusSwitchOnStackEmptied() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
        final int focusedStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);

        // Launch activity on new secondary display.
        launchActivityOnDisplay(BROADCAST_RECEIVER_ACTIVITY, newDisplay.mDisplayId);
        mAmWmState.assertFocusedActivity("Focus must be on secondary display",
                BROADCAST_RECEIVER_ACTIVITY);

        // Lock the device, so that activity containers will be detached.
        sleepDevice();

        // Finish activity on secondary display.
        executeShellCommand(FINISH_ACTIVITY_BROADCAST);

        // Unlock and check if the focus is switched back to primary display.
        wakeUpAndUnlockDevice();
        mAmWmState.waitForFocusedStack(mDevice, focusedStackId);
        mAmWmState.waitForValidState(mDevice, VIRTUAL_DISPLAY_ACTIVITY);
        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
        mAmWmState.assertFocusedActivity("Focus must be switched back to primary display",
                VIRTUAL_DISPLAY_ACTIVITY);
    }

    /**
     * Tests that input events on the primary display take focus from the virtual display.
     */
    public void testStackFocusSwitchOnTouchEvent() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();

        mAmWmState.computeState(mDevice, new String[] {VIRTUAL_DISPLAY_ACTIVITY});
        mAmWmState.assertFocusedActivity("Focus must be switched back to primary display",
                VIRTUAL_DISPLAY_ACTIVITY);

        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);

        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
        mAmWmState.assertFocusedActivity("Activity launched on secondary display must be focused",
                TEST_ACTIVITY_NAME);

        final ReportedDisplayMetrics displayMetrics = getDisplayMetrics();
        final int width = displayMetrics.getWidth();
        final int height = displayMetrics.getHeight();
        executeShellCommand("input tap " + (width / 2) + " " + (height / 2));

        mAmWmState.computeState(mDevice, new String[] {VIRTUAL_DISPLAY_ACTIVITY});
        mAmWmState.assertFocusedActivity("Focus must be switched back to primary display",
                VIRTUAL_DISPLAY_ACTIVITY);
    }

    /** Test that system is allowed to launch on secondary displays. */
    public void testPermissionLaunchFromSystem() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
        mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
                VIRTUAL_DISPLAY_ACTIVITY);
        final int defaultDisplayFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
        ActivityManagerState.ActivityStack focusedStack
                = mAmWmState.getAmState().getStackById(defaultDisplayFocusedStackId);
        assertEquals("Focus must remain on primary display", DEFAULT_DISPLAY_ID,
                focusedStack.mDisplayId);

        // Launch activity on new secondary display.
        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.assertFocusedActivity("Focus must be on secondary display",
                TEST_ACTIVITY_NAME);
        final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
        focusedStack = mAmWmState.getAmState().getStackById(externalFocusedStackId);
        assertEquals("Focused stack must be on secondary display", newDisplay.mDisplayId,
                focusedStack.mDisplayId);

        // Launch other activity with different uid and check it is launched on dynamic stack on
        // secondary display.
        final String startCmd =  "am start -n " + SECOND_PACKAGE_NAME + "/." + SECOND_ACTIVITY_NAME
                + " --display " + newDisplay.mDisplayId;
        executeShellCommand(startCmd);

        mAmWmState.waitForValidState(mDevice, new String[] {SECOND_ACTIVITY_NAME},
                null /* stackIds */, false /* compareTaskAndStackBounds */, SECOND_PACKAGE_NAME);
        mAmWmState.assertFocusedActivity("Focus must be on newly launched app", SECOND_PACKAGE_NAME,
                SECOND_ACTIVITY_NAME);
        assertEquals("Activity launched by system must be on external display",
                externalFocusedStackId, mAmWmState.getAmState().getFocusedStackId());
    }

    /** Tests that an activity can launch an activity from a different UID into its own task. */
    public void testPermissionLaunchMultiUidTask() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();

        launchActivityOnDisplay(LAUNCHING_ACTIVITY, newDisplay.mDisplayId);
        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});

        // Check that the first activity is launched onto the secondary display
        final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mDisplayId);
        ActivityManagerState.ActivityStack frontStack =
                mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Activity launched on secondary display must be resumed",
                getActivityComponentName(LAUNCHING_ACTIVITY),
                frontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);

        // Launch an activity from a different UID into the first activity's task
        getLaunchActivityBuilder()
                .setTargetPackage(SECOND_PACKAGE_NAME)
                .setTargetActivityName(SECOND_ACTIVITY_NAME).execute();

        mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);
        frontStack = mAmWmState.getAmState().getStackById(frontStackId);
        mAmWmState.assertFocusedActivity("Focus must be on newly launched app",
                SECOND_PACKAGE_NAME, SECOND_ACTIVITY_NAME);
        assertEquals("Secondary display must contain 1 task", 1, frontStack.getTasks().size());
    }

    /**
     * Test that launching from app that is not present on external display and doesn't own it to
     * that external display is not allowed.
     */
    public void testPermissionLaunchFromDifferentApp() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
        mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
                VIRTUAL_DISPLAY_ACTIVITY);
        final int defaultDisplayFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
        ActivityManagerState.ActivityStack focusedStack
                = mAmWmState.getAmState().getStackById(defaultDisplayFocusedStackId);
        assertEquals("Focus must remain on primary display", DEFAULT_DISPLAY_ID,
                focusedStack.mDisplayId);

        // Launch activity on new secondary display.
        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.assertFocusedActivity("Focus must be on secondary display",
                TEST_ACTIVITY_NAME);
        final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
        focusedStack = mAmWmState.getAmState().getStackById(externalFocusedStackId);
        assertEquals("Focused stack must be on secondary display", newDisplay.mDisplayId,
                focusedStack.mDisplayId);

        final String logSeparator = clearLogcat();

        // Launch other activity with different uid and check it is launched on primary display.
        final String broadcastAction = SECOND_PACKAGE_NAME + ".LAUNCH_BROADCAST_ACTION";
        final String includeStoppedPackagesFlag = " -f 0x00000020";
        executeShellCommand("am broadcast -a " + broadcastAction + " -p " + SECOND_PACKAGE_NAME
                + " --ei target_display " + newDisplay.mDisplayId + includeStoppedPackagesFlag);

        int tries = 0;
        boolean match = false;
        final Pattern pattern = Pattern.compile(".*SecurityException launching activity.*");
        while (tries < 5 && !match) {
            String[] logs = getDeviceLogsForComponent("LaunchBroadcastReceiver", logSeparator);
            for (String line : logs) {
                Matcher m = pattern.matcher(line);
                if (m.matches()) {
                    match = true;
                    break;
                }
            }
            tries++;
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }

        assertTrue("Expected exception not found", match);

        mAmWmState.waitForValidState(mDevice, new String[] {TEST_ACTIVITY_NAME},
                null /* stackIds */, false /* compareTaskAndStackBounds */, componentName);
        mAmWmState.assertFocusedActivity(
                "Focus must be on first activity", componentName, TEST_ACTIVITY_NAME);
        assertEquals("Focused stack must be on secondary display's stack",
                externalFocusedStackId, mAmWmState.getAmState().getFocusedStackId());
    }

    /**
     * Test that all activities that were on the private display are destroyed on display removal.
     */
    // TODO: Flaky, add to presubmit when b/63404575 is fixed.
    public void testContentDestroyOnDisplayRemoved() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new private virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);

        // Launch activities on new secondary display.
        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
        mAmWmState.assertFocusedActivity("Launched activity must be focused", TEST_ACTIVITY_NAME);
        launchActivityOnDisplay(RESIZEABLE_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true /* visible */);
        mAmWmState.assertFocusedActivity("Launched activity must be focused",
                RESIZEABLE_ACTIVITY_NAME);

        // Destroy the display and check if activities are removed from system.
        final String logSeparator = clearLogcat();
        destroyVirtualDisplays();
        final String activityName1
                = ActivityManagerTestBase.getActivityComponentName(TEST_ACTIVITY_NAME);
        final String activityName2
                = ActivityManagerTestBase.getActivityComponentName(RESIZEABLE_ACTIVITY_NAME);
        final String windowName1
                = ActivityManagerTestBase.getWindowName(TEST_ACTIVITY_NAME);
        final String windowName2
                = ActivityManagerTestBase.getWindowName(RESIZEABLE_ACTIVITY_NAME);
        mAmWmState.waitForWithAmState(mDevice,
                (state) -> !state.containsActivity(activityName1)
                        && !state.containsActivity(activityName2),
                "Waiting for activity to be removed");
        mAmWmState.waitForWithWmState(mDevice,
                (state) -> !state.containsWindow(windowName1)
                        && !state.containsWindow(windowName2),
                "Waiting for activity window to be gone");

        // Check AM state.
        assertFalse("Activity from removed display must be destroyed",
                mAmWmState.getAmState().containsActivity(activityName1));
        assertFalse("Activity from removed display must be destroyed",
                mAmWmState.getAmState().containsActivity(activityName2));
        // Check WM state.
        assertFalse("Activity windows from removed display must be destroyed",
                mAmWmState.getWmState().containsWindow(windowName1));
        assertFalse("Activity windows from removed display must be destroyed",
                mAmWmState.getWmState().containsWindow(windowName2));
        // Check activity logs.
        assertActivityDestroyed(TEST_ACTIVITY_NAME, logSeparator);
        assertActivityDestroyed(RESIZEABLE_ACTIVITY_NAME, logSeparator);
    }

    /**
     * Test that the update of display metrics updates all its content.
     */
    @Presubmit
    public void testDisplayResize() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);

        // Launch a resizeable activity on new secondary display.
        final String initialLogSeparator = clearLogcat();
        launchActivityOnDisplay(RESIZEABLE_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true /* visible */);
        mAmWmState.assertFocusedActivity("Launched activity must be focused",
                RESIZEABLE_ACTIVITY_NAME);

        // Grab reported sizes and compute new with slight size change.
        final ReportedSizes initialSize = getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY_NAME,
                initialLogSeparator);

        // Resize the docked stack, so that activity with virtual display will also be resized.
        final String logSeparator = clearLogcat();
        executeShellCommand(getResizeVirtualDisplayCommand());

        mAmWmState.waitForWithAmState(mDevice, amState -> {
            try {
                return readConfigChangeNumber(RESIZEABLE_ACTIVITY_NAME, logSeparator) == 1
                        && amState.hasActivityState(RESIZEABLE_ACTIVITY_NAME, STATE_RESUMED);
            } catch (Exception e) {
                logE("Error waiting for valid state: " + e.getMessage());
                return false;
            }
        }, "Wait for the configuration change to happen and for activity to be resumed.");

        mAmWmState.computeState(mDevice, new String[] {RESIZEABLE_ACTIVITY_NAME,
                VIRTUAL_DISPLAY_ACTIVITY}, false /* compareTaskAndStackBounds */);
        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true);
        mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true);

        // Check if activity in virtual display was resized properly.
        assertRelaunchOrConfigChanged(RESIZEABLE_ACTIVITY_NAME, 0 /* numRelaunch */,
                1 /* numConfigChange */, logSeparator);

        final ReportedSizes updatedSize = getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY_NAME,
                logSeparator);
        assertTrue(updatedSize.widthDp <= initialSize.widthDp);
        assertTrue(updatedSize.heightDp <= initialSize.heightDp);
        assertTrue(updatedSize.displayWidth == initialSize.displayWidth / 2);
        assertTrue(updatedSize.displayHeight == initialSize.displayHeight / 2);
    }

    /** Read the number of configuration changes sent to activity from logs. */
    private int readConfigChangeNumber(String activityName, String logSeparator) throws Exception {
        return (new ActivityLifecycleCounts(activityName, logSeparator)).mConfigurationChangedCount;
    }

    /**
     * Tests that when an activity is launched with displayId specified and there is an existing
     * matching task on some other display - that task will moved to the target display.
     */
    public void testMoveToDisplayOnLaunch() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Launch activity with unique affinity, so it will the only one in its task.
        launchActivity(LAUNCHING_ACTIVITY);

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
        final int defaultDisplayStackId = mAmWmState.getAmState().getFocusedStackId();
        // Launch something to that display so that a new stack is created. We need this to be able
        // to compare task numbers in stacks later.
        launchActivityOnDisplay(RESIZEABLE_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true /* visible */);

        final int taskNum = mAmWmState.getAmState().getStackById(defaultDisplayStackId)
                .getTasks().size();
        final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mDisplayId);
        final int taskNumOnSecondary = mAmWmState.getAmState().getStackById(frontStackId)
                .getTasks().size();

        // Launch activity on new secondary display.
        // Using custom command here, because normally we add flags Intent#FLAG_ACTIVITY_NEW_TASK
        // and Intent#FLAG_ACTIVITY_MULTIPLE_TASK when launching on some specific display. We don't
        // do it here as we want an existing task to be used.
        final String launchCommand = "am start -n " + getActivityComponentName(LAUNCHING_ACTIVITY)
                + " --display " + newDisplay.mDisplayId;
        executeShellCommand(launchCommand);
        mAmWmState.waitForActivityState(mDevice, LAUNCHING_ACTIVITY, STATE_RESUMED);

        // Check that activity is brought to front.
        mAmWmState.assertFocusedActivity("Existing task must be brought to front",
                LAUNCHING_ACTIVITY);
        mAmWmState.assertResumedActivity("Existing task must be resumed", LAUNCHING_ACTIVITY);

        // Check that activity is on the right display.
        final ActivityManagerState.ActivityStack firstFrontStack =
                mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Activity must be moved to the secondary display",
                getActivityComponentName(LAUNCHING_ACTIVITY), firstFrontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);

        // Check that task has moved from primary display to secondary.
        final int taskNumFinal = mAmWmState.getAmState().getStackById(defaultDisplayStackId)
                .getTasks().size();
        mAmWmState.assertEquals("Task number in default stack must be decremented.", taskNum - 1,
                taskNumFinal);
        final int taskNumFinalOnSecondary = mAmWmState.getAmState().getStackById(frontStackId)
                .getTasks().size();
        mAmWmState.assertEquals("Task number in stack on external display must be incremented.",
                taskNumOnSecondary + 1, taskNumFinalOnSecondary);
    }

    /**
     * Tests that when primary display is rotated secondary displays are not affected.
     */
    public void testRotationNotAffectingSecondaryScreen() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        // Create new virtual display.
        final DisplayState newDisplay = new VirtualDisplayBuilder(this)
                .setResizeDisplay(false)
                .build();
        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);

        // Launch activity on new secondary display.
        String logSeparator = clearLogcat();
        launchActivityOnDisplay(RESIZEABLE_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.assertFocusedActivity("Focus must be on secondary display",
                RESIZEABLE_ACTIVITY_NAME);
        final ReportedSizes initialSizes = getLastReportedSizesForActivity(
                RESIZEABLE_ACTIVITY_NAME, logSeparator);
        assertNotNull("Test activity must have reported initial sizes on launch", initialSizes);

        // Rotate primary display and check that activity on secondary display is not affected.
        rotateAndCheckSameSizes(RESIZEABLE_ACTIVITY_NAME);

        // Launch activity to secondary display when primary one is rotated.
        final int initialRotation = mAmWmState.getWmState().getRotation();
        setDeviceRotation((initialRotation + 1) % 4);

        logSeparator = clearLogcat();
        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
        mAmWmState.waitForActivityState(mDevice, TEST_ACTIVITY_NAME, STATE_RESUMED);
        mAmWmState.assertFocusedActivity("Focus must be on secondary display",
                TEST_ACTIVITY_NAME);
        final ReportedSizes testActivitySizes = getLastReportedSizesForActivity(
                TEST_ACTIVITY_NAME, logSeparator);
        assertEquals("Sizes of secondary display must not change after rotation of primary display",
                initialSizes, testActivitySizes);
    }

    private void rotateAndCheckSameSizes(String activityName) throws Exception {
        for (int rotation = 3; rotation >= 0; --rotation) {
            final String logSeparator = clearLogcat();
            setDeviceRotation(rotation);
            final ReportedSizes rotatedSizes = getLastReportedSizesForActivity(activityName,
                    logSeparator);
            assertNull("Sizes must not change after rotation", rotatedSizes);
        }
    }

    /**
     * Tests that task affinity does affect what display an activity is launched on but that
     * matching the task component root does.
     */
    public void testTaskMatchAcrossDisplays() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();

        launchActivityOnDisplay(LAUNCHING_ACTIVITY, newDisplay.mDisplayId);
        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});

        // Check that activity is on the right display.
        final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mDisplayId);
        final ActivityManagerState.ActivityStack firstFrontStack =
                mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Activity launched on secondary display must be resumed",
                getActivityComponentName(LAUNCHING_ACTIVITY), firstFrontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);

        executeShellCommand("am start -n " + getActivityComponentName(ALT_LAUNCHING_ACTIVITY));
        mAmWmState.waitForValidState(mDevice, new String[] {ALT_LAUNCHING_ACTIVITY},
                null /* stackIds */, false /* compareTaskAndStackBounds */, componentName);

        // Check that second activity gets launched on the default display
        final int defaultDisplayFrontStackId = mAmWmState.getAmState().getFrontStackId(
                DEFAULT_DISPLAY_ID);
        final ActivityManagerState.ActivityStack defaultDisplayFrontStack =
                mAmWmState.getAmState().getStackById(defaultDisplayFrontStackId);
        assertEquals("Activity launched on default display must be resumed",
                getActivityComponentName(ALT_LAUNCHING_ACTIVITY),
                defaultDisplayFrontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on primary display",
                defaultDisplayFrontStackId);

        executeShellCommand("am start -n " + getActivityComponentName(LAUNCHING_ACTIVITY));
        mAmWmState.waitForFocusedStack(mDevice, frontStackId);

        // Check that the third intent is redirected to the first task
        final ActivityManagerState.ActivityStack secondFrontStack
                = mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Activity launched on default display must be resumed",
                getActivityComponentName(LAUNCHING_ACTIVITY), secondFrontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on primary display", frontStackId);
        assertEquals("Focused stack must only contain 1 task",
                1, secondFrontStack.getTasks().size());
        assertEquals("Focused task must only contain 1 activity",
                1, secondFrontStack.getTasks().get(0).mActivities.size());
    }

    /**
     * Tests than a new task launched by an activity will end up on that activity's display
     * even if the focused stack is not on that activity's display.
     */
    public void testNewTaskSameDisplay() throws Exception {
        if (!supportsMultiDisplay()) { return; }

        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();

        launchActivityOnDisplay(BROADCAST_RECEIVER_ACTIVITY, newDisplay.mDisplayId);
        mAmWmState.computeState(mDevice, new String[] {BROADCAST_RECEIVER_ACTIVITY});

        // Check that the first activity is launched onto the secondary display
        final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mDisplayId);
        final ActivityManagerState.ActivityStack firstFrontStack =
                mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Activity launched on secondary display must be resumed",
                getActivityComponentName(BROADCAST_RECEIVER_ACTIVITY),
                firstFrontStack.mResumedActivity);
        mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);

        executeShellCommand("am start -n " + getActivityComponentName(TEST_ACTIVITY_NAME));
        mAmWmState.waitForValidState(mDevice, new String[] {TEST_ACTIVITY_NAME},
                null /* stackIds */, false /* compareTaskAndStackBounds */, componentName);

        // Check that the second activity is launched on the default display
        final int focusedStackId = mAmWmState.getAmState().getFocusedStackId();
        final ActivityManagerState.ActivityStack focusedStack
                = mAmWmState.getAmState().getStackById(focusedStackId);
        assertEquals("Activity launched on default display must be resumed",
                getActivityComponentName(TEST_ACTIVITY_NAME), focusedStack.mResumedActivity);
        assertEquals("Focus must be on primary display", DEFAULT_DISPLAY_ID,
                focusedStack.mDisplayId);

        executeShellCommand("am broadcast -a trigger_broadcast --ez launch_activity true "
                + "--ez new_task true --es target_activity " + LAUNCHING_ACTIVITY);

        // Check that the third activity ends up in a new task in the same stack as the
        // first activity
        mAmWmState.waitForValidState(mDevice, new String[] {LAUNCHING_ACTIVITY},
                null /* stackIds */, false /* compareTaskAndStackBounds */, componentName);
        mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);
        final ActivityManagerState.ActivityStack secondFrontStack =
                mAmWmState.getAmState().getStackById(frontStackId);
        assertEquals("Activity must be launched on secondary display",
                getActivityComponentName(LAUNCHING_ACTIVITY),
                secondFrontStack.mResumedActivity);
        assertEquals("Secondary display must contain 2 tasks",
                2, secondFrontStack.getTasks().size());
    }

    /**
     * Test that display overrides apply correctly and won't be affected by display changes.
     * This sets overrides to display size and density, initiates a display changed event by locking
     * and unlocking the phone and verifies that overrides are kept.
     */
    @Presubmit
    public void testForceDisplayMetrics() throws Exception {
        launchHomeActivity();

        // Read initial sizes.
        final ReportedDisplayMetrics originalDisplayMetrics = getDisplayMetrics();

        // Apply new override values that don't match the physical metrics.
        final int overrideWidth = (int) (originalDisplayMetrics.physicalWidth * 1.5);
        final int overrideHeight = (int) (originalDisplayMetrics.physicalHeight * 1.5);
        executeShellCommand(WM_SIZE + " " + overrideWidth + "x" + overrideHeight);
        final int overrideDensity = (int) (originalDisplayMetrics.physicalDensity * 1.1);
        executeShellCommand(WM_DENSITY + " " + overrideDensity);

        // Check if overrides applied correctly.
        ReportedDisplayMetrics displayMetrics = getDisplayMetrics();
        assertEquals(overrideWidth, displayMetrics.overrideWidth);
        assertEquals(overrideHeight, displayMetrics.overrideHeight);
        assertEquals(overrideDensity, displayMetrics.overrideDensity);

        // Lock and unlock device. This will cause a DISPLAY_CHANGED event to be triggered and
        // might update the metrics.
        sleepDevice();
        wakeUpAndUnlockDevice();
        mAmWmState.waitForHomeActivityVisible(mDevice);

        // Check if overrides are still applied.
        displayMetrics = getDisplayMetrics();
        assertEquals(overrideWidth, displayMetrics.overrideWidth);
        assertEquals(overrideHeight, displayMetrics.overrideHeight);
        assertEquals(overrideDensity, displayMetrics.overrideDensity);

        // All overrides will be cleared in tearDown.
    }

    /** Get physical and override display metrics from WM. */
    private ReportedDisplayMetrics getDisplayMetrics() throws Exception {
        mDumpLines.clear();
        final CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
        mDevice.executeShellCommand(WM_SIZE, outputReceiver);
        mDevice.executeShellCommand(WM_DENSITY, outputReceiver);
        final String dump = outputReceiver.getOutput();
        mDumpLines.clear();
        Collections.addAll(mDumpLines, dump.split("\\n"));
        return ReportedDisplayMetrics.create(mDumpLines);
    }

    private static class ReportedDisplayMetrics {
        private static final Pattern sPhysicalSizePattern =
                Pattern.compile("Physical size: (\\d+)x(\\d+)");
        private static final Pattern sOverrideSizePattern =
                Pattern.compile("Override size: (\\d+)x(\\d+)");
        private static final Pattern sPhysicalDensityPattern =
                Pattern.compile("Physical density: (\\d+)");
        private static final Pattern sOverrideDensityPattern =
                Pattern.compile("Override density: (\\d+)");

        int physicalWidth;
        int physicalHeight;
        int physicalDensity;

        boolean sizeOverrideSet;
        int overrideWidth;
        int overrideHeight;
        boolean densityOverrideSet;
        int overrideDensity;

        /** Get width that WM operates with. */
        int getWidth() {
            return sizeOverrideSet ? overrideWidth : physicalWidth;
        }

        /** Get height that WM operates with. */
        int getHeight() {
            return sizeOverrideSet ? overrideHeight : physicalHeight;
        }

        /** Get density that WM operates with. */
        int getDensity() {
            return densityOverrideSet ? overrideDensity : physicalDensity;
        }

        static ReportedDisplayMetrics create(LinkedList<String> dump) {
            final ReportedDisplayMetrics result = new ReportedDisplayMetrics();

            boolean physicalSizeFound = false;
            boolean physicalDensityFound = false;

            while (!dump.isEmpty()) {
                final String line = dump.pop().trim();

                Matcher matcher = sPhysicalSizePattern.matcher(line);
                if (matcher.matches()) {
                    physicalSizeFound = true;
                    log(line);
                    result.physicalWidth = Integer.parseInt(matcher.group(1));
                    result.physicalHeight = Integer.parseInt(matcher.group(2));
                    continue;
                }

                matcher = sOverrideSizePattern.matcher(line);
                if (matcher.matches()) {
                    log(line);
                    result.overrideWidth = Integer.parseInt(matcher.group(1));
                    result.overrideHeight = Integer.parseInt(matcher.group(2));
                    result.sizeOverrideSet = true;
                    continue;
                }

                matcher = sPhysicalDensityPattern.matcher(line);
                if (matcher.matches()) {
                    physicalDensityFound = true;
                    log(line);
                    result.physicalDensity = Integer.parseInt(matcher.group(1));
                    continue;
                }

                matcher = sOverrideDensityPattern.matcher(line);
                if (matcher.matches()) {
                    log(line);
                    result.overrideDensity = Integer.parseInt(matcher.group(1));
                    result.densityOverrideSet = true;
                    continue;
                }
            }

            assertTrue("Physical display size must be reported", physicalSizeFound);
            assertTrue("Physical display density must be reported", physicalDensityFound);

            return result;
        }
    }

    /** Assert that component received onMovedToDisplay and onConfigurationChanged callbacks. */
    private void assertMovedToDisplay(String componentName, String logSeparator) throws Exception {
        final ActivityLifecycleCounts lifecycleCounts
                = new ActivityLifecycleCounts(componentName, logSeparator);
        if (lifecycleCounts.mDestroyCount != 0) {
            fail(componentName + " has been destroyed " + lifecycleCounts.mDestroyCount
                    + " time(s), wasn't expecting any");
        } else if (lifecycleCounts.mCreateCount != 0) {
            fail(componentName + " has been (re)created " + lifecycleCounts.mCreateCount
                    + " time(s), wasn't expecting any");
        } else if (lifecycleCounts.mConfigurationChangedCount != 1) {
            fail(componentName + " has received "
                    + lifecycleCounts.mConfigurationChangedCount
                    + " onConfigurationChanged() calls, expecting " + 1);
        } else if (lifecycleCounts.mMovedToDisplayCount != 1) {
            fail(componentName + " has received "
                    + lifecycleCounts.mMovedToDisplayCount
                    + " onMovedToDisplay() calls, expecting " + 1);
        }
    }

    private static String getResizeVirtualDisplayCommand() {
        return getAmStartCmd(VIRTUAL_DISPLAY_ACTIVITY) + " -f 0x20000000" +
                " --es command resize_display";
    }
}
