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