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