blob: 86e7b6c98156a07346299c71c9d503b1237a3a3f [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.cts;
import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.log.LogUtil.CLog;
import java.awt.Rectangle;
public class ActivityManagerDockedStackTests extends ActivityManagerTestBase {
private static final String TEST_ACTIVITY_NAME = "TestActivity";
private static final String NON_RESIZEABLE_ACTIVITY_NAME = "NonResizeableActivity";
private static final String DOCKED_ACTIVITY_NAME = "DockedActivity";
private static final String NO_RELAUNCH_ACTIVITY_NAME = "NoRelaunchActivity";
private static final String SINGLE_INSTANCE_ACTIVITY_NAME = "SingleInstanceActivity";
private static final String SINGLE_TASK_ACTIVITY_NAME = "SingleTaskActivity";
private static final int TASK_SIZE = 600;
private static final int STACK_SIZE = 300;
public void testStackList() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
return;
}
executeShellCommand(getAmStartCmd(TEST_ACTIVITY_NAME));
mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
mAmWmState.assertContainsStack(
"Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
mAmWmState.assertDoesNotContainStack("Must not contain docked stack.", DOCKED_STACK_ID);
}
public void testDockActivity() throws Exception {
if (!supportsMultiWindowMode() || !supportsSplitScreenMultiWindow()) {
CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
return;
}
launchActivityInDockStack(TEST_ACTIVITY_NAME);
mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
}
public void testNonResizeableNotDocked() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
return;
}
launchActivityInDockStack(NON_RESIZEABLE_ACTIVITY_NAME);
mAmWmState.computeState(mDevice, new String[] {NON_RESIZEABLE_ACTIVITY_NAME});
mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
mAmWmState.assertDoesNotContainStack("Must not contain docked stack.", DOCKED_STACK_ID);
mAmWmState.assertFrontStack(
"Fullscreen stack must be front stack.", FULLSCREEN_WORKSPACE_STACK_ID);
}
public void testLaunchToSide() throws Exception {
if (!supportsMultiWindowMode() || !supportsSplitScreenMultiWindow()) {
CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
return;
}
launchActivityInDockStack(LAUNCHING_ACTIVITY);
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
launchActivityToSide();
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME});
mAmWmState.assertContainsStack(
"Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
}
public void testLaunchToSideAndBringToFront() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
return;
}
launchActivityInDockStack(LAUNCHING_ACTIVITY);
final String[] waitForFirstVisible = new String[] {TEST_ACTIVITY_NAME};
final String[] waitForSecondVisible = new String[] {NO_RELAUNCH_ACTIVITY_NAME};
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
// Launch activity to side.
launchActivityToSide();
mAmWmState.computeState(mDevice, waitForFirstVisible);
int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
.getTasks().size();
mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
TEST_ACTIVITY_NAME);
// Launch another activity to side to cover first one.
launchActivityInStack(NO_RELAUNCH_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
mAmWmState.computeState(mDevice, waitForSecondVisible);
int taskNumberCovered = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
.getTasks().size();
mAmWmState.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_NAME);
// Launch activity that was first launched to side. It should be brought to front.
launchActivityToSide();
mAmWmState.computeState(mDevice, waitForFirstVisible);
int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
.getTasks().size();
mAmWmState.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_NAME);
}
public void testLaunchToSideMultiple() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
return;
}
launchActivityInDockStack(LAUNCHING_ACTIVITY);
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
final String[] waitForActivitiesVisible =
new String[] {TEST_ACTIVITY_NAME, LAUNCHING_ACTIVITY};
// Launch activity to side.
launchActivityToSide();
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
.getTasks().size();
mAmWmState.assertNotNull("Launched to side activity must be in fullscreen stack.",
mAmWmState.getAmState()
.getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));
// Try to launch to side same activity again.
launchActivityToSide();
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
.getTasks().size();
mAmWmState.assertEquals("Task number mustn't change.", taskNumberInitial, taskNumberFinal);
mAmWmState.assertFocusedActivity("Launched to side activity must remain in front.",
TEST_ACTIVITY_NAME);
mAmWmState.assertNotNull("Launched to side activity must remain in fullscreen stack.",
mAmWmState.getAmState()
.getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));
}
public void testLaunchToSideSingleInstance() throws Exception {
launchTargetToSide(SINGLE_INSTANCE_ACTIVITY_NAME, false);
}
public void testLaunchToSideSingleTask() throws Exception {
launchTargetToSide(SINGLE_TASK_ACTIVITY_NAME, false);
}
public void testLaunchToSideMultipleWithDifferentIntent() throws Exception {
launchTargetToSide(TEST_ACTIVITY_NAME, true);
}
private void launchTargetToSide(String targetActivityName,
boolean taskCountMustIncrement) throws Exception {
if (!supportsSplitScreenMultiWindow()) {
CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
return;
}
launchActivityInDockStack(LAUNCHING_ACTIVITY);
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
final String[] waitForActivitiesVisible =
new String[] {targetActivityName, LAUNCHING_ACTIVITY};
// Launch activity to side with data.
launchActivityToSide(true, false, targetActivityName);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
mAmWmState.assertContainsStack(
"Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
.getTasks().size();
mAmWmState.assertNotNull("Launched to side activity must be in fullscreen stack.",
mAmWmState.getAmState()
.getTaskByActivityName(targetActivityName, FULLSCREEN_WORKSPACE_STACK_ID));
// Try to launch to side same activity again with different data.
launchActivityToSide(true, false, targetActivityName);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
int taskNumberSecondLaunch = mAmWmState.getAmState()
.getStackById(FULLSCREEN_WORKSPACE_STACK_ID).getTasks().size();
if (taskCountMustIncrement) {
mAmWmState.assertEquals("Task number must be incremented.", taskNumberInitial + 1,
taskNumberSecondLaunch);
} else {
mAmWmState.assertEquals("Task number must not change.", taskNumberInitial,
taskNumberSecondLaunch);
}
mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
targetActivityName);
mAmWmState.assertNotNull("Launched to side activity must be launched in fullscreen stack.",
mAmWmState.getAmState()
.getTaskByActivityName(targetActivityName, FULLSCREEN_WORKSPACE_STACK_ID));
// Try to launch to side same activity again with no data.
launchActivityToSide(false, false, targetActivityName);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
.getTasks().size();
if (taskCountMustIncrement) {
mAmWmState.assertEquals("Task number must be incremented.", taskNumberSecondLaunch + 1,
taskNumberFinal);
} else {
mAmWmState.assertEquals("Task number must not change.", taskNumberSecondLaunch,
taskNumberFinal);
}
mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
targetActivityName);
mAmWmState.assertNotNull("Launched to side activity must be launched in fullscreen stack.",
mAmWmState.getAmState()
.getTaskByActivityName(targetActivityName, FULLSCREEN_WORKSPACE_STACK_ID));
}
public void testLaunchToSideMultipleWithFlag() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
return;
}
launchActivityInDockStack(LAUNCHING_ACTIVITY);
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
final String[] waitForActivitiesVisible =
new String[] {LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME};
// Launch activity to side.
launchActivityToSide();
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
.getTasks().size();
mAmWmState.assertNotNull("Launched to side activity must be in fullscreen stack.",
mAmWmState.getAmState()
.getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));
// Try to launch to side same activity again, but with Intent#FLAG_ACTIVITY_MULTIPLE_TASK.
launchActivityToSide(false, true);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
.getTasks().size();
mAmWmState.assertEquals("Task number must be incremented.", taskNumberInitial + 1,
taskNumberFinal);
mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
TEST_ACTIVITY_NAME);
mAmWmState.assertNotNull("Launched to side activity must remain in fullscreen stack.",
mAmWmState.getAmState()
.getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));
}
public void testRotationWhenDocked() throws Exception {
if (!supportsMultiWindowMode() || !supportsSplitScreenMultiWindow()) {
CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
return;
}
launchActivityInDockStack(LAUNCHING_ACTIVITY);
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
launchActivityToSide();
mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
mAmWmState.assertContainsStack(
"Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
// Rotate device single steps (90°) 0-1-2-3.
// Each time we compute the state we implicitly assert valid bounds.
String[] waitForActivitiesVisible =
new String[] {LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME};
setDeviceRotation(0);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
setDeviceRotation(1);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
setDeviceRotation(2);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
setDeviceRotation(3);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
// 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.
setDeviceRotation(1);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
setDeviceRotation(3);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
setDeviceRotation(0);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
setDeviceRotation(2);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
setDeviceRotation(0);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
}
public void testRotationWhenDockedWhileLocked() throws Exception {
if (!supportsMultiWindowMode() || !supportsSplitScreenMultiWindow()) {
CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
return;
}
launchActivityInDockStack(LAUNCHING_ACTIVITY);
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
launchActivityToSide();
mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
mAmWmState.assertSanity();
mAmWmState.assertContainsStack(
"Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
String[] waitForActivitiesVisible =
new String[] {LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME};
lockDevice();
setDeviceRotation(0);
unlockDevice();
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
lockDevice();
setDeviceRotation(1);
unlockDevice();
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
lockDevice();
setDeviceRotation(2);
unlockDevice();
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
lockDevice();
setDeviceRotation(3);
unlockDevice();
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
}
public void testResizeDockedStack() throws Exception {
if (!supportsMultiWindowMode() || !supportsSplitScreenMultiWindow()) {
CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
return;
}
launchActivityInDockStack(DOCKED_ACTIVITY_NAME);
mAmWmState.computeState(mDevice, new String[] {DOCKED_ACTIVITY_NAME});
launchActivityInStack(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
resizeDockedStack(STACK_SIZE, STACK_SIZE, TASK_SIZE, TASK_SIZE);
mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME, DOCKED_ACTIVITY_NAME},
false /* compareTaskAndStackBounds */);
mAmWmState.assertContainsStack("Must contain docked stack", DOCKED_STACK_ID);
mAmWmState.assertContainsStack("Must contain fullscreen stack",
FULLSCREEN_WORKSPACE_STACK_ID);
assertEquals(new Rectangle(0, 0, STACK_SIZE, STACK_SIZE),
mAmWmState.getAmState().getStackById(DOCKED_STACK_ID).getBounds());
mAmWmState.assertDockedTaskBounds(TASK_SIZE, DOCKED_ACTIVITY_NAME);
mAmWmState.assertVisibility(DOCKED_ACTIVITY_NAME, true);
mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true);
}
public void testActivityLifeCycleOnResizeDockedStack() throws Exception {
if (!supportsMultiWindowMode() || !supportsSplitScreenMultiWindow()) {
CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
return;
}
final String[] waitTestActivityName = new String[] {TEST_ACTIVITY_NAME};
executeShellCommand(getAmStartCmd(TEST_ACTIVITY_NAME));
mAmWmState.computeState(mDevice, waitTestActivityName);
final Rectangle fullScreenBounds =
mAmWmState.getWmState().getStack(FULLSCREEN_WORKSPACE_STACK_ID).getBounds();
moveActivityToDockStack(TEST_ACTIVITY_NAME);
mAmWmState.computeState(mDevice, waitTestActivityName);
launchActivityInStack(NO_RELAUNCH_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
mAmWmState.computeState(mDevice,
new String[]{TEST_ACTIVITY_NAME, NO_RELAUNCH_ACTIVITY_NAME});
final Rectangle initialDockBounds =
mAmWmState.getWmState().getStack(DOCKED_STACK_ID).getBounds();
clearLogcat();
Rectangle newBounds = computeNewDockBounds(fullScreenBounds, initialDockBounds, true);
resizeDockedStack(newBounds.width, newBounds.height, newBounds.width, newBounds.height);
mAmWmState.computeState(mDevice,
new String[]{TEST_ACTIVITY_NAME, NO_RELAUNCH_ACTIVITY_NAME});
// 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(mDevice,
new String[]{TEST_ACTIVITY_NAME, NO_RELAUNCH_ACTIVITY_NAME});
assertActivityLifecycle(TEST_ACTIVITY_NAME, true);
assertActivityLifecycle(NO_RELAUNCH_ACTIVITY_NAME, false);
}
private Rectangle computeNewDockBounds(
Rectangle fullscreenBounds, Rectangle 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 Rectangle newBounds = new Rectangle(dockBounds);
if (inLandscape) {
// In landscape we change the width.
newBounds.width *= sizeChangeFactor;
} else {
// In portrait we change the height
newBounds.height *= sizeChangeFactor;
}
return newBounds;
}
private void launchActivityToSide() throws Exception {
launchActivityToSide(false, false);
}
private void launchActivityToSide(boolean randomData, boolean multipleTaskFlag)
throws Exception {
launchActivityToSide(randomData, multipleTaskFlag, null);
}
}