diff options
18 files changed, 537 insertions, 313 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index c1c844078d6f..a66741c90b1c 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 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ 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 a446720c1c39..f5eba96a96d1 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 @@ class ActivityStack extends Task { @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 8af862473386..02601ff4b6e3 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 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { 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 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { MoveTaskToFullscreenHelper::processLeafTask, this, PooledLambda.__(Task.class)); fromStack.forAllLeafTasks(c, false /* traverseTopToBottom */); c.recycle(); - mToDisplay = null; + mToDisplayArea = null; mTopTask = null; } @@ -411,19 +411,18 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { 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 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { 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 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } if (!reparented) { - moveHomeStackToFrontIfNeeded(flags, currentStack.getDisplay(), reason); + moveHomeStackToFrontIfNeeded(flags, currentStack.getDisplayArea(), reason); } final ActivityRecord r = task.getTopNonFinishingActivity(); @@ -1451,15 +1450,16 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { 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 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { 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 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { 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 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } 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 0a0049d1550d..d777f3fee1a2 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 @@ public class ActivityStartController { 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 85517a44d656..7931cd58d977 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * 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 getStackCount() { - return mTaskContainers.mChildren.size(); + 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 ActivityStack getStackAt(int index) { - return mTaskContainers.mChildren.get(index); + protected int getStackCount() { + 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } // 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } // Time to remove any exiting applications? - mTaskContainers.removeExistingAppTokensIfPossible(); + for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) { + getTaskDisplayAreaAt(i).removeExistingAppTokensIfPossible(); + } } @Override @@ -4475,7 +4503,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } void assignStackOrdering() { - mTaskContainers.assignStackOrdering(getPendingTransaction()); + for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) { + getTaskDisplayAreaAt(i).assignStackOrdering(getPendingTransaction()); + } } /** @@ -5002,13 +5032,15 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo || 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * @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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } 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 264da9fc681b..caaa173cb4c0 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 @@ public class DisplayPolicy { 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 57a54d0e84ef..f672394251f2 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 @@ class KeyguardController { * 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 84229f003032..6fda1170a3f5 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 @@ public class RecentsAnimationController implements DeathRecipient { // 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 2eeda4dcfeed..e1ef76f128cd 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } // 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } 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; - - noResumedActivities &= resumedActivityProcess == null; - if (resumedActivityProcess != null) { - allFocusedProcessesDiffer &= !resumedActivityProcess.equals(targetActivity.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); + } } } sendHint = noResumedActivities || allFocusedProcessesDiffer; @@ -3462,10 +3518,13 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> 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; - } - printThisActivity(pw, displayContent.mTaskContainers.getResumedActivity(), dumpPackage, - needSep, " ResumedActivity:"); + 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; + } + } + 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 13e4d8b038b1..8e45dc306b58 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.PooledLambda; 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 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> { */ 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 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> { return candidate; } - ActivityRecord getResumedActivity() { + ActivityRecord getFocusedActivity() { final ActivityStack focusedStack = getFocusedStack(); if (focusedStack == null) { return null; @@ -1572,7 +1579,7 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> { } boolean isRemoved() { - return mDisplayContent.isRemoved(); + return mRemoved; } /** @@ -1609,4 +1616,82 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> { 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 e6757e145f2f..da4401a68e7c 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 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { 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 30fa0529597c..75f2e1f0a8ba 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -477,26 +477,27 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { 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); @@ -557,13 +558,16 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { 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 687af64e9d4f..3cbb85b55a4c 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 @@ public class WindowManagerService extends IWindowManager.Stub @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 1cca207d5336..bdba4b6c8ac8 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 @@ public class ActivityStarterTests extends ActivityTestsBase { } 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 @@ public class ActivityStarterTests extends ActivityTestsBase { // 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 d9c3ace4589d..add4e9cf3948 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 @@ public class RecentTasksTest extends ActivityTestsBase { 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 @@ public class RecentTasksTest extends ActivityTestsBase { 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 48d4e705ff4b..b648346eeb28 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 @@ public class RootActivityContainerTests extends ActivityTestsBase { // 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 2dbfd06b3019..62d311ae7b36 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java @@ -627,9 +627,12 @@ public class TaskOrganizerTests extends WindowTestsBase { 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 50584c61cf92..519ac780bd6b 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 @@ public class TaskRecordTests extends ActivityTestsBase { 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(); |