blob: 525faef3fec12554b725a45be80983f3ea905ceb [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.wm;
import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
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.content.Intent.ACTION_MAIN;
import static android.content.Intent.CATEGORY_HOME;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
import static android.server.wm.WindowManagerState.STATE_RESUMED;
import static android.server.wm.WindowManagerState.STATE_STOPPED;
import static android.server.wm.UiDeviceUtils.pressBackButton;
import static android.server.wm.UiDeviceUtils.pressHomeButton;
import static android.server.wm.VirtualDisplayHelper.waitForDefaultDisplayState;
import static android.server.wm.app.Components.ALT_LAUNCHING_ACTIVITY;
import static android.server.wm.app.Components.ALWAYS_FOCUSABLE_PIP_ACTIVITY;
import static android.server.wm.app.Components.BROADCAST_RECEIVER_ACTIVITY;
import static android.server.wm.app.Components.DOCKED_ACTIVITY;
import static android.server.wm.app.Components.LAUNCHING_ACTIVITY;
import static android.server.wm.app.Components.LAUNCH_PIP_ON_PIP_ACTIVITY;
import static android.server.wm.app.Components.MOVE_TASK_TO_BACK_ACTIVITY;
import static android.server.wm.app.Components.MoveTaskToBackActivity.EXTRA_FINISH_POINT;
import static android.server.wm.app.Components.MoveTaskToBackActivity.FINISH_POINT_ON_PAUSE;
import static android.server.wm.app.Components.MoveTaskToBackActivity.FINISH_POINT_ON_STOP;
import static android.server.wm.app.Components.NO_HISTORY_ACTIVITY;
import static android.server.wm.app.Components.RESIZEABLE_ACTIVITY;
import static android.server.wm.app.Components.SHOW_WHEN_LOCKED_DIALOG_ACTIVITY;
import static android.server.wm.app.Components.TEST_ACTIVITY;
import static android.server.wm.app.Components.TOP_ACTIVITY;
import static android.server.wm.app.Components.TRANSLUCENT_ACTIVITY;
import static android.server.wm.app.Components.TRANSLUCENT_TOP_ACTIVITY;
import static android.server.wm.app.Components.TURN_SCREEN_ON_ACTIVITY;
import static android.server.wm.app.Components.TURN_SCREEN_ON_ATTR_ACTIVITY;
import static android.server.wm.app.Components.TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY;
import static android.server.wm.app.Components.TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY;
import static android.server.wm.app.Components.TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY;
import static android.server.wm.app.Components.TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY;
import static android.server.wm.app.Components.TopActivity.ACTION_CONVERT_FROM_TRANSLUCENT;
import static android.server.wm.app.Components.TopActivity.ACTION_CONVERT_TO_TRANSLUCENT;
import static android.view.Display.DEFAULT_DISPLAY;
import static org.junit.Assert.assertEquals;
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.content.ComponentName;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.platform.test.annotations.Presubmit;
import android.server.wm.CommandSession.ActivitySession;
import android.server.wm.CommandSession.ActivitySessionClient;
import android.server.wm.app.Components;
import org.junit.Rule;
import org.junit.Test;
/**
* Build/Install/Run:
* atest CtsWindowManagerDeviceTestCases:ActivityVisibilityTests
*/
@Presubmit
@android.server.wm.annotation.Group2
public class ActivityVisibilityTests extends ActivityManagerTestBase {
@Rule
public final DisableScreenDozeRule mDisableScreenDozeRule = new DisableScreenDozeRule();
@Test
public void testTranslucentActivityOnTopOfPinnedStack() throws Exception {
if (!supportsPip()) {
return;
}
executeShellCommand(getAmStartCmdOverHome(LAUNCH_PIP_ON_PIP_ACTIVITY));
mWmState.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 = mWmState.getStackIdByActivity(
LAUNCH_PIP_ON_PIP_ACTIVITY);
assertNotEquals(stackId, INVALID_STACK_ID);
moveTopActivityToPinnedRootTask(stackId);
mWmState.waitForValidState(
new WaitForValidActivityState.Builder(ALWAYS_FOCUSABLE_PIP_ACTIVITY)
.setWindowingMode(WINDOWING_MODE_PINNED)
.setActivityType(ACTIVITY_TYPE_STANDARD)
.build());
mWmState.assertFrontStack("Pinned stack must be the front stack.",
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
mWmState.assertVisibility(LAUNCH_PIP_ON_PIP_ACTIVITY, true);
mWmState.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);
mWmState.assertFrontStack("Fullscreen stack must be the front stack.",
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
mWmState.assertVisibility(ALWAYS_FOCUSABLE_PIP_ACTIVITY, true);
mWmState.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.
*/
@Test
public void testHomeVisibleOnActivityTaskPinned() throws Exception {
if (!supportsPip()) {
return;
}
launchHomeActivity();
launchActivity(TEST_ACTIVITY);
launchHomeActivity();
launchActivity(ALWAYS_FOCUSABLE_PIP_ACTIVITY);
final int stackId = mWmState.getStackIdByActivity(
ALWAYS_FOCUSABLE_PIP_ACTIVITY);
assertNotEquals(stackId, INVALID_STACK_ID);
moveTopActivityToPinnedRootTask(stackId);
mWmState.waitForValidState(
new WaitForValidActivityState.Builder(ALWAYS_FOCUSABLE_PIP_ACTIVITY)
.setWindowingMode(WINDOWING_MODE_PINNED)
.setActivityType(ACTIVITY_TYPE_STANDARD)
.build());
mWmState.assertVisibility(ALWAYS_FOCUSABLE_PIP_ACTIVITY, true);
mWmState.assertVisibility(TEST_ACTIVITY, false);
mWmState.assertHomeActivityVisible(true);
}
@Test
public void testHomeVisibleOnEmptyDisplay() throws Exception {
if (!hasHomeScreen()) {
return;
}
removeRootTasksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
forceStopHome();
assertEquals(mWmState.getResumedActivitiesCount(), 0);
assertEquals(mWmState.getRootTasksCount() , 0);
pressHomeButton();
mWmState.waitForHomeActivityVisible();
mWmState.assertHomeActivityVisible(true);
}
private void forceStopHome() {
final Intent intent = new Intent(ACTION_MAIN);
intent.addCategory(CATEGORY_HOME);
final ResolveInfo resolveInfo =
mContext.getPackageManager().resolveActivity(intent, MATCH_DEFAULT_ONLY);
String KILL_APP_COMMAND = "am force-stop " + resolveInfo.activityInfo.packageName;
executeShellCommand(KILL_APP_COMMAND);
}
@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);
mWmState.computeState(
new WaitForValidActivityState(TEST_ACTIVITY),
new WaitForValidActivityState(DOCKED_ACTIVITY),
new WaitForValidActivityState(TRANSLUCENT_ACTIVITY));
mWmState.assertContainsStack("Must contain fullscreen stack.",
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
mWmState.assertContainsStack("Must contain docked stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
mWmState.assertVisibility(DOCKED_ACTIVITY, true);
mWmState.assertVisibility(TEST_ACTIVITY, true);
mWmState.assertVisibility(TRANSLUCENT_ACTIVITY, true);
}
@Test
public void testTurnScreenOnActivity() {
assumeTrue(supportsLockScreen());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
final ActivitySessionClient activityClient = createManagedActivityClientSession();
testTurnScreenOnActivity(lockScreenSession, activityClient,
true /* useWindowFlags */, true /* showWhenLocked */);
testTurnScreenOnActivity(lockScreenSession, activityClient,
false /* useWindowFlags */, true /* showWhenLocked */);
testTurnScreenOnActivity(lockScreenSession, activityClient,
true /* useWindowFlags */, false /* showWhenLocked */);
testTurnScreenOnActivity(lockScreenSession, activityClient,
false /* useWindowFlags */, false /* showWhenLocked */);
}
@Test
public void testTurnScreenOnActivity_slowLaunch() {
assumeTrue(supportsLockScreen());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
final ActivitySessionClient activityClient = createManagedActivityClientSession();
// The activity will be paused first because the flags turn-screen-on and show-when-locked
// haven't been applied from relayout. And if it is slow, the ensure-visibility from pause
// timeout should still notify the client activity to be visible. Then the relayout can
// send the visible request to apply the flags and turn on screen.
testTurnScreenOnActivity(lockScreenSession, activityClient, true /* useWindowFlags */,
true /* showWhenLocked */, 1000 /* sleepMsInOnCreate */);
}
@Test
public void testTurnScreenOnActivity_DismissSplitScreen() {
assumeTrue(supportsLockScreen());
assumeTrue(supportsSplitScreenMultiWindow());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
final ActivitySessionClient activityClient = createManagedActivityClientSession();
testTurnScreenOnActivityMustDismissSplitScreen(lockScreenSession, activityClient,
true /* useWindowFlags */, true /* showWhenLocked */);
testTurnScreenOnActivityMustDismissSplitScreen(lockScreenSession, activityClient,
true /* useWindowFlags */, false /* showWhenLocked */);
testTurnScreenOnActivityMustDismissSplitScreen(lockScreenSession, activityClient,
false /* useWindowFlags */, true /* showWhenLocked */);
testTurnScreenOnActivityMustDismissSplitScreen(lockScreenSession, activityClient,
false /* useWindowFlags */, false /* showWhenLocked */);
}
private void testTurnScreenOnActivityMustDismissSplitScreen(LockScreenSession lockScreenSession,
ActivitySessionClient activityClient, boolean useWindowFlags, boolean showWhenLocked) {
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
getLaunchActivityBuilder().setTargetActivity(RESIZEABLE_ACTIVITY));
mWmState.assertContainsStack("Must contain split screen secondary stack.",
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
mWmState.assertContainsStack("Must contain split screen primary stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
testTurnScreenOnActivity(lockScreenSession, activityClient, useWindowFlags, showWhenLocked);
mWmState.assertDoesNotContainStack("Must not contain split screen secondary stack.",
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
mWmState.assertDoesNotContainStack("Must not contain split screen primary stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
}
private void testTurnScreenOnActivity(LockScreenSession lockScreenSession,
ActivitySessionClient activitySessionClient, boolean useWindowFlags,
boolean showWhenLocked) {
testTurnScreenOnActivity(lockScreenSession, activitySessionClient, useWindowFlags,
showWhenLocked, 0 /* sleepMsInOnCreate */);
}
private void testTurnScreenOnActivity(LockScreenSession lockScreenSession,
ActivitySessionClient activitySessionClient, boolean useWindowFlags,
boolean showWhenLocked, int sleepMsInOnCreate) {
ActivitySession activity = sleepDeviceAndLaunchTurnScreenOnActivity(lockScreenSession,
activitySessionClient, useWindowFlags, showWhenLocked, sleepMsInOnCreate,
WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
mWmState.assertVisibility(TURN_SCREEN_ON_ACTIVITY, true);
assertTrue("Display turns on by " + (useWindowFlags ? "flags" : "APIs"),
isDisplayOn(DEFAULT_DISPLAY));
activity.finish();
}
@Test
public void testFreeformWindowToTurnScreenOn() {
assumeTrue(supportsLockScreen());
assumeTrue(supportsFreeform());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
final ActivitySessionClient activityClient = createManagedActivityClientSession();
testFreeformWindowTurnScreenOnActivity(lockScreenSession, activityClient,
true/* useWindowFlags */, true/* showWhenLocked */);
testFreeformWindowTurnScreenOnActivity(lockScreenSession, activityClient,
true/* useWindowFlags */, false/* showWhenLocked */);
testFreeformWindowTurnScreenOnActivity(lockScreenSession, activityClient,
false/* useWindowFlags */, true/* showWhenLocked */);
testFreeformWindowTurnScreenOnActivity(lockScreenSession, activityClient,
false/* useWindowFlags */, false/* showWhenLocked */);
}
private void testFreeformWindowTurnScreenOnActivity(LockScreenSession lockScreenSession,
ActivitySessionClient activityClient, boolean useWindowFlags,
boolean showWhenLocked) {
ActivitySession activity = sleepDeviceAndLaunchTurnScreenOnActivity(lockScreenSession,
activityClient, useWindowFlags, showWhenLocked,
0 /* sleepMsInOnCreate */, WINDOWING_MODE_FREEFORM);
mWmState.waitForValidState(
new WaitForValidActivityState.Builder(TURN_SCREEN_ON_ACTIVITY)
.setWindowingMode(WINDOWING_MODE_FULLSCREEN)
.build());
assertTrue(mWmState.containsActivityInWindowingMode(
TURN_SCREEN_ON_ACTIVITY, WINDOWING_MODE_FULLSCREEN));
mWmState.assertVisibility(TURN_SCREEN_ON_ACTIVITY, true);
assertTrue("Display should be turned on by flags.", isDisplayOn(DEFAULT_DISPLAY));
activity.finish();
}
private ActivitySession sleepDeviceAndLaunchTurnScreenOnActivity(
LockScreenSession lockScreenSession, ActivitySessionClient activitySessionClient,
boolean useWindowFlags, boolean showWhenLocked, int sleepMsInOnCreate,
int windowingMode) {
lockScreenSession.sleepDevice();
return activitySessionClient.startActivity(
getLaunchActivityBuilder().setUseInstrumentation().setIntentExtra(extra -> {
extra.putBoolean(Components.TurnScreenOnActivity.EXTRA_USE_WINDOW_FLAGS,
useWindowFlags);
extra.putBoolean(Components.TurnScreenOnActivity.EXTRA_SHOW_WHEN_LOCKED,
showWhenLocked);
extra.putLong(Components.TurnScreenOnActivity.EXTRA_SLEEP_MS_IN_ON_CREATE,
sleepMsInOnCreate);
}).setTargetActivity(TURN_SCREEN_ON_ACTIVITY).setWindowingMode(windowingMode));
}
@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)
.setUseInstrumentation()
.execute();
mWmState.assertVisibility(BROADCAST_RECEIVER_ACTIVITY, true);
// Launch something to fullscreen stack to make it focused.
launchActivity(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
mWmState.assertVisibility(TEST_ACTIVITY, true);
// Finish activity in non-focused (docked) stack.
mBroadcastActionTrigger.finishBroadcastReceiverActivity();
mWmState.computeState(LAUNCHING_ACTIVITY);
// The testing activities support multiple resume (target SDK >= Q).
mWmState.waitForActivityState(LAUNCHING_ACTIVITY, STATE_RESUMED);
mWmState.assertVisibility(LAUNCHING_ACTIVITY, true);
mWmState.waitAndAssertActivityRemoved(BROADCAST_RECEIVER_ACTIVITY);
}
@Test
public void testLaunchTaskOnHome() {
if (!hasHomeScreen()) {
return;
}
getLaunchActivityBuilder().setTargetActivity(BROADCAST_RECEIVER_ACTIVITY)
.setIntentFlags(FLAG_ACTIVITY_NEW_TASK).execute();
getLaunchActivityBuilder().setTargetActivity(BROADCAST_RECEIVER_ACTIVITY)
.setIntentFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME).execute();
mBroadcastActionTrigger.finishBroadcastReceiverActivity();
mWmState.waitForHomeActivityVisible();
mWmState.assertHomeActivityVisible(true);
}
@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()) {
mWmState.assertHomeActivityVisible(true /* visible */);
}
// Launch an activity that calls "moveTaskToBack" to finish itself.
launchActivity(MOVE_TASK_TO_BACK_ACTIVITY, EXTRA_FINISH_POINT, finishPoint);
mWmState.assertVisibility(MOVE_TASK_TO_BACK_ACTIVITY, true);
// Launch a different activity on top.
launchActivity(BROADCAST_RECEIVER_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
mWmState.waitForActivityState(BROADCAST_RECEIVER_ACTIVITY, STATE_RESUMED);
mWmState.waitForActivityState(MOVE_TASK_TO_BACK_ACTIVITY,STATE_STOPPED);
final boolean shouldBeVisible =
!mWmState.isBehindOpaqueActivities(MOVE_TASK_TO_BACK_ACTIVITY);
mWmState.assertVisibility(MOVE_TASK_TO_BACK_ACTIVITY, shouldBeVisible);
mWmState.assertVisibility(BROADCAST_RECEIVER_ACTIVITY, true);
// Finish the top-most activity.
mBroadcastActionTrigger.finishBroadcastReceiverActivity();
//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()) {
mWmState.waitForHomeActivityVisible();
mWmState.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()) {
mWmState.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();
mWmState.waitForValidState(ALT_LAUNCHING_ACTIVITY);
// Ensure the alternate launching activity is in focus
mWmState.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()) {
mWmState.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()) {
mWmState.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.
mWmState.waitForValidState(ALT_LAUNCHING_ACTIVITY);
// Ensure the alternate launching activity is still in focus.
mWmState.assertFocusedActivity("Alt Launching Activity must be focused",
ALT_LAUNCHING_ACTIVITY);
pressBackButton();
// Wait for the bottom activity back to the foreground.
mWmState.waitForValidState(LAUNCHING_ACTIVITY);
// Ensure launching activity was brought forward.
mWmState.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() {
if (!hasHomeScreen()) {
return;
}
// Start with home on top
launchHomeActivity();
// Launch no history activity
launchActivity(NO_HISTORY_ACTIVITY);
// Launch an activity that won't report idle.
launchNoIdleActivity();
pressBackButton();
mWmState.waitForHomeActivityVisible();
mWmState.assertHomeActivityVisible(true);
}
/**
* Asserts that a no-history activity is not stopped and removed after a translucent activity
* above becomes resumed.
*/
@Test
public void testNoHistoryActivityNotFinishedBehindTranslucentActivity() {
// Launch a no-history activity
launchActivity(NO_HISTORY_ACTIVITY);
// Launch a translucent activity
launchActivity(TRANSLUCENT_ACTIVITY);
// Wait for the activity resumed
mWmState.waitForActivityState(TRANSLUCENT_ACTIVITY, STATE_RESUMED);
mWmState.assertVisibility(NO_HISTORY_ACTIVITY, true);
pressBackButton();
// Wait for the activity resumed
mWmState.waitForActivityState(NO_HISTORY_ACTIVITY, STATE_RESUMED);
mWmState.assertVisibility(NO_HISTORY_ACTIVITY, true);
}
/**
* If the next activity hasn't reported idle but it has drawn and the transition has done, the
* previous activity should be stopped and invisible without waiting for idle timeout.
*/
@Test
public void testActivityStoppedWhileNextActivityNotIdle() {
final ComponentName activityWithSameAffinity = TURN_SCREEN_ON_ATTR_ACTIVITY;
launchActivity(activityWithSameAffinity);
launchNoIdleActivity();
waitAndAssertActivityState(activityWithSameAffinity, STATE_STOPPED,
"Activity should be stopped before idle timeout");
mWmState.assertVisibility(activityWithSameAffinity, false);
}
private void launchNoIdleActivity() {
getLaunchActivityBuilder()
.setUseInstrumentation()
.setIntentExtra(
extra -> extra.putBoolean(Components.TestActivity.EXTRA_NO_IDLE, true))
.setTargetActivity(TEST_ACTIVITY)
.setWindowingMode(WINDOWING_MODE_FULLSCREEN)
.execute();
}
@Test
public void testTurnScreenOnAttrNoLockScreen() {
assumeTrue(supportsLockScreen());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.disableLockScreen().sleepDevice();
separateTestJournal();
launchActivity(TURN_SCREEN_ON_ATTR_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
mWmState.assertVisibility(TURN_SCREEN_ON_ATTR_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
assertSingleLaunch(TURN_SCREEN_ON_ATTR_ACTIVITY);
}
@Test
public void testTurnScreenOnAttrNoLockScreen_SplitScreen() {
assumeTrue(supportsLockScreen());
assumeTrue(supportsSplitScreenMultiWindow());
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
getLaunchActivityBuilder().setTargetActivity(RESIZEABLE_ACTIVITY));
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.disableLockScreen().sleepDevice();
launchActivity(TURN_SCREEN_ON_ATTR_ACTIVITY,
WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
mWmState.assertVisibility(TURN_SCREEN_ON_ATTR_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
}
@Test
public void testTurnScreenOnWithAttr_Freeform() {
assumeTrue(supportsLockScreen());
assumeTrue(supportsFreeform());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.disableLockScreen().sleepDevice();
launchActivity(TURN_SCREEN_ON_ATTR_ACTIVITY, WINDOWING_MODE_FREEFORM);
mWmState.assertVisibility(TURN_SCREEN_ON_ATTR_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
}
@Test
public void testTurnScreenOnAttrWithLockScreen() {
assumeTrue(supportsSecureLock());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.setLockCredential().sleepDevice();
separateTestJournal();
launchActivityNoWait(TURN_SCREEN_ON_ATTR_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
// Wait for the activity stopped because lock screen prevent showing the activity.
mWmState.waitForActivityState(TURN_SCREEN_ON_ATTR_ACTIVITY, STATE_STOPPED);
assertFalse("Display keeps off", isDisplayOn(DEFAULT_DISPLAY));
assertSingleLaunchAndStop(TURN_SCREEN_ON_ATTR_ACTIVITY);
}
@Test
public void testTurnScreenOnShowOnLockAttr() {
assumeTrue(supportsLockScreen());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.sleepDevice();
mWmState.waitForAllStoppedActivities();
separateTestJournal();
launchActivity(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
mWmState.assertVisibility(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
assertSingleLaunch(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY);
}
@Test
public void testTurnScreenOnShowOnLockAttrDismissSplitScreen() {
assumeTrue(supportsLockScreen());
assumeTrue(supportsSplitScreenMultiWindow());
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
getLaunchActivityBuilder().setTargetActivity(RESIZEABLE_ACTIVITY));
mWmState.assertContainsStack("Must contain split screen secondary stack.",
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
mWmState.assertContainsStack("Must contain split screen primary stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.sleepDevice();
mWmState.waitForAllStoppedActivities();
launchActivity(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY,
WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
mWmState.assertVisibility(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
lockScreenSession.unlockDevice();
mWmState.assertDoesNotContainStack("Must not contain split screen secondary stack.",
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
mWmState.assertDoesNotContainStack("Must not contain split screen primary stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
}
@Test
public void testChangeToFullscrenWhenLockWithAttrInFreeform() {
assumeTrue(supportsLockScreen());
assumeTrue(supportsFreeform());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.sleepDevice();
mWmState.waitForAllStoppedActivities();
launchActivityNoWait(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY, WINDOWING_MODE_FREEFORM);
mWmState.waitForValidState(
new WaitForValidActivityState.Builder(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY)
.setWindowingMode(WINDOWING_MODE_FULLSCREEN)
.build());
assertTrue(mWmState.containsActivityInWindowingMode(
TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY, WINDOWING_MODE_FULLSCREEN));
mWmState.assertVisibility(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
}
@Test
public void testTurnScreenOnAttrRemove() {
assumeTrue(supportsLockScreen());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.sleepDevice();
mWmState.waitForAllStoppedActivities();
separateTestJournal();
launchActivity(TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
assertSingleLaunch(TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY);
lockScreenSession.sleepDevice();
mWmState.waitForAllStoppedActivities();
separateTestJournal();
launchActivity(TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY);
mWmState.waitForActivityState(TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY, STATE_STOPPED);
// 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(DEFAULT_DISPLAY));
assertSingleStartAndStop(TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY);
}
@Test
public void testTurnScreenOnSingleTask() {
assumeTrue(supportsLockScreen());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.sleepDevice();
separateTestJournal();
launchActivity(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
mWmState.assertVisibility(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
assertSingleLaunch(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY);
lockScreenSession.sleepDevice();
// We should make sure test activity stopped to prevent a false alarm stop state
// included in the lifecycle count.
waitAndAssertActivityState(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, STATE_STOPPED,
"Activity should be stopped");
separateTestJournal();
launchActivity(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY);
mWmState.assertVisibility(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, true);
// Wait more for display state change since turning the display ON may take longer
// and reported after the activity launch.
waitForDefaultDisplayState(true /* wantOn */);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
assertSingleStart(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY);
}
@Test
public void testTurnScreenOnActivity_withRelayout() {
assumeTrue(supportsLockScreen());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.sleepDevice();
launchActivity(TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY);
mWmState.assertVisibility(TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY, true);
lockScreenSession.sleepDevice();
waitAndAssertActivityState(TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY, STATE_STOPPED,
"Activity should be stopped");
assertFalse("Display keeps off", isDisplayOn(DEFAULT_DISPLAY));
}
@Test
public void testGoingHomeMultipleTimes() throws Exception {
for (int i = 0; i < 10; i++) {
// Start activity normally
launchActivityOnDisplay(TEST_ACTIVITY, DEFAULT_DISPLAY);
waitAndAssertTopResumedActivity(TEST_ACTIVITY, DEFAULT_DISPLAY,
"Activity launched on default display must be focused");
// Start home activity directly
launchHomeActivity();
mWmState.assertHomeActivityVisible(true);
waitAndAssertActivityState(TEST_ACTIVITY, STATE_STOPPED,
"Activity should become STOPPED");
mWmState.assertVisibility(TEST_ACTIVITY, false);
}
}
@Test
public void testPressingHomeButtonMultipleTimes() throws Exception {
for (int i = 0; i < 10; i++) {
// Start activity normally
launchActivityOnDisplay(TEST_ACTIVITY, DEFAULT_DISPLAY);
waitAndAssertTopResumedActivity(TEST_ACTIVITY, DEFAULT_DISPLAY,
"Activity launched on default display must be focused");
// Press home button
pressHomeButton();
// Wait and assert home and activity states
mWmState.waitForHomeActivityVisible();
mWmState.assertHomeActivityVisible(true);
waitAndAssertActivityState(TEST_ACTIVITY, STATE_STOPPED,
"Activity should become STOPPED");
mWmState.assertVisibility(TEST_ACTIVITY, false);
}
}
@Test
public void testPressingHomeButtonMultipleTimesQuick() throws Exception {
for (int i = 0; i < 10; i++) {
// Start activity normally
launchActivityOnDisplay(TEST_ACTIVITY, DEFAULT_DISPLAY);
// Press home button
pressHomeButton();
mWmState.waitForHomeActivityVisible();
mWmState.assertHomeActivityVisible(true);
}
waitAndAssertActivityState(TEST_ACTIVITY, STATE_STOPPED,
"Activity should become STOPPED");
mWmState.assertVisibility(TEST_ACTIVITY, false);
}
@Test
public void testConvertTranslucentOnTranslucentActivity() {
final ActivitySessionClient activityClient = createManagedActivityClientSession();
// Start CONVERT_TRANSLUCENT_DIALOG_ACTIVITY on top of LAUNCHING_ACTIVITY
final ActivitySession activity = activityClient.startActivity(
getLaunchActivityBuilder().setTargetActivity(TRANSLUCENT_TOP_ACTIVITY));
verifyActivityVisibilities(TRANSLUCENT_TOP_ACTIVITY, false);
verifyActivityVisibilities(LAUNCHING_ACTIVITY, false);
activity.sendCommand(ACTION_CONVERT_FROM_TRANSLUCENT);
verifyActivityVisibilities(LAUNCHING_ACTIVITY, true);
activity.sendCommand(ACTION_CONVERT_TO_TRANSLUCENT);
verifyActivityVisibilities(LAUNCHING_ACTIVITY, false);
}
@Test
public void testConvertTranslucentOnNonTopTranslucentActivity() {
final ActivitySessionClient activityClient = createManagedActivityClientSession();
final ActivitySession activity = activityClient.startActivity(
getLaunchActivityBuilder().setTargetActivity(TRANSLUCENT_TOP_ACTIVITY));
getLaunchActivityBuilder().setTargetActivity(SHOW_WHEN_LOCKED_DIALOG_ACTIVITY)
.setUseInstrumentation().execute();
verifyActivityVisibilities(SHOW_WHEN_LOCKED_DIALOG_ACTIVITY, false);
verifyActivityVisibilities(TRANSLUCENT_TOP_ACTIVITY, false);
verifyActivityVisibilities(LAUNCHING_ACTIVITY, false);
activity.sendCommand(ACTION_CONVERT_FROM_TRANSLUCENT);
verifyActivityVisibilities(LAUNCHING_ACTIVITY, true);
activity.sendCommand(ACTION_CONVERT_TO_TRANSLUCENT);
verifyActivityVisibilities(LAUNCHING_ACTIVITY, false);
}
@Test
public void testConvertTranslucentOnOpaqueActivity() {
final ActivitySessionClient activityClient = createManagedActivityClientSession();
final ActivitySession activity = activityClient.startActivity(
getLaunchActivityBuilder().setTargetActivity(TOP_ACTIVITY));
verifyActivityVisibilities(TOP_ACTIVITY, false);
verifyActivityVisibilities(LAUNCHING_ACTIVITY, true);
activity.sendCommand(ACTION_CONVERT_TO_TRANSLUCENT);
verifyActivityVisibilities(LAUNCHING_ACTIVITY, false);
activity.sendCommand(ACTION_CONVERT_FROM_TRANSLUCENT);
verifyActivityVisibilities(LAUNCHING_ACTIVITY, true);
}
@Test
public void testConvertTranslucentOnNonTopOpaqueActivity() {
final ActivitySessionClient activityClient = createManagedActivityClientSession();
final ActivitySession activity = activityClient.startActivity(
getLaunchActivityBuilder().setTargetActivity(TOP_ACTIVITY));
getLaunchActivityBuilder().setTargetActivity(SHOW_WHEN_LOCKED_DIALOG_ACTIVITY)
.setUseInstrumentation().execute();
verifyActivityVisibilities(SHOW_WHEN_LOCKED_DIALOG_ACTIVITY, false);
verifyActivityVisibilities(TOP_ACTIVITY, false);
verifyActivityVisibilities(LAUNCHING_ACTIVITY, true);
activity.sendCommand(ACTION_CONVERT_TO_TRANSLUCENT);
verifyActivityVisibilities(LAUNCHING_ACTIVITY, false);
activity.sendCommand(ACTION_CONVERT_FROM_TRANSLUCENT);
verifyActivityVisibilities(LAUNCHING_ACTIVITY, true);
}
private void verifyActivityVisibilities(ComponentName activityBehind,
boolean behindFullScreen) {
if (behindFullScreen) {
mWmState.waitForActivityState(activityBehind, STATE_STOPPED);
mWmState.assertVisibility(activityBehind, false);
} else {
mWmState.waitForValidState(activityBehind);
mWmState.assertVisibility(activityBehind, true);
}
}
}