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