1 /* 2 * Copyright (C) 2018 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.wm.activity.lifecycle; 18 19 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 20 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; 21 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; 22 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; 23 import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT; 24 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; 25 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 26 import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP; 27 import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED; 28 import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP; 29 import static android.server.wm.ComponentNameUtils.getActivityName; 30 import static android.server.wm.UiDeviceUtils.pressWakeupButton; 31 import static android.server.wm.WindowManagerState.STATE_DESTROYED; 32 import static android.server.wm.WindowManagerState.STATE_RESUMED; 33 import static android.server.wm.activity.lifecycle.LifecycleConstants.ON_STOP; 34 import static android.server.wm.activity.lifecycle.LifecycleConstants.getComponentName; 35 import static android.server.wm.app.Components.ALIAS_TEST_ACTIVITY; 36 import static android.server.wm.app.Components.NO_HISTORY_ACTIVITY; 37 import static android.server.wm.app.Components.SHOW_WHEN_LOCKED_TRANSLUCENT_ACTIVITY; 38 import static android.server.wm.app.Components.TEST_ACTIVITY; 39 40 import static org.junit.Assert.assertEquals; 41 import static org.junit.Assert.assertNotEquals; 42 import static org.junit.Assert.assertTrue; 43 import static org.junit.Assume.assumeTrue; 44 import static org.junit.Assume.assumeFalse; 45 46 import android.app.Activity; 47 import android.content.ComponentName; 48 import android.content.Intent; 49 import android.os.Bundle; 50 import android.platform.test.annotations.Presubmit; 51 import android.server.wm.ActivityLauncher; 52 import android.server.wm.HelperActivities; 53 import android.server.wm.LockScreenSession; 54 import android.server.wm.WaitForValidActivityState; 55 import android.server.wm.app.Components; 56 57 import org.junit.Test; 58 59 /** 60 * Build/Install/Run: 61 * atest CtsWindowManagerDeviceActivity:ActivityStarterTests 62 */ 63 @Presubmit 64 @android.server.wm.annotation.Group3 65 public class ActivityStarterTests extends ActivityLifecycleClientTestBase { 66 67 private static final ComponentName STANDARD_ACTIVITY 68 = getComponentName(HelperActivities.StandardActivity.class); 69 private static final ComponentName SECOND_STANDARD_ACTIVITY 70 = getComponentName(HelperActivities.SecondStandardActivity.class); 71 private static final ComponentName SINGLE_TOP_ACTIVITY 72 = getComponentName(SingleTopActivity.class); 73 private static final ComponentName SINGLE_INSTANCE_ACTIVITY 74 = getComponentName(SingleInstanceActivity.class); 75 private static final ComponentName SINGLE_TASK_ACTIVITY 76 = getComponentName(SingleTaskActivity.class); 77 private static final ComponentName STANDARD_SINGLE_TOP_ACTIVITY 78 = getComponentName(StandardWithSingleTopActivity.class); 79 private static final ComponentName TEST_LAUNCHING_ACTIVITY 80 = getComponentName(TestLaunchingActivity.class); 81 private static final ComponentName LAUNCHING_AND_FINISH_ACTIVITY 82 = getComponentName(LaunchingAndFinishActivity.class); 83 private static final ComponentName CLEAR_TASK_ON_LAUNCH_ACTIVITY 84 = getComponentName(ClearTaskOnLaunchActivity.class); 85 private static final ComponentName FINISH_ON_TASK_LAUNCH_ACTIVITY 86 = getComponentName(FinishOnTaskLaunchActivity.class); 87 private static final ComponentName DOCUMENT_INTO_EXISTING_ACTIVITY 88 = getComponentName(DocumentIntoExistingActivity.class); 89 private static final ComponentName RELINQUISHTASKIDENTITY_ACTIVITY 90 = getComponentName(RelinquishTaskIdentityActivity.class); 91 92 93 /** 94 * Ensures that the following launch flag combination works when starting an activity which is 95 * already running: - {@code FLAG_ACTIVITY_CLEAR_TOP} - {@code 96 * FLAG_ACTIVITY_RESET_TASK_IF_NEEDED} - {@code FLAG_ACTIVITY_NEW_TASK} 97 */ 98 @Test testClearTopNewTaskResetTask()99 public void testClearTopNewTaskResetTask() throws Exception { 100 // Start activity normally 101 launchActivityAndWait(FirstActivity.class); 102 103 // Navigate home 104 launchHomeActivity(); 105 waitAndAssertActivityStates(state(FirstActivity.class, ON_STOP)); 106 getTransitionLog().clear(); 107 108 // Start activity again with flags in question. Verify activity is resumed. 109 // A new instance of activity will be created, and the old one destroyed. 110 final Activity secondLaunchActivity = new Launcher(FirstActivity.class) 111 .setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_NEW_TASK 112 | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) 113 .launch(); 114 mWmState.waitForActivityState(secondLaunchActivity.getComponentName(), STATE_RESUMED); 115 assertEquals("The activity should be started and be resumed", 116 getActivityName(secondLaunchActivity.getComponentName()), 117 mWmState.getTopActivityName(0)); 118 } 119 120 /** 121 * This test case tests "standard" activity behavior. 122 * A first launched standard activity and a second launched standard activity 123 * must be in same task. 124 */ 125 @Test testLaunchStandardActivity()126 public void testLaunchStandardActivity() { 127 // Launch a standard activity. 128 launchActivity(STANDARD_ACTIVITY); 129 130 final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId(); 131 final int instances = mWmState.getActivityCountInTask(taskId, null); 132 133 // Launch a second standard activity. 134 launchActivity(SECOND_STANDARD_ACTIVITY); 135 136 // Make sure instances in task are increased. 137 assertEquals("instances of activity in task must be increased.", instances + 1, 138 mWmState.getActivityCountInTask(taskId, null)); 139 140 // Make sure the stack for the second standard activity is front. 141 assertEquals("The stack for the second standard activity must be front.", 142 getActivityName(SECOND_STANDARD_ACTIVITY), 143 mWmState.getTopActivityName(0)); 144 145 // Make sure the standard activity and the second standard activity are in same task. 146 assertEquals("Activity must be in same task.", taskId, 147 mWmState.getTaskByActivity(SECOND_STANDARD_ACTIVITY).getTaskId()); 148 } 149 150 /** 151 * This test case tests show-when-locked behavior for a "no-history" activity. 152 * The no-history activity should be resumed over lockscreen. 153 */ 154 @Test testLaunchNoHistoryActivityShowWhenLocked()155 public void testLaunchNoHistoryActivityShowWhenLocked() { 156 // Allow TV devices to skip this test. 157 assumeFalse(isLeanBack()); 158 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 159 lockScreenSession.sleepDevice(); 160 161 getLaunchActivityBuilder().setTargetActivity(NO_HISTORY_ACTIVITY) 162 .setIntentExtra(extra -> extra.putBoolean( 163 Components.NoHistoryActivity.EXTRA_SHOW_WHEN_LOCKED, true)) 164 .setUseInstrumentation().execute(); 165 waitAndAssertActivityState(NO_HISTORY_ACTIVITY, STATE_RESUMED, 166 "Activity should be resumed"); 167 } 168 169 /** 170 * This test case tests the behavior for a "no-history" activity after turning the screen off. 171 * The no-history activity must be resumed over lockscreen when launched again. 172 */ 173 @Test testNoHistoryActivityNotFinished()174 public void testNoHistoryActivityNotFinished() { 175 assumeTrue(supportsLockScreen()); 176 177 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 178 // Launch a no-history activity 179 getLaunchActivityBuilder().setTargetActivity(NO_HISTORY_ACTIVITY) 180 .setIntentExtra(extra -> extra.putBoolean( 181 Components.NoHistoryActivity.EXTRA_SHOW_WHEN_LOCKED, true)) 182 .setUseInstrumentation().execute(); 183 184 // Wait for the activity resumed. 185 mWmState.waitForActivityState(NO_HISTORY_ACTIVITY, STATE_RESUMED); 186 187 lockScreenSession.sleepDevice(); 188 189 // Launch a no-history activity 190 launchActivity(NO_HISTORY_ACTIVITY); 191 192 // Wait for the activity resumed 193 waitAndAssertActivityState(NO_HISTORY_ACTIVITY, STATE_RESUMED, 194 "Activity must be resumed"); 195 } 196 197 /** 198 * This test case tests the behavior that a fullscreen activity was started on top of the 199 * no-history activity within different tasks during sleeping. The no-history activity must be 200 * finished. 201 */ 202 @Test testNoHistoryActivityWithDifferentTask()203 public void testNoHistoryActivityWithDifferentTask() { 204 assumeTrue(supportsLockScreen()); 205 206 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 207 // Launch a no-history activity 208 getLaunchActivityBuilder().setTargetActivity(NO_HISTORY_ACTIVITY) 209 .setIntentExtra(extra -> extra.putBoolean( 210 Components.NoHistoryActivity.EXTRA_SHOW_WHEN_LOCKED, true)) 211 .setWaitForLaunched(false) 212 .setUseInstrumentation() 213 .execute(); 214 215 // Wait for the activity resumed. 216 waitAndAssertActivityState(NO_HISTORY_ACTIVITY, STATE_RESUMED, 217 "Activity must be resumed"); 218 final int taskId = mWmState.getTaskByActivity(NO_HISTORY_ACTIVITY).getTaskId(); 219 lockScreenSession.sleepDevice(); 220 221 // Launch a single instance activity 222 getLaunchActivityBuilder().setTargetActivity(SINGLE_INSTANCE_ACTIVITY) 223 .setIntentExtra(extra -> extra.putBoolean( 224 SingleInstanceActivity.EXTRA_SHOW_WHEN_LOCKED, true)) 225 .setWaitForLaunched(false) 226 .setUseInstrumentation() 227 .execute(); 228 229 // Make sure the activity is finished. 230 final String waitFinishMsg = "Instance of no-history activity must not exist"; 231 assertTrue(waitFinishMsg, mWmState.waitForWithAmState( 232 amState -> 0 == amState.getActivityCountInTask(taskId, NO_HISTORY_ACTIVITY), 233 waitFinishMsg)); 234 235 // Turn the screen on after the test is completed to prevent keyDispatchingTimedOut during 236 // the lockScreenSession close. 237 pressWakeupButton(); 238 } 239 240 /** 241 * This test case tests the behavior that a translucent activity was started on top of the 242 * no-history activity during sleeping. The no-history activity must not be finished. 243 */ 244 @Test testNoHistoryActivityWithTranslucentActivity()245 public void testNoHistoryActivityWithTranslucentActivity() { 246 assumeTrue(supportsLockScreen()); 247 248 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 249 // Launch a no-history activity 250 getLaunchActivityBuilder().setTargetActivity(NO_HISTORY_ACTIVITY) 251 .setIntentExtra(extra -> extra.putBoolean( 252 Components.NoHistoryActivity.EXTRA_SHOW_WHEN_LOCKED, true)) 253 .setWaitForLaunched(false) 254 .setUseInstrumentation() 255 .execute(); 256 257 // Wait for the activity resumed. 258 waitAndAssertActivityState(NO_HISTORY_ACTIVITY, STATE_RESUMED, 259 "Activity must be resumed"); 260 261 final int taskId = mWmState.getTaskByActivity(NO_HISTORY_ACTIVITY).getTaskId(); 262 lockScreenSession.sleepDevice(); 263 launchActivityNoWait(SHOW_WHEN_LOCKED_TRANSLUCENT_ACTIVITY); 264 265 final String waitFinishMsg = "Instance of no-history activity must exist"; 266 assertTrue(waitFinishMsg, mWmState.waitForWithAmState( 267 amState -> 1 == amState.getActivityCountInTask(taskId, NO_HISTORY_ACTIVITY), 268 waitFinishMsg)); 269 270 // Turn the screen on after the test is completed to prevent keyDispatchingTimedOut during 271 // the lockScreenSession close. 272 pressWakeupButton(); 273 } 274 275 /** 276 * This test case tests "single top" activity behavior. 277 * - A first launched standard activity and a second launched single top 278 * activity are in same task. 279 * - A new instance of single top activity is not created if task 280 * already has a its activity at the top of its task. 281 */ 282 @Test testLaunchSingleTopActivity()283 public void testLaunchSingleTopActivity() { 284 // Launch a standard activity. 285 launchActivity(STANDARD_ACTIVITY); 286 287 final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId(); 288 289 // Launch a single top activity. 290 launchActivity(SINGLE_TOP_ACTIVITY); 291 292 final int instances = mWmState.getActivityCountInTask(taskId, null); 293 294 // Make sure the single top activity is in focus. 295 mWmState.assertFocusedActivity(SINGLE_TOP_ACTIVITY + "must be focused Activity", 296 SINGLE_TOP_ACTIVITY); 297 298 // Make sure the stack for the single top activity is front. 299 assertEquals("The stack for the single top activity must be front.", 300 getActivityName(SINGLE_TOP_ACTIVITY), 301 mWmState.getTopActivityName(0)); 302 303 // Make sure the standard activity and the single top activity are in same task. 304 assertEquals("Two activities must be in same task.", taskId, 305 mWmState.getTaskByActivity(SINGLE_TOP_ACTIVITY).getTaskId()); 306 307 // Launch a single top activity. 308 launchActivity(SINGLE_TOP_ACTIVITY); 309 310 // Make sure that instances of activity are not increased. 311 assertEquals("instances of activity must not be increased.", instances, 312 mWmState.getActivityCountInTask(taskId, null)); 313 } 314 315 /** 316 * This test case tests "single instance" activity behavior. 317 * - A first launched standard activity and a second launched single instance 318 * activity are not in same task. 319 * - A single instance activity is always the single and only member of its task. 320 */ 321 @Test testLaunchSingleInstanceActivity()322 public void testLaunchSingleInstanceActivity() { 323 // Launch a standard activity. 324 launchActivity(STANDARD_ACTIVITY); 325 326 final int firstTaskId = mWmState 327 .getTaskByActivity(STANDARD_ACTIVITY).getTaskId(); 328 329 // Launch a single instance activity 330 launchActivity(SINGLE_INSTANCE_ACTIVITY); 331 332 final int secondTaskId = mWmState 333 .getTaskByActivity(SINGLE_INSTANCE_ACTIVITY).getTaskId(); 334 335 // Make sure the single instance activity is in focus. 336 mWmState.assertFocusedActivity(SINGLE_INSTANCE_ACTIVITY + "must be focused Activity", 337 SINGLE_INSTANCE_ACTIVITY); 338 // Make sure the single instance activity is front. 339 assertEquals("The stack for the single instance activity must be front.", 340 getActivityName(SINGLE_INSTANCE_ACTIVITY), 341 mWmState.getTopActivityName(0)); 342 343 // Make sure the standard activity and the test activity are not in same task. 344 assertNotEquals("Activity must be in different task.", firstTaskId, secondTaskId); 345 346 // Make sure the single instance activity is only member of its task. 347 assertEquals("Single instance activity is only member of its task", 1, 348 mWmState.getActivityCountInTask(secondTaskId, null)); 349 } 350 351 /** 352 * This test case tests "single task" activity behavior. 353 * - A first launched standard activity and a second launched single task activity 354 * are in same task. 355 * - Instance of single task activity is only one in its task. 356 */ 357 @Test testLaunchSingleTaskActivity()358 public void testLaunchSingleTaskActivity() { 359 // Launch a standard activity. 360 launchActivity(STANDARD_ACTIVITY); 361 362 final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId(); 363 364 // Launch a single task activity 365 launchActivity(SINGLE_TASK_ACTIVITY); 366 367 // Make sure the single task activity is in focus. 368 mWmState.assertFocusedActivity(SINGLE_TASK_ACTIVITY + "must be focused Activity", 369 SINGLE_TASK_ACTIVITY); 370 371 // Make sure the stack for the single task activity is front. 372 assertEquals("The stack for the single task activity must be front.", 373 getActivityName(SINGLE_TASK_ACTIVITY), 374 mWmState.getTopActivityName(0)); 375 376 // Make sure the test activity is in same task. 377 assertEquals("Activity must be in same task.", taskId, 378 mWmState.getTaskByActivity(SINGLE_TASK_ACTIVITY).getTaskId()); 379 380 // Launch a second standard activity 381 launchActivity(SECOND_STANDARD_ACTIVITY); 382 383 // Launch a single task activity again. 384 launchActivity(SINGLE_TASK_ACTIVITY); 385 mWmState.waitForActivityRemoved(SECOND_STANDARD_ACTIVITY); 386 387 // Make sure the number of instances for single task activity is only one. 388 assertEquals("Instance of single task activity in its task must be only one", 1, 389 mWmState.getActivityCountInTask(taskId, SINGLE_TASK_ACTIVITY)); 390 // Make sure that instance of standard activity does not exists. 391 assertEquals("Instance of second standard activity must not exist.", 0, 392 mWmState.getActivityCountInTask(taskId, SECOND_STANDARD_ACTIVITY)); 393 394 } 395 396 /** 397 * Tests that the existing task would be brought to top while launching alias activity or 398 * real activity without creating new activity instances, tasks, or stacks. 399 */ 400 @Test testLaunchAliasActivity()401 public void testLaunchAliasActivity() { 402 // Launch alias activity. 403 getLaunchActivityBuilder().setUseInstrumentation().setTargetActivity(ALIAS_TEST_ACTIVITY) 404 .setIntentFlags(FLAG_ACTIVITY_NEW_TASK).execute(); 405 406 final int testStacks = countTestRootTasks(); 407 final int taskId = mWmState.getTaskByActivity(ALIAS_TEST_ACTIVITY).getTaskId(); 408 409 // Return to home and launch the alias activity again. 410 launchHomeActivity(); 411 getLaunchActivityBuilder().setUseInstrumentation().setTargetActivity(ALIAS_TEST_ACTIVITY) 412 .setIntentFlags(FLAG_ACTIVITY_NEW_TASK).execute(); 413 assertEquals("Instance of the activity in its task must be only one", 1, 414 mWmState.getActivityCountInTask(taskId, ALIAS_TEST_ACTIVITY)); 415 assertEquals("Test stack count should not be increased.", testStacks, 416 countTestRootTasks()); 417 418 // Return to home and launch the real activity. 419 launchHomeActivity(); 420 getLaunchActivityBuilder().setUseInstrumentation().setTargetActivity(TEST_ACTIVITY) 421 .setIntentFlags(FLAG_ACTIVITY_NEW_TASK).execute(); 422 assertEquals("Instance of the activity in its task must be only one", 1, 423 mWmState.getActivityCountInTask(taskId, ALIAS_TEST_ACTIVITY)); 424 assertEquals("Test stack count should not be increased.", testStacks, 425 countTestRootTasks()); 426 } 427 countTestRootTasks()428 private int countTestRootTasks() { 429 return mWmState.getRootTasksCount( 430 t -> ALIAS_TEST_ACTIVITY.getPackageName().equals(t.getPackageName())); 431 } 432 433 /** 434 * This test case tests behavior of activities launched with FLAG_ACTIVITY_NEW_TASK 435 * and FLAG_ACTIVITY_CLEAR_TASK. 436 * A first launched activity is finished, then a second activity is created if the 437 * second activity is launched with FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_CLEAR_TASK. 438 */ 439 @Test testLaunchActivityWithFlagNewTaskAndClearTask()440 public void testLaunchActivityWithFlagNewTaskAndClearTask() { 441 // Launch a standard activity with FLAG_ACTIVITY_NEW_TASK. 442 getLaunchActivityBuilder() 443 .setTargetActivity(STANDARD_ACTIVITY) 444 .setIntentFlags(FLAG_ACTIVITY_NEW_TASK) 445 .execute(); 446 447 final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId(); 448 449 // Launch Activity with FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_CLEAR_TASK. 450 getLaunchActivityBuilder() 451 .setTargetActivity(STANDARD_ACTIVITY) 452 .setLaunchingActivity(TEST_LAUNCHING_ACTIVITY) 453 .setIntentFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK) 454 .execute(); 455 456 mWmState.waitForActivityState(STANDARD_ACTIVITY, STATE_DESTROYED); 457 458 // Make sure the number of instances for standard activity is one 459 // because previous standard activity to be finished due to FLAG_ACTIVITY_CLEAR_TASK. 460 assertEquals("Instance of activity must be one", 1, 461 mWmState.getActivityCountInTask(taskId, STANDARD_ACTIVITY)); 462 463 // Make sure the stack for the standard activity is front. 464 assertEquals("The stack for the standard activity must be front.", 465 getActivityName(STANDARD_ACTIVITY), 466 mWmState.getTopActivityName(0)); 467 } 468 469 /** 470 * This test case tests behavior of activity launched with FLAG_ACTIVITY_CLEAR_TOP. 471 * A top activity is finished when an activity is launched with FLAG_ACTIVITY_CLEAR_TOP. 472 */ 473 @Test testLaunchActivityWithFlagClearTop()474 public void testLaunchActivityWithFlagClearTop() { 475 // Launch a standard activity 476 getLaunchActivityBuilder() 477 .setTargetActivity(STANDARD_ACTIVITY) 478 .setUseInstrumentation() 479 .execute(); 480 481 final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId(); 482 483 // Launch a second standard activity 484 getLaunchActivityBuilder() 485 .setTargetActivity(SECOND_STANDARD_ACTIVITY) 486 .setUseInstrumentation() 487 .execute(); 488 489 // Launch a standard activity again with CLEAR_TOP_FLAG 490 getLaunchActivityBuilder() 491 .setTargetActivity(STANDARD_ACTIVITY) 492 .setUseInstrumentation() 493 .setIntentFlags(FLAG_ACTIVITY_CLEAR_TOP) 494 .execute(); 495 496 mWmState.waitForActivityState(STANDARD_ACTIVITY, STATE_RESUMED); 497 498 // Make sure that the standard activity is in focus. 499 mWmState.assertFocusedActivity(STANDARD_ACTIVITY + "must be focused Activity", 500 STANDARD_ACTIVITY); 501 502 // Make sure the stack for the standard activity is front. 503 assertEquals("The stack for the standard activity must be front.", 504 getActivityName(STANDARD_ACTIVITY), 505 mWmState.getTopActivityName(0)); 506 507 // Make sure the activity is not in same task. 508 assertEquals("Activity must be in same task.", taskId, 509 mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId()); 510 // Make sure the second standard activity is finished. 511 final String waitFinishMsg = "Instance of second standard activity must not exist"; 512 assertTrue(waitFinishMsg, mWmState.waitForWithAmState( 513 amState -> 0 == amState.getActivityCountInTask(taskId, SECOND_STANDARD_ACTIVITY), 514 waitFinishMsg)); 515 } 516 517 @Test testLaunchActivityWithFlagPreviousIsTop()518 public void testLaunchActivityWithFlagPreviousIsTop() { 519 // Launch a standard activity 520 getLaunchActivityBuilder() 521 .setTargetActivity(SINGLE_TOP_ACTIVITY) 522 .execute(); 523 524 final int taskId = mWmState.getTaskByActivity( 525 SINGLE_TOP_ACTIVITY).getTaskId(); 526 527 // Launch a standard activity again with PREVIOUS_IS_TOP 528 getLaunchActivityBuilder() 529 .setTargetActivity(SINGLE_TOP_ACTIVITY) 530 .setLaunchingActivity(LAUNCHING_AND_FINISH_ACTIVITY) 531 .setIntentFlags(FLAG_ACTIVITY_PREVIOUS_IS_TOP) 532 .execute(); 533 534 assertEquals("Instance of activity must be one", 1, 535 mWmState.getActivityCountInTask(taskId, SINGLE_TOP_ACTIVITY)); 536 } 537 538 /** 539 * This test case tests behavior of activity launched with FLAG_ACTIVITY_SINGLE_TOP. 540 * A single top activity must not be launched if it is already running at the top 541 * of the history stack. 542 */ 543 @Test testLaunchActivityWithFlagSingleTop()544 public void testLaunchActivityWithFlagSingleTop() { 545 // Launch a standard activity 546 getLaunchActivityBuilder() 547 .setUseInstrumentation() 548 .setTargetActivity(STANDARD_ACTIVITY) 549 .execute(); 550 551 final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId(); 552 553 // Launch a standard activity with SINGLE_TOP flag. 554 // This standard activity launches a standard activity with single top flag. 555 getLaunchActivityBuilder() 556 .setTargetActivity(STANDARD_SINGLE_TOP_ACTIVITY) 557 .setUseInstrumentation() 558 .setIntentFlags(FLAG_ACTIVITY_SINGLE_TOP) 559 .execute(); 560 561 mWmState.waitForActivityState(STANDARD_SINGLE_TOP_ACTIVITY, STATE_RESUMED); 562 563 // Make sure that a new instance is not created if it is already running at the top 564 // of the history stack. 565 assertEquals("Multiple single top activities must not be created.", 1, 566 mWmState 567 .getActivityCountInTask(taskId, STANDARD_SINGLE_TOP_ACTIVITY)); 568 569 570 // Make sure that activity is in focus. 571 mWmState.assertFocusedActivity(STANDARD_SINGLE_TOP_ACTIVITY + "must be focused Activity", 572 STANDARD_SINGLE_TOP_ACTIVITY); 573 // Make sure the stack for the single top activity is front. 574 assertEquals("The stack for the single top activity must be front.", 575 getActivityName(STANDARD_SINGLE_TOP_ACTIVITY), 576 mWmState.getTopActivityName(0)); 577 578 // Make sure the standard activity and the single top activity are in same task. 579 assertEquals("Activity must be in same task.", taskId, 580 mWmState.getTaskByActivity(STANDARD_SINGLE_TOP_ACTIVITY) 581 .getTaskId()); 582 } 583 584 /** 585 * This test case tests behavior of activity launched with FLAG_ACTIVITY_MULTIPLE_TASK 586 * and FLAG_ACTIVITY_NEW_TASK. 587 * Second launched activity which is launched with FLAG_ACTIVITY_MULTIPLE_TASK and 588 * FLAG_ACTIVITY_NEW_TASK is created in new task/stack. So, a first launched activity 589 * and a second launched activity are in different task/stack. 590 */ 591 @Test testActivityWithFlagMultipleTaskAndNewTask()592 public void testActivityWithFlagMultipleTaskAndNewTask() { 593 // Launch a standard activity 594 getLaunchActivityBuilder() 595 .setTargetActivity(STANDARD_ACTIVITY) 596 .setIntentFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK) 597 .execute(); 598 599 final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId(); 600 601 // Launch a standard activity with FLAG_ACTIVITY_MULTIPLE_TASK|FLAG_ACTIVITY_NEW_TASK 602 getLaunchActivityBuilder() 603 .setTargetActivity(STANDARD_ACTIVITY) 604 .setLaunchingActivity(TEST_LAUNCHING_ACTIVITY) 605 .setIntentFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK) 606 .execute(); 607 608 // Make sure the stack for the standard activity is front. 609 assertEquals("The stack for the standard activity must be front.", 610 getActivityName(STANDARD_ACTIVITY), 611 mWmState.getTopActivityName(0)); 612 // Make sure the first standard activity and second standard activity are not in same task. 613 assertNotEquals("Activity must not be in same task.", taskId, 614 mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId()); 615 } 616 617 /** 618 * This test case tests behavior of activity launched with ClearTaskOnLaunch attribute and 619 * FLAG_ACTIVITY_RESET_TASK_IF_NEEDED. The activities above will be removed from the task when 620 * the clearTaskonlaunch activity is re-launched again. 621 */ 622 @Test testActivityWithClearTaskOnLaunch()623 public void testActivityWithClearTaskOnLaunch() { 624 // Launch a clearTaskonlaunch activity 625 getLaunchActivityBuilder() 626 .setUseInstrumentation() 627 .setTargetActivity(CLEAR_TASK_ON_LAUNCH_ACTIVITY) 628 .setIntentFlags(FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) 629 .execute(); 630 mWmState.waitForActivityState(CLEAR_TASK_ON_LAUNCH_ACTIVITY, STATE_RESUMED); 631 final int taskId = mWmState.getTaskByActivity(CLEAR_TASK_ON_LAUNCH_ACTIVITY).getTaskId(); 632 633 // Launch a standard activity 634 getLaunchActivityBuilder() 635 .setUseInstrumentation() 636 .setTargetActivity(STANDARD_ACTIVITY) 637 .execute(); 638 mWmState.waitForActivityState(STANDARD_ACTIVITY, STATE_RESUMED); 639 640 // Return to home 641 launchHomeActivity(); 642 643 // Launch the clearTaskonlaunch activity again 644 getLaunchActivityBuilder() 645 .setUseInstrumentation() 646 .setTargetActivity(CLEAR_TASK_ON_LAUNCH_ACTIVITY) 647 .setIntentFlags(FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) 648 .execute(); 649 mWmState.waitForActivityState(CLEAR_TASK_ON_LAUNCH_ACTIVITY, STATE_RESUMED); 650 mWmState.waitForActivityState(STANDARD_ACTIVITY, STATE_DESTROYED); 651 652 // Make sure the task for the clearTaskonlaunch activity is front. 653 assertEquals("The task for the clearTaskonlaunch activity must be front.", 654 getActivityName(CLEAR_TASK_ON_LAUNCH_ACTIVITY), 655 mWmState.getTopActivityName(0)); 656 657 assertEquals("Instance of the activity in its task must be cleared", 0, 658 mWmState.getActivityCountInTask(taskId, STANDARD_ACTIVITY)); 659 } 660 661 /** 662 * This test case tests behavior of activity with finishOnTaskLaunch attribute when the 663 * activity's task is relaunched from home, this activity should be finished. 664 */ 665 @Test testActivityWithFinishOnTaskLaunch()666 public void testActivityWithFinishOnTaskLaunch() { 667 // Launch a standard activity. 668 launchActivity(STANDARD_ACTIVITY); 669 670 final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId(); 671 final int instances = mWmState.getActivityCountInTask(taskId, null); 672 673 // Launch a activity with finishOnTaskLaunch 674 launchActivity(FINISH_ON_TASK_LAUNCH_ACTIVITY); 675 676 // Make sure instances in task are increased. 677 assertEquals("instances of activity in task must be increased.", instances + 1, 678 mWmState.getActivityCountInTask(taskId, null)); 679 680 // Navigate home 681 launchHomeActivity(); 682 683 // Simulate to launch the activity from home again 684 getLaunchActivityBuilder() 685 .setUseInstrumentation() 686 .setTargetActivity(STANDARD_ACTIVITY) 687 .setIntentFlags(FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) 688 .execute(); 689 mWmState.waitForActivityState(STANDARD_ACTIVITY, STATE_RESUMED); 690 691 // Make sure the activity is removed. 692 mWmState.waitAndAssertActivityRemoved(FINISH_ON_TASK_LAUNCH_ACTIVITY); 693 } 694 695 @Test testActivityWithDocumentIntoExisting()696 public void testActivityWithDocumentIntoExisting() { 697 // Launch a documentLaunchMode="intoExisting" activity 698 launchActivityWithData(DOCUMENT_INTO_EXISTING_ACTIVITY, "test"); 699 waitAndAssertActivityState(DOCUMENT_INTO_EXISTING_ACTIVITY, STATE_RESUMED, 700 "Activity should be resumed"); 701 final int taskId = mWmState.getTaskByActivity(DOCUMENT_INTO_EXISTING_ACTIVITY).getTaskId(); 702 703 // Navigate home 704 launchHomeActivity(); 705 706 // Launch the alias activity. 707 final ComponentName componentName = new ComponentName(mContext.getPackageName(), 708 DocumentIntoExistingActivity.class.getPackageName() 709 + ".ActivityStarterTests$DocumentIntoExistingAliasActivity"); 710 launchActivityWithData(componentName, "test"); 711 712 waitAndAssertActivityState(DOCUMENT_INTO_EXISTING_ACTIVITY, STATE_RESUMED, 713 "Activity should be resumed"); 714 final int taskId2 = mWmState.getTaskByActivity(DOCUMENT_INTO_EXISTING_ACTIVITY).getTaskId(); 715 assertEquals("Activity must be in the same task.", taskId, taskId2); 716 assertEquals("Activity is the only member of its task", 1, 717 mWmState.getActivityCountInTask(taskId2, null)); 718 } 719 720 /** 721 * This test case tests behavior of activity with relinquishTaskIdentify attribute. Ensure the 722 * relinquishTaskIdentity work if the activities are in the same app. 723 */ 724 @Test testActivityWithRelinquishTaskIdentity()725 public void testActivityWithRelinquishTaskIdentity() { 726 // Launch a relinquishTaskIdentity activity and test activity with different affinity into 727 // a same task. 728 getLaunchActivityBuilder().setTargetActivity(RELINQUISHTASKIDENTITY_ACTIVITY) 729 .setIntentExtra(extra -> extra.putBoolean( 730 RelinquishTaskIdentityActivity.EXTRA_LAUNCHED, true)) 731 .setUseInstrumentation() 732 .setWaitForLaunched(true) 733 .execute(); 734 // get the task affinity(e.g. 10825:android.server.wm.cts) without the uid information 735 String affinity = mWmState.getTaskByActivity(RELINQUISHTASKIDENTITY_ACTIVITY).getAffinity(); 736 affinity = affinity.substring(affinity.indexOf(":") + 1); 737 738 final int taskId = mWmState.getTaskByActivity(RELINQUISHTASKIDENTITY_ACTIVITY).getTaskId(); 739 final int taskId2 = mWmState.getTaskByActivity(TEST_LAUNCHING_ACTIVITY).getTaskId(); 740 741 // verify the activities are in the same task 742 assertEquals("Activity must be in the same task.", taskId, taskId2); 743 // verify the relinquishTaskIdentify function should work since the activities are in the 744 // same app 745 assertNotEquals("Affinity should not be same with the package name.", 746 RELINQUISHTASKIDENTITY_ACTIVITY.getPackageName(), affinity); 747 } 748 749 /** 750 * This test case tests behavior of activity with launch_adjacent and new_task. Ensure the flags 751 * make activity in multi-window mode. 752 */ 753 @Test testLaunchActivityWithLaunchAdjacentAndNewTask()754 public void testLaunchActivityWithLaunchAdjacentAndNewTask() { 755 assumeTrue("Skipping test: no split multi-window support", 756 supportsSplitScreenMultiWindow()); 757 758 mTaskOrganizer.registerOrganizerIfNeeded(); 759 760 // Launch activity with FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_LAUNCH_ADJACENT. 761 launchAndAssertActivityWindowingMode( 762 FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_LAUNCH_ADJACENT, 763 WINDOWING_MODE_MULTI_WINDOW); 764 } 765 766 /** 767 * This test case tests behavior of activity with launch_adjacent. Ensure the flag is ignored 768 * if without new_task together. 769 */ 770 @Test testLaunchActivityWithLaunchAdjacent()771 public void testLaunchActivityWithLaunchAdjacent() { 772 assumeTrue("Skipping test: no split multi-window support", 773 supportsSplitScreenMultiWindow()); 774 775 // Launch activity with FLAG_ACTIVITY_LAUNCH_ADJACENT only. 776 launchAndAssertActivityWindowingMode(FLAG_ACTIVITY_LAUNCH_ADJACENT, 777 WINDOWING_MODE_FULLSCREEN); 778 } 779 launchAndAssertActivityWindowingMode(int flags, int expectWindowingMode)780 private void launchAndAssertActivityWindowingMode(int flags, int expectWindowingMode) { 781 getLaunchActivityBuilder() 782 .setTargetActivity(STANDARD_ACTIVITY) 783 .setIntentFlags(flags) 784 .setWindowingMode(WINDOWING_MODE_FULLSCREEN) 785 .execute(); 786 787 // wait for the expected windowing mode 788 mWmState.waitForValidState(new WaitForValidActivityState.Builder(STANDARD_ACTIVITY) 789 .setWindowingMode(expectWindowingMode) 790 .build()); 791 792 assertEquals(expectWindowingMode, 793 mWmState.getActivity(STANDARD_ACTIVITY).getWindowingMode()); 794 } 795 796 // Test activity 797 public static class RelinquishTaskIdentityActivity extends Activity { 798 public static final String EXTRA_LAUNCHED = "extraLaunched"; 799 @Override onCreate(Bundle icicle)800 protected void onCreate(Bundle icicle) { 801 super.onCreate(icicle); 802 if (getIntent().getBooleanExtra(EXTRA_LAUNCHED, false)) { 803 startActivityForResult( 804 new Intent(this, TestLaunchingActivity.class), 1 /* requestCode */); 805 } 806 } 807 } 808 809 // Test activity 810 public static class StandardWithSingleTopActivity extends Activity { 811 812 @Override onCreate(Bundle savedInstanceState)813 protected void onCreate(Bundle savedInstanceState) { 814 super.onCreate(savedInstanceState); 815 final Intent intent = new Intent().setComponent( 816 new ComponentName(this /* context */, getClass())); 817 intent.addFlags(FLAG_ACTIVITY_SINGLE_TOP); 818 startActivity(intent); 819 } 820 } 821 822 // Test activity 823 public static class ClearTaskOnLaunchActivity extends Activity { 824 } 825 826 // Test activity 827 public static class FinishOnTaskLaunchActivity extends Activity { 828 } 829 830 // Test activity 831 public static class SingleTopActivity extends Activity { 832 } 833 834 // Test activity 835 public static class SingleTaskActivity extends Activity { 836 } 837 838 // Test activity 839 public static class SingleInstanceActivity extends Activity { 840 public static final String EXTRA_SHOW_WHEN_LOCKED = "showWhenLocked"; 841 @Override onCreate(Bundle icicle)842 protected void onCreate(Bundle icicle) { 843 super.onCreate(icicle); 844 if (getIntent().getBooleanExtra(EXTRA_SHOW_WHEN_LOCKED, false)) { 845 setShowWhenLocked(true); 846 } 847 } 848 } 849 850 // Test activity 851 public static class DocumentIntoExistingActivity extends Activity { 852 } 853 854 // Launching activity 855 public static class TestLaunchingActivity extends Activity { 856 @Override onCreate(Bundle savedInstanceState)857 protected void onCreate(Bundle savedInstanceState) { 858 super.onCreate(savedInstanceState); 859 860 final Intent intent = getIntent(); 861 if (intent != null) { 862 ActivityLauncher.launchActivityFromExtras(this, intent.getExtras()); 863 } 864 } 865 866 @Override onNewIntent(Intent intent)867 protected void onNewIntent(Intent intent) { 868 super.onNewIntent(intent); 869 ActivityLauncher.launchActivityFromExtras(this, intent.getExtras()); 870 } 871 } 872 873 public static class LaunchingAndFinishActivity extends TestLaunchingActivity { 874 @Override onCreate(Bundle savedInstanceState)875 protected void onCreate(Bundle savedInstanceState) { 876 super.onCreate(savedInstanceState); 877 finish(); 878 } 879 } 880 } 881