1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package android.server.am; 18 19 import static android.app.ActivityManager.StackId.INVALID_STACK_ID; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 21 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 22 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; 23 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 24 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; 25 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 26 import static android.server.am.ActivityManagerState.STATE_PAUSED; 27 import static android.server.am.ActivityManagerState.STATE_RESUMED; 28 import static android.server.am.ActivityManagerState.STATE_STOPPED; 29 import static android.server.am.ComponentNameUtils.getActivityName; 30 import static android.server.am.Components.ALT_LAUNCHING_ACTIVITY; 31 import static android.server.am.Components.ALWAYS_FOCUSABLE_PIP_ACTIVITY; 32 import static android.server.am.Components.BROADCAST_RECEIVER_ACTIVITY; 33 import static android.server.am.Components.BroadcastReceiverActivity.ACTION_TRIGGER_BROADCAST; 34 import static android.server.am.Components.BroadcastReceiverActivity.EXTRA_FINISH_BROADCAST; 35 import static android.server.am.Components.DOCKED_ACTIVITY; 36 import static android.server.am.Components.LAUNCHING_ACTIVITY; 37 import static android.server.am.Components.LAUNCH_PIP_ON_PIP_ACTIVITY; 38 import static android.server.am.Components.MOVE_TASK_TO_BACK_ACTIVITY; 39 import static android.server.am.Components.MoveTaskToBackActivity.EXTRA_FINISH_POINT; 40 import static android.server.am.Components.MoveTaskToBackActivity.FINISH_POINT_ON_PAUSE; 41 import static android.server.am.Components.MoveTaskToBackActivity.FINISH_POINT_ON_STOP; 42 import static android.server.am.Components.NO_HISTORY_ACTIVITY; 43 import static android.server.am.Components.SWIPE_REFRESH_ACTIVITY; 44 import static android.server.am.Components.TEST_ACTIVITY; 45 import static android.server.am.Components.TRANSLUCENT_ACTIVITY; 46 import static android.server.am.Components.TURN_SCREEN_ON_ACTIVITY; 47 import static android.server.am.Components.TURN_SCREEN_ON_ATTR_ACTIVITY; 48 import static android.server.am.Components.TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY; 49 import static android.server.am.Components.TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY; 50 import static android.server.am.Components.TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY; 51 import static android.server.am.Components.TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY; 52 import static android.server.am.UiDeviceUtils.pressBackButton; 53 54 import static org.junit.Assert.assertFalse; 55 import static org.junit.Assert.assertNotEquals; 56 import static org.junit.Assert.assertTrue; 57 import static org.junit.Assume.assumeTrue; 58 59 import android.platform.test.annotations.Presubmit; 60 61 import org.junit.Rule; 62 import org.junit.Test; 63 64 /** 65 * Build/Install/Run: 66 * atest CtsActivityManagerDeviceTestCases:ActivityManagerActivityVisibilityTests 67 */ 68 public class ActivityManagerActivityVisibilityTests extends ActivityManagerTestBase { 69 70 // TODO(b/70247058): Use {@link Context#sendBroadcast(Intent). 71 // Shell command to finish {@link #BROADCAST_RECEIVER_ACTIVITY}. 72 private static final String FINISH_ACTIVITY_BROADCAST = "am broadcast -a " 73 + ACTION_TRIGGER_BROADCAST + " --ez " + EXTRA_FINISH_BROADCAST + " true"; 74 75 @Rule 76 public final DisableScreenDozeRule mDisableScreenDozeRule = new DisableScreenDozeRule(); 77 78 @Presubmit 79 @Test testTranslucentActivityOnTopOfPinnedStack()80 public void testTranslucentActivityOnTopOfPinnedStack() throws Exception { 81 if (!supportsPip()) { 82 return; 83 } 84 85 executeShellCommand(getAmStartCmdOverHome(LAUNCH_PIP_ON_PIP_ACTIVITY)); 86 mAmWmState.waitForValidState(LAUNCH_PIP_ON_PIP_ACTIVITY); 87 // NOTE: moving to pinned stack will trigger the pip-on-pip activity to launch the 88 // translucent activity. 89 final int stackId = mAmWmState.getAmState().getStackIdByActivity( 90 LAUNCH_PIP_ON_PIP_ACTIVITY); 91 92 assertNotEquals(stackId, INVALID_STACK_ID); 93 executeShellCommand(getMoveToPinnedStackCommand(stackId)); 94 mAmWmState.waitForValidState( 95 new WaitForValidActivityState.Builder(ALWAYS_FOCUSABLE_PIP_ACTIVITY) 96 .setWindowingMode(WINDOWING_MODE_PINNED) 97 .setActivityType(ACTIVITY_TYPE_STANDARD) 98 .build()); 99 100 mAmWmState.assertFrontStack("Pinned stack must be the front stack.", 101 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD); 102 mAmWmState.assertVisibility(LAUNCH_PIP_ON_PIP_ACTIVITY, true); 103 mAmWmState.assertVisibility(ALWAYS_FOCUSABLE_PIP_ACTIVITY, true); 104 } 105 106 /** 107 * Asserts that the home activity is visible when a translucent activity is launched in the 108 * fullscreen stack over the home activity. 109 */ 110 @Test testTranslucentActivityOnTopOfHome()111 public void testTranslucentActivityOnTopOfHome() throws Exception { 112 if (!hasHomeScreen()) { 113 return; 114 } 115 116 launchHomeActivity(); 117 launchActivity(ALWAYS_FOCUSABLE_PIP_ACTIVITY); 118 119 mAmWmState.assertFrontStack("Fullscreen stack must be the front stack.", 120 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); 121 mAmWmState.assertVisibility(ALWAYS_FOCUSABLE_PIP_ACTIVITY, true); 122 mAmWmState.assertHomeActivityVisible(true); 123 } 124 125 /** 126 * Assert that the home activity is visible if a task that was launched from home is pinned 127 * and also assert the next task in the fullscreen stack isn't visible. 128 */ 129 @Presubmit 130 @Test testHomeVisibleOnActivityTaskPinned()131 public void testHomeVisibleOnActivityTaskPinned() throws Exception { 132 if (!supportsPip()) { 133 return; 134 } 135 136 launchHomeActivity(); 137 launchActivity(TEST_ACTIVITY); 138 launchHomeActivity(); 139 launchActivity(ALWAYS_FOCUSABLE_PIP_ACTIVITY); 140 final int stackId = mAmWmState.getAmState().getStackIdByActivity( 141 ALWAYS_FOCUSABLE_PIP_ACTIVITY); 142 143 assertNotEquals(stackId, INVALID_STACK_ID); 144 executeShellCommand(getMoveToPinnedStackCommand(stackId)); 145 mAmWmState.waitForValidState( 146 new WaitForValidActivityState.Builder(ALWAYS_FOCUSABLE_PIP_ACTIVITY) 147 .setWindowingMode(WINDOWING_MODE_PINNED) 148 .setActivityType(ACTIVITY_TYPE_STANDARD) 149 .build()); 150 151 mAmWmState.assertVisibility(ALWAYS_FOCUSABLE_PIP_ACTIVITY, true); 152 mAmWmState.assertVisibility(TEST_ACTIVITY, false); 153 mAmWmState.assertHomeActivityVisible(true); 154 } 155 156 @Presubmit 157 @Test testTranslucentActivityOverDockedStack()158 public void testTranslucentActivityOverDockedStack() throws Exception { 159 if (!supportsSplitScreenMultiWindow()) { 160 // Skipping test: no multi-window support 161 return; 162 } 163 164 launchActivitiesInSplitScreen( 165 getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY), 166 getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY)); 167 launchActivity(TRANSLUCENT_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); 168 mAmWmState.computeState(false /* compareTaskAndStackBounds */, 169 new WaitForValidActivityState(TEST_ACTIVITY), 170 new WaitForValidActivityState(DOCKED_ACTIVITY), 171 new WaitForValidActivityState(TRANSLUCENT_ACTIVITY)); 172 mAmWmState.assertContainsStack("Must contain fullscreen stack.", 173 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD); 174 mAmWmState.assertContainsStack("Must contain docked stack.", 175 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD); 176 mAmWmState.assertVisibility(DOCKED_ACTIVITY, true); 177 mAmWmState.assertVisibility(TEST_ACTIVITY, true); 178 mAmWmState.assertVisibility(TRANSLUCENT_ACTIVITY, true); 179 } 180 181 @Presubmit 182 @Test testTurnScreenOnActivity()183 public void testTurnScreenOnActivity() throws Exception { 184 try (final LockScreenSession lockScreenSession = new LockScreenSession()) { 185 lockScreenSession.sleepDevice(); 186 launchActivity(TURN_SCREEN_ON_ACTIVITY); 187 188 mAmWmState.assertVisibility(TURN_SCREEN_ON_ACTIVITY, true); 189 assertTrue("Display turns on", isDisplayOn()); 190 } 191 } 192 193 @Presubmit 194 @Test testFinishActivityInNonFocusedStack()195 public void testFinishActivityInNonFocusedStack() throws Exception { 196 if (!supportsSplitScreenMultiWindow()) { 197 // Skipping test: no multi-window support 198 return; 199 } 200 201 // Launch two activities in docked stack. 202 launchActivityInSplitScreenWithRecents(LAUNCHING_ACTIVITY); 203 getLaunchActivityBuilder() 204 .setTargetActivity(BROADCAST_RECEIVER_ACTIVITY) 205 .setWaitForLaunched(true) 206 .execute(); 207 mAmWmState.assertVisibility(BROADCAST_RECEIVER_ACTIVITY, true); 208 // Launch something to fullscreen stack to make it focused. 209 launchActivity(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY); 210 mAmWmState.assertVisibility(TEST_ACTIVITY, true); 211 // Finish activity in non-focused (docked) stack. 212 executeShellCommand(FINISH_ACTIVITY_BROADCAST); 213 214 mAmWmState.waitForActivityState(LAUNCHING_ACTIVITY, STATE_PAUSED); 215 mAmWmState.waitForAllExitingWindows(); 216 217 mAmWmState.computeState(LAUNCHING_ACTIVITY); 218 mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true); 219 mAmWmState.assertVisibility(BROADCAST_RECEIVER_ACTIVITY, false); 220 } 221 222 @Test testFinishActivityWithMoveTaskToBackAfterPause()223 public void testFinishActivityWithMoveTaskToBackAfterPause() throws Exception { 224 performFinishActivityWithMoveTaskToBack(FINISH_POINT_ON_PAUSE); 225 } 226 227 @Test testFinishActivityWithMoveTaskToBackAfterStop()228 public void testFinishActivityWithMoveTaskToBackAfterStop() throws Exception { 229 performFinishActivityWithMoveTaskToBack(FINISH_POINT_ON_STOP); 230 } 231 performFinishActivityWithMoveTaskToBack(String finishPoint)232 private void performFinishActivityWithMoveTaskToBack(String finishPoint) throws Exception { 233 // Make sure home activity is visible. 234 launchHomeActivity(); 235 if (hasHomeScreen()) { 236 mAmWmState.assertHomeActivityVisible(true /* visible */); 237 } 238 239 // Launch an activity that calls "moveTaskToBack" to finish itself. 240 launchActivity(MOVE_TASK_TO_BACK_ACTIVITY, EXTRA_FINISH_POINT, finishPoint); 241 mAmWmState.assertVisibility(MOVE_TASK_TO_BACK_ACTIVITY, true); 242 243 // Launch a different activity on top. 244 launchActivity(BROADCAST_RECEIVER_ACTIVITY); 245 mAmWmState.waitForActivityState(BROADCAST_RECEIVER_ACTIVITY, STATE_RESUMED); 246 final boolean shouldBeVisible = 247 !mAmWmState.getAmState().isBehindOpaqueActivities(MOVE_TASK_TO_BACK_ACTIVITY); 248 mAmWmState.assertVisibility(MOVE_TASK_TO_BACK_ACTIVITY, shouldBeVisible); 249 mAmWmState.assertVisibility(BROADCAST_RECEIVER_ACTIVITY, true); 250 251 // Finish the top-most activity. 252 executeShellCommand(FINISH_ACTIVITY_BROADCAST); 253 //TODO: BUG: MoveTaskToBackActivity returns to the top of the stack when 254 // BroadcastActivity finishes, so homeActivity is not visible afterwards 255 256 // Home must be visible. 257 if (hasHomeScreen()) { 258 mAmWmState.waitForHomeActivityVisible(); 259 mAmWmState.assertHomeActivityVisible(true /* visible */); 260 } 261 } 262 263 /** 264 * Asserts that launching between reorder to front activities exhibits the correct backstack 265 * behavior. 266 */ 267 @Test testReorderToFrontBackstack()268 public void testReorderToFrontBackstack() throws Exception { 269 // Start with home on top 270 launchHomeActivity(); 271 if (hasHomeScreen()) { 272 mAmWmState.assertHomeActivityVisible(true /* visible */); 273 } 274 275 // Launch the launching activity to the foreground 276 launchActivity(LAUNCHING_ACTIVITY); 277 278 // Launch the alternate launching activity from launching activity with reorder to front. 279 getLaunchActivityBuilder().setTargetActivity(ALT_LAUNCHING_ACTIVITY) 280 .setReorderToFront(true).execute(); 281 282 // Launch the launching activity from the alternate launching activity with reorder to 283 // front. 284 getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY) 285 .setLaunchingActivity(ALT_LAUNCHING_ACTIVITY) 286 .setReorderToFront(true) 287 .execute(); 288 289 // Press back 290 pressBackButton(); 291 292 mAmWmState.waitForValidState(ALT_LAUNCHING_ACTIVITY); 293 294 // Ensure the alternate launching activity is in focus 295 mAmWmState.assertFocusedActivity("Alt Launching Activity must be focused", 296 ALT_LAUNCHING_ACTIVITY); 297 } 298 299 /** 300 * Asserts that the activity focus and history is preserved moving between the activity and 301 * home stack. 302 */ 303 @Test testReorderToFrontChangingStack()304 public void testReorderToFrontChangingStack() throws Exception { 305 // Start with home on top 306 launchHomeActivity(); 307 if (hasHomeScreen()) { 308 mAmWmState.assertHomeActivityVisible(true /* visible */); 309 } 310 311 // Launch the launching activity to the foreground 312 launchActivity(LAUNCHING_ACTIVITY); 313 314 // Launch the alternate launching activity from launching activity with reorder to front. 315 getLaunchActivityBuilder().setTargetActivity(ALT_LAUNCHING_ACTIVITY) 316 .setReorderToFront(true) 317 .execute(); 318 319 // Return home 320 launchHomeActivity(); 321 if (hasHomeScreen()) { 322 mAmWmState.assertHomeActivityVisible(true /* visible */); 323 } 324 // Launch the launching activity from the alternate launching activity with reorder to 325 // front. 326 327 // Bring launching activity back to the foreground 328 launchActivityNoWait(LAUNCHING_ACTIVITY); 329 // Wait for the most front activity of the task. 330 mAmWmState.waitForValidState(ALT_LAUNCHING_ACTIVITY); 331 332 // Ensure the alternate launching activity is still in focus. 333 mAmWmState.assertFocusedActivity("Alt Launching Activity must be focused", 334 ALT_LAUNCHING_ACTIVITY); 335 336 pressBackButton(); 337 338 // Wait for the bottom activity back to the foreground. 339 mAmWmState.waitForValidState(LAUNCHING_ACTIVITY); 340 341 // Ensure launching activity was brought forward. 342 mAmWmState.assertFocusedActivity("Launching Activity must be focused", 343 LAUNCHING_ACTIVITY); 344 } 345 346 /** 347 * Asserts that a nohistory activity is stopped and removed immediately after a resumed activity 348 * above becomes visible and does not idle. 349 */ 350 @Test testNoHistoryActivityFinishedResumedActivityNotIdle()351 public void testNoHistoryActivityFinishedResumedActivityNotIdle() throws Exception { 352 if (!hasHomeScreen()) { 353 return; 354 } 355 356 // Start with home on top 357 launchHomeActivity(); 358 359 // Launch no history activity 360 launchActivity(NO_HISTORY_ACTIVITY); 361 362 // Launch an activity with a swipe refresh layout configured to prevent idle. 363 launchActivity(SWIPE_REFRESH_ACTIVITY); 364 365 pressBackButton(); 366 mAmWmState.waitForHomeActivityVisible(); 367 mAmWmState.assertHomeActivityVisible(true); 368 } 369 370 @Test testTurnScreenOnAttrNoLockScreen()371 public void testTurnScreenOnAttrNoLockScreen() throws Exception { 372 try (final LockScreenSession lockScreenSession = new LockScreenSession()) { 373 lockScreenSession.disableLockScreen() 374 .sleepDevice(); 375 final LogSeparator logSeparator = separateLogs(); 376 launchActivity(TURN_SCREEN_ON_ATTR_ACTIVITY); 377 mAmWmState.assertVisibility(TURN_SCREEN_ON_ATTR_ACTIVITY, true); 378 assertTrue("Display turns on", isDisplayOn()); 379 assertSingleLaunch(TURN_SCREEN_ON_ATTR_ACTIVITY, logSeparator); 380 } 381 } 382 383 @Test testTurnScreenOnAttrWithLockScreen()384 public void testTurnScreenOnAttrWithLockScreen() throws Exception { 385 if (!supportsSecureLock()) { 386 return; 387 } 388 389 try (final LockScreenSession lockScreenSession = new LockScreenSession()) { 390 lockScreenSession.setLockCredential() 391 .sleepDevice(); 392 final LogSeparator logSeparator = separateLogs(); 393 launchActivityNoWait(TURN_SCREEN_ON_ATTR_ACTIVITY); 394 // Wait for the activity stopped because lock screen prevent showing the activity. 395 mAmWmState.waitForActivityState(TURN_SCREEN_ON_ATTR_ACTIVITY, STATE_STOPPED); 396 assertFalse("Display keeps off", isDisplayOn()); 397 assertSingleLaunchAndStop(TURN_SCREEN_ON_ATTR_ACTIVITY, logSeparator); 398 } 399 } 400 401 @Test testTurnScreenOnShowOnLockAttr()402 public void testTurnScreenOnShowOnLockAttr() throws Exception { 403 try (final LockScreenSession lockScreenSession = new LockScreenSession()) { 404 lockScreenSession.sleepDevice(); 405 mAmWmState.waitForAllStoppedActivities(); 406 final LogSeparator logSeparator = separateLogs(); 407 launchActivity(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY); 408 mAmWmState.assertVisibility(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY, true); 409 assertTrue("Display turns on", isDisplayOn()); 410 assertSingleLaunch(TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY, logSeparator); 411 } 412 } 413 414 @Test testTurnScreenOnAttrRemove()415 public void testTurnScreenOnAttrRemove() throws Exception { 416 try (final LockScreenSession lockScreenSession = new LockScreenSession()) { 417 lockScreenSession.sleepDevice(); 418 mAmWmState.waitForAllStoppedActivities(); 419 LogSeparator logSeparator = separateLogs(); 420 launchActivity(TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY); 421 assertTrue("Display turns on", isDisplayOn()); 422 assertSingleLaunch(TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY, logSeparator); 423 424 lockScreenSession.sleepDevice(); 425 mAmWmState.waitForAllStoppedActivities(); 426 logSeparator = separateLogs(); 427 launchActivity(TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY); 428 // Display should keep off, because setTurnScreenOn(false) has been called at 429 // {@link TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY}'s onStop. 430 assertFalse("Display keeps off", isDisplayOn()); 431 assertSingleStartAndStop(TURN_SCREEN_ON_ATTR_REMOVE_ATTR_ACTIVITY, logSeparator); 432 } 433 } 434 435 @Test 436 @Presubmit testTurnScreenOnSingleTask()437 public void testTurnScreenOnSingleTask() throws Exception { 438 try (final LockScreenSession lockScreenSession = new LockScreenSession()) { 439 lockScreenSession.sleepDevice(); 440 LogSeparator logSeparator = separateLogs(); 441 launchActivity(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY); 442 mAmWmState.assertVisibility(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, true); 443 assertTrue("Display turns on", isDisplayOn()); 444 assertSingleLaunch(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, logSeparator); 445 446 lockScreenSession.sleepDevice(); 447 logSeparator = separateLogs(); 448 launchActivity(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY); 449 mAmWmState.assertVisibility(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, true); 450 assertTrue("Display turns on", isDisplayOn()); 451 assertSingleStart(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, logSeparator); 452 } 453 } 454 455 @Test testTurnScreenOnActivity_withRelayout()456 public void testTurnScreenOnActivity_withRelayout() throws Exception { 457 try (final LockScreenSession lockScreenSession = new LockScreenSession()) { 458 lockScreenSession.sleepDevice(); 459 launchActivity(TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY); 460 mAmWmState.assertVisibility(TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY, true); 461 462 lockScreenSession.sleepDevice(); 463 mAmWmState.waitForActivityState(TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY, STATE_STOPPED); 464 465 // Ensure there was an actual stop if the waitFor timed out. 466 assertTrue(getActivityName(TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY) + " stopped", 467 mAmWmState.getAmState().hasActivityState( 468 TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY, STATE_STOPPED)); 469 assertFalse("Display keeps off", isDisplayOn()); 470 } 471 } 472 } 473