• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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