blob: 0496bd6066b566325d8125fbc349cb860e3ed527 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package android.server.wm.lifecycle;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
import static android.server.wm.ComponentNameUtils.getActivityName;
import static android.server.wm.UiDeviceUtils.pressWakeupButton;
import static android.server.wm.WindowManagerState.STATE_DESTROYED;
import static android.server.wm.WindowManagerState.STATE_RESUMED;
import static android.server.wm.app.Components.ALIAS_TEST_ACTIVITY;
import static android.server.wm.app.Components.NO_HISTORY_ACTIVITY;
import static android.server.wm.app.Components.SHOW_WHEN_LOCKED_TRANSLUCENT_ACTIVITY;
import static android.server.wm.app.Components.TEST_ACTIVITY;
import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_STOP;
import static android.view.Display.DEFAULT_DISPLAY;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import android.app.Activity;
import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
import android.server.wm.ActivityLauncher;
import android.server.wm.WindowManagerState;
import android.server.wm.app.Components;
import android.util.Log;
import android.view.WindowManager;
import org.junit.Test;
import java.util.List;
import java.util.function.Predicate;
/**
* Build/Install/Run:
* atest CtsWindowManagerDeviceTestCases:ActivityStarterTests
*/
@Presubmit
@android.server.wm.annotation.Group3
public class ActivityStarterTests extends ActivityLifecycleClientTestBase {
private static final ComponentName STANDARD_ACTIVITY
= getComponentName(StandardActivity.class);
private static final ComponentName SECOND_STANDARD_ACTIVITY
= getComponentName(SecondStandardActivity.class);
private static final ComponentName SINGLE_TOP_ACTIVITY
= getComponentName(SingleTopActivity.class);
private static final ComponentName SINGLE_INSTANCE_ACTIVITY
= getComponentName(SingleInstanceActivity.class);
private static final ComponentName SINGLE_TASK_ACTIVITY
= getComponentName(SingleTaskActivity.class);
private static final ComponentName STANDARD_SINGLE_TOP_ACTIVITY
= getComponentName(StandardWithSingleTopActivity.class);
private static final ComponentName TEST_LAUNCHING_ACTIVITY
= getComponentName(TestLaunchingActivity.class);
private static final ComponentName LAUNCHING_AND_FINISH_ACTIVITY
= getComponentName(LaunchingAndFinishActivity.class);
private static final ComponentName CLEAR_TASK_ON_LAUNCH_ACTIVITY
= getComponentName(ClearTaskOnLaunchActivity.class);
private static final ComponentName FINISH_ON_TASK_LAUNCH_ACTIVITY
= getComponentName(FinishOnTaskLaunchActivity.class);
private static final ComponentName DOCUMENT_INTO_EXISTING_ACTIVITY
= getComponentName(DocumentIntoExistingActivity.class);
private static final ComponentName RELINQUISHTASKIDENTITY_ACTIVITY
= getComponentName(RelinquishTaskIdentityActivity.class);
/**
* Ensures that the following launch flag combination works when starting an activity which is
* already running:
* - {@code FLAG_ACTIVITY_CLEAR_TOP}
* - {@code FLAG_ACTIVITY_RESET_TASK_IF_NEEDED}
* - {@code FLAG_ACTIVITY_NEW_TASK}
*/
@Test
public void testClearTopNewTaskResetTask() throws Exception {
// Start activity normally
launchActivityAndWait(FirstActivity.class);
// Navigate home
launchHomeActivity();
waitAndAssertActivityStates(state(FirstActivity.class, ON_STOP));
getLifecycleLog().clear();
// Start activity again with flags in question. Verify activity is resumed.
// A new instance of activity will be created, and the old one destroyed.
final Activity secondLaunchActivity = new Launcher(FirstActivity.class)
.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_NEW_TASK
| FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
.launch();
mWmState.waitForActivityState(secondLaunchActivity.getComponentName(), STATE_RESUMED);
assertEquals("The activity should be started and be resumed",
getActivityName(secondLaunchActivity.getComponentName()),
mWmState.getTopActivityName(0));
}
/**
* This test case tests "standard" activity behavior.
* A first launched standard activity and a second launched standard activity
* must be in same task.
*/
@Test
public void testLaunchStandardActivity() {
// Launch a standard activity.
launchActivity(STANDARD_ACTIVITY);
final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId();
final int instances = mWmState.getActivityCountInTask(taskId, null);
// Launch a second standard activity.
launchActivity(SECOND_STANDARD_ACTIVITY);
// Make sure instances in task are increased.
assertEquals("instances of activity in task must be increased.", instances + 1,
mWmState.getActivityCountInTask(taskId, null));
// Make sure the stack for the second standard activity is front.
assertEquals("The stack for the second standard activity must be front.",
getActivityName(SECOND_STANDARD_ACTIVITY),
mWmState.getTopActivityName(0));
// Make sure the standard activity and the second standard activity are in same task.
assertEquals("Activity must be in same task.", taskId,
mWmState.getTaskByActivity(SECOND_STANDARD_ACTIVITY).getTaskId());
}
/**
* This test case tests show-when-locked behavior for a "no-history" activity.
* The no-history activity should be resumed over lockscreen.
*/
@Test
public void testLaunchNoHistoryActivityShowWhenLocked() {
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.sleepDevice();
getLaunchActivityBuilder().setTargetActivity(NO_HISTORY_ACTIVITY)
.setIntentExtra(extra -> extra.putBoolean(
Components.NoHistoryActivity.EXTRA_SHOW_WHEN_LOCKED, true))
.setUseInstrumentation().execute();
waitAndAssertActivityState(NO_HISTORY_ACTIVITY, STATE_RESUMED,
"Activity should be resumed");
}
/**
* This test case tests the behavior for a "no-history" activity after turning the screen off.
* The no-history activity must be resumed over lockscreen when launched again.
*/
@Test
public void testNoHistoryActivityNotFinished() {
assumeTrue(supportsLockScreen());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
// Launch a no-history activity
getLaunchActivityBuilder().setTargetActivity(NO_HISTORY_ACTIVITY)
.setIntentExtra(extra -> extra.putBoolean(
Components.NoHistoryActivity.EXTRA_SHOW_WHEN_LOCKED, true))
.setUseInstrumentation().execute();
// Wait for the activity resumed.
mWmState.waitForActivityState(NO_HISTORY_ACTIVITY, STATE_RESUMED);
lockScreenSession.sleepDevice();
// Launch a no-history activity
launchActivity(NO_HISTORY_ACTIVITY);
// Wait for the activity resumed
waitAndAssertActivityState(NO_HISTORY_ACTIVITY, STATE_RESUMED,
"Activity must be resumed");
}
/**
* This test case tests the behavior that a fullscreen activity was started on top of the
* no-history activity within different tasks during sleeping. The no-history activity must be
* finished.
*/
@Test
public void testNoHistoryActivityWithDifferentTask() {
assumeTrue(supportsLockScreen());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
// Launch a no-history activity
getLaunchActivityBuilder().setTargetActivity(NO_HISTORY_ACTIVITY)
.setIntentExtra(extra -> extra.putBoolean(
Components.NoHistoryActivity.EXTRA_SHOW_WHEN_LOCKED, true))
.setWaitForLaunched(false)
.setUseInstrumentation()
.execute();
// Wait for the activity resumed.
waitAndAssertActivityState(NO_HISTORY_ACTIVITY, STATE_RESUMED,
"Activity must be resumed");
final int taskId = mWmState.getTaskByActivity(NO_HISTORY_ACTIVITY).getTaskId();
lockScreenSession.sleepDevice();
// Launch a single instance activity
getLaunchActivityBuilder().setTargetActivity(SINGLE_INSTANCE_ACTIVITY)
.setIntentExtra(extra -> extra.putBoolean(
SingleInstanceActivity.EXTRA_SHOW_WHEN_LOCKED, true))
.setWaitForLaunched(false)
.setUseInstrumentation()
.execute();
// Make sure the activity is finished.
final String waitFinishMsg = "Instance of no-history activity must not exist";
assertTrue(waitFinishMsg, mWmState.waitForWithAmState(
amState -> 0 == amState.getActivityCountInTask(taskId, NO_HISTORY_ACTIVITY),
waitFinishMsg));
// Turn the screen on after the test is completed to prevent keyDispatchingTimedOut during
// the lockScreenSession close.
pressWakeupButton();
}
/**
* This test case tests the behavior that a translucent activity was started on top of the
* no-history activity during sleeping. The no-history activity must not be finished.
*/
@Test
public void testNoHistoryActivityWithTranslucentActivity() {
assumeTrue(supportsLockScreen());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
// Launch a no-history activity
getLaunchActivityBuilder().setTargetActivity(NO_HISTORY_ACTIVITY)
.setIntentExtra(extra -> extra.putBoolean(
Components.NoHistoryActivity.EXTRA_SHOW_WHEN_LOCKED, true))
.setWaitForLaunched(false)
.setUseInstrumentation()
.execute();
// Wait for the activity resumed.
waitAndAssertActivityState(NO_HISTORY_ACTIVITY, STATE_RESUMED,
"Activity must be resumed");
final int taskId = mWmState.getTaskByActivity(NO_HISTORY_ACTIVITY).getTaskId();
lockScreenSession.sleepDevice();
launchActivityNoWait(SHOW_WHEN_LOCKED_TRANSLUCENT_ACTIVITY);
final String waitFinishMsg = "Instance of no-history activity must exist";
assertTrue(waitFinishMsg, mWmState.waitForWithAmState(
amState -> 1 == amState.getActivityCountInTask(taskId, NO_HISTORY_ACTIVITY),
waitFinishMsg));
// Turn the screen on after the test is completed to prevent keyDispatchingTimedOut during
// the lockScreenSession close.
pressWakeupButton();
}
/**
* This test case tests "single top" activity behavior.
* - A first launched standard activity and a second launched single top
* activity are in same task.
* - A new instance of single top activity is not created if task
* already has a its activity at the top of its task.
*/
@Test
public void testLaunchSingleTopActivity() {
// Launch a standard activity.
launchActivity(STANDARD_ACTIVITY);
final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId();
// Launch a single top activity.
launchActivity(SINGLE_TOP_ACTIVITY);
final int instances = mWmState.getActivityCountInTask(taskId, null);
// Make sure the single top activity is in focus.
mWmState.assertFocusedActivity(SINGLE_TOP_ACTIVITY + "must be focused Activity",
SINGLE_TOP_ACTIVITY);
// Make sure the stack for the single top activity is front.
assertEquals("The stack for the single top activity must be front.",
getActivityName(SINGLE_TOP_ACTIVITY),
mWmState.getTopActivityName(0));
// Make sure the standard activity and the single top activity are in same task.
assertEquals("Two activities must be in same task.", taskId,
mWmState.getTaskByActivity(SINGLE_TOP_ACTIVITY).getTaskId());
// Launch a single top activity.
launchActivity(SINGLE_TOP_ACTIVITY);
// Make sure that instances of activity are not increased.
assertEquals("instances of activity must not be increased.", instances,
mWmState.getActivityCountInTask(taskId, null));
}
/**
* This test case tests "single instance" activity behavior.
* - A first launched standard activity and a second launched single instance
* activity are not in same task.
* - A single instance activity is always the single and only member of its task.
*/
@Test
public void testLaunchSingleInstanceActivity() {
// Launch a standard activity.
launchActivity(STANDARD_ACTIVITY);
final int firstTaskId = mWmState
.getTaskByActivity(STANDARD_ACTIVITY).getTaskId();
// Launch a single instance activity
launchActivity(SINGLE_INSTANCE_ACTIVITY);
final int secondTaskId = mWmState
.getTaskByActivity(SINGLE_INSTANCE_ACTIVITY).getTaskId();
// Make sure the single instance activity is in focus.
mWmState.assertFocusedActivity(SINGLE_INSTANCE_ACTIVITY + "must be focused Activity",
SINGLE_INSTANCE_ACTIVITY);
// Make sure the single instance activity is front.
assertEquals("The stack for the single instance activity must be front.",
getActivityName(SINGLE_INSTANCE_ACTIVITY),
mWmState.getTopActivityName(0));
// Make sure the standard activity and the test activity are not in same task.
assertNotEquals("Activity must be in different task.", firstTaskId, secondTaskId);
// Make sure the single instance activity is only member of its task.
assertEquals("Single instance activity is only member of its task", 1,
mWmState.getActivityCountInTask(secondTaskId, null));
}
/**
* This test case tests "single task" activity behavior.
* - A first launched standard activity and a second launched single task activity
* are in same task.
* - Instance of single task activity is only one in its task.
*/
@Test
public void testLaunchSingleTaskActivity() {
// Launch a standard activity.
launchActivity(STANDARD_ACTIVITY);
final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId();
// Launch a single task activity
launchActivity(SINGLE_TASK_ACTIVITY);
// Make sure the single task activity is in focus.
mWmState.assertFocusedActivity(SINGLE_TASK_ACTIVITY + "must be focused Activity",
SINGLE_TASK_ACTIVITY);
// Make sure the stack for the single task activity is front.
assertEquals("The stack for the single task activity must be front.",
getActivityName(SINGLE_TASK_ACTIVITY),
mWmState.getTopActivityName(0));
// Make sure the test activity is in same task.
assertEquals("Activity must be in same task.", taskId,
mWmState.getTaskByActivity(SINGLE_TASK_ACTIVITY).getTaskId());
// Launch a second standard activity
launchActivity(SECOND_STANDARD_ACTIVITY);
// Launch a single task activity again.
launchActivity(SINGLE_TASK_ACTIVITY);
mWmState.waitForActivityRemoved(SECOND_STANDARD_ACTIVITY);
// Make sure the number of instances for single task activity is only one.
assertEquals("Instance of single task activity in its task must be only one", 1,
mWmState.getActivityCountInTask(taskId, SINGLE_TASK_ACTIVITY));
// Make sure that instance of standard activity does not exists.
assertEquals("Instance of second standard activity must not exist.", 0,
mWmState.getActivityCountInTask(taskId, SECOND_STANDARD_ACTIVITY));
}
/**
* Tests that the existing task would be brought to top while launching alias activity or
* real activity without creating new activity instances, tasks, or stacks.
*/
@Test
public void testLaunchAliasActivity() {
// Launch alias activity.
getLaunchActivityBuilder().setUseInstrumentation().setTargetActivity(ALIAS_TEST_ACTIVITY)
.setIntentFlags(FLAG_ACTIVITY_NEW_TASK).execute();
final int testStacks = countTestRootTasks();
final int taskId = mWmState.getTaskByActivity(ALIAS_TEST_ACTIVITY).getTaskId();
// Return to home and launch the alias activity again.
launchHomeActivity();
getLaunchActivityBuilder().setUseInstrumentation().setTargetActivity(ALIAS_TEST_ACTIVITY)
.setIntentFlags(FLAG_ACTIVITY_NEW_TASK).execute();
assertEquals("Instance of the activity in its task must be only one", 1,
mWmState.getActivityCountInTask(taskId, ALIAS_TEST_ACTIVITY));
assertEquals("Test stack count should not be increased.", testStacks,
countTestRootTasks());
// Return to home and launch the real activity.
launchHomeActivity();
getLaunchActivityBuilder().setUseInstrumentation().setTargetActivity(TEST_ACTIVITY)
.setIntentFlags(FLAG_ACTIVITY_NEW_TASK).execute();
assertEquals("Instance of the activity in its task must be only one", 1,
mWmState.getActivityCountInTask(taskId, ALIAS_TEST_ACTIVITY));
assertEquals("Test stack count should not be increased.", testStacks,
countTestRootTasks());
}
private int countTestRootTasks() {
return mWmState.getRootTasksCount(
t -> ALIAS_TEST_ACTIVITY.getPackageName().equals(t.getPackageName()));
}
/**
* This test case tests behavior of activities launched with FLAG_ACTIVITY_NEW_TASK
* and FLAG_ACTIVITY_CLEAR_TASK.
* A first launched activity is finished, then a second activity is created if the
* second activity is launched with FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_CLEAR_TASK.
*/
@Test
public void testLaunchActivityWithFlagNewTaskAndClearTask() {
// Launch a standard activity with FLAG_ACTIVITY_NEW_TASK.
getLaunchActivityBuilder()
.setTargetActivity(STANDARD_ACTIVITY)
.setIntentFlags(FLAG_ACTIVITY_NEW_TASK)
.execute();
final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId();
// Launch Activity with FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_CLEAR_TASK.
getLaunchActivityBuilder()
.setTargetActivity(STANDARD_ACTIVITY)
.setLaunchingActivity(TEST_LAUNCHING_ACTIVITY)
.setIntentFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)
.execute();
mWmState.waitForActivityState(STANDARD_ACTIVITY, STATE_DESTROYED);
// Make sure the number of instances for standard activity is one
// because previous standard activity to be finished due to FLAG_ACTIVITY_CLEAR_TASK.
assertEquals("Instance of activity must be one", 1,
mWmState.getActivityCountInTask(taskId, STANDARD_ACTIVITY));
// Make sure the stack for the standard activity is front.
assertEquals("The stack for the standard activity must be front.",
getActivityName(STANDARD_ACTIVITY),
mWmState.getTopActivityName(0));
}
/**
* This test case tests behavior of activity launched with FLAG_ACTIVITY_CLEAR_TOP.
* A top activity is finished when an activity is launched with FLAG_ACTIVITY_CLEAR_TOP.
*/
@Test
public void testLaunchActivityWithFlagClearTop() {
// Launch a standard activity
getLaunchActivityBuilder()
.setTargetActivity(STANDARD_ACTIVITY)
.setUseInstrumentation()
.execute();
final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId();
// Launch a second standard activity
getLaunchActivityBuilder()
.setTargetActivity(SECOND_STANDARD_ACTIVITY)
.setUseInstrumentation()
.execute();
// Launch a standard activity again with CLEAR_TOP_FLAG
getLaunchActivityBuilder()
.setTargetActivity(STANDARD_ACTIVITY)
.setUseInstrumentation()
.setIntentFlags(FLAG_ACTIVITY_CLEAR_TOP)
.execute();
mWmState.waitForActivityState(STANDARD_ACTIVITY, STATE_RESUMED);
// Make sure that the standard activity is in focus.
mWmState.assertFocusedActivity(STANDARD_ACTIVITY + "must be focused Activity",
STANDARD_ACTIVITY);
// Make sure the stack for the standard activity is front.
assertEquals("The stack for the standard activity must be front.",
getActivityName(STANDARD_ACTIVITY),
mWmState.getTopActivityName(0));
// Make sure the activity is not in same task.
assertEquals("Activity must be in same task.", taskId,
mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId());
// Make sure the second standard activity is finished.
final String waitFinishMsg = "Instance of second standard activity must not exist";
assertTrue(waitFinishMsg, mWmState.waitForWithAmState(
amState -> 0 == amState.getActivityCountInTask(taskId, SECOND_STANDARD_ACTIVITY),
waitFinishMsg));
}
@Test
public void testLaunchActivityWithFlagPreviousIsTop() {
// Launch a standard activity
getLaunchActivityBuilder()
.setTargetActivity(SINGLE_TOP_ACTIVITY)
.execute();
final int taskId = mWmState.getTaskByActivity(
SINGLE_TOP_ACTIVITY).getTaskId();
// Launch a standard activity again with PREVIOUS_IS_TOP
getLaunchActivityBuilder()
.setTargetActivity(SINGLE_TOP_ACTIVITY)
.setLaunchingActivity(LAUNCHING_AND_FINISH_ACTIVITY)
.setIntentFlags(FLAG_ACTIVITY_PREVIOUS_IS_TOP)
.execute();
assertEquals("Instance of activity must be one", 1,
mWmState.getActivityCountInTask(taskId, SINGLE_TOP_ACTIVITY));
}
/**
* This test case tests behavior of activity launched with FLAG_ACTIVITY_SINGLE_TOP.
* A single top activity must not be launched if it is already running at the top
* of the history stack.
*/
@Test
public void testLaunchActivityWithFlagSingleTop() {
// Launch a standard activity
getLaunchActivityBuilder()
.setUseInstrumentation()
.setTargetActivity(STANDARD_ACTIVITY)
.execute();
final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId();
// Launch a standard activity with SINGLE_TOP flag.
// This standard activity launches a standard activity with single top flag.
getLaunchActivityBuilder()
.setTargetActivity(STANDARD_SINGLE_TOP_ACTIVITY)
.setUseInstrumentation()
.setIntentFlags(FLAG_ACTIVITY_SINGLE_TOP)
.execute();
mWmState.waitForActivityState(STANDARD_SINGLE_TOP_ACTIVITY, STATE_RESUMED);
// Make sure that a new instance is not created if it is already running at the top
// of the history stack.
assertEquals("Multiple single top activities must not be created.", 1,
mWmState
.getActivityCountInTask(taskId, STANDARD_SINGLE_TOP_ACTIVITY));
// Make sure that activity is in focus.
mWmState.assertFocusedActivity(STANDARD_SINGLE_TOP_ACTIVITY + "must be focused Activity",
STANDARD_SINGLE_TOP_ACTIVITY);
// Make sure the stack for the single top activity is front.
assertEquals("The stack for the single top activity must be front.",
getActivityName(STANDARD_SINGLE_TOP_ACTIVITY),
mWmState.getTopActivityName(0));
// Make sure the standard activity and the single top activity are in same task.
assertEquals("Activity must be in same task.", taskId,
mWmState.getTaskByActivity(STANDARD_SINGLE_TOP_ACTIVITY)
.getTaskId());
}
/**
* This test case tests behavior of activity launched with FLAG_ACTIVITY_MULTIPLE_TASK
* and FLAG_ACTIVITY_NEW_TASK.
* Second launched activity which is launched with FLAG_ACTIVITY_MULTIPLE_TASK and
* FLAG_ACTIVITY_NEW_TASK is created in new task/stack. So, a first launched activity
* and a second launched activity are in different task/stack.
*/
@Test
public void testActivityWithFlagMultipleTaskAndNewTask() {
// Launch a standard activity
getLaunchActivityBuilder()
.setTargetActivity(STANDARD_ACTIVITY)
.setIntentFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
.execute();
final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId();
// Launch a standard activity with FLAG_ACTIVITY_MULTIPLE_TASK|FLAG_ACTIVITY_NEW_TASK
getLaunchActivityBuilder()
.setTargetActivity(STANDARD_ACTIVITY)
.setLaunchingActivity(TEST_LAUNCHING_ACTIVITY)
.setIntentFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
.execute();
// Make sure the stack for the standard activity is front.
assertEquals("The stack for the standard activity must be front.",
getActivityName(STANDARD_ACTIVITY),
mWmState.getTopActivityName(0));
// Make sure the first standard activity and second standard activity are not in same task.
assertNotEquals("Activity must not be in same task.", taskId,
mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId());
}
/**
* This test case tests behavior of activity launched with ClearTaskOnLaunch attribute and
* FLAG_ACTIVITY_RESET_TASK_IF_NEEDED. The activities above will be removed from the task when
* the clearTaskonlaunch activity is re-launched again.
*/
@Test
public void testActivityWithClearTaskOnLaunch() {
// Launch a clearTaskonlaunch activity
getLaunchActivityBuilder()
.setUseInstrumentation()
.setTargetActivity(CLEAR_TASK_ON_LAUNCH_ACTIVITY)
.setIntentFlags(FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
.execute();
mWmState.waitForActivityState(CLEAR_TASK_ON_LAUNCH_ACTIVITY, STATE_RESUMED);
final int taskId = mWmState.getTaskByActivity(CLEAR_TASK_ON_LAUNCH_ACTIVITY).getTaskId();
// Launch a standard activity
getLaunchActivityBuilder()
.setUseInstrumentation()
.setTargetActivity(STANDARD_ACTIVITY)
.execute();
mWmState.waitForActivityState(STANDARD_ACTIVITY, STATE_RESUMED);
// Return to home
launchHomeActivity();
// Launch the clearTaskonlaunch activity again
getLaunchActivityBuilder()
.setUseInstrumentation()
.setTargetActivity(CLEAR_TASK_ON_LAUNCH_ACTIVITY)
.setIntentFlags(FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
.execute();
mWmState.waitForActivityState(CLEAR_TASK_ON_LAUNCH_ACTIVITY, STATE_RESUMED);
mWmState.waitForActivityState(STANDARD_ACTIVITY, STATE_DESTROYED);
// Make sure the task for the clearTaskonlaunch activity is front.
assertEquals("The task for the clearTaskonlaunch activity must be front.",
getActivityName(CLEAR_TASK_ON_LAUNCH_ACTIVITY),
mWmState.getTopActivityName(0));
assertEquals("Instance of the activity in its task must be cleared", 0,
mWmState.getActivityCountInTask(taskId, STANDARD_ACTIVITY));
}
/**
* This test case tests behavior of activity with finishOnTaskLaunch attribute when the
* activity's task is relaunched from home, this activity should be finished.
*/
@Test
public void testActivityWithFinishOnTaskLaunch() {
// Launch a standard activity.
launchActivity(STANDARD_ACTIVITY);
final int taskId = mWmState.getTaskByActivity(STANDARD_ACTIVITY).getTaskId();
final int instances = mWmState.getActivityCountInTask(taskId, null);
// Launch a activity with finishOnTaskLaunch
launchActivity(FINISH_ON_TASK_LAUNCH_ACTIVITY);
// Make sure instances in task are increased.
assertEquals("instances of activity in task must be increased.", instances + 1,
mWmState.getActivityCountInTask(taskId, null));
// Navigate home
launchHomeActivity();
// Simulate to launch the activity from home again
getLaunchActivityBuilder()
.setUseInstrumentation()
.setTargetActivity(STANDARD_ACTIVITY)
.setIntentFlags(FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
.execute();
mWmState.waitForActivityState(STANDARD_ACTIVITY, STATE_RESUMED);
// Make sure the activity is finished.
assertEquals("Instance of the activity in its task must be cleared", 0,
mWmState.getActivityCountInTask(taskId, FINISH_ON_TASK_LAUNCH_ACTIVITY));
}
@Test
public void testActivityWithDocumentIntoExisting() {
// Launch a documentLaunchMode="intoExisting" activity
launchActivityWithData(DOCUMENT_INTO_EXISTING_ACTIVITY, "test");
waitAndAssertActivityState(DOCUMENT_INTO_EXISTING_ACTIVITY, STATE_RESUMED,
"Activity should be resumed");
final int taskId = mWmState.getTaskByActivity(DOCUMENT_INTO_EXISTING_ACTIVITY).getTaskId();
// Navigate home
launchHomeActivity();
// Launch the alias activity.
final ComponentName componentName = new ComponentName(mContext.getPackageName(),
DocumentIntoExistingActivity.class.getPackageName()
+ ".ActivityStarterTests$DocumentIntoExistingAliasActivity");
launchActivityWithData(componentName, "test");
waitAndAssertActivityState(DOCUMENT_INTO_EXISTING_ACTIVITY, STATE_RESUMED,
"Activity should be resumed");
final int taskId2 = mWmState.getTaskByActivity(DOCUMENT_INTO_EXISTING_ACTIVITY).getTaskId();
assertEquals("Activity must be in the same task.", taskId, taskId2);
assertEquals("Activity is the only member of its task", 1,
mWmState.getActivityCountInTask(taskId2, null));
}
/**
* This test case tests behavior of activity with relinquishTaskIdentify attribute. Ensure the
* relinquishTaskIdentity doesn't work if the app is not installed in the system partition.
*/
@Test
public void testActivityWithRelinquishTaskIdentity() {
// Launch a relinquishTaskIdentity activity and test activity with different affinity into
// a same task.
getLaunchActivityBuilder().setTargetActivity(RELINQUISHTASKIDENTITY_ACTIVITY)
.setIntentExtra(extra -> extra.putBoolean(
RelinquishTaskIdentityActivity.EXTRA_LAUNCHED, true))
.setUseInstrumentation()
.setWaitForLaunched(true)
.execute();
// get the task affinity(e.g. 10825:android.server.wm.cts) without the uid information
String affinity = mWmState.getTaskByActivity(RELINQUISHTASKIDENTITY_ACTIVITY).getAffinity();
affinity = affinity.substring(affinity.indexOf(":") + 1);
final int taskId = mWmState.getTaskByActivity(RELINQUISHTASKIDENTITY_ACTIVITY).getTaskId();
final int taskId2 = mWmState.getTaskByActivity(TEST_LAUNCHING_ACTIVITY).getTaskId();
// verify the activities are in the same task
assertEquals("Activity must be in the same task.", taskId, taskId2);
// verify the relinquishTaskIdentify function is ignored since it isn't a app that in system
// partition
assertEquals("Affinity should be same with the package name.",
RELINQUISHTASKIDENTITY_ACTIVITY.getPackageName(), affinity);
}
// Test activity
public static class RelinquishTaskIdentityActivity extends Activity {
public static final String EXTRA_LAUNCHED = "extraLaunched";
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (getIntent().getBooleanExtra(EXTRA_LAUNCHED, false)) {
startActivityForResult(
new Intent(this, TestLaunchingActivity.class), 1 /* requestCode */);
}
}
}
// Test activity
public static class StandardActivity extends Activity {
}
// Test activity
public static class SecondStandardActivity extends Activity {
}
// Test activity
public static class StandardWithSingleTopActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = new Intent().setComponent(
new ComponentName(this /* context */, getClass()));
intent.addFlags(FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
}
// Test activity
public static class ClearTaskOnLaunchActivity extends Activity {
}
// Test activity
public static class FinishOnTaskLaunchActivity extends Activity {
}
// Test activity
public static class SingleTopActivity extends Activity {
}
// Test activity
public static class SingleTaskActivity extends Activity {
}
// Test activity
public static class SingleInstanceActivity extends Activity {
public static final String EXTRA_SHOW_WHEN_LOCKED = "showWhenLocked";
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (getIntent().getBooleanExtra(EXTRA_SHOW_WHEN_LOCKED, false)) {
setShowWhenLocked(true);
}
}
}
// Test activity
public static class DocumentIntoExistingActivity extends Activity {
}
// Launching activity
public static class TestLaunchingActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = getIntent();
if (intent != null) {
ActivityLauncher.launchActivityFromExtras(this, intent.getExtras());
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
ActivityLauncher.launchActivityFromExtras(this, intent.getExtras());
}
}
public static class LaunchingAndFinishActivity extends TestLaunchingActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
finish();
}
}
}