blob: ee16237d2f1aa5913b931b23269119d33fbc51bb [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package android.server.am;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
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_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.server.am.ActivityManagerState.STATE_PAUSED;
import static android.server.am.ActivityManagerState.STATE_RESUMED;
import static android.server.am.ActivityManagerState.STATE_STOPPED;
import static android.server.am.ComponentNameUtils.getActivityName;
import static android.server.am.Components.ALT_LAUNCHING_ACTIVITY;
import static android.server.am.Components.ALWAYS_FOCUSABLE_PIP_ACTIVITY;
import static android.server.am.Components.BROADCAST_RECEIVER_ACTIVITY;
import static android.server.am.Components.BroadcastReceiverActivity.ACTION_TRIGGER_BROADCAST;
import static android.server.am.Components.BroadcastReceiverActivity.EXTRA_FINISH_BROADCAST;
import static android.server.am.Components.DOCKED_ACTIVITY;
import static android.server.am.Components.LAUNCHING_ACTIVITY;
import static android.server.am.Components.LAUNCH_PIP_ON_PIP_ACTIVITY;
import static android.server.am.Components.MOVE_TASK_TO_BACK_ACTIVITY;
import static android.server.am.Components.MoveTaskToBackActivity.EXTRA_FINISH_POINT;
import static android.server.am.Components.MoveTaskToBackActivity.FINISH_POINT_ON_PAUSE;
import static android.server.am.Components.MoveTaskToBackActivity.FINISH_POINT_ON_STOP;
import static android.server.am.Components.NO_HISTORY_ACTIVITY;
import static android.server.am.Components.SWIPE_REFRESH_ACTIVITY;
import static android.server.am.Components.TEST_ACTIVITY;
import static android.server.am.Components.TRANSLUCENT_ACTIVITY;
import static android.server.am.Components.TURN_SCREEN_ON_ACTIVITY;
import static android.server.am.Components.TURN_SCREEN_ON_ATTR_ACTIVITY;
import static android.server.am.Components.TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY;
import static android.server.am.Components.TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY;
import static android.server.am.Components.TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY;
import static android.server.am.Components.TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY;
import static android.server.am.UiDeviceUtils.pressBackButton;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.Presubmit;
import org.junit.Rule;
import org.junit.Test;
/**
* Build/Install/Run:
* atest CtsActivityManagerDeviceTestCases:ActivityManagerActivityVisibilityTests
*/
public class ActivityManagerActivityVisibilityTests extends ActivityManagerTestBase {
@Rule
public final DisableScreenDozeRule mDisableScreenDozeRule = new DisableScreenDozeRule();
@Presubmit
@Test
public void testTranslucentActivityOnTopOfPinnedStack() throws Exception {
if (!supportsPip()) {
return;
}
executeShellCommand(getAmStartCmdOverHome(LAUNCH_PIP_ON_PIP_ACTIVITY));
mAmWmState.waitForValidState(LAUNCH_PIP_ON_PIP_ACTIVITY);
// NOTE: moving to pinned stack will trigger the pip-on-pip activity to launch the
// translucent activity.
final int stackId = mAmWmState.getAmState().getStackIdByActivity(
LAUNCH_PIP_ON_PIP_ACTIVITY);
assertNotEquals(stackId, INVALID_STACK_ID);
executeShellCommand(getMoveToPinnedStackCommand(stackId));
mAmWmState.waitForValidState(
new WaitForValidActivityState.Builder(ALWAYS_FOCUSABLE_PIP_ACTIVITY)
.setWindowingMode(WINDOWING_MODE_PINNED)
.setActivityType(ACTIVITY_TYPE_STANDARD)
.build());
mAmWmState.assertFrontStack("Pinned stack must be the front stack.",
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
mAmWmState.assertVisibility(LAUNCH_PIP_ON_PIP_ACTIVITY, true);
mAmWmState.assertVisibility(ALWAYS_FOCUSABLE_PIP_ACTIVITY, true);
}
/**
* Asserts that the home activity is visible when a translucent activity is launched in the
* fullscreen stack over the home activity.
*/
@Test
public void testTranslucentActivityOnTopOfHome() throws Exception {
if (!hasHomeScreen()) {
return;
}
launchHomeActivity();
launchActivity(ALWAYS_FOCUSABLE_PIP_ACTIVITY);
mAmWmState.assertFrontStack("Fullscreen stack must be the front stack.",
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
mAmWmState.assertVisibility(ALWAYS_FOCUSABLE_PIP_ACTIVITY, true);
mAmWmState.assertHomeActivityVisible(true);
}
/**
* Assert that the home activity is visible if a task that was launched from home is pinned
* and also assert the next task in the fullscreen stack isn't visible.
*/
@Presubmit
@Test
public void testHomeVisibleOnActivityTaskPinned() throws Exception {
if (!supportsPip()) {
return;
}
launchHomeActivity();
launchActivity(TEST_ACTIVITY);
launchHomeActivity();
launchActivity(ALWAYS_FOCUSABLE_PIP_ACTIVITY);
final int stackId = mAmWmState.getAmState().getStackIdByActivity(
ALWAYS_FOCUSABLE_PIP_ACTIVITY);
assertNotEquals(stackId, INVALID_STACK_ID);
executeShellCommand(getMoveToPinnedStackCommand(stackId));
mAmWmState.waitForValidState(
new WaitForValidActivityState.Builder(ALWAYS_FOCUSABLE_PIP_ACTIVITY)
.setWindowingMode(WINDOWING_MODE_PINNED)
.setActivityType(ACTIVITY_TYPE_STANDARD)
.build());
mAmWmState.assertVisibility(ALWAYS_FOCUSABLE_PIP_ACTIVITY, true);
mAmWmState.assertVisibility(TEST_ACTIVITY, false);
mAmWmState.assertHomeActivityVisible(true);
}
@Presubmit
@Test
public void testTranslucentActivityOverDockedStack() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
// Skipping test: no multi-window support
return;
}
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
launchActivity(TRANSLUCENT_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
mAmWmState.computeState(false /* compareTaskAndStackBounds */,
new WaitForValidActivityState(TEST_ACTIVITY),
new WaitForValidActivityState(DOCKED_ACTIVITY),
new WaitForValidActivityState(TRANSLUCENT_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);
mAmWmState.assertVisibility(DOCKED_ACTIVITY, true);
mAmWmState.assertVisibility(TEST_ACTIVITY, true);
mAmWmState.assertVisibility(TRANSLUCENT_ACTIVITY, true);
}
@Presubmit
@Test
public void testTurnScreenOnActivity() throws Exception {
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.sleepDevice();
launchActivity(TURN_SCREEN_ON_ACTIVITY);
mAmWmState.assertVisibility(TURN_SCREEN_ON_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn());
}
}
@Presubmit
@Test
public void testFinishActivityInNonFocusedStack() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
// Skipping test: no multi-window support
return;
}
// Launch two activities in docked stack.
launchActivityInSplitScreenWithRecents(LAUNCHING_ACTIVITY);
getLaunchActivityBuilder()
.setTargetActivity(BROADCAST_RECEIVER_ACTIVITY)
.setWaitForLaunched(true)
.execute();
mAmWmState.assertVisibility(BROADCAST_RECEIVER_ACTIVITY, true);
// Launch something to fullscreen stack to make it focused.
launchActivity(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
mAmWmState.assertVisibility(TEST_ACTIVITY, true);
// Finish activity in non-focused (docked) stack.
executeShellCommand(FINISH_ACTIVITY_BROADCAST);
mAmWmState.waitForActivityState(LAUNCHING_ACTIVITY, STATE_PAUSED);
mAmWmState.waitForAllExitingWindows();
mAmWmState.computeState(LAUNCHING_ACTIVITY);
mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true);
mAmWmState.assertVisibility(BROADCAST_RECEIVER_ACTIVITY, false);
}
@Test
public void testFinishActivityWithMoveTaskToBackAfterPause() throws Exception {
performFinishActivityWithMoveTaskToBack(FINISH_POINT_ON_PAUSE);
}
@Test
public void testFinishActivityWithMoveTaskToBackAfterStop() throws Exception {
performFinishActivityWithMoveTaskToBack(FINISH_POINT_ON_STOP);
}
private void performFinishActivityWithMoveTaskToBack(String finishPoint) throws Exception {
// Make sure home activity is visible.
launchHomeActivity();
if (hasHomeScreen()) {
mAmWmState.assertHomeActivityVisible(true /* visible */);
}
// Launch an activity that calls "moveTaskToBack" to finish itself.
launchActivity(MOVE_TASK_TO_BACK_ACTIVITY, EXTRA_FINISH_POINT, finishPoint);
mAmWmState.assertVisibility(MOVE_TASK_TO_BACK_ACTIVITY, true);
// Launch a different activity on top.
launchActivity(BROADCAST_RECEIVER_ACTIVITY);
mAmWmState.waitForActivityState(BROADCAST_RECEIVER_ACTIVITY, STATE_RESUMED);
// Wait for transition complete.
mAmWmState.waitForValidState(MOVE_TASK_TO_BACK_ACTIVITY);
final boolean shouldBeVisible =
!mAmWmState.getAmState().isBehindOpaqueActivities(MOVE_TASK_TO_BACK_ACTIVITY);
mAmWmState.assertVisibility(MOVE_TASK_TO_BACK_ACTIVITY, shouldBeVisible);
mAmWmState.assertVisibility(BROADCAST_RECEIVER_ACTIVITY, true);
// Finish the top-most activity.
executeShellCommand(FINISH_ACTIVITY_BROADCAST);
//TODO: BUG: MoveTaskToBackActivity returns to the top of the stack when
// BroadcastActivity finishes, so homeActivity is not visible afterwards
// Home must be visible.
if (hasHomeScreen()) {
mAmWmState.waitForHomeActivityVisible();
mAmWmState.assertHomeActivityVisible(true /* visible */);
}
}
/**
* Asserts that launching between reorder to front activities exhibits the correct backstack
* behavior.
*/
@Test
public void testReorderToFrontBackstack() throws Exception {
// Start with home on top
launchHomeActivity();
if (hasHomeScreen()) {
mAmWmState.assertHomeActivityVisible(true /* visible */);
}
// Launch the launching activity to the foreground
launchActivity(LAUNCHING_ACTIVITY);
// Launch the alternate launching activity from launching activity with reorder to front.
getLaunchActivityBuilder().setTargetActivity(ALT_LAUNCHING_ACTIVITY)
.setReorderToFront(true).execute();
// Launch the launching activity from the alternate launching activity with reorder to
// front.
getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY)
.setLaunchingActivity(ALT_LAUNCHING_ACTIVITY)
.setReorderToFront(true)
.execute();
// Press back
pressBackButton();
mAmWmState.waitForValidState(ALT_LAUNCHING_ACTIVITY);
// Ensure the alternate launching activity is in focus
mAmWmState.assertFocusedActivity("Alt Launching Activity must be focused",
ALT_LAUNCHING_ACTIVITY);
}
/**
* Asserts that the activity focus and history is preserved moving between the activity and
* home stack.
*/
@Test
public void testReorderToFrontChangingStack() throws Exception {
// Start with home on top
launchHomeActivity();
if (hasHomeScreen()) {
mAmWmState.assertHomeActivityVisible(true /* visible */);
}
// Launch the launching activity to the foreground
launchActivity(LAUNCHING_ACTIVITY);
// Launch the alternate launching activity from launching activity with reorder to front.
getLaunchActivityBuilder().setTargetActivity(ALT_LAUNCHING_ACTIVITY)
.setReorderToFront(true)
.execute();
// Return home
launchHomeActivity();
if (hasHomeScreen()) {
mAmWmState.assertHomeActivityVisible(true /* visible */);
}
// Launch the launching activity from the alternate launching activity with reorder to
// front.
// Bring launching activity back to the foreground
launchActivityNoWait(LAUNCHING_ACTIVITY);
// Wait for the most front activity of the task.
mAmWmState.waitForValidState(ALT_LAUNCHING_ACTIVITY);
// Ensure the alternate launching activity is still in focus.
mAmWmState.assertFocusedActivity("Alt Launching Activity must be focused",
ALT_LAUNCHING_ACTIVITY);
pressBackButton();
// Wait for the bottom activity back to the foreground.
mAmWmState.waitForValidState(LAUNCHING_ACTIVITY);
// Ensure launching activity was brought forward.
mAmWmState.assertFocusedActivity("Launching Activity must be focused",
LAUNCHING_ACTIVITY);
}
/**
* Asserts that a nohistory activity is stopped and removed immediately after a resumed activity
* above becomes visible and does not idle.
*/
@Test
public void testNoHistoryActivityFinishedResumedActivityNotIdle() throws Exception {
if (!hasHomeScreen()) {
return;
}
// Start with home on top
launchHomeActivity();
// Launch no history activity
launchActivity(NO_HISTORY_ACTIVITY);
// Launch an activity with a swipe refresh layout configured to prevent idle.
launchActivity(SWIPE_REFRESH_ACTIVITY);
pressBackButton();
mAmWmState.waitForHomeActivityVisible();
mAmWmState.assertHomeActivityVisible(true);
}
@Test
public void testTurnScreenOnAttrNoLockScreen() throws Exception {
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.disableLockScreen()
.sleepDevice();
final LogSeparator logSeparator = separateLogs();
launchActivity(TURN_SCREEN_ON_ATTR_ACTIVITY);
mAmWmState.assertVisibility(TURN_SCREEN_ON_ATTR_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn());
assertSingleLaunch(TURN_SCREEN_ON_ATTR_ACTIVITY, logSeparator);
}
}
@Test
public void testTurnScreenOnAttrWithLockScreen() throws Exception {
if (!supportsSecureLock()) {
return;
}
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.setLockCredential()
.sleepDevice();
final LogSeparator logSeparator = separateLogs();
launchActivityNoWait(TURN_SCREEN_ON_ATTR_ACTIVITY);
// Wait for the activity stopped because lock screen prevent showing the activity.
mAmWmState.waitForActivityState(TURN_SCREEN_ON_ATTR_ACTIVITY, STATE_STOPPED);
assertFalse("Display keeps off", isDisplayOn());
assertSingleLaunchAndStop(TURN_SCREEN_ON_ATTR_ACTIVITY, logSeparator);
}
}
@Test
public void testTurnScreenOnShowOnLockAttr() throws Exception {
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.sleepDevice();
mAmWmState.waitForAllStoppedActivities();
final LogSeparator logSeparator = separateLogs();
launchActivity(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY);
mAmWmState.assertVisibility(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn());
assertSingleLaunch(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY, logSeparator);
}
}
@Test
public void testTurnScreenOnAttrRemove() throws Exception {
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.sleepDevice();
mAmWmState.waitForAllStoppedActivities();
LogSeparator logSeparator = separateLogs();
launchActivity(TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY);
assertTrue("Display turns on", isDisplayOn());
assertSingleLaunch(TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY, logSeparator);
lockScreenSession.sleepDevice();
mAmWmState.waitForAllStoppedActivities();
logSeparator = separateLogs();
launchActivity(TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY);
// Display should keep off, because setTurnScreenOn(false) has been called at
// {@link TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY}'s onStop.
assertFalse("Display keeps off", isDisplayOn());
assertSingleStartAndStop(TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY, logSeparator);
}
}
@Test
@Presubmit
public void testTurnScreenOnSingleTask() throws Exception {
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.sleepDevice();
LogSeparator logSeparator = separateLogs();
launchActivity(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY);
mAmWmState.assertVisibility(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn());
assertSingleLaunch(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, logSeparator);
lockScreenSession.sleepDevice();
logSeparator = separateLogs();
launchActivity(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY);
mAmWmState.assertVisibility(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn());
assertSingleStart(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, logSeparator);
}
}
@Test
public void testTurnScreenOnActivity_withRelayout() throws Exception {
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.sleepDevice();
launchActivity(TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY);
mAmWmState.assertVisibility(TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY, true);
lockScreenSession.sleepDevice();
mAmWmState.waitForActivityState(TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY, STATE_STOPPED);
// Ensure there was an actual stop if the waitFor timed out.
assertTrue(getActivityName(TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY) + " stopped",
mAmWmState.getAmState().hasActivityState(
TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY, STATE_STOPPED));
assertFalse("Display keeps off", isDisplayOn());
}
}
}