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 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: 96 * - {@code FLAG_ACTIVITY_CLEAR_TOP} 97 * - {@code FLAG_ACTIVITY_RESET_TASK_IF_NEEDED} 98 * - {@code FLAG_ACTIVITY_NEW_TASK} 99 */ 100 @Test testClearTopNewTaskResetTask()101 public void testClearTopNewTaskResetTask() throws Exception { 102 // Start activity normally 103 launchActivityAndWait(FirstActivity.class); 104 105 // Navigate home 106 launchHomeActivity(); 107 waitAndAssertActivityStates(state(FirstActivity.class, ON_STOP)); 108 getLifecycleLog().clear(); 109 110 // Start activity again with flags in question. Verify activity is resumed. 111 // A new instance of activity will be created, and the old one destroyed. 112 final Activity secondLaunchActivity = new Launcher(FirstActivity.class) 113 .setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_NEW_TASK 114 | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) 115 .launch(); 116 mWmState.waitForActivityState(secondLaunchActivity.getComponentName(), STATE_RESUMED); 117 assertEquals("The activity should be started and be resumed", 118 getActivityName(secondLaunchActivity.getComponentName()), 119 mWmState.getTopActivityName(0)); 120 } 121 122 /** 123 * This test case tests "standard" activity behavior. 124 * A first launched standard activity and a second launched standard activity 125 * must be in same task. 126 */ 127 @Test testLaunchStandardActivity()128 public void testLaunchStandardActivity() { 129 // Launch a standard activity. 130 launchActivity(STANDARD_ACTIVITY); 131 132 final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId(); 133 final int instances = mWmState.getActivityCountInTask(taskId, null); 134 135 // Launch a second standard activity. 136 launchActivity(SECOND_STANDARD_ACTIVITY); 137 138 // Make sure instances in task are increased. 139 assertEquals("instances of activity in task must be increased.", instances + 1, 140 mWmState.getActivityCountInTask(taskId, null)); 141 142 // Make sure the stack for the second standard activity is front. 143 assertEquals("The stack for the second standard activity must be front.", 144 getActivityName(SECOND_STANDARD_ACTIVITY), 145 mWmState.getTopActivityName(0)); 146 147 // Make sure the standard activity and the second standard activity are in same task. 148 assertEquals("Activity must be in same task.", taskId, 149 mWmState.getTaskByActivity(SECOND_STANDARD_ACTIVITY).getTaskId()); 150 } 151 152 /** 153 * This test case tests show-when-locked behavior for a "no-history" activity. 154 * The no-history activity should be resumed over lockscreen. 155 */ 156 @Test testLaunchNoHistoryActivityShowWhenLocked()157 public void testLaunchNoHistoryActivityShowWhenLocked() { 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 finished. 692 assertEquals("Instance of the activity in its task must be cleared", 0, 693 mWmState.getActivityCountInTask(taskId, FINISH_ON_TASK_LAUNCH_ACTIVITY)); 694 } 695 696 @Test testActivityWithDocumentIntoExisting()697 public void testActivityWithDocumentIntoExisting() { 698 // Launch a documentLaunchMode="intoExisting" activity 699 launchActivityWithData(DOCUMENT_INTO_EXISTING_ACTIVITY, "test"); 700 waitAndAssertActivityState(DOCUMENT_INTO_EXISTING_ACTIVITY, STATE_RESUMED, 701 "Activity should be resumed"); 702 final int taskId = mWmState.getTaskByActivity(DOCUMENT_INTO_EXISTING_ACTIVITY).getTaskId(); 703 704 // Navigate home 705 launchHomeActivity(); 706 707 // Launch the alias activity. 708 final ComponentName componentName = new ComponentName(mContext.getPackageName(), 709 DocumentIntoExistingActivity.class.getPackageName() 710 + ".ActivityStarterTests$DocumentIntoExistingAliasActivity"); 711 launchActivityWithData(componentName, "test"); 712 713 waitAndAssertActivityState(DOCUMENT_INTO_EXISTING_ACTIVITY, STATE_RESUMED, 714 "Activity should be resumed"); 715 final int taskId2 = mWmState.getTaskByActivity(DOCUMENT_INTO_EXISTING_ACTIVITY).getTaskId(); 716 assertEquals("Activity must be in the same task.", taskId, taskId2); 717 assertEquals("Activity is the only member of its task", 1, 718 mWmState.getActivityCountInTask(taskId2, null)); 719 } 720 721 /** 722 * This test case tests behavior of activity with relinquishTaskIdentify attribute. Ensure the 723 * relinquishTaskIdentity work if the activities are in the same app. 724 */ 725 @Test testActivityWithRelinquishTaskIdentity()726 public void testActivityWithRelinquishTaskIdentity() { 727 // Launch a relinquishTaskIdentity activity and test activity with different affinity into 728 // a same task. 729 getLaunchActivityBuilder().setTargetActivity(RELINQUISHTASKIDENTITY_ACTIVITY) 730 .setIntentExtra(extra -> extra.putBoolean( 731 RelinquishTaskIdentityActivity.EXTRA_LAUNCHED, true)) 732 .setUseInstrumentation() 733 .setWaitForLaunched(true) 734 .execute(); 735 // get the task affinity(e.g. 10825:android.server.wm.cts) without the uid information 736 String affinity = mWmState.getTaskByActivity(RELINQUISHTASKIDENTITY_ACTIVITY).getAffinity(); 737 affinity = affinity.substring(affinity.indexOf(":") + 1); 738 739 final int taskId = mWmState.getTaskByActivity(RELINQUISHTASKIDENTITY_ACTIVITY).getTaskId(); 740 final int taskId2 = mWmState.getTaskByActivity(TEST_LAUNCHING_ACTIVITY).getTaskId(); 741 742 // verify the activities are in the same task 743 assertEquals("Activity must be in the same task.", taskId, taskId2); 744 // verify the relinquishTaskIdentify function should work since the activities are in the 745 // same app 746 assertNotEquals("Affinity should not be same with the package name.", 747 RELINQUISHTASKIDENTITY_ACTIVITY.getPackageName(), affinity); 748 } 749 750 // Test activity 751 public static class RelinquishTaskIdentityActivity extends Activity { 752 public static final String EXTRA_LAUNCHED = "extraLaunched"; 753 @Override onCreate(Bundle icicle)754 protected void onCreate(Bundle icicle) { 755 super.onCreate(icicle); 756 if (getIntent().getBooleanExtra(EXTRA_LAUNCHED, false)) { 757 startActivityForResult( 758 new Intent(this, TestLaunchingActivity.class), 1 /* requestCode */); 759 } 760 } 761 } 762 763 // Test activity 764 public static class StandardActivity extends Activity { 765 } 766 767 // Test activity 768 public static class SecondStandardActivity extends Activity { 769 } 770 771 // Test activity 772 public static class StandardWithSingleTopActivity extends Activity { 773 774 @Override onCreate(Bundle savedInstanceState)775 protected void onCreate(Bundle savedInstanceState) { 776 super.onCreate(savedInstanceState); 777 final Intent intent = new Intent().setComponent( 778 new ComponentName(this /* context */, getClass())); 779 intent.addFlags(FLAG_ACTIVITY_SINGLE_TOP); 780 startActivity(intent); 781 } 782 } 783 784 // Test activity 785 public static class ClearTaskOnLaunchActivity extends Activity { 786 } 787 788 // Test activity 789 public static class FinishOnTaskLaunchActivity extends Activity { 790 } 791 792 // Test activity 793 public static class SingleTopActivity extends Activity { 794 } 795 796 // Test activity 797 public static class SingleTaskActivity extends Activity { 798 } 799 800 // Test activity 801 public static class SingleInstanceActivity extends Activity { 802 public static final String EXTRA_SHOW_WHEN_LOCKED = "showWhenLocked"; 803 @Override onCreate(Bundle icicle)804 protected void onCreate(Bundle icicle) { 805 super.onCreate(icicle); 806 if (getIntent().getBooleanExtra(EXTRA_SHOW_WHEN_LOCKED, false)) { 807 setShowWhenLocked(true); 808 } 809 } 810 } 811 812 // Test activity 813 public static class DocumentIntoExistingActivity extends Activity { 814 } 815 816 // Launching activity 817 public static class TestLaunchingActivity extends Activity { 818 @Override onCreate(Bundle savedInstanceState)819 protected void onCreate(Bundle savedInstanceState) { 820 super.onCreate(savedInstanceState); 821 822 final Intent intent = getIntent(); 823 if (intent != null) { 824 ActivityLauncher.launchActivityFromExtras(this, intent.getExtras()); 825 } 826 } 827 828 @Override onNewIntent(Intent intent)829 protected void onNewIntent(Intent intent) { 830 super.onNewIntent(intent); 831 ActivityLauncher.launchActivityFromExtras(this, intent.getExtras()); 832 } 833 } 834 835 public static class LaunchingAndFinishActivity extends TestLaunchingActivity { 836 @Override onCreate(Bundle savedInstanceState)837 protected void onCreate(Bundle savedInstanceState) { 838 super.onCreate(savedInstanceState); 839 finish(); 840 } 841 } 842 } 843