blob: c5952b3381f54b69467f3827077aae2e7d0ab151 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.server.am;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.server.am.Components.DOCKED_ACTIVITY;
import static android.server.am.Components.LAUNCHING_ACTIVITY;
import static android.server.am.Components.NON_RESIZEABLE_ACTIVITY;
import static android.server.am.Components.NO_RELAUNCH_ACTIVITY;
import static android.server.am.Components.RESIZEABLE_ACTIVITY;
import static android.server.am.Components.SINGLE_INSTANCE_ACTIVITY;
import static android.server.am.Components.SINGLE_TASK_ACTIVITY;
import static android.server.am.Components.TEST_ACTIVITY;
import static android.server.am.Components.TestActivity.TEST_ACTIVITY_ACTION_FINISH_SELF;
import static android.server.am.UiDeviceUtils.pressHomeButton;
import static android.server.am.WindowManagerState.TRANSIT_WALLPAPER_OPEN;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import android.content.ComponentName;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.server.am.CommandSession.ActivityCallback;
import android.support.test.filters.FlakyTest;
import org.junit.Before;
import org.junit.Test;
/**
* Build/Install/Run:
* atest CtsActivityManagerDeviceTestCases:ActivityManagerSplitScreenTests
*/
public class ActivityManagerSplitScreenTests extends ActivityManagerTestBase {
private static final int TASK_SIZE = 600;
private static final int STACK_SIZE = 300;
private boolean mIsHomeRecentsComponent;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
mIsHomeRecentsComponent = mAmWmState.getAmState().isHomeRecentsComponent();
assumeTrue("Skipping test: no split multi-window support",
supportsSplitScreenMultiWindow());
}
@Test
public void testMinimumDeviceSize() throws Exception {
mAmWmState.assertDeviceDefaultDisplaySize(
"Devices supporting multi-window must be larger than the default minimum"
+ " task size");
}
@Test
@Presubmit
@FlakyTest(bugId = 71792393)
public void testStackList() throws Exception {
launchActivity(TEST_ACTIVITY);
mAmWmState.computeState(TEST_ACTIVITY);
mAmWmState.assertContainsStack("Must contain home stack.",
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
mAmWmState.assertContainsStack("Must contain fullscreen stack.",
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
mAmWmState.assertDoesNotContainStack("Must not contain docked stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
}
@Test
@Presubmit
public void testDockActivity() throws Exception {
launchActivityInSplitScreenWithRecents(TEST_ACTIVITY);
mAmWmState.assertContainsStack("Must contain home stack.",
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
mAmWmState.assertContainsStack("Must contain docked stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
}
@Test
@Presubmit
public void testNonResizeableNotDocked() throws Exception {
launchActivityInSplitScreenWithRecents(NON_RESIZEABLE_ACTIVITY);
mAmWmState.assertContainsStack("Must contain home stack.",
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
mAmWmState.assertDoesNotContainStack("Must not contain docked stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
mAmWmState.assertFrontStack("Fullscreen stack must be front stack.",
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
}
@Test
@Presubmit
public void testLaunchToSide() throws Exception {
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
mAmWmState.assertContainsStack("Must contain fullscreen stack.",
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
mAmWmState.assertContainsStack("Must contain docked stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
}
@Test
@Presubmit
public void testLaunchToSideMultiWindowCallbacks() throws Exception {
// Launch two activities in split-screen mode.
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
mAmWmState.assertContainsStack("Must contain fullscreen stack.",
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
mAmWmState.assertContainsStack("Must contain docked stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
// Exit split-screen mode and ensure we only get 1 multi-window mode changed callback.
separateTestJournal();
removeStacksInWindowingModes(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
final ActivityLifecycleCounts lifecycleCounts = waitForOnMultiWindowModeChanged(
TEST_ACTIVITY);
assertEquals(1, lifecycleCounts.getCount(ActivityCallback.ON_MULTI_WINDOW_MODE_CHANGED));
}
@Test
@Presubmit
@FlakyTest(bugId = 72956284)
public void testNoUserLeaveHintOnMultiWindowModeChanged() throws Exception {
launchActivity(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
// Move to docked stack.
separateTestJournal();
setActivityTaskWindowingMode(TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
ActivityLifecycleCounts lifecycleCounts = waitForOnMultiWindowModeChanged(TEST_ACTIVITY);
assertEquals("mMultiWindowModeChangedCount",
1, lifecycleCounts.getCount(ActivityCallback.ON_MULTI_WINDOW_MODE_CHANGED));
assertEquals("mUserLeaveHintCount",
0, lifecycleCounts.getCount(ActivityCallback.ON_USER_LEAVE_HINT));
// Make sure docked stack is focused. This way when we dismiss it later fullscreen stack
// will come up.
launchActivity(TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
// Move activity back to fullscreen stack.
separateTestJournal();
setActivityTaskWindowingMode(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
lifecycleCounts = waitForOnMultiWindowModeChanged(TEST_ACTIVITY);
assertEquals("mMultiWindowModeChangedCount",
1, lifecycleCounts.getCount(ActivityCallback.ON_MULTI_WINDOW_MODE_CHANGED));
assertEquals("mUserLeaveHintCount",
0, lifecycleCounts.getCount(ActivityCallback.ON_USER_LEAVE_HINT));
}
@Test
@Presubmit
public void testLaunchToSideAndBringToFront() throws Exception {
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
TEST_ACTIVITY);
// Launch another activity to side to cover first one.
launchActivity(NO_RELAUNCH_ACTIVITY, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
int taskNumberCovered = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertEquals("Fullscreen stack must have one task added.",
taskNumberInitial + 1, taskNumberCovered);
mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
NO_RELAUNCH_ACTIVITY);
// Launch activity that was first launched to side. It should be brought to front.
getLaunchActivityBuilder()
.setTargetActivity(TEST_ACTIVITY)
.setToSide(true)
.setWaitForLaunched(true)
.execute();
int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertEquals("Task number in fullscreen stack must remain the same.",
taskNumberCovered, taskNumberFinal);
mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
TEST_ACTIVITY);
}
@Test
@Presubmit
@FlakyTest(bugId = 71792393)
public void testLaunchToSideMultiple() throws Exception {
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertNotNull("Launched to side activity must be in fullscreen stack.",
mAmWmState.getAmState().getTaskByActivity(
TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
// Try to launch to side same activity again.
getLaunchActivityBuilder().setToSide(true).execute();
mAmWmState.computeState(TEST_ACTIVITY, LAUNCHING_ACTIVITY);
int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertEquals("Task number mustn't change.", taskNumberInitial, taskNumberFinal);
mAmWmState.assertFocusedActivity("Launched to side activity must remain in front.",
TEST_ACTIVITY);
assertNotNull("Launched to side activity must remain in fullscreen stack.",
mAmWmState.getAmState().getTaskByActivity(
TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
}
@Test
@Presubmit
@FlakyTest(bugId = 73808815)
public void testLaunchToSideSingleInstance() throws Exception {
launchTargetToSide(SINGLE_INSTANCE_ACTIVITY, false);
}
@Test
public void testLaunchToSideSingleTask() throws Exception {
launchTargetToSide(SINGLE_TASK_ACTIVITY, false);
}
@Presubmit
@FlakyTest(bugId = 71792393)
@Test
public void testLaunchToSideMultipleWithDifferentIntent() throws Exception {
launchTargetToSide(TEST_ACTIVITY, true);
}
private void launchTargetToSide(ComponentName targetActivityName,
boolean taskCountMustIncrement) throws Exception {
// Launch in fullscreen first
getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY)
.setUseInstrumentation()
.setWaitForLaunched(true)
.execute();
// Move to split-screen primary
final int taskId = mAmWmState.getAmState().getTaskByActivity(LAUNCHING_ACTIVITY).mTaskId;
moveTaskToPrimarySplitScreen(taskId, true /* showRecents */);
// Launch target to side
final LaunchActivityBuilder targetActivityLauncher = getLaunchActivityBuilder()
.setTargetActivity(targetActivityName)
.setToSide(true)
.setRandomData(true)
.setMultipleTask(false);
targetActivityLauncher.execute();
mAmWmState.computeState(targetActivityName, LAUNCHING_ACTIVITY);
mAmWmState.assertContainsStack("Must contain secondary stack.",
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertNotNull("Launched to side activity must be in fullscreen stack.",
mAmWmState.getAmState().getTaskByActivity(
targetActivityName, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
// Try to launch to side same activity again with different data.
targetActivityLauncher.execute();
mAmWmState.computeState(targetActivityName, LAUNCHING_ACTIVITY);
int taskNumberSecondLaunch = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
if (taskCountMustIncrement) {
assertEquals("Task number must be incremented.", taskNumberInitial + 1,
taskNumberSecondLaunch);
} else {
assertEquals("Task number must not change.", taskNumberInitial,
taskNumberSecondLaunch);
}
mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
targetActivityName);
assertNotNull("Launched to side activity must be launched in fullscreen stack.",
mAmWmState.getAmState().getTaskByActivity(
targetActivityName, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
// Try to launch to side same activity again with different random data. Note that null
// cannot be used here, since the first instance of TestActivity is launched with no data
// in order to launch into split screen.
targetActivityLauncher.execute();
mAmWmState.computeState(targetActivityName, LAUNCHING_ACTIVITY);
int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
if (taskCountMustIncrement) {
assertEquals("Task number must be incremented.", taskNumberSecondLaunch + 1,
taskNumberFinal);
} else {
assertEquals("Task number must not change.", taskNumberSecondLaunch,
taskNumberFinal);
}
mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
targetActivityName);
assertNotNull("Launched to side activity must be launched in fullscreen stack.",
mAmWmState.getAmState().getTaskByActivity(
targetActivityName, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
}
@Presubmit
@Test
public void testLaunchToSideMultipleWithFlag() throws Exception {
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertNotNull("Launched to side activity must be in fullscreen stack.",
mAmWmState.getAmState().getTaskByActivity(
TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
// Try to launch to side same activity again, but with Intent#FLAG_ACTIVITY_MULTIPLE_TASK.
getLaunchActivityBuilder().setToSide(true).setMultipleTask(true).execute();
mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertEquals("Task number must be incremented.", taskNumberInitial + 1,
taskNumberFinal);
mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
TEST_ACTIVITY);
assertNotNull("Launched to side activity must remain in fullscreen stack.",
mAmWmState.getAmState().getTaskByActivity(
TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
}
@Test
public void testRotationWhenDocked() throws Exception {
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
mAmWmState.assertContainsStack("Must contain fullscreen stack.",
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
mAmWmState.assertContainsStack("Must contain docked stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
// Rotate device single steps (90°) 0-1-2-3.
// Each time we compute the state we implicitly assert valid bounds.
try (final RotationSession rotationSession = new RotationSession()) {
for (int i = 0; i < 4; i++) {
rotationSession.set(i);
mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
}
// Double steps (180°) We ended the single step at 3. So, we jump directly to 1 for
// double step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side.
rotationSession.set(ROTATION_90);
mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
rotationSession.set(ROTATION_270);
mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
rotationSession.set(ROTATION_0);
mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
rotationSession.set(ROTATION_180);
mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
rotationSession.set(ROTATION_0);
mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
}
}
@Test
@Presubmit
public void testRotationWhenDockedWhileLocked() throws Exception {
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
mAmWmState.assertSanity();
mAmWmState.assertContainsStack("Must contain fullscreen stack.",
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
mAmWmState.assertContainsStack("Must contain docked stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
try (final RotationSession rotationSession = new RotationSession();
final LockScreenSession lockScreenSession = new LockScreenSession()) {
for (int i = 0; i < 4; i++) {
lockScreenSession.sleepDevice();
rotationSession.set(i);
lockScreenSession.wakeUpDevice()
.unlockDevice();
mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
}
}
}
@Test
public void testMinimizedFromEachDockedSide() throws Exception {
try (final RotationSession rotationSession = new RotationSession()) {
for (int i = 0; i < 2; i++) {
rotationSession.set(i);
launchActivityInDockStackAndMinimize(TEST_ACTIVITY);
if (!mAmWmState.isScreenPortrait() && isTablet()) {
// Test minimize to the right only on tablets in landscape
removeStacksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
launchActivityInDockStackAndMinimize(TEST_ACTIVITY,
SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT);
}
removeStacksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
}
}
}
@Test
@Presubmit
public void testRotationWhileDockMinimized() throws Exception {
launchActivityInDockStackAndMinimize(TEST_ACTIVITY);
// Rotate device single steps (90°) 0-1-2-3.
// Each time we compute the state we implicitly assert valid bounds in minimized mode.
try (final RotationSession rotationSession = new RotationSession()) {
for (int i = 0; i < 4; i++) {
rotationSession.set(i);
mAmWmState.computeState(TEST_ACTIVITY);
}
// Double steps (180°) We ended the single step at 3. So, we jump directly to 1 for
// double step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side in
// minimized mode.
rotationSession.set(ROTATION_90);
mAmWmState.computeState(TEST_ACTIVITY);
rotationSession.set(ROTATION_270);
mAmWmState.computeState(TEST_ACTIVITY);
rotationSession.set(ROTATION_0);
mAmWmState.computeState(TEST_ACTIVITY);
rotationSession.set(ROTATION_180);
mAmWmState.computeState(TEST_ACTIVITY);
rotationSession.set(ROTATION_0);
mAmWmState.computeState(TEST_ACTIVITY);
}
}
@Test
public void testMinimizeAndUnminimizeThenGoingHome() throws Exception {
// Rotate the screen to check that minimize, unminimize, dismiss the docked stack and then
// going home has the correct app transition
try (final RotationSession rotationSession = new RotationSession()) {
for (int rotation = ROTATION_0; rotation <= ROTATION_270; rotation++) {
rotationSession.set(rotation);
launchActivityInDockStackAndMinimize(DOCKED_ACTIVITY);
if (mIsHomeRecentsComponent) {
launchActivity(TEST_ACTIVITY,
WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
} else {
// Unminimize the docked stack
pressAppSwitchButtonAndWaitForRecents();
waitForDockNotMinimized();
assertDockNotMinimized();
}
// Dismiss the dock stack
setActivityTaskWindowingMode(DOCKED_ACTIVITY,
WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
mAmWmState.computeState(DOCKED_ACTIVITY);
// Go home and check the app transition
assertNotEquals(TRANSIT_WALLPAPER_OPEN,
mAmWmState.getWmState().getDefaultDisplayLastTransition());
pressHomeButton();
mAmWmState.waitForHomeActivityVisible();
assertEquals(TRANSIT_WALLPAPER_OPEN,
mAmWmState.getWmState().getDefaultDisplayLastTransition());
}
}
}
@FlakyTest(bugId = 73813034)
@Test
@Presubmit
public void testFinishDockActivityWhileMinimized() throws Exception {
launchActivityInDockStackAndMinimize(TEST_ACTIVITY);
mBroadcastActionTrigger.doAction(TEST_ACTIVITY_ACTION_FINISH_SELF);
waitForDockNotMinimized();
mAmWmState.assertNotExist(TEST_ACTIVITY);
assertDockNotMinimized();
}
@Test
@Presubmit
public void testDockedStackToMinimizeWhenUnlocked() throws Exception {
launchActivityInSplitScreenWithRecents(TEST_ACTIVITY);
mAmWmState.computeState(TEST_ACTIVITY);
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.sleepDevice()
.wakeUpDevice()
.unlockDevice();
mAmWmState.computeState(TEST_ACTIVITY);
assertDockMinimized();
}
}
@Test
public void testMinimizedStateWhenUnlockedAndUnMinimized() throws Exception {
launchActivityInDockStackAndMinimize(TEST_ACTIVITY);
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.sleepDevice()
.wakeUpDevice()
.unlockDevice();
mAmWmState.computeState(TEST_ACTIVITY);
// Unminimized back to splitscreen
if (mIsHomeRecentsComponent) {
launchActivity(RESIZEABLE_ACTIVITY,
WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
} else {
pressAppSwitchButtonAndWaitForRecents();
}
mAmWmState.computeState(TEST_ACTIVITY);
}
}
/**
* Verify split screen mode visibility after stack resize occurs.
*/
@Test
@Presubmit
@FlakyTest(bugId = 110276714)
public void testResizeDockedStack() throws Exception {
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
resizeDockedStack(STACK_SIZE, STACK_SIZE, TASK_SIZE, TASK_SIZE);
mAmWmState.computeState(false /* compareTaskAndStackBounds */,
new WaitForValidActivityState(TEST_ACTIVITY),
new WaitForValidActivityState(DOCKED_ACTIVITY));
mAmWmState.assertContainsStack("Must contain secondary split-screen stack.",
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
mAmWmState.assertContainsStack("Must contain primary split-screen stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
mAmWmState.assertVisibility(DOCKED_ACTIVITY, true);
mAmWmState.assertVisibility(TEST_ACTIVITY, true);
}
@Test
public void testActivityLifeCycleOnResizeDockedStack() throws Exception {
launchActivity(TEST_ACTIVITY);
mAmWmState.computeState(TEST_ACTIVITY);
final Rect fullScreenBounds = mAmWmState.getWmState().getStandardStackByWindowingMode(
WINDOWING_MODE_FULLSCREEN).getBounds();
setActivityTaskWindowingMode(TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
mAmWmState.computeState(TEST_ACTIVITY);
launchActivity(NO_RELAUNCH_ACTIVITY, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
mAmWmState.computeState(TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY);
final Rect initialDockBounds = mAmWmState.getWmState().getStandardStackByWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) .getBounds();
separateTestJournal();
Rect newBounds = computeNewDockBounds(fullScreenBounds, initialDockBounds, true);
resizeDockedStack(
newBounds.width(), newBounds.height(), newBounds.width(), newBounds.height());
mAmWmState.computeState(TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY);
// We resize twice to make sure we cross an orientation change threshold for both
// activities.
newBounds = computeNewDockBounds(fullScreenBounds, initialDockBounds, false);
resizeDockedStack(
newBounds.width(), newBounds.height(), newBounds.width(), newBounds.height());
mAmWmState.computeState(TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY);
assertActivityLifecycle(TEST_ACTIVITY, true /* relaunched */);
assertActivityLifecycle(NO_RELAUNCH_ACTIVITY, false /* relaunched */);
}
private Rect computeNewDockBounds(
Rect fullscreenBounds, Rect dockBounds, boolean reduceSize) {
final boolean inLandscape = fullscreenBounds.width() > dockBounds.width();
// We are either increasing size or reducing it.
final float sizeChangeFactor = reduceSize ? 0.5f : 1.5f;
final Rect newBounds = new Rect(dockBounds);
if (inLandscape) {
// In landscape we change the width.
newBounds.right = (int) (newBounds.left + (newBounds.width() * sizeChangeFactor));
} else {
// In portrait we change the height
newBounds.bottom = (int) (newBounds.top + (newBounds.height() * sizeChangeFactor));
}
return newBounds;
}
@Test
@Presubmit
public void testStackListOrderLaunchDockedActivity() throws Exception {
assumeTrue(!mIsHomeRecentsComponent);
launchActivityInSplitScreenWithRecents(TEST_ACTIVITY);
final int homeStackIndex = mAmWmState.getStackIndexByActivityType(ACTIVITY_TYPE_HOME);
final int recentsStackIndex = mAmWmState.getStackIndexByActivityType(ACTIVITY_TYPE_RECENTS);
assertThat("Recents stack should be on top of home stack",
recentsStackIndex, lessThan(homeStackIndex));
}
@Test
@Presubmit
public void testStackListOrderOnSplitScreenDismissed() throws Exception {
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
setActivityTaskWindowingMode(DOCKED_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
mAmWmState.computeState(new WaitForValidActivityState.Builder(DOCKED_ACTIVITY)
.setWindowingMode(WINDOWING_MODE_FULLSCREEN)
.build());
final int homeStackIndex = mAmWmState.getStackIndexByActivityType(ACTIVITY_TYPE_HOME);
final int prevSplitScreenPrimaryIndex =
mAmWmState.getAmState().getStackIndexByActivity(DOCKED_ACTIVITY);
final int prevSplitScreenSecondaryIndex =
mAmWmState.getAmState().getStackIndexByActivity(TEST_ACTIVITY);
final int expectedHomeStackIndex =
(prevSplitScreenPrimaryIndex > prevSplitScreenSecondaryIndex
? prevSplitScreenPrimaryIndex : prevSplitScreenSecondaryIndex) - 1;
assertEquals("Home stack needs to be directly behind the top stack",
expectedHomeStackIndex, homeStackIndex);
}
private void launchActivityInDockStackAndMinimize(ComponentName activityName) throws Exception {
launchActivityInDockStackAndMinimize(activityName, SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT);
}
private void launchActivityInDockStackAndMinimize(ComponentName activityName, int createMode)
throws Exception {
launchActivityInSplitScreenWithRecents(activityName, createMode);
pressHomeButton();
waitForAndAssertDockMinimized();
}
private void assertDockMinimized() {
assertTrue(mAmWmState.getWmState().isDockedStackMinimized());
}
private void waitForAndAssertDockMinimized() throws Exception {
waitForDockMinimized();
assertDockMinimized();
mAmWmState.computeState(TEST_ACTIVITY);
mAmWmState.assertContainsStack("Must contain docked stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
mAmWmState.assertFocusedStack("Home activity should be focused in minimized mode",
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
}
private void assertDockNotMinimized() {
assertFalse(mAmWmState.getWmState().isDockedStackMinimized());
}
private void waitForDockMinimized() throws Exception {
mAmWmState.waitForWithWmState(state -> state.isDockedStackMinimized(),
"***Waiting for Dock stack to be minimized");
}
private void waitForDockNotMinimized() throws Exception {
mAmWmState.waitForWithWmState(state -> !state.isDockedStackMinimized(),
"***Waiting for Dock stack to not be minimized");
}
}