summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Charles Chen <charlesccchen@google.com> 2021-08-03 17:28:21 +0800
committer Charles Chen <charlesccchen@google.com> 2021-08-24 14:52:15 +0800
commit3f7830eaf15c56064c01deae5806a6ef9d5cb395 (patch)
tree30777b84f9427ca321904cf0f72a5dab1ec1c31e
parenta6a85a9be2fa34bf00dd5c2c275c273f79f4bbb7 (diff)
Introduce TaskFragment transition type
Previously AppTransitionController didn't recognize TaskFragment transitions, so it uses Task opening/closing animation for TaskFragment transitions. This CL introduces and uses TaskFragment transition if the animation target is TaskFragment. The new transition type can be used for registering RemoteAnimation implemented by TaskFragmentOrganizer as well. This CL also provides a fallback mechanism for TaskFragment transitions if the RemoteAnimation fails or one of opening/closing animation target is not a pure organized TaskFragment. Bug: 194649929 Test: manual - the reproducible step in b/194649929#comment1 Test: atest WmTests:AppTransitionTests AppTransitionControllerTest Change-Id: I0094694fa5cd95d8bbb7da94d2aaf7aac6e1fe09
-rw-r--r--core/java/android/view/WindowManager.java17
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java1
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java23
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java67
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java124
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java88
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java39
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java106
18 files changed, 445 insertions, 69 deletions
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 9b3550477aaa..329ea4a02145 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -320,6 +320,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
*/
@IntDef(prefix = { "TRANSIT_OLD_" }, value = {
@@ -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 {}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index f1644e9cfa5a..a4d2348d03f1 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -756,6 +756,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:
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 174b3965f11a..6aea848b12f7 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -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 + ">";
}
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index d6b0086d8dd9..eeadabde1476 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -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;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 9ca09d20cd49..b35f74876eeb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -218,7 +218,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());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 1b4d0a4ab5a4..3e8a2e9b7b17 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -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();
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 3a6aac9d03d5..11e3fd4e050a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -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,
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index c3279bf05737..67aac13e3734 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -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;
@@ -147,6 +150,91 @@ public class AppTransitionTests extends WindowTestsBase {
}
@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.
final DisplayContent dc1 = createNewDisplay(Display.STATE_ON);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 473d3038e3dc..14dc33e5840b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -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 -> {
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 7cb7c79d63a0..8a6db2c62a10 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -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);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index 1b078b7454b2..22e687a0bb15 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -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")
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
index 56d01cd34e01..030733bf4424 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
@@ -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(
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 8d4acbbac993..f2eb709b4bb8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -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(
diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
index c44c22fefd7a..cb858845e03e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
@@ -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)
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
index c45c18d16c38..d68edbafb592 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
@@ -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");
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 5e4c67ce9e5c..e528a4a23e45 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -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);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 807494429999..67e8c879a3e0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -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);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 050fd80411fc..e7ef6ae7cc0a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -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;