Simplified ActivityStack.shouldBeVisible()
The method can now be simplified since we have a stack per task so
if a stack should be visible is now a question of if it is occluded
by another stack.
Also,
- Fixed an issue where the windowing mode of the primary split-screen
stack was changing to split-screen-secondary instead of fullscreen
when we are exiting split-screen mode because we are not allowed to
to create fullscreen stack when there is a primary split-screen stack. We
now clear the reference to the primary split-screen stack when exiting
split-screen mode.
- Re-worked windowing mode resolution to be inside ActivityDisplay
object since the determination of the windowing mode is dependant on the
display.
Test: bit FrameworksServicesTests:com.android.server.am.ActivityStackTests
Test: Existing tests pass.
Test: go/wm-smoke
Bug: 64146578
Fixes: 67914671
Change-Id: I7e8cfe49fbf6a5836ded022bb11adcde58ae689c
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index c15b5e2..7a4a0d4 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -110,7 +110,6 @@
import android.app.ProfilerInfo;
import android.app.ResultInfo;
import android.app.WaitResult;
-import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -223,13 +222,6 @@
// at the top of its container (e.g. stack).
static final boolean ON_TOP = true;
- // Used to indicate that an objects (e.g. task) removal from its container
- // (e.g. stack) is due to it moving to another container.
- static final boolean MOVING = true;
-
- // Force the focus to change to the stack we are moving a task to..
- static final boolean FORCE_FOCUS = true;
-
// Don't execute any calls to resume.
static final boolean DEFER_RESUME = true;
@@ -405,6 +397,7 @@
* object each time.
*/
private final Rect tempRect = new Rect();
+ private final ActivityOptions mTmpOptions = ActivityOptions.makeBasic();
// The default minimal size that will be used if the activity doesn't specify its minimal size.
// It will be calculated when the default display gets added.
@@ -2186,89 +2179,6 @@
return null;
}
- /**
- * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
- * @param windowingMode The windowing mode we are checking support for.
- * @param supportsMultiWindow If we should consider support for multi-window mode in general.
- * @param supportsSplitScreen If we should consider support for split-screen multi-window.
- * @param supportsFreeform If we should consider support for freeform multi-window.
- * @param supportsPip If we should consider support for picture-in-picture mutli-window.
- * @param activityType The activity type under consideration.
- * @return true if the windowing mode is supported.
- */
- boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
- boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip,
- int activityType) {
-
- if (windowingMode == WINDOWING_MODE_UNDEFINED
- || windowingMode == WINDOWING_MODE_FULLSCREEN) {
- return true;
- }
- if (!supportsMultiWindow) {
- return false;
- }
-
- if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
- || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
- return supportsSplitScreen && WindowConfiguration.supportSplitScreenWindowingMode(
- windowingMode, activityType);
- }
-
- if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
- return false;
- }
-
- if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) {
- return false;
- }
- return true;
- }
-
- private int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
- @Nullable TaskRecord task, int activityType) {
-
- // First preference if the windowing mode in the activity options if set.
- int windowingMode = (options != null)
- ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
-
- // If windowing mode is unset, then next preference is the candidate task, then the
- // activity record.
- if (windowingMode == WINDOWING_MODE_UNDEFINED) {
- if (task != null) {
- windowingMode = task.getWindowingMode();
- }
- if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
- windowingMode = r.getWindowingMode();
- }
- }
-
- // Make sure the windowing mode we are trying to use makes sense for what is supported.
- boolean supportsMultiWindow = mService.mSupportsMultiWindow;
- boolean supportsSplitScreen = mService.mSupportsSplitScreenMultiWindow;
- boolean supportsFreeform = mService.mSupportsFreeformWindowManagement;
- boolean supportsPip = mService.mSupportsPictureInPicture;
- if (supportsMultiWindow) {
- if (task != null) {
- supportsMultiWindow = task.isResizeable();
- supportsSplitScreen = task.supportsSplitScreenWindowingMode();
- // TODO: Do we need to check for freeform and Pip support here?
- } else if (r != null) {
- supportsMultiWindow = r.isResizeable();
- supportsSplitScreen = r.supportsSplitScreenWindowingMode();
- supportsFreeform = r.supportsFreeform();
- supportsPip = r.supportsPictureInPicture();
- }
- }
-
- if (windowingMode != WINDOWING_MODE_UNDEFINED
- && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
- supportsFreeform, supportsPip, activityType)) {
- return windowingMode;
- }
- // Return root/systems windowing mode
- return getWindowingMode();
- }
-
int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
@Nullable TaskRecord task) {
// Preference is given to the activity type for the activity then the task since the type
@@ -2329,7 +2239,6 @@
}
final int activityType = resolveActivityType(r, options, candidateTask);
- int windowingMode = resolveWindowingMode(r, options, candidateTask, activityType);
T stack = null;
// Next preference for stack goes to the display Id set in the activity options or the
@@ -2347,7 +2256,7 @@
}
final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
if (display != null) {
- stack = display.getOrCreateStack(windowingMode, activityType, onTop);
+ stack = display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
if (stack != null) {
return stack;
}
@@ -2365,10 +2274,14 @@
stack = r.getStack();
}
if (stack != null) {
- if (stack.isCompatible(windowingMode, activityType)) {
- return stack;
- }
display = stack.getDisplay();
+ if (display != null) {
+ final int windowingMode =
+ display.resolveWindowingMode(r, options, candidateTask, activityType);
+ if (stack.isCompatible(windowingMode, activityType)) {
+ return stack;
+ }
+ }
}
if (display == null
@@ -2379,7 +2292,7 @@
display = getDefaultDisplay();
}
- return display.getOrCreateStack(windowingMode, activityType, onTop);
+ return display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
}
/**
@@ -2596,6 +2509,8 @@
final ActivityDisplay toDisplay = getActivityDisplay(toDisplayId);
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ // Tell the display we are exiting split-screen mode.
+ toDisplay.onExitingSplitScreenMode();
// 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.
@@ -2625,35 +2540,34 @@
final ArrayList<TaskRecord> tasks = fromStack.getAllTasks();
if (!tasks.isEmpty()) {
+ mTmpOptions.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
final int size = tasks.size();
- final ActivityStack fullscreenStack = toDisplay.getOrCreateStack(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, onTop);
+ for (int i = 0; i < size; ++i) {
+ final TaskRecord task = tasks.get(i);
+ final ActivityStack toStack = toDisplay.getOrCreateStack(
+ null, mTmpOptions, task, task.getActivityType(), onTop);
- if (onTop) {
- final int returnToType =
- toDisplay.getTopVisibleStackActivityType(WINDOWING_MODE_PINNED);
- for (int i = 0; i < size; i++) {
- final TaskRecord task = tasks.get(i);
+ if (onTop) {
+ final int returnToType =
+ toDisplay.getTopVisibleStackActivityType(WINDOWING_MODE_PINNED);
final boolean isTopTask = i == (size - 1);
if (inPinnedWindowingMode) {
- // Update the return-to to reflect where the pinned stack task was moved
- // from so that we retain the stack that was previously visible if the
- // pinned stack is recreated. See moveActivityToPinnedStackLocked().
+ // Update the return-to to reflect where the pinned stack task was
+ // moved from so that we retain the stack that was previously
+ // visible if the pinned stack is recreated.
+ // See moveActivityToPinnedStackLocked().
task.setTaskToReturnTo(returnToType);
}
// Defer resume until all the tasks have been moved to the fullscreen stack
- task.reparent(fullscreenStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
+ task.reparent(toStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
isTopTask /* animate */, DEFER_RESUME,
schedulePictureInPictureModeChange,
"moveTasksToFullscreenStack - onTop");
- }
- } else {
- for (int i = 0; i < size; i++) {
- final TaskRecord task = tasks.get(i);
+ } else {
// Position the tasks in the fullscreen stack in order at the bottom of the
// stack. Also defer resume until all the tasks have been moved to the
// fullscreen stack.
- task.reparent(fullscreenStack, i /* position */,
+ task.reparent(toStack, ON_TOP,
REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE, DEFER_RESUME,
schedulePictureInPictureModeChange,
"moveTasksToFullscreenStack - NOT_onTop");
@@ -3080,23 +2994,16 @@
+ " task=" + task);
}
- // We don't allow moving a unresizeable task to the docked stack since the docked stack is
- // used for split-screen mode and will cause things like the docked divider to show up. We
- // instead leave the task in its current stack or move it to the fullscreen stack if it
- // isn't currently in a stack.
+ // Leave the task in its current stack or a fullscreen stack if it isn't resizeable and the
+ // preferred stack is in multi-window mode.
if (inMultiWindowMode && !task.isResizeable()) {
- Slog.w(TAG, "Can not move unresizeable task=" + task + " to docked stack."
- + " Moving to stackId=" + stackId + " instead.");
- // Temporarily disable resizeablility of the task as we don't want it to be resized if,
- // for example, a docked stack is created which will lead to the stack we are moving
- // from being resized and and its resizeable tasks being resized.
- try {
- task.mTemporarilyUnresizable = true;
- stack = stack.getDisplay().createStack(
- WINDOWING_MODE_FULLSCREEN, stack.getActivityType(), toTop);
- } finally {
- task.mTemporarilyUnresizable = false;
+ Slog.w(TAG, "Can not move unresizeable task=" + task + " to multi-window stack=" + stack
+ + " Moving to a fullscreen stack instead.");
+ if (prevStack != null) {
+ return prevStack;
}
+ stack = stack.getDisplay().createStack(
+ WINDOWING_MODE_FULLSCREEN, stack.getActivityType(), toTop);
}
return stack;
}
@@ -4287,9 +4194,9 @@
final boolean isSecondaryDisplayPreferred =
(preferredDisplayId != DEFAULT_DISPLAY && preferredDisplayId != INVALID_DISPLAY);
final boolean inSplitScreenMode = actualStack != null
- && actualStack.inSplitScreenWindowingMode();
+ && actualStack.getDisplay().hasSplitScreenPrimaryStack();
if (((!inSplitScreenMode && preferredWindowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
- && !isSecondaryDisplayPreferred) || task.isActivityTypeHome()) {
+ && !isSecondaryDisplayPreferred) || !task.isActivityTypeStandardOrUndefined()) {
return;
}