5/n Add support for multiple task display areas
Replaces the references to DisplayContent#mTaskContainers field with
iteration over all child task containers where necessary.
This does not change the behavior for the regular non-foldable
devices, since they would normally have only one task display area,
so iterating throught the list is logically equivalent to referencing
it directly.
Bug: 152116619
Test: WM CTS and unit tests
Change-Id: Ibc1b18ad4c06236e944abd49089672105506ec2c
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index c1c8440..a66741c 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -7411,7 +7411,17 @@
*/
boolean isResumedActivityOnDisplay() {
final DisplayContent display = getDisplay();
- return display != null && this == display.mTaskContainers.getResumedActivity();
+ if (display == null) {
+ return false;
+ }
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ final ActivityRecord resumedActivity = taskDisplayArea.getFocusedActivity();
+ if (resumedActivity != null) {
+ return resumedActivity == this;
+ }
+ }
+ return false;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index a446720..f5eba96 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -1119,8 +1119,8 @@
@Override
public boolean isAttached() {
- final DisplayContent display = getDisplay();
- return display != null && !display.isRemoved();
+ final TaskDisplayArea taskDisplayArea = getDisplayArea();
+ return taskDisplayArea != null && !taskDisplayArea.isRemoved();
}
// TODO: Should each user have there own stacks?
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 8af8624..02601ff 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -385,15 +385,15 @@
private final MoveTaskToFullscreenHelper mMoveTaskToFullscreenHelper =
new MoveTaskToFullscreenHelper();
private class MoveTaskToFullscreenHelper {
- private DisplayContent mToDisplay;
+ private TaskDisplayArea mToDisplayArea;
private boolean mOnTop;
private Task mTopTask;
private boolean mSchedulePictureInPictureModeChange;
- void process(ActivityStack fromStack, DisplayContent toDisplay, boolean onTop,
+ void process(ActivityStack fromStack, TaskDisplayArea toDisplayArea, boolean onTop,
boolean schedulePictureInPictureModeChange) {
mSchedulePictureInPictureModeChange = schedulePictureInPictureModeChange;
- mToDisplay = toDisplay;
+ mToDisplayArea = toDisplayArea;
mOnTop = onTop;
mTopTask = fromStack.getTopMostTask();
@@ -401,7 +401,7 @@
MoveTaskToFullscreenHelper::processLeafTask, this, PooledLambda.__(Task.class));
fromStack.forAllLeafTasks(c, false /* traverseTopToBottom */);
c.recycle();
- mToDisplay = null;
+ mToDisplayArea = null;
mTopTask = null;
}
@@ -411,19 +411,18 @@
task.getActivityType())) {
final ActivityStack stack = (ActivityStack) task;
stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- if (mToDisplay.getDisplayId() != stack.getDisplayId()) {
- stack.reparent(mToDisplay.getDefaultTaskDisplayArea(), mOnTop);
+ if (mToDisplayArea.getDisplayId() != stack.getDisplayId()) {
+ stack.reparent(mToDisplayArea, mOnTop);
} else if (mOnTop) {
- mToDisplay.mTaskContainers.positionStackAtTop(stack,
- false /* includingParents */);
+ mToDisplayArea.positionStackAtTop(stack, false /* includingParents */);
} else {
- mToDisplay.mTaskContainers.positionStackAtBottom(stack);
+ mToDisplayArea.positionStackAtBottom(stack);
}
return;
}
- final ActivityStack toStack = mToDisplay.mTaskContainers.getOrCreateStack(
- null, mTmpOptions, task, task.getActivityType(), mOnTop);
+ final ActivityStack toStack = mToDisplayArea.getOrCreateStack(null, mTmpOptions, task,
+ task.getActivityType(), mOnTop);
if (task == toStack) {
// The task was reused as the root task.
return;
@@ -1418,7 +1417,7 @@
mRootWindowContainer.getLaunchStack(null, options, task, ON_TOP);
if (stack != currentStack) {
- moveHomeStackToFrontIfNeeded(flags, stack.getDisplay(), reason);
+ moveHomeStackToFrontIfNeeded(flags, stack.getDisplayArea(), reason);
task.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE, DEFER_RESUME,
reason);
currentStack = stack;
@@ -1437,7 +1436,7 @@
}
if (!reparented) {
- moveHomeStackToFrontIfNeeded(flags, currentStack.getDisplay(), reason);
+ moveHomeStackToFrontIfNeeded(flags, currentStack.getDisplayArea(), reason);
}
final ActivityRecord r = task.getTopNonFinishingActivity();
@@ -1451,15 +1450,16 @@
currentStack, forceNonResizeable);
}
- private void moveHomeStackToFrontIfNeeded(int flags, DisplayContent display, String reason) {
- final ActivityStack focusedStack = display.getFocusedStack();
+ private void moveHomeStackToFrontIfNeeded(int flags, TaskDisplayArea taskDisplayArea,
+ String reason) {
+ final ActivityStack focusedStack = taskDisplayArea.getFocusedStack();
- if ((display.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
+ if ((taskDisplayArea.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
&& (flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0)
|| (focusedStack != null && focusedStack.isActivityTypeRecents())) {
- // We move home stack to front when we are on a fullscreen display and caller has
+ // We move home stack to front when we are on a fullscreen display area and caller has
// requested the home activity to move with it. Or the previous stack is recents.
- display.mTaskContainers.moveHomeStackToFront(reason);
+ taskDisplayArea.moveHomeStackToFront(reason);
}
}
@@ -1511,15 +1511,15 @@
mService.deferWindowLayout();
try {
final int windowingMode = fromStack.getWindowingMode();
- final DisplayContent toDisplay =
- mRootWindowContainer.getDisplayContent(toDisplayId);
+ final TaskDisplayArea toDisplayArea = mRootWindowContainer
+ .getDisplayContent(toDisplayId).getDefaultTaskDisplayArea();
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
// We are moving all tasks from the docked stack to the fullscreen stack,
// which is dismissing the docked stack, so resize all other stacks to
// fullscreen here already so we don't end up with resize trashing.
- for (int i = toDisplay.getStackCount() - 1; i >= 0; --i) {
- final ActivityStack otherStack = toDisplay.getStackAt(i);
+ for (int i = toDisplayArea.getStackCount() - 1; i >= 0; --i) {
+ final ActivityStack otherStack = toDisplayArea.getStackAt(i);
if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
continue;
}
@@ -1535,7 +1535,7 @@
if (fromStack.hasChild()) {
mTmpOptions.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
mMoveTaskToFullscreenHelper.process(
- fromStack, toDisplay, onTop, schedulePictureInPictureModeChange);
+ fromStack, toDisplayArea, onTop, schedulePictureInPictureModeChange);
}
mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
@@ -1546,6 +1546,7 @@
}
void moveTasksToFullscreenStackLocked(ActivityStack fromStack, boolean onTop) {
+ // TODO(b/153089193): Support moving within the same task display area
mWindowManager.inSurfaceTransaction(() ->
moveTasksToFullscreenStackInSurfaceTransaction(fromStack, DEFAULT_DISPLAY, onTop));
}
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 0a0049d..d777f3f 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -189,9 +189,10 @@
mSupervisor.beginDeferResume();
final ActivityStack homeStack;
try {
+ // TODO(multi-display-area): Support starting home in a task display area
// Make sure home stack exist on display.
- homeStack = display.mTaskContainers.getOrCreateStack(WINDOWING_MODE_FULLSCREEN,
- ACTIVITY_TYPE_HOME, ON_TOP);
+ homeStack = display.getDefaultTaskDisplayArea().getOrCreateStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
} finally {
mSupervisor.endDeferResume();
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 85517a4..7931cd5 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2060,20 +2060,53 @@
* activity type. Null is no compatible stack on the display.
*/
ActivityStack getStack(int windowingMode, int activityType) {
- return mTaskContainers.getStack(windowingMode, activityType);
+ for (int tdaNdx = getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final ActivityStack stack = getTaskDisplayAreaAt(tdaNdx)
+ .getStack(windowingMode, activityType);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
+ protected int getTaskDisplayAreaCount() {
+ // TODO(multi-display-area): Report actual display area count
+ return 1;
+ }
+
+ protected TaskDisplayArea getTaskDisplayAreaAt(int index) {
+ // TODO(multi-display-area): Report actual display area values
+ return mTaskContainers;
+ }
+
+ ActivityStack getStack(int rootTaskId) {
+ for (int tdaNdx = getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final ActivityStack stack = getTaskDisplayAreaAt(tdaNdx).getStack(rootTaskId);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
}
protected int getStackCount() {
- return mTaskContainers.mChildren.size();
- }
-
- protected ActivityStack getStackAt(int index) {
- return mTaskContainers.mChildren.get(index);
+ int totalStackCount = 0;
+ for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+ totalStackCount += getTaskDisplayAreaAt(i).getStackCount();
+ }
+ return totalStackCount;
}
@VisibleForTesting
ActivityStack getTopStack() {
- return mTaskContainers.getTopStack();
+ for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getTaskDisplayAreaAt(i).getTopStack();
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
}
/**
@@ -2449,7 +2482,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(
DisplayContent::processTaskForTouchExcludeRegion, this,
PooledLambda.__(Task.class), focusedTask, delta);
- mTaskContainers.forAllTasks(c);
+ forAllTasks(c);
c.recycle();
// If we removed the focused task above, add it back and only leave its
@@ -2630,9 +2663,8 @@
}
void prepareFreezingTaskBounds() {
- for (int stackNdx = mTaskContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mTaskContainers.getChildAt(stackNdx);
- stack.prepareFreezingTaskBounds();
+ for (int tdaNdx = getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ getTaskDisplayAreaAt(tdaNdx).prepareFreezingTaskBounds();
}
}
@@ -2738,8 +2770,8 @@
final ActivityStack focusedStack = getFocusedStack();
if (focusedStack != null) {
proto.write(FOCUSED_ROOT_TASK_ID, focusedStack.getRootTaskId());
- final ActivityRecord focusedActivity = focusedStack.getDisplay().mTaskContainers
- .getResumedActivity();
+ final ActivityRecord focusedActivity = focusedStack.getDisplayArea()
+ .getFocusedActivity();
if (focusedActivity != null) {
focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
}
@@ -2797,13 +2829,6 @@
if (mLastFocus != mCurrentFocus) {
pw.print(" mLastFocus="); pw.println(mLastFocus);
}
- if (mTaskContainers.mPreferredTopFocusableStack != null) {
- pw.println(prefix + "mPreferredTopFocusableStack="
- + mTaskContainers.mPreferredTopFocusableStack);
- }
- if (mTaskContainers.mLastFocusedStack != null) {
- pw.println(prefix + "mLastFocusedStack=" + mTaskContainers.mLastFocusedStack);
- }
if (mLosingFocus.size() > 0) {
pw.println();
pw.println(" Windows losing focus:");
@@ -2837,10 +2862,9 @@
}
pw.println();
- pw.println(prefix + "Application tokens in top down Z order:");
- for (int stackNdx = mTaskContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mTaskContainers.getChildAt(stackNdx);
- stack.dump(pw, prefix + " ", dumpAll);
+ pw.println(prefix + "Task display areas in top down Z order:");
+ for (int tdaNdx = getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ getTaskDisplayAreaAt(tdaNdx).dump(pw, prefix + " ", dumpAll);
}
pw.println();
@@ -4002,7 +4026,9 @@
}
// Initialize state of exiting applications.
- mTaskContainers.setExitingTokensHasVisible(hasVisible);
+ for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+ getTaskDisplayAreaAt(i).setExitingTokensHasVisible(hasVisible);
+ }
}
void removeExistingTokensIfPossible() {
@@ -4014,7 +4040,9 @@
}
// Time to remove any exiting applications?
- mTaskContainers.removeExistingAppTokensIfPossible();
+ for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+ getTaskDisplayAreaAt(i).removeExistingAppTokensIfPossible();
+ }
}
@Override
@@ -4475,7 +4503,9 @@
}
void assignStackOrdering() {
- mTaskContainers.assignStackOrdering(getPendingTransaction());
+ for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+ getTaskDisplayAreaAt(i).assignStackOrdering(getPendingTransaction());
+ }
}
/**
@@ -5002,13 +5032,15 @@
|| windowingMode == WINDOWING_MODE_MULTI_WINDOW);
}
- ActivityStack createStack(int windowingMode, int activityType, boolean onTop) {
- return mTaskContainers.createStack(windowingMode, activityType, onTop, null /* info */,
- null /* intent */, false /* createdByOrganizer */);
- }
-
+ @Nullable
ActivityStack getFocusedStack() {
- return mTaskContainers.getFocusedStack();
+ for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getTaskDisplayAreaAt(i).getFocusedStack();
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
}
/**
@@ -5016,11 +5048,15 @@
* ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
*/
void removeStacksInWindowingModes(int... windowingModes) {
- mTaskContainers.removeStacksInWindowingModes(windowingModes);
+ for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+ getTaskDisplayAreaAt(i).removeStacksInWindowingModes(windowingModes);
+ }
}
void removeStacksWithActivityTypes(int... activityTypes) {
- mTaskContainers.removeStacksWithActivityTypes(activityTypes);
+ for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+ getTaskDisplayAreaAt(i).removeStacksWithActivityTypes(activityTypes);
+ }
}
ActivityRecord topRunningActivity() {
@@ -5037,7 +5073,14 @@
* @return The top running activity. {@code null} if none is available.
*/
ActivityRecord topRunningActivity(boolean considerKeyguardState) {
- return mTaskContainers.topRunningActivity(considerKeyguardState);
+ for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+ final ActivityRecord activity = getTaskDisplayAreaAt(i)
+ .topRunningActivity(considerKeyguardState);
+ if (activity != null) {
+ return activity;
+ }
+ }
+ return null;
}
boolean updateDisplayOverrideConfigurationLocked() {
@@ -5149,7 +5192,7 @@
// The display may be about to rotate seamlessly, and the animation of closing apps may
// still animate in old rotation. So make sure the outdated animation won't show on the
// rotated display.
- mTaskContainers.forAllActivities(a -> {
+ forAllActivities(a -> {
if (a.nowVisible && a != mFixedRotationLaunchingApp
&& a.getWindowConfiguration().getRotation() != newRotation) {
final WindowContainer<?> w = a.getAnimatingContainer();
@@ -5210,40 +5253,17 @@
void remove() {
mRemoving = true;
- final boolean destroyContentOnRemoval = shouldDestroyContentOnRemove();
ActivityStack lastReparentedStack = null;
- mTaskContainers.mPreferredTopFocusableStack = null;
- // Stacks could be reparented from the removed display to other display. While
- // reparenting the last stack of the removed display, the remove display is ready to be
- // released (no more ActivityStack). But, we cannot release it at that moment or the
- // related WindowContainer will also be removed. So, we set display as removed after
- // reparenting stack finished.
- final TaskDisplayArea toTaskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
mRootWindowContainer.mStackSupervisor.beginDeferResume();
try {
- int numStacks = getStackCount();
- // Keep the order from bottom to top.
- for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
- final ActivityStack stack = getStackAt(stackNdx);
- // Always finish non-standard type stacks.
- if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
- stack.finishAllActivitiesImmediately();
- } else {
- // If default display is in split-window mode, set windowing mode of the stack
- // to split-screen secondary. Otherwise, set the windowing mode to undefined by
- // default to let stack inherited the windowing mode from the new display.
- final int windowingMode = toTaskDisplayArea.isSplitScreenModeActivated()
- ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
- : WINDOWING_MODE_UNDEFINED;
- stack.reparent(toTaskDisplayArea, true /* onTop */);
- stack.setWindowingMode(windowingMode);
- lastReparentedStack = stack;
+ int numTaskContainers = getTaskDisplayAreaCount();
+ for (int tdaNdx = 0; tdaNdx < numTaskContainers; tdaNdx++) {
+ final ActivityStack lastReparentedStackFromArea = getTaskDisplayAreaAt(tdaNdx)
+ .remove();
+ if (lastReparentedStackFromArea != null) {
+ lastReparentedStack = lastReparentedStackFromArea;
}
- // Stacks may be removed from this display. Ensure each stack will be processed and
- // the loop will end.
- stackNdx -= numStacks - getStackCount();
- numStacks = getStackCount();
}
} finally {
mRootWindowContainer.mStackSupervisor.endDeferResume();
@@ -5270,12 +5290,27 @@
return;
}
- final ActivityStack stack = getStackCount() == 1 ? getStackAt(0) : null;
- if (stack != null && stack.isActivityTypeHome() && !stack.hasChild()) {
- // Release this display if an empty home stack is the only thing left.
- // Since it is the last stack, this display will be released along with the stack
- // removal.
- stack.removeIfPossible();
+ // Check if all task display areas have only the empty home stacks left.
+ boolean onlyEmptyHomeStacksLeft = true;
+ for (int tdaNdx = getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = getTaskDisplayAreaAt(tdaNdx);
+ if (taskDisplayArea.getStackCount() != 1) {
+ onlyEmptyHomeStacksLeft = false;
+ break;
+ }
+ final ActivityStack stack = taskDisplayArea.getStackAt(0);
+ if (!stack.isActivityTypeHome() || stack.hasChild()) {
+ onlyEmptyHomeStacksLeft = false;
+ break;
+ }
+ }
+ if (onlyEmptyHomeStacksLeft) {
+ // Release this display if only empty home stack(s) are left. This display will be
+ // released along with the stack(s) removal.
+ for (int tdaNdx = getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final ActivityStack s = getTaskDisplayAreaAt(tdaNdx).getStackAt(0);
+ s.removeIfPossible();
+ }
} else if (getTopStack() == null) {
removeIfPossible();
mRootWindowContainer.mStackSupervisor
@@ -5334,10 +5369,9 @@
void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients) {
- for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = getStackAt(stackNdx);
- stack.ensureActivitiesVisible(starting, configChanges, preserveWindows,
- notifyClients);
+ for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+ getTaskDisplayAreaAt(i).ensureActivitiesVisible(starting, configChanges,
+ preserveWindows, notifyClients);
}
}
@@ -5350,13 +5384,18 @@
}
void setDisplayToSingleTaskInstance() {
- final int childCount = getStackCount();
- if (childCount > 1) {
+ final int taskDisplayAreaCount = getTaskDisplayAreaCount();
+ if (taskDisplayAreaCount > 1) {
+ throw new IllegalArgumentException(
+ "Display already has multiple task display areas. display=" + this);
+ }
+ final int stackCount = getDefaultTaskDisplayArea().getStackCount();
+ if (stackCount > 1) {
throw new IllegalArgumentException("Display already has multiple stacks. display="
+ this);
}
- if (childCount > 0) {
- final ActivityStack stack = getStackAt(0);
+ if (stackCount > 0) {
+ final ActivityStack stack = getDefaultTaskDisplayArea().getStackAt(0);
if (stack.getChildCount() > 1) {
throw new IllegalArgumentException("Display stack already has multiple tasks."
+ " display=" + this + " stack=" + stack);
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 264da9f..caaa173 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -3247,7 +3247,7 @@
final int dockedAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
final boolean inSplitScreen =
- mService.mRoot.getDefaultDisplay().mTaskContainers.isSplitScreenModeActivated();
+ mService.mRoot.getDefaultTaskDisplayArea().isSplitScreenModeActivated();
if (inSplitScreen) {
mService.getStackBounds(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
mDockedStackBounds);
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 57a54d0..f672394 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -529,11 +529,14 @@
* occlusion state.
*/
private ActivityStack getStackForControllingOccluding(DisplayContent display) {
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- if (stack != null && stack.isFocusableAndVisible()
- && !stack.inPinnedWindowingMode()) {
- return stack;
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ if (stack != null && stack.isFocusableAndVisible()
+ && !stack.inPinnedWindowingMode()) {
+ return stack;
+ }
}
}
return null;
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 84229f0..6fda117 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -340,7 +340,7 @@
// Make leashes for each of the visible/target tasks and add it to the recents animation to
// be started
- // TODO(multi-display-area): Support Recents on multiple task display areas
+ // TODO(b/153090560): Support Recents on multiple task display areas
final ArrayList<Task> visibleTasks = mDisplayContent.getDefaultTaskDisplayArea()
.getVisibleTasks();
final ActivityStack targetStack = mDisplayContent.getDefaultTaskDisplayArea()
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 2eeda4d..e1ef76f 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1643,7 +1643,9 @@
displayId = DEFAULT_DISPLAY;
}
- final ActivityRecord r = getDisplayContent(displayId).mTaskContainers.getHomeActivity();
+ // TODO(multi-display-area): Resume home on the right task container
+ final ActivityRecord r = getDisplayContent(displayId).getDefaultTaskDisplayArea()
+ .getHomeActivity();
final String myReason = reason + " resumeHomeActivity";
// Only resume home activity if isn't finishing.
@@ -1800,19 +1802,23 @@
final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
final ActivityStack topFocusedStack = getTopDisplayFocusedStack();
// Traverse all displays.
- for (int i = getChildCount() - 1; i >= 0; i--) {
- final DisplayContent display = getChildAt(i);
- // Traverse all stacks on a display.
- for (int j = display.getStackCount() - 1; j >= 0; --j) {
- final ActivityStack stack = display.getStackAt(j);
- // Get top activity from a visible stack and add it to the list.
- if (stack.shouldBeVisible(null /* starting */)) {
- final ActivityRecord top = stack.getTopNonFinishingActivity();
- if (top != null) {
- if (stack == topFocusedStack) {
- topActivityTokens.add(0, top.appToken);
- } else {
- topActivityTokens.add(top.appToken);
+ for (int dNdx = getChildCount() - 1; dNdx >= 0; dNdx--) {
+ final DisplayContent display = getChildAt(dNdx);
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea =
+ display.getTaskDisplayAreaAt(tdaNdx);
+ // Traverse all stacks on a display area.
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ // Get top activity from a visible stack and add it to the list.
+ if (stack.shouldBeVisible(null /* starting */)) {
+ final ActivityRecord top = stack.getTopNonFinishingActivity();
+ if (top != null) {
+ if (stack == topFocusedStack) {
+ topActivityTokens.add(0, top.appToken);
+ } else {
+ topActivityTokens.add(top.appToken);
+ }
}
}
}
@@ -1844,10 +1850,13 @@
// focus order.
for (int i = getChildCount() - 1; i >= 0; --i) {
final DisplayContent display = getChildAt(i);
- final ActivityRecord resumedActivityOnDisplay = display.mTaskContainers
- .getResumedActivity();
- if (resumedActivityOnDisplay != null) {
- return resumedActivityOnDisplay;
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ final ActivityRecord resumedActivityOnTaskContainer = taskDisplayArea
+ .getFocusedActivity();
+ if (resumedActivityOnTaskContainer != null) {
+ return resumedActivityOnTaskContainer;
+ }
}
}
return null;
@@ -1867,16 +1876,19 @@
WindowProcessController fgApp = null;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- if (isTopDisplayFocusedStack(stack)) {
- final ActivityRecord resumedActivity = stack.getResumedActivity();
- if (resumedActivity != null) {
- fgApp = resumedActivity.app;
- } else if (stack.mPausingActivity != null) {
- fgApp = stack.mPausingActivity.app;
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ if (isTopDisplayFocusedStack(stack)) {
+ final ActivityRecord resumedActivity = stack.getResumedActivity();
+ if (resumedActivity != null) {
+ fgApp = resumedActivity.app;
+ } else if (stack.mPausingActivity != null) {
+ fgApp = stack.mPausingActivity.app;
+ }
+ break;
}
- break;
}
}
}
@@ -1992,9 +2004,12 @@
mStackSupervisor.mStartingUsers.add(uss);
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- stack.switchUser(userId);
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ stack.switchUser(userId);
+ }
}
}
@@ -2196,13 +2211,17 @@
ActivityStack focusedStack = getTopDisplayFocusedStack();
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- // It is possible that request to finish activity might also remove its task and stack,
- // so we need to be careful with indexes in the loop and check child count every time.
- for (int stackNdx = 0; stackNdx < display.getStackCount(); ++stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- final Task t = stack.finishTopCrashedActivityLocked(app, reason);
- if (stack == focusedStack || finishedTask == null) {
- finishedTask = t;
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ // It is possible that request to finish activity might also remove its task and
+ // stack, so we need to be careful with indexes in the loop and check child count
+ // every time.
+ for (int stackNdx = 0; stackNdx < display.getStackCount(); ++stackNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(stackNdx);
+ final Task t = stack.finishTopCrashedActivityLocked(app, reason);
+ if (stack == focusedStack || finishedTask == null) {
+ finishedTask = t;
+ }
}
}
}
@@ -2229,26 +2248,29 @@
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
boolean resumedOnDisplay = false;
final DisplayContent display = getChildAt(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- final ActivityRecord topRunningActivity = stack.topRunningActivity();
- if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
- continue;
- }
- if (stack == targetStack) {
- // Simply update the result for targetStack because the targetStack had
- // already resumed in above. We don't want to resume it again, especially in
- // some cases, it would cause a second launch failure if app process was dead.
- resumedOnDisplay |= result;
- continue;
- }
- if (display.mTaskContainers.isTopStack(stack)
- && topRunningActivity.isState(RESUMED)) {
- // Kick off any lingering app transitions form the MoveTaskToFront operation,
- // but only consider the top task and stack on that display.
- stack.executeAppTransition(targetOptions);
- } else {
- resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ final ActivityRecord topRunningActivity = stack.topRunningActivity();
+ if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
+ continue;
+ }
+ if (stack == targetStack) {
+ // Simply update the result for targetStack because the targetStack had
+ // already resumed in above. We don't want to resume it again, especially in
+ // some cases, it would cause a second launch failure if app process was
+ // dead.
+ resumedOnDisplay |= result;
+ continue;
+ }
+ if (taskDisplayArea.isTopStack(stack) && topRunningActivity.isState(RESUMED)) {
+ // Kick off any lingering app transitions form the MoveTaskToFront
+ // operation, but only consider the top task and stack on that display.
+ stack.executeAppTransition(targetOptions);
+ } else {
+ resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);
+ }
}
}
if (!resumedOnDisplay) {
@@ -2284,32 +2306,37 @@
}
// Set the sleeping state of the stacks on the display.
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- if (displayShouldSleep) {
- stack.goToSleepIfPossible(false /* shuttingDown */);
- } else {
- // When the display which can only contain one task turns on, start a special
- // transition. {@link AppTransitionController#handleAppTransitionReady} later
- // picks up the transition, and schedules
- // {@link ITaskStackListener#onSingleTaskDisplayDrawn} callback which is
- // triggered after contents are drawn on the display.
- if (display.isSingleTaskInstance()) {
- display.mDisplayContent.prepareAppTransition(
- TRANSIT_SHOW_SINGLE_TASK_DISPLAY, false);
- }
- stack.awakeFromSleepingLocked();
- if (display.isSingleTaskInstance()) {
- display.executeAppTransition();
- }
- if (stack.isFocusedStackOnDisplay()
- && !mStackSupervisor.getKeyguardController()
- .isKeyguardOrAodShowing(display.mDisplayId)) {
- // If the keyguard is unlocked - resume immediately.
- // It is possible that the display will not be awake at the time we
- // process the keyguard going away, which can happen before the sleep token
- // is released. As a result, it is important we resume the activity here.
- resumeFocusedStacksTopActivities();
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ if (displayShouldSleep) {
+ stack.goToSleepIfPossible(false /* shuttingDown */);
+ } else {
+ // When the display which can only contain one task turns on, start a
+ // special transition.
+ // {@link AppTransitionController#handleAppTransitionReady} later picks up
+ // the transition, and schedules
+ // {@link ITaskStackListener#onSingleTaskDisplayDrawn} callback which is
+ // triggered after contents are drawn on the display.
+ if (display.isSingleTaskInstance()) {
+ display.mDisplayContent.prepareAppTransition(
+ TRANSIT_SHOW_SINGLE_TASK_DISPLAY, false);
+ }
+ stack.awakeFromSleepingLocked();
+ if (display.isSingleTaskInstance()) {
+ display.executeAppTransition();
+ }
+ if (stack.isFocusedStackOnDisplay()
+ && !mStackSupervisor.getKeyguardController()
+ .isKeyguardOrAodShowing(display.mDisplayId)) {
+ // If the keyguard is unlocked - resume immediately.
+ // It is possible that the display will not be awake at the time we
+ // process the keyguard going away, which can happen before the sleep
+ // token is released. As a result, it is important we resume the
+ // activity here.
+ resumeFocusedStacksTopActivities();
+ }
}
}
}
@@ -2318,7 +2345,7 @@
protected ActivityStack getStack(int stackId) {
for (int i = getChildCount() - 1; i >= 0; --i) {
- final ActivityStack stack = getChildAt(i).mTaskContainers.getStack(stackId);
+ final ActivityStack stack = getChildAt(i).getStack(stackId);
if (stack != null) {
return stack;
}
@@ -2414,9 +2441,12 @@
if (displayId == INVALID_DISPLAY) {
for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- list.add(getStackInfo(stack));
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ list.add(getStackInfo(stack));
+ }
}
}
return list;
@@ -2425,9 +2455,12 @@
if (display == null) {
return list;
}
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- list.add(getStackInfo(stack));
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ list.add(getStackInfo(stack));
+ }
}
return list;
}
@@ -2646,19 +2679,21 @@
boolean allSleep = true;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- // Stacks and activities could be removed while putting activities to sleep if
- // the app process was gone. This prevents us getting exception by accessing an
- // invalid stack index.
- if (stackNdx >= display.getStackCount()) {
- continue;
- }
-
- final ActivityStack stack = display.getStackAt(stackNdx);
- if (allowDelay) {
- allSleep &= stack.goToSleepIfPossible(shuttingDown);
- } else {
- stack.goToSleep();
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ // Stacks and activities could be removed while putting activities to sleep if
+ // the app process was gone. This prevents us getting exception by accessing an
+ // invalid stack index.
+ if (sNdx >= taskDisplayArea.getStackCount()) {
+ continue;
+ }
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ if (allowDelay) {
+ allSleep &= stack.goToSleepIfPossible(shuttingDown);
+ } else {
+ stack.goToSleep();
+ }
}
}
}
@@ -2910,14 +2945,17 @@
windowingMode = options != null ? options.getLaunchWindowingMode()
: r.getWindowingMode();
}
- windowingMode = displayContent.mTaskContainers.validateWindowingMode(windowingMode, r,
- candidateTask, r.getActivityType());
// Return the topmost valid stack on the display.
- for (int i = displayContent.getStackCount() - 1; i >= 0; --i) {
- final ActivityStack stack = displayContent.getStackAt(i);
- if (isValidLaunchStack(stack, r, windowingMode)) {
- return stack;
+ for (int tdaNdx = displayContent.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = displayContent.getTaskDisplayAreaAt(tdaNdx);
+ final int validatedWindowingMode = taskDisplayArea
+ .validateWindowingMode(windowingMode, r, candidateTask, r.getActivityType());
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ if (isValidLaunchStack(stack, r, validatedWindowingMode)) {
+ return stack;
+ }
}
}
@@ -3034,9 +3072,12 @@
boolean hasVisibleActivities = false;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- hasVisibleActivities |= stack.handleAppDied(app);
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ hasVisibleActivities |= stack.handleAppDied(app);
+ }
}
}
return hasVisibleActivities;
@@ -3147,10 +3188,14 @@
void finishVoiceTask(IVoiceInteractionSession session) {
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- final int numStacks = display.getStackCount();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- stack.finishVoiceTask(session);
+ int numTaskContainers = display.getTaskDisplayAreaCount();
+ for (int tdaNdx = 0; tdaNdx < numTaskContainers; tdaNdx++) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ final int numStacks = display.getStackCount();
+ for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(stackNdx);
+ stack.finishVoiceTask(session);
+ }
}
}
}
@@ -3214,14 +3259,17 @@
boolean foundResumed = false;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- final ActivityRecord r = stack.getResumedActivity();
- if (r != null) {
- if (!r.nowVisible) {
- return false;
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ final ActivityRecord r = stack.getResumedActivity();
+ if (r != null) {
+ if (!r.nowVisible) {
+ return false;
+ }
+ foundResumed = true;
}
- foundResumed = true;
}
}
}
@@ -3232,16 +3280,19 @@
boolean pausing = true;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- final ActivityRecord r = stack.mPausingActivity;
- if (r != null && !r.isState(PAUSED, STOPPED, STOPPING)) {
- if (DEBUG_STATES) {
- Slog.d(TAG_STATES,
- "allPausedActivitiesComplete: r=" + r + " state=" + r.getState());
- pausing = false;
- } else {
- return false;
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ final ActivityRecord r = stack.mPausingActivity;
+ if (r != null && !r.isState(PAUSED, STOPPED, STOPPING)) {
+ if (DEBUG_STATES) {
+ Slog.d(TAG_STATES, "allPausedActivitiesComplete: r=" + r
+ + " state=" + r.getState());
+ pausing = false;
+ } else {
+ return false;
+ }
}
}
}
@@ -3297,9 +3348,11 @@
void cancelInitializingActivities() {
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- stack.cancelInitializingActivities();
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ taskDisplayArea.getStackAt(sNdx).cancelInitializingActivities();
+ }
}
}
}
@@ -3402,20 +3455,23 @@
}
if (!sendHint) { // targetActivity != null
- // Send power hint when the activity's process is different than the current resumed
- // activity on all displays, or if there are no resumed activities in the system.
+ // Send power hint when the activity's process is different than the current top resumed
+ // activity on all display areas, or if there are no resumed activities in the system.
boolean noResumedActivities = true;
boolean allFocusedProcessesDiffer = true;
for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
- final DisplayContent displayContent = getChildAt(displayNdx);
- final ActivityRecord resumedActivity = displayContent.mTaskContainers
- .getResumedActivity();
- final WindowProcessController resumedActivityProcess =
- resumedActivity == null ? null : resumedActivity.app;
+ final DisplayContent dc = getChildAt(displayNdx);
+ for (int tdaNdx = dc.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = dc.getTaskDisplayAreaAt(tdaNdx);
+ final ActivityRecord resumedActivity = taskDisplayArea.getFocusedActivity();
+ final WindowProcessController resumedActivityProcess =
+ resumedActivity == null ? null : resumedActivity.app;
- noResumedActivities &= resumedActivityProcess == null;
- if (resumedActivityProcess != null) {
- allFocusedProcessesDiffer &= !resumedActivityProcess.equals(targetActivity.app);
+ noResumedActivities &= resumedActivityProcess == null;
+ if (resumedActivityProcess != null) {
+ allFocusedProcessesDiffer &= !resumedActivityProcess.equals(
+ targetActivity.app);
+ }
}
}
sendHint = noResumedActivities || allFocusedProcessesDiffer;
@@ -3462,10 +3518,13 @@
int numDisplays = getChildCount();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
- activities.addAll(stack.getDumpActivitiesLocked(name));
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
+ activities.addAll(stack.getDumpActivitiesLocked(name));
+ }
}
}
}
@@ -3505,14 +3564,21 @@
DisplayContent displayContent = getChildAt(displayNdx);
pw.print("Display #"); pw.print(displayContent.mDisplayId);
pw.println(" (activities from top to bottom):");
- for (int stackNdx = displayContent.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = displayContent.getStackAt(stackNdx);
- pw.println();
- printed = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
- needSep = printed;
+ for (int tdaNdx = displayContent.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = displayContent.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ pw.println();
+ printed = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
+ needSep = printed;
+ }
}
- printThisActivity(pw, displayContent.mTaskContainers.getResumedActivity(), dumpPackage,
- needSep, " ResumedActivity:");
+ pw.println(" (resumed activities in task display areas from top to bottom):");
+ for (int tdaNdx = displayContent.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = displayContent.getTaskDisplayAreaAt(tdaNdx);
+ printThisActivity(pw, taskDisplayArea.getFocusedActivity(), dumpPackage, needSep,
+ " ResumedActivity:");
+ }
}
printed |= dumpHistoryList(fd, pw, mStackSupervisor.mFinishingActivities, " ",
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 13e4d8b..8e45dc3 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -63,6 +63,7 @@
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.protolog.common.ProtoLog;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -134,6 +135,12 @@
*/
private ArrayList<OnStackOrderChangedListener> mStackOrderChangedCallbacks = new ArrayList<>();
+ /**
+ * The task display area is removed from the system and we are just waiting for all activities
+ * on it to be finished before removing this object.
+ */
+ private boolean mRemoved;
+
TaskDisplayArea(DisplayContent displayContent, WindowManagerService service) {
super(service, Type.ANY, "TaskContainers", FEATURE_TASK_CONTAINER);
mDisplayContent = displayContent;
@@ -986,7 +993,7 @@
return candidate;
}
- ActivityRecord getResumedActivity() {
+ ActivityRecord getFocusedActivity() {
final ActivityStack focusedStack = getFocusedStack();
if (focusedStack == null) {
return null;
@@ -1572,7 +1579,7 @@
}
boolean isRemoved() {
- return mDisplayContent.isRemoved();
+ return mRemoved;
}
/**
@@ -1609,4 +1616,82 @@
interface OnStackOrderChangedListener {
void onStackOrderChanged(ActivityStack stack);
}
+
+ void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
+ boolean preserveWindows, boolean notifyClients) {
+ for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = getStackAt(stackNdx);
+ stack.ensureActivitiesVisible(starting, configChanges, preserveWindows,
+ notifyClients);
+ }
+ }
+
+ void prepareFreezingTaskBounds() {
+ for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = getChildAt(stackNdx);
+ stack.prepareFreezingTaskBounds();
+ }
+ }
+
+ /**
+ * Removes the stacks in the node applying the content removal node from the display.
+ * @return last reparented stack, or {@code null} if the stacks had to be destroyed.
+ */
+ ActivityStack remove() {
+ mPreferredTopFocusableStack = null;
+ // TODO(b/153090332): Allow setting content removal mode per task display area
+ final boolean destroyContentOnRemoval = mDisplayContent.shouldDestroyContentOnRemove();
+ final TaskDisplayArea toDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+ ActivityStack lastReparentedStack = null;
+
+ // Stacks could be reparented from the removed display area to other display area. After
+ // reparenting the last stack of the removed display area, the display area becomes ready to
+ // be released (no more ActivityStack-s). But, we cannot release it at that moment or the
+ // related WindowContainer will also be removed. So, we set display area as removed after
+ // reparenting stack finished.
+ // Keep the order from bottom to top.
+ int numStacks = getStackCount();
+ for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
+ final ActivityStack stack = getStackAt(stackNdx);
+ // Always finish non-standard type stacks.
+ if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
+ stack.finishAllActivitiesImmediately();
+ } else {
+ // If default display is in split-window mode, set windowing mode of the
+ // stack to split-screen secondary. Otherwise, set the windowing mode to
+ // undefined by default to let stack inherited the windowing mode from the
+ // new display.
+ final int windowingMode = toDisplayArea.isSplitScreenModeActivated()
+ ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+ : WINDOWING_MODE_UNDEFINED;
+ stack.reparent(toDisplayArea, true /* onTop */);
+ stack.setWindowingMode(windowingMode);
+ lastReparentedStack = stack;
+ }
+ // Stacks may be removed from this display. Ensure each stack will be processed
+ // and the loop will end.
+ stackNdx -= numStacks - getStackCount();
+ numStacks = getStackCount();
+ }
+ mRemoved = true;
+
+ return lastReparentedStack;
+ }
+
+
+ @Override
+ void dump(PrintWriter pw, String prefix, boolean dumpAll) {
+ pw.println(prefix + "TaskDisplayArea " + getName());
+ if (mPreferredTopFocusableStack != null) {
+ pw.println(prefix + " mPreferredTopFocusableStack=" + mPreferredTopFocusableStack);
+ }
+ if (mLastFocusedStack != null) {
+ pw.println(prefix + " mLastFocusedStack=" + mLastFocusedStack);
+ }
+ pw.println(prefix + " Application tokens in top down Z order:");
+ for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = getChildAt(stackNdx);
+ stack.dump(pw, prefix + " ", dumpAll);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index e6757e1..da4401a 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -705,14 +705,19 @@
private void adjustBoundsToAvoidConflictInDisplay(@NonNull DisplayContent display,
@NonNull Rect inOutBounds) {
final List<Rect> taskBoundsToCheck = new ArrayList<>();
- for (int i = 0; i < display.getStackCount(); ++i) {
- final ActivityStack stack = display.getStackAt(i);
- if (!stack.inFreeformWindowingMode()) {
- continue;
- }
+ int numTaskContainers = display.getTaskDisplayAreaCount();
+ for (int tdaNdx = 0; tdaNdx < numTaskContainers; tdaNdx++) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ int numStacks = taskDisplayArea.getStackCount();
+ for (int sNdx = 0; sNdx < numStacks; ++sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ if (!stack.inFreeformWindowingMode()) {
+ continue;
+ }
- for (int j = 0; j < stack.getChildCount(); ++j) {
- taskBoundsToCheck.add(stack.getChildAt(j).getBounds());
+ for (int j = 0; j < stack.getChildCount(); ++j) {
+ taskBoundsToCheck.add(stack.getChildAt(j).getBounds());
+ }
}
}
adjustBoundsToAvoidConflict(display.getBounds(), taskBoundsToCheck, inOutBounds);
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 9ffd8d2..2bbf8db 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -395,26 +395,27 @@
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- TaskDisplayArea taskDisplayArea =
- mService.mRootWindowContainer.getDisplayContent(displayId).mTaskContainers;
- if (taskDisplayArea == null) {
+ TaskDisplayArea defaultTaskDisplayArea = mService.mRootWindowContainer
+ .getDisplayContent(displayId).getDefaultTaskDisplayArea();
+ if (defaultTaskDisplayArea == null) {
return;
}
Task task = token == null
? null : WindowContainer.fromBinder(token.asBinder()).asTask();
if (task == null) {
- taskDisplayArea.mLaunchRootTask = null;
+ defaultTaskDisplayArea.mLaunchRootTask = null;
return;
}
if (!task.mCreatedByOrganizer) {
throw new IllegalArgumentException("Attempt to set task not created by "
+ "organizer as launch root task=" + task);
}
- if (task.getDisplayArea() != taskDisplayArea) {
+ if (task.getDisplayArea() == null
+ || task.getDisplayArea().getDisplayId() != displayId) {
throw new RuntimeException("Can't set launch root for display " + displayId
+ " to task on display " + task.getDisplayContent().getDisplayId());
}
- taskDisplayArea.mLaunchRootTask = task;
+ task.getDisplayArea().mLaunchRootTask = task;
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -475,13 +476,16 @@
throw new IllegalArgumentException("Display " + displayId + " doesn't exist");
}
ArrayList<RunningTaskInfo> out = new ArrayList<>();
- for (int i = dc.getStackCount() - 1; i >= 0; --i) {
- final Task task = dc.getStackAt(i);
- if (activityTypes != null
- && !ArrayUtils.contains(activityTypes, task.getActivityType())) {
- continue;
+ for (int tdaNdx = dc.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = dc.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final Task task = taskDisplayArea.getStackAt(sNdx);
+ if (activityTypes != null
+ && !ArrayUtils.contains(activityTypes, task.getActivityType())) {
+ continue;
+ }
+ out.add(task.getTaskInfo());
}
- out.add(task.getTaskInfo());
}
return out;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 687af64..3cbb85b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7318,7 +7318,7 @@
@Override
public boolean isStackVisibleLw(int windowingMode) {
- // TODO(multi-display-area): Support multiple task display areas & displays
+ // TODO(b/153090332): Support multiple task display areas & displays
final TaskDisplayArea tc = mRoot.getDefaultTaskDisplayArea();
return tc.isStackVisible(windowingMode);
}
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 1cca207..bdba4b6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -495,9 +495,12 @@
}
private void assertNoTasks(DisplayContent display) {
- for (int i = display.getStackCount() - 1; i >= 0; --i) {
- final ActivityStack stack = display.getStackAt(i);
- assertFalse(stack.hasChild());
+ for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ assertFalse(stack.hasChild());
+ }
}
}
@@ -1042,10 +1045,14 @@
// move everything to secondary because test expects this but usually sysui
// does it.
DisplayContent dc = mService.mRootWindowContainer.getDisplayContent(mDisplayId);
- for (int i = dc.getStackCount() - 1; i >= 0; --i) {
- if (!WindowConfiguration.isSplitScreenWindowingMode(
- dc.getStackAt(i).getWindowingMode())) {
- dc.getStackAt(i).reparent(mSecondary, POSITION_BOTTOM);
+ for (int tdaNdx = dc.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = dc.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+ if (!WindowConfiguration.isSplitScreenWindowingMode(
+ stack.getWindowingMode())) {
+ stack.reparent(mSecondary, POSITION_BOTTOM);
+ }
}
}
}
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 d9c3ace..add4e9c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -686,8 +686,8 @@
mRecentTasks.setOnlyTestVisibleRange();
mRecentTasks.setParameters(-1 /* min */, 3 /* max */, -1 /* ms */);
- final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
- final Task alwaysOnTopTask = display.createStack(WINDOWING_MODE_MULTI_WINDOW,
+ final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+ final Task alwaysOnTopTask = taskDisplayArea.createStack(WINDOWING_MODE_MULTI_WINDOW,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
alwaysOnTopTask.setAlwaysOnTop(true);
@@ -862,8 +862,8 @@
final ActivityStack homeStack = mTaskContainer.getRootHomeTask();
final DisplayContent otherDisplay = addNewDisplayContentAt(DisplayContent.POSITION_TOP);
- final ActivityStack otherDisplayStack = otherDisplay.createStack(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ final ActivityStack otherDisplayStack = otherDisplay.getDefaultTaskDisplayArea()
+ .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// Add a number of tasks (beyond the max) on each display, ensure that the tasks are not
// removed
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index 48d4e70..b648346 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -349,8 +349,8 @@
// Create Recents on secondary display.
final TestDisplayContent secondDisplay = addNewDisplayContentAt(
DisplayContent.POSITION_TOP);
- final ActivityStack stack = secondDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
- ACTIVITY_TYPE_RECENTS, true /* onTop */);
+ final ActivityStack stack = secondDisplay.getDefaultTaskDisplayArea()
+ .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */);
final Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
new ActivityBuilder(mService).setTask(task).build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index 6ef714e..2ce9c2b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -618,9 +618,12 @@
private List<Task> getTasksCreatedByOrganizer(DisplayContent dc) {
ArrayList<Task> out = new ArrayList<>();
- for (int i = dc.getStackCount() - 1; i >= 0; --i) {
- final Task t = dc.getStackAt(i);
- if (t.mCreatedByOrganizer) out.add(t);
+ for (int tdaNdx = dc.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+ final TaskDisplayArea taskDisplayArea = dc.getTaskDisplayAreaAt(tdaNdx);
+ for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+ final Task t = taskDisplayArea.getStackAt(sNdx);
+ if (t.mCreatedByOrganizer) out.add(t);
+ }
}
return out;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 50584c6..519ac78 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -354,7 +354,7 @@
spyOn(parentWindowContainer);
parentWindowContainer.setBounds(fullScreenBounds);
doReturn(parentWindowContainer).when(task).getParent();
- doReturn(display.mTaskContainers).when(task).getDisplayArea();
+ doReturn(display.getDefaultTaskDisplayArea()).when(task).getDisplayArea();
doReturn(stack).when(task).getStack();
doReturn(true).when(parentWindowContainer).handlesOrientationChangeFromDescendant();