Merge "Introduce TaskFragment transition type" into sc-v2-dev am: 03adaa2230 am: a44f783b30

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15435280

Change-Id: Ic8556930d8975704ad10b71e8796aefcbf443571
This commit is contained in:
Charles Chen
2021-08-24 10:36:07 +00:00
committed by Automerger Merge Worker
18 changed files with 445 additions and 69 deletions

View File

@@ -319,6 +319,19 @@ public interface WindowManager extends ViewManager {
*/
int TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE = 27;
/**
* A window in a new task fragment is being opened.
* @hide
*/
int TRANSIT_OLD_TASK_FRAGMENT_OPEN = 28;
/**
* A window in the top-most activity of task fragment is being closed to reveal the activity
* below.
* @hide
*/
int TRANSIT_OLD_TASK_FRAGMENT_CLOSE = 29;
/**
* @hide
*/
@@ -344,7 +357,9 @@ public interface WindowManager extends ViewManager {
TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN,
TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE,
TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE,
TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE
TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE,
TRANSIT_OLD_TASK_FRAGMENT_OPEN,
TRANSIT_OLD_TASK_FRAGMENT_CLOSE
})
@Retention(RetentionPolicy.SOURCE)
@interface TransitionOldType {}

View File

@@ -670,6 +670,7 @@ final class AccessibilityController {
if (magnifying) {
switch (transition) {
case WindowManager.TRANSIT_OLD_ACTIVITY_OPEN:
case WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN:
case WindowManager.TRANSIT_OLD_TASK_OPEN:
case WindowManager.TRANSIT_OLD_TASK_TO_FRONT:
case WindowManager.TRANSIT_OLD_WALLPAPER_OPEN:

View File

@@ -40,6 +40,8 @@ import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
import static android.view.WindowManager.TRANSIT_OLD_NONE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
@@ -1005,6 +1007,21 @@ public class AppTransition implements Dump {
animAttr = enter
? WindowAnimation_launchTaskBehindSourceAnimation
: WindowAnimation_launchTaskBehindTargetAnimation;
break;
// TODO(b/189386466): Use activity transition as the fallback. Investigate if we
// need new TaskFragment transition.
case TRANSIT_OLD_TASK_FRAGMENT_OPEN:
animAttr = enter
? WindowAnimation_activityOpenEnterAnimation
: WindowAnimation_activityOpenExitAnimation;
break;
// TODO(b/189386466): Use activity transition as the fallback. Investigate if we
// need new TaskFragment transition.
case TRANSIT_OLD_TASK_FRAGMENT_CLOSE:
animAttr = enter
? WindowAnimation_activityCloseEnterAnimation
: WindowAnimation_activityCloseExitAnimation;
break;
}
a = animAttr != 0 ? loadAnimationAttr(lp, animAttr, transit) : null;
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
@@ -1315,6 +1332,12 @@ public class AppTransition implements Dump {
case TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE: {
return "TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE";
}
case TRANSIT_OLD_TASK_FRAGMENT_OPEN: {
return "TRANSIT_OLD_TASK_FRAGMENT_OPEN";
}
case TRANSIT_OLD_TASK_FRAGMENT_CLOSE: {
return "TRANSIT_OLD_TASK_FRAGMENT_CLOSE";
}
default: {
return "<UNKNOWN: " + transition + ">";
}

View File

@@ -39,6 +39,8 @@ import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
import static android.view.WindowManager.TRANSIT_OLD_NONE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
@@ -68,6 +70,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACT
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.os.Trace;
import android.util.ArrayMap;
@@ -86,6 +89,8 @@ import android.view.animation.Animation;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.function.Predicate;
@@ -102,6 +107,20 @@ public class AppTransitionController {
private RemoteAnimationDefinition mRemoteAnimationDefinition = null;
private static final int KEYGUARD_GOING_AWAY_ANIMATION_DURATION = 400;
private static final int TYPE_NONE = 0;
private static final int TYPE_ACTIVITY = 1;
private static final int TYPE_TASK_FRAGMENT = 2;
private static final int TYPE_TASK = 3;
@IntDef(prefix = { "TYPE_" }, value = {
TYPE_NONE,
TYPE_ACTIVITY,
TYPE_TASK_FRAGMENT,
TYPE_TASK
})
@Retention(RetentionPolicy.SOURCE)
@interface TransitContainerType {}
private final ArrayMap<WindowContainer, Integer> mTempTransitionReasons = new ArrayMap<>();
AppTransitionController(WindowManagerService service, DisplayContent displayContent) {
@@ -387,33 +406,38 @@ public class AppTransitionController {
openingApps, closingApps, true /* visible */);
final ArraySet<WindowContainer> closingWcs = getAnimationTargets(
openingApps, closingApps, false /* visible */);
final boolean isActivityOpening = !openingWcs.isEmpty()
&& openingWcs.valueAt(0).asActivityRecord() != null;
final boolean isActivityClosing = !closingWcs.isEmpty()
&& closingWcs.valueAt(0).asActivityRecord() != null;
final boolean isTaskOpening = !openingWcs.isEmpty() && !isActivityOpening;
final boolean isTaskClosing = !closingWcs.isEmpty() && !isActivityClosing;
if (appTransition.containsTransitRequest(TRANSIT_TO_FRONT) && isTaskOpening) {
final WindowContainer<?> openingContainer = !openingWcs.isEmpty()
? openingWcs.valueAt(0) : null;
final WindowContainer<?> closingContainer = !closingWcs.isEmpty()
? closingWcs.valueAt(0) : null;
@TransitContainerType int openingType = getTransitContainerType(openingContainer);
@TransitContainerType int closingType = getTransitContainerType(closingContainer);
if (appTransition.containsTransitRequest(TRANSIT_TO_FRONT) && openingType == TYPE_TASK) {
return TRANSIT_OLD_TASK_TO_FRONT;
}
if (appTransition.containsTransitRequest(TRANSIT_TO_BACK) && isTaskClosing) {
if (appTransition.containsTransitRequest(TRANSIT_TO_BACK) && closingType == TYPE_TASK) {
return TRANSIT_OLD_TASK_TO_BACK;
}
if (appTransition.containsTransitRequest(TRANSIT_OPEN)) {
if (isTaskOpening) {
if (openingType == TYPE_TASK) {
return (appTransition.getTransitFlags() & TRANSIT_FLAG_OPEN_BEHIND) != 0
? TRANSIT_OLD_TASK_OPEN_BEHIND : TRANSIT_OLD_TASK_OPEN;
}
if (isActivityOpening) {
if (openingType == TYPE_ACTIVITY) {
return TRANSIT_OLD_ACTIVITY_OPEN;
}
if (openingType == TYPE_TASK_FRAGMENT) {
return TRANSIT_OLD_TASK_FRAGMENT_OPEN;
}
}
if (appTransition.containsTransitRequest(TRANSIT_CLOSE)) {
if (isTaskClosing) {
if (closingType == TYPE_TASK) {
return TRANSIT_OLD_TASK_CLOSE;
}
if (isActivityClosing) {
if (closingType == TYPE_TASK_FRAGMENT) {
return TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
}
if (closingType == TYPE_ACTIVITY) {
for (int i = closingApps.size() - 1; i >= 0; i--) {
if (closingApps.valueAt(i).visibleIgnoringKeyguard) {
return TRANSIT_OLD_ACTIVITY_CLOSE;
@@ -430,6 +454,23 @@ public class AppTransitionController {
return TRANSIT_OLD_NONE;
}
@TransitContainerType
private static int getTransitContainerType(@Nullable WindowContainer<?> container) {
if (container == null) {
return TYPE_NONE;
}
if (container.asTask() != null) {
return TYPE_TASK;
}
if (container.asTaskFragment() != null) {
return TYPE_TASK_FRAGMENT;
}
if (container.asActivityRecord() != null) {
return TYPE_ACTIVITY;
}
return TYPE_NONE;
}
private static WindowManager.LayoutParams getAnimLp(ActivityRecord activity) {
final WindowState mainWindow = activity != null ? activity.findMainWindow() : null;
return mainWindow != null ? mainWindow.mAttrs : null;

View File

@@ -219,7 +219,7 @@ public class ActivityRecordTests extends WindowTestsBase {
public void testNoCleanupMovingActivityInSameStack() {
final ActivityRecord activity = createActivityWith2LevelTask();
final Task rootTask = activity.getRootTask();
final Task newTask = new TaskBuilder(mAtm.mTaskSupervisor).setParentTask(rootTask).build();
final Task newTask = createTaskInRootTask(rootTask, 0 /* userId */);
activity.reparent(newTask, 0, null /*reason*/);
verify(rootTask, times(0)).cleanUpActivityReferences(any());
}

View File

@@ -478,7 +478,7 @@ public class ActivityStarterTests extends WindowTestsBase {
final ActivityRecord splitSecondActivity =
new ActivityBuilder(mAtm).setCreateTask(true).build();
final ActivityRecord splitPrimaryActivity = new TaskBuilder(mSupervisor)
.setParentTask(splitOrg.mPrimary)
.setParentTaskFragment(splitOrg.mPrimary)
.setCreateActivity(true)
.build()
.getTopMostActivity();
@@ -856,7 +856,7 @@ public class ActivityStarterTests extends WindowTestsBase {
// Create another activity on top of the secondary display.
final Task topStack = secondaryTaskContainer.createRootTask(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
final Task topTask = new TaskBuilder(mSupervisor).setParentTask(topStack).build();
final Task topTask = new TaskBuilder(mSupervisor).setParentTaskFragment(topStack).build();
new ActivityBuilder(mAtm).setTask(topTask).build();
doReturn(mActivityMetricsLogger).when(mSupervisor).getActivityMetricsLogger();
@@ -920,7 +920,7 @@ public class ActivityStarterTests extends WindowTestsBase {
DEFAULT_COMPONENT_PACKAGE_NAME + ".SingleTaskActivity");
final Task task = new TaskBuilder(mSupervisor)
.setComponent(componentName)
.setParentTask(stack)
.setParentTaskFragment(stack)
.build();
return new ActivityBuilder(mAtm)
.setComponent(componentName)
@@ -1056,8 +1056,8 @@ public class ActivityStarterTests extends WindowTestsBase {
final ActivityStarter starter = prepareStarter(0 /* flags */);
starter.mStartActivity = new ActivityBuilder(mAtm).build();
final Task task = new TaskBuilder(mAtm.mTaskSupervisor)
.setParentTask(mAtm.mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */))
.setParentTaskFragment(createTask(mDisplayContent, WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD))
.setUserId(10)
.build();

View File

@@ -375,7 +375,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
final ArraySet<ActivityRecord> closing = new ArraySet<>();
closing.add(activity3);
// Promote animation targets to TaskStack level. Invisible ActivityRecords don't affect
// Promote animation targets to root Task level. Invisible ActivityRecords don't affect
// promotion decision.
assertEquals(
new ArraySet<>(new WindowContainer[]{activity1.getRootTask()}),
@@ -520,6 +520,128 @@ public class AppTransitionControllerTest extends WindowTestsBase {
opening, closing, false /* visible */));
}
@Test
public void testGetAnimationTargets_openingClosingTaskFragment() {
// [DefaultTDA] - [Task] -+- [TaskFragment1] - [ActivityRecord1] (opening, invisible)
// +- [TaskFragment2] - [ActivityRecord2] (closing, visible)
final Task parentTask = createTask(mDisplayContent);
final TaskFragment taskFragment1 = createTaskFragmentWithParentTask(parentTask,
false /* createEmbeddedTask */);
final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
activity1.setVisible(false);
activity1.mVisibleRequested = true;
final TaskFragment taskFragment2 = createTaskFragmentWithParentTask(parentTask,
false /* createEmbeddedTask */);
final ActivityRecord activity2 = taskFragment2.getTopMostActivity();
activity2.setVisible(true);
activity2.mVisibleRequested = false;
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
final ArraySet<ActivityRecord> closing = new ArraySet<>();
closing.add(activity2);
// Promote animation targets up to TaskFragment level, not beyond.
assertEquals(new ArraySet<>(new WindowContainer[]{taskFragment1}),
AppTransitionController.getAnimationTargets(
opening, closing, true /* visible */));
assertEquals(new ArraySet<>(new WindowContainer[]{taskFragment2}),
AppTransitionController.getAnimationTargets(
opening, closing, false /* visible */));
}
@Test
public void testGetAnimationTargets_openingClosingTaskFragmentWithEmbeddedTask() {
// [DefaultTDA] - [Task] -+- [TaskFragment1] - [ActivityRecord1] (opening, invisible)
// +- [TaskFragment2] - [ActivityRecord2] (closing, visible)
final Task parentTask = createTask(mDisplayContent);
final TaskFragment taskFragment1 = createTaskFragmentWithParentTask(parentTask,
true /* createEmbeddedTask */);
final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
activity1.setVisible(false);
activity1.mVisibleRequested = true;
final TaskFragment taskFragment2 = createTaskFragmentWithParentTask(parentTask,
true /* createEmbeddedTask */);
final ActivityRecord activity2 = taskFragment2.getTopMostActivity();
activity2.setVisible(true);
activity2.mVisibleRequested = false;
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
final ArraySet<ActivityRecord> closing = new ArraySet<>();
closing.add(activity2);
// Promote animation targets up to TaskFragment level, not beyond.
assertEquals(new ArraySet<>(new WindowContainer[]{taskFragment1}),
AppTransitionController.getAnimationTargets(
opening, closing, true /* visible */));
assertEquals(new ArraySet<>(new WindowContainer[]{taskFragment2}),
AppTransitionController.getAnimationTargets(
opening, closing, false /* visible */));
}
@Test
public void testGetAnimationTargets_openingTheOnlyTaskFragmentInTask() {
// [DefaultTDA] -+- [Task1] - [TaskFragment1] - [ActivityRecord1] (opening, invisible)
// +- [Task2] - [ActivityRecord2] (closing, visible)
final Task task1 = createTask(mDisplayContent);
final TaskFragment taskFragment1 = createTaskFragmentWithParentTask(task1,
false /* createEmbeddedTask */);
final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
activity1.setVisible(false);
activity1.mVisibleRequested = true;
final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
activity2.setVisible(true);
activity2.mVisibleRequested = false;
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
final ArraySet<ActivityRecord> closing = new ArraySet<>();
closing.add(activity2);
// Promote animation targets up to leaf Task level because there's only one TaskFragment in
// the Task.
assertEquals(new ArraySet<>(new WindowContainer[]{task1}),
AppTransitionController.getAnimationTargets(
opening, closing, true /* visible */));
assertEquals(new ArraySet<>(new WindowContainer[]{activity2.getTask()}),
AppTransitionController.getAnimationTargets(
opening, closing, false /* visible */));
}
@Test
public void testGetAnimationTargets_closingTheOnlyTaskFragmentInTask() {
// [DefaultTDA] -+- [Task1] - [TaskFragment1] - [ActivityRecord1] (closing, visible)
// +- [Task2] - [ActivityRecord2] (opening, invisible)
final Task task1 = createTask(mDisplayContent);
final TaskFragment taskFragment1 = createTaskFragmentWithParentTask(task1,
false /* createEmbeddedTask */);
final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
activity1.setVisible(true);
activity1.mVisibleRequested = false;
final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
activity2.setVisible(false);
activity2.mVisibleRequested = true;
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity2);
final ArraySet<ActivityRecord> closing = new ArraySet<>();
closing.add(activity1);
// Promote animation targets up to leaf Task level because there's only one TaskFragment in
// the Task.
assertEquals(new ArraySet<>(new WindowContainer[]{activity2.getTask()}),
AppTransitionController.getAnimationTargets(
opening, closing, true /* visible */));
assertEquals(new ArraySet<>(new WindowContainer[]{task1}),
AppTransitionController.getAnimationTargets(
opening, closing, false /* visible */));
}
static class TestRemoteAnimationRunner implements IRemoteAnimationRunner {
@Override
public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,

View File

@@ -23,6 +23,8 @@ import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_UNSET;
import static android.view.WindowManager.TRANSIT_OPEN;
@@ -40,6 +42,7 @@ import static org.mockito.ArgumentMatchers.any;
import android.os.IBinder;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
import android.view.Display;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
@@ -146,6 +149,91 @@ public class AppTransitionTests extends WindowTestsBase {
true /*skipAppTransitionAnimation*/));
}
@Test
public void testTaskFragmentOpeningTransition() {
final ActivityRecord activity = createHierarchyForTaskFragmentTest(
false /* createEmbeddedTask */);
activity.setVisible(false);
mDisplayContent.prepareAppTransition(TRANSIT_OPEN);
mDisplayContent.mOpeningApps.add(activity);
assertEquals(TRANSIT_OLD_TASK_FRAGMENT_OPEN,
AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
null /* wallpaperTarget */, null /* oldWallpaper */,
false /* skipAppTransitionAnimation */));
}
@Test
public void testEmbeddedTaskOpeningTransition() {
final ActivityRecord activity = createHierarchyForTaskFragmentTest(
true /* createEmbeddedTask */);
activity.setVisible(false);
mDisplayContent.prepareAppTransition(TRANSIT_OPEN);
mDisplayContent.mOpeningApps.add(activity);
assertEquals(TRANSIT_OLD_TASK_FRAGMENT_OPEN,
AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
null /* wallpaperTarget */, null /* oldWallpaper */,
false /* skipAppTransitionAnimation */));
}
@Test
public void testTaskFragmentClosingTransition() {
final ActivityRecord activity = createHierarchyForTaskFragmentTest(
false /* createEmbeddedTask */);
activity.setVisible(true);
mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);
mDisplayContent.mClosingApps.add(activity);
assertEquals(TRANSIT_OLD_TASK_FRAGMENT_CLOSE,
AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
null /* wallpaperTarget */, null /* oldWallpaper */,
false /* skipAppTransitionAnimation */));
}
@Test
public void testEmbeddedTaskClosingTransition() {
final ActivityRecord activity = createHierarchyForTaskFragmentTest(
true /* createEmbeddedTask */);
activity.setVisible(true);
mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);
mDisplayContent.mClosingApps.add(activity);
assertEquals(TRANSIT_OLD_TASK_FRAGMENT_CLOSE,
AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
null /* wallpaperTarget */, null /* oldWallpaper */,
false /* skipAppTransitionAnimation */));
}
/**
* Creates a {@link Task} with two {@link TaskFragment TaskFragments}.
* The bottom TaskFragment is to prevent
* {@link AppTransitionController#getAnimationTargets(ArraySet, ArraySet, boolean) the animation
* target} to promote to Task or above.
*
* @param createEmbeddedTask {@code true} to create embedded Task for verified TaskFragment
* @return The Activity to be put in either opening or closing Activity
*/
private ActivityRecord createHierarchyForTaskFragmentTest(boolean createEmbeddedTask) {
final Task parentTask = createTask(mDisplayContent);
final TaskFragment bottomTaskFragment = createTaskFragmentWithParentTask(parentTask,
false /* createEmbeddedTask */);
final ActivityRecord bottomActivity = bottomTaskFragment.getTopMostActivity();
bottomActivity.setOccludesParent(true);
bottomActivity.setVisible(true);
final TaskFragment verifiedTaskFragment = createTaskFragmentWithParentTask(parentTask,
createEmbeddedTask);
final ActivityRecord activity = verifiedTaskFragment.getTopMostActivity();
activity.setOccludesParent(true);
return activity;
}
@Test
public void testAppTransitionStateForMultiDisplay() {
// Create 2 displays & presume both display the state is ON for ready to display & animate.

View File

@@ -2352,10 +2352,10 @@ public class DisplayContentTests extends WindowTestsBase {
ACTIVITY_TYPE_STANDARD, ON_TOP);
final Task rootTask4 = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, ON_TOP);
final Task task1 = new TaskBuilder(mAtm.mTaskSupervisor).setParentTask(rootTask1).build();
final Task task2 = new TaskBuilder(mAtm.mTaskSupervisor).setParentTask(rootTask2).build();
final Task task3 = new TaskBuilder(mAtm.mTaskSupervisor).setParentTask(rootTask3).build();
final Task task4 = new TaskBuilder(mAtm.mTaskSupervisor).setParentTask(rootTask4).build();
final Task task1 = new TaskBuilder(mSupervisor).setParentTaskFragment(rootTask1).build();
final Task task2 = new TaskBuilder(mSupervisor).setParentTaskFragment(rootTask2).build();
final Task task3 = new TaskBuilder(mSupervisor).setParentTaskFragment(rootTask3).build();
final Task task4 = new TaskBuilder(mSupervisor).setParentTaskFragment(rootTask4).build();
// Reordering root tasks while removing root tasks.
doAnswer(invocation -> {

View File

@@ -117,7 +117,7 @@ public class LaunchParamsPersisterTests extends WindowTestsBase {
Task rootTask = mTestDisplay.getDefaultTaskDisplayArea()
.createRootTask(TEST_WINDOWING_MODE, ACTIVITY_TYPE_STANDARD, /* onTop */ true);
mTestTask = new TaskBuilder(mSupervisor).setComponent(TEST_COMPONENT)
.setParentTask(rootTask).build();
.setParentTaskFragment(rootTask).build();
mTestTask.mUserId = TEST_USER_ID;
mTestTask.mLastNonFullscreenBounds = TEST_BOUNDS;
mTestTask.setHasBeenVisible(true);
@@ -353,7 +353,7 @@ public class LaunchParamsPersisterTests extends WindowTestsBase {
final Task anotherTaskOfTheSameUser = new TaskBuilder(mSupervisor)
.setComponent(ALTERNATIVE_COMPONENT)
.setUserId(TEST_USER_ID)
.setParentTask(stack)
.setParentTaskFragment(stack)
.build();
anotherTaskOfTheSameUser.setWindowingMode(WINDOWING_MODE_FREEFORM);
anotherTaskOfTheSameUser.setBounds(200, 300, 400, 500);
@@ -365,7 +365,7 @@ public class LaunchParamsPersisterTests extends WindowTestsBase {
final Task anotherTaskOfDifferentUser = new TaskBuilder(mSupervisor)
.setComponent(TEST_COMPONENT)
.setUserId(ALTERNATIVE_USER_ID)
.setParentTask(stack)
.setParentTaskFragment(stack)
.build();
anotherTaskOfDifferentUser.setWindowingMode(WINDOWING_MODE_FREEFORM);
anotherTaskOfDifferentUser.setBounds(300, 400, 500, 600);

View File

@@ -331,7 +331,7 @@ public class RecentTasksTest extends WindowTestsBase {
// other task
Task task1 = createTaskBuilder(".Task1")
.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
.setParentTask(mTaskContainer.getRootHomeTask()).build();
.setParentTaskFragment(mTaskContainer.getRootHomeTask()).build();
Task task2 = createTaskBuilder(".Task1")
.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
.build();
@@ -471,8 +471,8 @@ public class RecentTasksTest extends WindowTestsBase {
final Task root = createTaskBuilder(".CreatedByOrganizerRoot").build();
root.mCreatedByOrganizer = true;
// Add organized and non-organized child.
final Task child1 = createTaskBuilder(".Task1").setParentTask(root).build();
final Task child2 = createTaskBuilder(".Task2").setParentTask(root).build();
final Task child1 = createTaskBuilder(".Task1").setParentTaskFragment(root).build();
final Task child2 = createTaskBuilder(".Task2").setParentTaskFragment(root).build();
doReturn(true).when(child1).isOrganized();
doReturn(false).when(child2).isOrganized();
mRecentTasks.add(root);
@@ -508,7 +508,8 @@ public class RecentTasksTest extends WindowTestsBase {
// tasks because their intents are identical.
mRecentTasks.add(task1);
// Go home to trigger the removal of untracked tasks.
mRecentTasks.add(createTaskBuilder(".Home").setParentTask(mTaskContainer.getRootHomeTask())
mRecentTasks.add(createTaskBuilder(".Home")
.setParentTaskFragment(mTaskContainer.getRootHomeTask())
.build());
triggerIdleToTrim();
@@ -675,7 +676,7 @@ public class RecentTasksTest extends WindowTestsBase {
public void testVisibleTasks_excludedFromRecents_firstTaskNotVisible() {
// Create some set of tasks, some of which are visible and some are not
Task homeTask = createTaskBuilder("com.android.pkg1", ".HomeTask")
.setParentTask(mTaskContainer.getRootHomeTask())
.setParentTaskFragment(mTaskContainer.getRootHomeTask())
.build();
homeTask.mUserSetupComplete = true;
mRecentTasks.add(homeTask);
@@ -696,7 +697,7 @@ public class RecentTasksTest extends WindowTestsBase {
t1.mUserSetupComplete = true;
mRecentTasks.add(t1);
Task homeTask = createTaskBuilder("com.android.pkg1", ".HomeTask")
.setParentTask(mTaskContainer.getRootHomeTask())
.setParentTaskFragment(mTaskContainer.getRootHomeTask())
.build();
homeTask.mUserSetupComplete = true;
mRecentTasks.add(homeTask);
@@ -949,10 +950,10 @@ public class RecentTasksTest extends WindowTestsBase {
// Add a number of tasks (beyond the max) but ensure that nothing is trimmed because all
// the tasks belong in stacks above the home stack
mRecentTasks.add(createTaskBuilder(".HomeTask1").setParentTask(homeStack).build());
mRecentTasks.add(createTaskBuilder(".Task1").setParentTask(aboveHomeStack).build());
mRecentTasks.add(createTaskBuilder(".Task2").setParentTask(aboveHomeStack).build());
mRecentTasks.add(createTaskBuilder(".Task3").setParentTask(aboveHomeStack).build());
mRecentTasks.add(createTaskBuilder(".HomeTask1").setParentTaskFragment(homeStack).build());
mRecentTasks.add(createTaskBuilder(".Task1").setParentTaskFragment(aboveHomeStack).build());
mRecentTasks.add(createTaskBuilder(".Task2").setParentTaskFragment(aboveHomeStack).build());
mRecentTasks.add(createTaskBuilder(".Task3").setParentTaskFragment(aboveHomeStack).build());
triggerTrimAndAssertNoTasksTrimmed();
}
@@ -970,11 +971,11 @@ public class RecentTasksTest extends WindowTestsBase {
// Add a number of tasks (beyond the max) but ensure that only the task in the stack behind
// the home stack is trimmed once a new task is added
final Task behindHomeTask = createTaskBuilder(".Task1")
.setParentTask(behindHomeStack)
.setParentTaskFragment(behindHomeStack)
.build();
mRecentTasks.add(behindHomeTask);
mRecentTasks.add(createTaskBuilder(".HomeTask1").setParentTask(homeStack).build());
mRecentTasks.add(createTaskBuilder(".Task2").setParentTask(aboveHomeStack).build());
mRecentTasks.add(createTaskBuilder(".HomeTask1").setParentTaskFragment(homeStack).build());
mRecentTasks.add(createTaskBuilder(".Task2").setParentTaskFragment(aboveHomeStack).build());
triggerTrimAndAssertTrimmed(behindHomeTask);
}
@@ -990,10 +991,12 @@ public class RecentTasksTest extends WindowTestsBase {
// Add a number of tasks (beyond the max) on each display, ensure that the tasks are not
// removed
mRecentTasks.add(createTaskBuilder(".HomeTask1").setParentTask(homeTask).build());
mRecentTasks.add(createTaskBuilder(".Task1").setParentTask(otherDisplayRootTask).build());
mRecentTasks.add(createTaskBuilder(".Task2").setParentTask(otherDisplayRootTask).build());
mRecentTasks.add(createTaskBuilder(".HomeTask2").setParentTask(homeTask).build());
mRecentTasks.add(createTaskBuilder(".HomeTask1").setParentTaskFragment(homeTask).build());
mRecentTasks.add(createTaskBuilder(".Task1").setParentTaskFragment(otherDisplayRootTask)
.build());
mRecentTasks.add(createTaskBuilder(".Task2").setParentTaskFragment(otherDisplayRootTask)
.build());
mRecentTasks.add(createTaskBuilder(".HomeTask2").setParentTaskFragment(homeTask).build());
triggerTrimAndAssertNoTasksTrimmed();
}
@@ -1023,7 +1026,7 @@ public class RecentTasksTest extends WindowTestsBase {
Task t1 = createTaskBuilder("com.android.pkg1", ".Task1").build();
mRecentTasks.add(t1);
mRecentTasks.add(createTaskBuilder("com.android.pkg1", ".HomeTask")
.setParentTask(mTaskContainer.getRootHomeTask()).build());
.setParentTaskFragment(mTaskContainer.getRootHomeTask()).build());
Task t2 = createTaskBuilder("com.android.pkg2", ".Task2").build();
mRecentTasks.add(t2);
mRecentTasks.add(createTaskBuilder("com.android.pkg1", ".PipTask")

View File

@@ -329,7 +329,7 @@ public class RootTaskTests extends WindowTestsBase {
// Create primary splitscreen root task.
final Task primarySplitScreen = new TaskBuilder(mAtm.mTaskSupervisor)
.setParentTask(organizer.mPrimary)
.setParentTaskFragment(organizer.mPrimary)
.setOnTop(true)
.build();
@@ -505,8 +505,8 @@ public class RootTaskTests extends WindowTestsBase {
targetActivity);
final ComponentName alias = new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME,
aliasActivity);
final Task parentTask = new TaskBuilder(mAtm.mTaskSupervisor).build();
final Task task = new TaskBuilder(mAtm.mTaskSupervisor).setParentTask(parentTask).build();
final Task parentTask = new TaskBuilder(mSupervisor).build();
final Task task = new TaskBuilder(mSupervisor).setParentTaskFragment(parentTask).build();
task.origActivity = alias;
task.realActivity = target;
new ActivityBuilder(mAtm).setComponent(target).setTask(task).setTargetActivity(

View File

@@ -168,7 +168,7 @@ public class RootWindowContainerTests extends WindowTestsBase {
@Test
public void testTaskLayerRank() {
final Task rootTask = new TaskBuilder(mSupervisor).build();
final Task task1 = new TaskBuilder(mSupervisor).setParentTask(rootTask).build();
final Task task1 = new TaskBuilder(mSupervisor).setParentTaskFragment(rootTask).build();
new ActivityBuilder(mAtm).setTask(task1).build().mVisibleRequested = true;
mWm.mRoot.rankTaskLayers();
@@ -523,7 +523,8 @@ public class RootWindowContainerTests extends WindowTestsBase {
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
final Task targetRootTask = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* onTop */);
final Task targetTask = new TaskBuilder(mSupervisor).setParentTask(targetRootTask).build();
final Task targetTask = new TaskBuilder(mSupervisor).setParentTaskFragment(targetRootTask)
.build();
// Create Recents on secondary display.
final TestDisplayContent secondDisplay = addNewDisplayContentAt(

View File

@@ -166,7 +166,7 @@ public class RunningTasksTest extends WindowTestsBase {
final Task task = new TaskBuilder(mAtm.mTaskSupervisor)
.setComponent(new ComponentName(mContext.getPackageName(), className))
.setTaskId(taskId)
.setParentTask(stack)
.setParentTaskFragment(stack)
.build();
task.lastActiveTime = lastActiveTime;
final ActivityRecord activity = new ActivityBuilder(mAtm)

View File

@@ -620,7 +620,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
final Task pinnedRootTask = mRootWindowContainer.getDefaultTaskDisplayArea()
.createRootTask(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, ON_TOP);
final Task pinnedTask = new TaskBuilder(mAtm.mTaskSupervisor)
.setParentTask(pinnedRootTask).build();
.setParentTaskFragment(pinnedRootTask).build();
new ActivityBuilder(mAtm).setActivityFlags(FLAG_ALWAYS_FOCUSABLE)
.setTask(pinnedTask).build();
pinnedRootTask.moveToFront("movePinnedRootTaskToFront");

View File

@@ -1716,7 +1716,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
final Task rootTask = display.getDefaultTaskDisplayArea()
.createRootTask(display.getWindowingMode(), ACTIVITY_TYPE_STANDARD, true);
rootTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
final Task task = new TaskBuilder(mSupervisor).setParentTask(rootTask).build();
final Task task = new TaskBuilder(mSupervisor).setParentTaskFragment(rootTask).build();
// Just work around the unnecessary adjustments for bounds.
task.getWindowConfiguration().setBounds(bounds);
}

View File

@@ -427,7 +427,7 @@ public class TaskTests extends WindowTestsBase {
TaskDisplayArea taskDisplayArea = mAtm.mRootWindowContainer.getDefaultTaskDisplayArea();
Task rootTask = taskDisplayArea.createRootTask(WINDOWING_MODE_FREEFORM,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
Task task = new TaskBuilder(mSupervisor).setParentTask(rootTask).build();
Task task = new TaskBuilder(mSupervisor).setParentTaskFragment(rootTask).build();
final Configuration parentConfig = rootTask.getConfiguration();
parentConfig.windowConfiguration.setBounds(parentBounds);
parentConfig.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
@@ -757,7 +757,7 @@ public class TaskTests extends WindowTestsBase {
DisplayInfo displayInfo = new DisplayInfo();
mAtm.mContext.getDisplay().getDisplayInfo(displayInfo);
final int displayHeight = displayInfo.logicalHeight;
final Task task = new TaskBuilder(mSupervisor).setParentTask(rootTask).build();
final Task task = new TaskBuilder(mSupervisor).setParentTaskFragment(rootTask).build();
final Configuration inOutConfig = new Configuration();
final Configuration parentConfig = new Configuration();
final int longSide = 1200;
@@ -1375,7 +1375,7 @@ public class TaskTests extends WindowTestsBase {
TaskDisplayArea taskDisplayArea = mAtm.mRootWindowContainer.getDefaultTaskDisplayArea();
Task rootTask = taskDisplayArea.createRootTask(windowingMode, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
Task task = new TaskBuilder(mSupervisor).setParentTask(rootTask).build();
Task task = new TaskBuilder(mSupervisor).setParentTaskFragment(rootTask).build();
final Configuration parentConfig = rootTask.getConfiguration();
parentConfig.windowConfiguration.setAppBounds(parentBounds);

View File

@@ -56,6 +56,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.StartingSurfaceController.DEBUG_ENABLE_SHELL_DRAWER;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
import static org.junit.Assert.assertEquals;
@@ -589,7 +590,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
Task createTaskInRootTask(Task rootTask, int userId) {
final Task task = new TaskBuilder(rootTask.mTaskSupervisor)
.setUserId(userId)
.setParentTask(rootTask)
.setParentTaskFragment(rootTask)
.build();
return task;
}
@@ -675,6 +676,26 @@ class WindowTestsBase extends SystemServiceTestsBase {
activity.mVisibleRequested = true;
}
/**
* Creates a {@link TaskFragment} and attach it to the {@code parentTask}.
*
* @param parentTask the {@link Task} this TaskFragment is going to be attached
* @param createEmbeddedTask Sets to {@code true} to create an embedded Task for this
* TaskFragment. Otherwise, create a {@link ActivityRecord}.
* @return the created TaskFragment
*/
static TaskFragment createTaskFragmentWithParentTask(@NonNull Task parentTask,
boolean createEmbeddedTask) {
final TaskFragmentBuilder builder = new TaskFragmentBuilder(parentTask.mAtmService)
.setParentTask(parentTask);
if (createEmbeddedTask) {
builder.createEmbeddedTask();
} else {
builder.createActivityCount(1);
}
return builder.build();
}
/** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
DisplayContent createNewDisplay() {
return createNewDisplayWithImeSupport(DISPLAY_IME_POLICY_LOCAL);
@@ -1042,7 +1063,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
// Apply the root activity info and intent
.setActivityInfo(aInfo)
.setIntent(intent)
.setParentTask(mParentTask).build();
.setParentTaskFragment(mParentTask).build();
} else if (mTask == null && mParentTask != null && DisplayContent.alwaysCreateRootTask(
mParentTask.getWindowingMode(), mParentTask.getActivityType())) {
// The parent task can be the task root.
@@ -1101,6 +1122,64 @@ class WindowTestsBase extends SystemServiceTestsBase {
}
}
static class TaskFragmentBuilder {
private final ActivityTaskManagerService mAtm;
private Task mParentTask;
private boolean mCreateParentTask;
private boolean mCreateEmbeddedTask;
private int mCreateActivityCount = 0;
TaskFragmentBuilder(ActivityTaskManagerService service) {
mAtm = service;
}
TaskFragmentBuilder setCreateParentTask() {
mCreateParentTask = true;
return this;
}
TaskFragmentBuilder setParentTask(Task task) {
mParentTask = task;
return this;
}
/** Creates a child embedded Task and its Activity */
TaskFragmentBuilder createEmbeddedTask() {
mCreateEmbeddedTask = true;
return this;
}
TaskFragmentBuilder createActivityCount(int count) {
mCreateActivityCount = count;
return this;
}
TaskFragment build() {
SystemServicesTestRule.checkHoldsLock(mAtm.mGlobalLock);
final TaskFragment taskFragment = new TaskFragment(mAtm, null /* fragmentToken */,
false /* createdByOrganizer */);
if (mParentTask == null && mCreateParentTask) {
mParentTask = new TaskBuilder(mAtm.mTaskSupervisor).build();
}
if (mParentTask != null) {
mParentTask.addChild(taskFragment, POSITION_TOP);
}
if (mCreateEmbeddedTask) {
new TaskBuilder(mAtm.mTaskSupervisor)
.setParentTaskFragment(taskFragment)
.setCreateActivity(true)
.build();
}
while (mCreateActivityCount > 0) {
final ActivityRecord activity = new ActivityBuilder(mAtm).build();
taskFragment.addChild(activity);
mCreateActivityCount--;
}
return taskFragment;
}
}
/**
* Builder for creating new tasks.
*/
@@ -1121,7 +1200,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
private IVoiceInteractionSession mVoiceSession;
private boolean mCreateParentTask = false;
private Task mParentTask;
private TaskFragment mParentTaskFragment;
private boolean mCreateActivity = false;
@@ -1205,8 +1284,8 @@ class WindowTestsBase extends SystemServiceTestsBase {
return this;
}
TaskBuilder setParentTask(Task parentTask) {
mParentTask = parentTask;
TaskBuilder setParentTaskFragment(TaskFragment parentTaskFragment) {
mParentTaskFragment = parentTaskFragment;
return this;
}
@@ -1219,12 +1298,13 @@ class WindowTestsBase extends SystemServiceTestsBase {
SystemServicesTestRule.checkHoldsLock(mSupervisor.mService.mGlobalLock);
// Create parent task.
if (mParentTask == null && mCreateParentTask) {
mParentTask = mTaskDisplayArea.createRootTask(
if (mParentTaskFragment == null && mCreateParentTask) {
mParentTaskFragment = mTaskDisplayArea.createRootTask(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
}
if (mParentTask != null && !Mockito.mockingDetails(mParentTask).isSpy()) {
spyOn(mParentTask);
if (mParentTaskFragment != null
&& !Mockito.mockingDetails(mParentTaskFragment).isSpy()) {
spyOn(mParentTaskFragment);
}
// Create task.
@@ -1252,13 +1332,15 @@ class WindowTestsBase extends SystemServiceTestsBase {
.setOnTop(mOnTop)
.setVoiceSession(mVoiceSession);
final Task task;
if (mParentTask == null) {
if (mParentTaskFragment == null) {
task = builder.setActivityType(mActivityType)
.setParent(mTaskDisplayArea)
.build();
} else {
task = builder.setParent(mParentTask).build();
mParentTask.moveToFront("build-task");
task = builder.setParent(mParentTaskFragment).build();
if (mParentTaskFragment.asTask() != null) {
mParentTaskFragment.asTask().moveToFront("build-task");
}
}
spyOn(task);
task.mUserId = mUserId;