summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/ActivityDisplay.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java167
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java3
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java6
-rw-r--r--services/core/java/com/android/server/wm/DockedStackDividerController.java30
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java13
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java2
-rw-r--r--services/core/java/com/android/server/wm/StackWindowController.java19
-rw-r--r--services/core/java/com/android/server/wm/TaskRecord.java3
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java335
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java62
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java59
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java9
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java9
15 files changed, 337 insertions, 396 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 751ae0db67d6..ed366453028e 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -267,6 +267,9 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
mWindowContainerController.positionChildAt(stack.getWindowContainerController(),
insertPosition, includingParents);
}
+ if (!wasContained) {
+ stack.setParent(this);
+ }
onStackOrderChanged();
}
@@ -692,7 +695,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
}
otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED, false /* animate */,
false /* showRecents */, false /* enteringSplitScreenMode */,
- true /* deferEnsuringVisibility */);
+ true /* deferEnsuringVisibility */, false /* creating */);
}
} finally {
final ActivityStack topFullscreenStack =
@@ -722,7 +725,8 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
}
otherStack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
false /* animate */, false /* showRecents */,
- true /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */);
+ true /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */,
+ false /* creating */);
}
} finally {
mSupervisor.mWindowManager.continueSurfaceLayout();
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 7fcee3db3e78..8d467c808e55 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -233,13 +233,40 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
@Override
- protected ConfigurationContainer getParent() {
+ protected ActivityDisplay getParent() {
return getDisplay();
}
+ void setParent(ActivityDisplay parent) {
+ ActivityDisplay current = getParent();
+ if (current != parent) {
+ mDisplayId = parent.mDisplayId;
+ onParentChanged();
+ }
+ }
+
@Override
protected void onParentChanged() {
+ ActivityDisplay display = getParent();
+ if (display != null) {
+ // Rotations are relative to the display. This means if there are 2 displays rotated
+ // differently (eg. 2 monitors with one landscape and one portrait), moving a stack
+ // from one to the other could look like a rotation change. To prevent this
+ // apparent rotation change (and corresponding bounds rotation), pretend like our
+ // current rotation is already the same as the new display.
+ // Note, if ActivityStack or related logic ever gets nested, this logic will need
+ // to move to onConfigurationChanged.
+ getConfiguration().windowConfiguration.setRotation(
+ display.getWindowConfiguration().getRotation());
+ }
super.onParentChanged();
+ if (display != null && inSplitScreenPrimaryWindowingMode()) {
+ // If we created a docked stack we want to resize it so it resizes all other stacks
+ // in the system.
+ getStackDockedModeBounds(null, null, mTmpRect2, mTmpRect3);
+ mStackSupervisor.resizeDockedStackLocked(
+ getOverrideBounds(), mTmpRect2, mTmpRect2, null, null, PRESERVE_WINDOWS);
+ }
mStackSupervisor.updateUIDsPresentOnDisplay();
}
@@ -353,7 +380,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
private final SparseArray<Rect> mTmpBounds = new SparseArray<>();
private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>();
+ private final Rect mTmpRect = new Rect();
private final Rect mTmpRect2 = new Rect();
+ private final Rect mTmpRect3 = new Rect();
private final ActivityOptions mTmpOptions = ActivityOptions.makeBasic();
/** List for processing through a set of activities */
@@ -469,10 +498,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// stacks on a wrong display.
mDisplayId = display.mDisplayId;
setActivityType(activityType);
- setWindowingMode(windowingMode);
mWindowContainerController = createStackWindowController(display.mDisplayId, onTop,
mTmpRect2);
- postAddToDisplay(display, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
+ setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
+ false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
+ true /* creating */);
+ display.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
}
T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
@@ -514,21 +545,85 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final int prevWindowingMode = getWindowingMode();
final boolean prevIsAlwaysOnTop = isAlwaysOnTop();
final ActivityDisplay display = getDisplay();
+ final int prevRotation = getWindowConfiguration().getRotation();
+ final int prevDensity = getConfiguration().densityDpi;
+ final int prevScreenW = getConfiguration().screenWidthDp;
+ final int prevScreenH = getConfiguration().screenHeightDp;
- getBounds(mTmpRect2);
- final boolean hasNewBounds = display != null && getWindowContainerController() != null
- && getWindowContainerController().updateBoundsForConfigChange(
- newParentConfig, getConfiguration(), mTmpRect2);
+ getBounds(mTmpRect); // previous bounds
super.onConfigurationChanged(newParentConfig);
if (display == null) {
- return;
+ return;
+ }
+
+ // Update bounds if applicable
+ boolean hasNewOverrideBounds = false;
+ // Use override windowing mode to prevent extra bounds changes if inheriting the mode.
+ if (getOverrideWindowingMode() == WINDOWING_MODE_PINNED) {
+ // Pinned calculation already includes rotation
+ mTmpRect2.set(mTmpRect);
+ hasNewOverrideBounds = getWindowContainerController().mContainer
+ .calculatePinnedBoundsForConfigChange(mTmpRect2);
+ } else {
+ final int newRotation = getWindowConfiguration().getRotation();
+ if (!matchParentBounds()) {
+ // If the parent (display) has rotated, rotate our bounds to best-fit where their
+ // bounds were on the pre-rotated display.
+ if (prevRotation != newRotation) {
+ mTmpRect2.set(mTmpRect);
+ getDisplay().getWindowContainerController().mContainer
+ .rotateBounds(newParentConfig.windowConfiguration.getBounds(),
+ prevRotation, newRotation, mTmpRect2);
+ hasNewOverrideBounds = true;
+ }
+
+ // If entering split screen or if something about the available split area changes,
+ // recalculate the split windows to match the new configuration.
+ if (prevRotation != newRotation
+ || prevDensity != getConfiguration().densityDpi
+ || prevWindowingMode != getWindowingMode()
+ || prevScreenW != getConfiguration().screenWidthDp
+ || prevScreenH != getConfiguration().screenHeightDp) {
+ // Use override windowing mode to prevent extra bounds changes if inheriting
+ // the mode.
+ if (getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || getOverrideWindowingMode()
+ == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
+ mTmpRect2.set(mTmpRect);
+ getWindowContainerController().mContainer
+ .calculateDockedBoundsForConfigChange(newParentConfig, mTmpRect2);
+ hasNewOverrideBounds = true;
+ }
+ }
+ }
+ }
+ if (getWindowingMode() != prevWindowingMode) {
+ // Use override windowing mode to prevent extra bounds changes if inheriting the mode.
+ if (getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ getStackDockedModeBounds(null, null, mTmpRect2, mTmpRect3);
+ // immediately resize so docked bounds are available in onSplitScreenModeActivated
+ resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */);
+ } else if (getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
+ Rect dockedBounds = display.getSplitScreenPrimaryStack().getBounds();
+ final boolean isMinimizedDock = getDisplay().getWindowContainerController()
+ .mContainer.getDockedDividerController().isMinimizedDock();
+ if (isMinimizedDock) {
+ TaskRecord topTask = display.getSplitScreenPrimaryStack().topTask();
+ if (topTask != null) {
+ dockedBounds = topTask.getBounds();
+ }
+ }
+ getStackDockedModeBounds(dockedBounds, null, mTmpRect2, mTmpRect3);
+ hasNewOverrideBounds = true;
+ }
}
if (prevWindowingMode != getWindowingMode()) {
display.onStackWindowingModeChanged(this);
}
- if (hasNewBounds) {
- resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */);
+ if (hasNewOverrideBounds) {
+ mStackSupervisor.resizeStackLocked(this, mTmpRect2, null, null, PRESERVE_WINDOWS,
+ true /* allowResizeInDockedMode */, true /* deferResume */);
}
if (prevIsAlwaysOnTop != isAlwaysOnTop()) {
// Since always on top is only on when the stack is freeform or pinned, the state
@@ -541,7 +636,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
@Override
public void setWindowingMode(int windowingMode) {
setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
- false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */);
+ false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
+ false /* creating */);
}
/**
@@ -569,10 +665,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
* @param enteringSplitScreenMode {@code true} if entering split mode.
* @param deferEnsuringVisibility Whether visibility updates are deferred. This is set when
* many operations (which can effect visibility) are being performed in bulk.
+ * @param creating {@code true} if this is being run during ActivityStack construction.
*/
void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents,
- boolean enteringSplitScreenMode, boolean deferEnsuringVisibility) {
- final boolean creating = mWindowContainerController == null;
+ boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, boolean creating) {
final int currentMode = getWindowingMode();
final int currentOverrideMode = getOverrideWindowingMode();
final ActivityDisplay display = getDisplay();
@@ -615,9 +711,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// doesn't support split-screen mode, go ahead an dismiss split-screen and display a
// warning toast about it.
mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
- display.getSplitScreenPrimaryStack().setWindowingMode(WINDOWING_MODE_UNDEFINED,
+ final ActivityStack primarySplitStack = display.getSplitScreenPrimaryStack();
+ primarySplitStack.setWindowingMode(WINDOWING_MODE_UNDEFINED,
false /* animate */, false /* showRecents */,
- false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */);
+ false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */,
+ primarySplitStack == this ? creating : false);
}
}
@@ -746,7 +844,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// the new display below
mTmpRect2.setEmpty();
mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop);
- postAddToDisplay(activityDisplay, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
+ setBounds(mTmpRect2.isEmpty() ? null : mTmpRect2);
+ activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
if (!displayRemoved) {
postReparent();
}
@@ -763,31 +862,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
/**
- * Updates internal state after adding to new display.
- * @param activityDisplay New display to which this stack was attached.
- * @param bounds Updated bounds.
- */
- private void postAddToDisplay(ActivityDisplay activityDisplay, Rect bounds, boolean onTop) {
- if (mDisplayId != activityDisplay.mDisplayId) {
- // rotations are relative to the display, so pretend like our current rotation is
- // the same as the new display so we don't try to rotate bounds.
- getConfiguration().windowConfiguration.setRotation(
- activityDisplay.getWindowConfiguration().getRotation());
- }
- mDisplayId = activityDisplay.mDisplayId;
- setBounds(bounds);
- onParentChanged();
-
- activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
- if (inSplitScreenPrimaryWindowingMode()) {
- // If we created a docked stack we want to resize it so it resizes all other stacks
- // in the system.
- mStackSupervisor.resizeDockedStackLocked(
- getOverrideBounds(), null, null, null, null, PRESERVE_WINDOWS);
- }
- }
-
- /**
* Updates the inner state of the stack to remove it from its current parent, so it can be
* either destroyed completely or re-parented.
*/
@@ -812,12 +886,13 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
/**
- * @see #getStackDockedModeBounds(Rect, Rect, Rect, boolean)
+ * @see #getStackDockedModeBounds(Rect, Rect, Rect, Rect)
*/
- void getStackDockedModeBounds(Rect currentTempTaskBounds, Rect outStackBounds,
- Rect outTempTaskBounds, boolean ignoreVisibility) {
- mWindowContainerController.getStackDockedModeBounds(currentTempTaskBounds,
- outStackBounds, outTempTaskBounds, ignoreVisibility);
+ void getStackDockedModeBounds(Rect dockedBounds, Rect currentTempTaskBounds,
+ Rect outStackBounds, Rect outTempTaskBounds) {
+ mWindowContainerController.getStackDockedModeBounds(getParent().getConfiguration(),
+ dockedBounds, currentTempTaskBounds,
+ outStackBounds, outTempTaskBounds);
}
void prepareFreezingTaskBounds() {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 082f5213cb5d..694e9d1d6917 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -2921,7 +2921,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
final Rect otherTaskRect = new Rect();
for (int i = display.getChildCount() - 1; i >= 0; --i) {
final ActivityStack current = display.getChildAt(i);
- if (current.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ if (!current.inSplitScreenSecondaryWindowingMode()) {
continue;
}
if (!current.affectedBySplitScreenResize()) {
@@ -2932,12 +2932,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// interaction.
continue;
}
- // Need to set windowing mode here before we try to get the dock bounds.
- current.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
- current.getStackDockedModeBounds(
+ current.getStackDockedModeBounds(dockedBounds,
tempOtherTaskBounds /* currentTempTaskBounds */,
tempRect /* outStackBounds */,
- otherTaskRect /* outTempTaskBounds */, true /* ignoreVisibility */);
+ otherTaskRect /* outTempTaskBounds */);
resizeStackLocked(current, !tempRect.isEmpty() ? tempRect : null,
!otherTaskRect.isEmpty() ? otherTaskRect : tempOtherTaskBounds,
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 1d0007545d78..4f01d699d248 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2430,7 +2430,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
stack.moveToFront("setTaskWindowingModeSplitScreenPrimary", task);
}
stack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, animate, showRecents,
- false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */);
+ false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
+ false /* creating */);
return windowingMode != task.getWindowingMode();
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4b939862904c..ab7d2597614c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1893,12 +1893,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (mPinnedStackControllerLocked != null && !hasPinnedStack()) {
mPinnedStackControllerLocked.onDisplayInfoChanged(getDisplayInfo());
}
-
- // The display size information is heavily dependent on the resources in the current
- // configuration, so we need to reconfigure it every time the configuration changes.
- // See {@link #configureDisplayPolicy}...sigh...
- mService.reconfigureDisplayLocked(this);
-
}
/**
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 6daf2f5ab59d..c37707291aed 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -227,32 +227,30 @@ public class DockedStackDividerController {
return DOCKED_INVALID;
}
- void getHomeStackBoundsInDockedMode(Rect outBounds) {
- final DisplayInfo di = mDisplayContent.getDisplayInfo();
- mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
- di.displayCutout, mTmpRect);
+ void getHomeStackBoundsInDockedMode(Configuration parentConfig, int dockSide, Rect outBounds) {
+ final DisplayCutout displayCutout = mDisplayContent.getDisplayInfo().displayCutout;
+ final int displayWidth = parentConfig.windowConfiguration.getBounds().width();
+ final int displayHeight = parentConfig.windowConfiguration.getBounds().height();
+ mService.mPolicy.getStableInsetsLw(parentConfig.windowConfiguration.getRotation(),
+ displayWidth, displayHeight, displayCutout, mTmpRect);
int dividerSize = mDividerWindowWidth - 2 * mDividerInsets;
- Configuration configuration = mDisplayContent.getConfiguration();
// The offset in the left (landscape)/top (portrait) is calculated with the minimized
// offset value with the divider size and any system insets in that direction.
- if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
+ if (parentConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
outBounds.set(0, mTaskHeightInMinimizedMode + dividerSize + mTmpRect.top,
- di.logicalWidth, di.logicalHeight);
+ displayWidth, displayHeight);
} else {
// In landscape also inset the left/right side with the statusbar height to match the
// minimized size height in portrait mode.
- final TaskStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
final int primaryTaskWidth = mTaskHeightInMinimizedMode + dividerSize + mTmpRect.top;
int left = mTmpRect.left;
- int right = di.logicalWidth - mTmpRect.right;
- if (stack != null) {
- if (stack.getDockSide() == DOCKED_LEFT) {
- left += primaryTaskWidth;
- } else if (stack.getDockSide() == DOCKED_RIGHT) {
- right -= primaryTaskWidth;
- }
+ int right = displayWidth - mTmpRect.right;
+ if (dockSide == DOCKED_LEFT) {
+ left += primaryTaskWidth;
+ } else if (dockSide == DOCKED_RIGHT) {
+ right -= primaryTaskWidth;
}
- outBounds.set(left, 0, right, di.logicalHeight);
+ outBounds.set(left, 0, right, displayHeight);
}
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 6627c2dc5cc3..b6609e467e85 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -21,7 +21,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
+import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
+
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
import static com.android.server.wm.AnimationAdapterProto.REMOTE;
@@ -43,18 +45,21 @@ import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
-import android.view.InputWindowHandle;
import android.view.IRecentsAnimationController;
import android.view.IRecentsAnimationRunner;
+import android.view.InputWindowHandle;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
import com.android.server.wm.utils.InsetUtils;
+
import com.google.android.collect.Sets;
+
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -320,7 +325,11 @@ public class RecentsAnimationController implements DeathRecipient {
}
// Save the minimized home height
- dc.getDockedDividerController().getHomeStackBoundsInDockedMode(mMinimizedHomeBounds);
+ final TaskStack dockedStack = dc.getSplitScreenPrimaryStackIgnoringVisibility();
+ dc.getDockedDividerController().getHomeStackBoundsInDockedMode(
+ dc.getConfiguration(),
+ dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide(),
+ mMinimizedHomeBounds);
mService.mWindowPlacerLocked.performSurfacePlacement();
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 1baca321d01d..239971653d12 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -249,6 +249,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
dc.configureDisplayPolicy();
}
+ mService.reconfigureDisplayLocked(dc);
+
return dc;
}
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index d8e1ebfbb1b1..baeedbc1d28e 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -200,14 +200,15 @@ public class StackWindowController
}
/**
- * @see TaskStack.getStackDockedModeBoundsLocked(Rect, Rect, Rect, boolean)
+ * @see TaskStack.getStackDockedModeBoundsLocked(ConfigurationContainer, Rect, Rect, Rect)
*/
- public void getStackDockedModeBounds(Rect currentTempTaskBounds, Rect outStackBounds,
- Rect outTempTaskBounds, boolean ignoreVisibility) {
+ public void getStackDockedModeBounds(Configuration parentConfig, Rect dockedBounds,
+ Rect currentTempTaskBounds,
+ Rect outStackBounds, Rect outTempTaskBounds) {
synchronized (mGlobalLock) {
if (mContainer != null) {
- mContainer.getStackDockedModeBoundsLocked(currentTempTaskBounds, outStackBounds,
- outTempTaskBounds, ignoreVisibility);
+ mContainer.getStackDockedModeBoundsLocked(parentConfig, dockedBounds,
+ currentTempTaskBounds, outStackBounds, outTempTaskBounds);
return;
}
outStackBounds.setEmpty();
@@ -372,14 +373,6 @@ public class StackWindowController
mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
}
- /** @see TaskStack.updateBoundsForConfigChange(Configuration, Configuration, Rect) */
- public boolean updateBoundsForConfigChange(
- Configuration parentConfig, Configuration prevConfig, Rect outBounds) {
- synchronized (mGlobalLock) {
- return mContainer.updateBoundsForConfigChange(parentConfig, prevConfig, outBounds);
- }
- }
-
@Override
public String toString() {
return "{StackWindowController stackId=" + mStackId + "}";
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index bd6689fae3ec..eec10aba5df2 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -452,13 +452,13 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont
void removeWindowContainer() {
mService.getLockTaskController().clearLockedTask(this);
mWindowContainerController.removeContainer();
+ mWindowContainerController = null;
if (!getWindowConfiguration().persistTaskBounds()) {
// Reset current bounds for task whose bounds shouldn't be persisted so it uses
// default configuration the next time it launches.
updateOverrideConfiguration(null);
}
mService.getTaskChangeNotificationController().notifyTaskRemoved(taskId);
- mWindowContainerController = null;
}
@Override
@@ -1265,7 +1265,6 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont
}
// Sync. with window manager
- updateOverrideConfigurationFromLaunchBounds();
final AppWindowContainerController appController = r.getWindowContainerController();
if (appController != null) {
// Only attempt to move in WM if the child has a controller. It is possible we haven't
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 912cb7fe449a..15de1ecec970 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -23,11 +23,8 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
-import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.DOCKED_BOTTOM;
@@ -66,7 +63,6 @@ import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
-import android.view.Surface;
import android.view.SurfaceControl;
import com.android.internal.policy.DividerSnapAlgorithm;
@@ -106,12 +102,6 @@ public class TaskStack extends WindowContainer<Task> implements
*/
private final Rect mFullyAdjustedImeBounds = new Rect();
- // Display rotation as of the last time {@link #mBounds} was set.
- private int mRotation;
-
- /** Density as of last time {@link #mBounds} was set. */
- private int mDensity;
-
private SurfaceControl mAnimationBackgroundSurface;
private boolean mAnimationBackgroundSurfaceIsShown = false;
@@ -291,28 +281,16 @@ public class TaskStack extends WindowContainer<Task> implements
}
private int setBounds(Rect existing, Rect bounds) {
- int rotation = Surface.ROTATION_0;
- int density = DENSITY_DPI_UNDEFINED;
- WindowContainer parent = getParent();
- if (parent != null) {
- parent.getBounds(mTmpRect);
- rotation = mDisplayContent.getDisplayInfo().rotation;
- density = mDisplayContent.getDisplayInfo().logicalDensityDpi;
- }
-
- if (equivalentBounds(existing, bounds) && mRotation == rotation) {
+ if (equivalentBounds(existing, bounds)) {
return BOUNDS_CHANGE_NONE;
}
final int result = super.setBounds(bounds);
- if (mDisplayContent != null) {
+ if (getParent() != null) {
updateAnimationBackgroundBounds();
}
- mRotation = rotation;
- mDensity = density;
-
updateAdjustedBounds();
updateSurfaceBounds();
@@ -420,78 +398,66 @@ public class TaskStack extends WindowContainer<Task> implements
}
/**
- * Updates the passed-in {@code inOutBounds} based on how it would change when this container's
- * override configuration is applied to the specified {@code parentConfig} and
- * {@code prevConfig}. This gets run *after* the override configuration is updated, so it's
- * safe to rely on wm hierarchy state in here (though eventually this dependence should be
- * removed).
+ * Updates the passed-in {@code inOutBounds} based on the current state of the
+ * pinned controller. This gets run *after* the override configuration is updated, so it's
+ * safe to rely on the controller's state in here (though eventually this dependence should
+ * be removed).
*
* This does NOT modify this TaskStack's configuration. However, it does, for the time-being,
- * update various controller state (pinned/docked).
+ * update pinned controller state.
*
- * @param parentConfig a parent configuration to compute relative to.
- * @param prevConfig the full configuration used to produce the incoming {@code inOutBounds}.
* @param inOutBounds the bounds to update (both input and output).
- * @return true if bounds were updated to some non-empty value. */
- boolean updateBoundsForConfigChange(
- Configuration parentConfig, Configuration prevConfig, Rect inOutBounds) {
- if (getOverrideWindowingMode() == WINDOWING_MODE_PINNED) {
- if ((mBoundsAnimatingRequested || mBoundsAnimating)
- && !mBoundsAnimationTarget.isEmpty()) {
- getFinalAnimationBounds(mTmpRect2);
- } else {
- mTmpRect2.set(prevConfig.windowConfiguration.getBounds());
- }
- boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
- mTmpRect2, mTmpRect3);
- if (updated) {
- inOutBounds.set(mTmpRect3);
-
- // Once we've set the bounds based on the rotation of the old bounds in the new
- // orientation, clear the animation target bounds since they are obsolete, and
- // cancel any currently running animations
- mBoundsAnimationTarget.setEmpty();
- mBoundsAnimationSourceHintBounds.setEmpty();
- mCancelCurrentBoundsAnimation = true;
- }
- return updated;
- }
-
- final int newRotation = parentConfig.windowConfiguration.getRotation();
- final int newDensity = parentConfig.densityDpi;
-
- if (prevConfig.windowConfiguration.getRotation() == newRotation
- && prevConfig.densityDpi == newDensity) {
- return false;
+ * @return true if bounds were updated to some non-empty value.
+ */
+ boolean calculatePinnedBoundsForConfigChange(Rect inOutBounds) {
+ if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
+ getFinalAnimationBounds(mTmpRect2);
+ } else {
+ mTmpRect2.set(inOutBounds);
}
+ boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
+ mTmpRect2, mTmpRect3);
+ if (updated) {
+ inOutBounds.set(mTmpRect3);
- if (matchParentBounds()) {
- return false;
+ // Once we've set the bounds based on the rotation of the old bounds in the new
+ // orientation, clear the animation target bounds since they are obsolete, and
+ // cancel any currently running animations
+ mBoundsAnimationTarget.setEmpty();
+ mBoundsAnimationSourceHintBounds.setEmpty();
+ mCancelCurrentBoundsAnimation = true;
}
+ return updated;
+ }
- mDisplayContent.rotateBounds(parentConfig.windowConfiguration.getBounds(),
- prevConfig.windowConfiguration.getRotation(), newRotation, inOutBounds);
- if (getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
- || getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
- boolean primary = getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
- repositionSplitScreenStackAfterRotation(parentConfig, primary, inOutBounds);
- final DisplayCutout cutout = mDisplayContent.getDisplayInfo().displayCutout;
- snapDockedStackAfterRotation(parentConfig, cutout, inOutBounds);
- if (primary) {
- final int newDockSide = getDockSide(mDisplayContent, parentConfig, inOutBounds);
-
- // Update the dock create mode and clear the dock create bounds, these
- // might change after a rotation and the original values will be invalid.
- mService.setDockedStackCreateStateLocked(
- (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
- ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
- : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT,
- null);
- mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
- }
+ /**
+ * Updates the passed-in {@code inOutBounds} based on the current state of the
+ * docked controller. This gets run *after* the override configuration is updated, so it's
+ * safe to rely on the controller's state in here (though eventually this dependence should
+ * be removed).
+ *
+ * This does NOT modify this TaskStack's configuration. However, it does, for the time-being,
+ * update docked controller state.
+ *
+ * @param parentConfig the parent configuration for reference.
+ * @param inOutBounds the bounds to update (both input and output).
+ */
+ void calculateDockedBoundsForConfigChange(Configuration parentConfig, Rect inOutBounds) {
+ final boolean primary = getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+ repositionSplitScreenStackAfterRotation(parentConfig, primary, inOutBounds);
+ final DisplayCutout cutout = mDisplayContent.getDisplayInfo().displayCutout;
+ snapDockedStackAfterRotation(parentConfig, cutout, inOutBounds);
+ if (primary) {
+ final int newDockSide = getDockSide(parentConfig, inOutBounds);
+ // Update the dock create mode and clear the dock create bounds, these
+ // might change after a rotation and the original values will be invalid.
+ mService.setDockedStackCreateStateLocked(
+ (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
+ ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
+ : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT,
+ null);
+ mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
}
-
- return true;
}
/**
@@ -721,7 +687,6 @@ public class TaskStack extends WindowContainer<Task> implements
@Override
public void onConfigurationChanged(Configuration newParentConfig) {
final int prevWindowingMode = getWindowingMode();
- final boolean prevIsAlwaysOnTop = isAlwaysOnTop();
super.onConfigurationChanged(newParentConfig);
// Only need to update surface size here since the super method will handle updating
@@ -736,17 +701,14 @@ public class TaskStack extends WindowContainer<Task> implements
if (prevWindowingMode != windowingMode) {
mDisplayContent.onStackWindowingModeChanged(this);
- updateBoundsForWindowModeChange();
- }
- if (prevIsAlwaysOnTop != isAlwaysOnTop) {
- // positionStackAt(POSITION_TOP, this) must be called even when always on top gets
- // turned off because we need to make sure that the stack is moved from among always on
- // top windows to below other always on top windows. Since the position the stack should
- // be inserted into is calculated properly in
- // {@link DisplayContent#findPositionForStack()} in both cases, we can just request that
- // the stack is put at top here.
- mDisplayContent.positionStackAt(POSITION_TOP, this, false /* includingParents */);
+ if (inSplitScreenSecondaryWindowingMode()) {
+ // When the stack is resized due to entering split screen secondary, offset the
+ // windows to compensate for the new stack position.
+ forAllWindows(w -> {
+ w.mWinAnimator.setOffsetPositionForStackResize(true);
+ }, true);
+ }
}
}
@@ -803,12 +765,7 @@ public class TaskStack extends WindowContainer<Task> implements
final boolean movedToNewDisplay = mDisplayContent == null;
mDisplayContent = dc;
- if (movedToNewDisplay) {
- updateBoundsForWindowModeChange();
- } else {
- updateBoundsForDisplayChanges();
- }
-
+ updateSurfaceBounds();
if (mAnimationBackgroundSurface == null) {
mAnimationBackgroundSurface = makeChildSurface(null).setColorLayer(true)
.setName("animation background stackId=" + mStackId)
@@ -818,95 +775,6 @@ public class TaskStack extends WindowContainer<Task> implements
super.onDisplayChanged(dc);
}
- private void updateBoundsForWindowModeChange() {
- final Rect bounds = calculateBoundsForWindowModeChange();
-
- if (inSplitScreenSecondaryWindowingMode()) {
- // When the stack is resized due to entering split screen secondary, offset the
- // windows to compensate for the new stack position.
- forAllWindows(w -> {
- w.mWinAnimator.setOffsetPositionForStackResize(true);
- }, true);
- }
-
- setBoundsForWindowModeChange(bounds);
- updateSurfaceBounds();
- }
-
- private void setBoundsForWindowModeChange(Rect bounds) {
- if (mDisplayContent == null) {
- return;
- }
-
- if (bounds != null) {
- setBounds(bounds);
- return;
- }
-
- updateBoundsForDisplayChanges();
- }
-
- private void updateBoundsForDisplayChanges() {
- // Avoid setting override bounds to bounds inherited from parent if there was no override
- // bounds set.
- if (matchParentBounds()) {
- setBounds(null);
- return;
- }
-
- mTmpRect2.set(getRawBounds());
- final int newRotation = mDisplayContent.getDisplayInfo().rotation;
- final int newDensity = mDisplayContent.getDisplayInfo().logicalDensityDpi;
- if (mRotation == newRotation && mDensity == newDensity) {
- setBounds(mTmpRect2);
- }
-
- // If the rotation or density didn't match, we'll update it in onConfigurationChanged.
- }
-
- private Rect calculateBoundsForWindowModeChange() {
- final boolean inSplitScreenPrimary = inSplitScreenPrimaryWindowingMode();
- final TaskStack splitScreenStack =
- mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
- if (inSplitScreenPrimary || (splitScreenStack != null
- && inSplitScreenSecondaryWindowingMode() && !splitScreenStack.fillsParent())) {
- // The existence of a docked stack affects the size of other static stack created since
- // the docked stack occupies a dedicated region on screen, but only if the dock stack is
- // not fullscreen. If it's fullscreen, it means that we are in the transition of
- // dismissing it, so we must not resize this stack.
- final Rect bounds = new Rect();
- mDisplayContent.getBounds(mTmpRect);
- mTmpRect2.setEmpty();
- if (splitScreenStack != null) {
- if (inSplitScreenSecondaryWindowingMode()
- && mDisplayContent.mDividerControllerLocked.isMinimizedDock()
- && splitScreenStack.getTopChild() != null) {
- // If the primary split screen stack is currently minimized, then don't use the
- // stack bounds of the minimized stack, instead, use the temporary task bounds
- // to calculate the appropriate uniminized size of any secondary split stack
- // TODO: Find a cleaner way for computing new stack bounds while minimized that
- // doesn't assume the primary stack's task bounds as the temp task bounds
- splitScreenStack.getTopChild().getBounds(mTmpRect2);
- } else {
- splitScreenStack.getRawBounds(mTmpRect2);
- }
- }
- final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
- == SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
- getStackDockedModeBounds(mTmpRect, bounds, mTmpRect2,
- mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
- return bounds;
- } else if (inPinnedWindowingMode()) {
- // Update the bounds based on any changes to the display info
- getAnimationOrCurrentBounds(mTmpRect2);
- if (mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
- mTmpRect2, mTmpRect3)) {
- return new Rect(mTmpRect3);
- }
- }
- return null;
- }
-
/**
* Determines the stack and task bounds of the other stack when in docked mode. The current task
* bounds is passed in but depending on the stack, the task and stack must match. Only in
@@ -918,12 +786,22 @@ public class TaskStack extends WindowContainer<Task> implements
* @param currentTempTaskBounds the current task bounds of the other stack
* @param outStackBounds the calculated stack bounds of the other stack
* @param outTempTaskBounds the calculated task bounds of the other stack
- * @param ignoreVisibility ignore visibility in getting the stack bounds
*/
- void getStackDockedModeBoundsLocked(Rect currentTempTaskBounds, Rect outStackBounds,
- Rect outTempTaskBounds, boolean ignoreVisibility) {
+ void getStackDockedModeBoundsLocked(Configuration parentConfig, Rect dockedBounds,
+ Rect currentTempTaskBounds, Rect outStackBounds, Rect outTempTaskBounds) {
outTempTaskBounds.setEmpty();
+ if (dockedBounds == null || dockedBounds.isEmpty()) {
+ // Calculate the primary docked bounds.
+ final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
+ == SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
+ getStackDockedModeBounds(parentConfig,
+ true /* primary */, outStackBounds, dockedBounds,
+ mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
+ return;
+ }
+ final int dockedSide = getDockSide(parentConfig, dockedBounds);
+
// When the home stack is resizable, should always have the same stack and task bounds
if (isActivityTypeHome()) {
final Task homeTask = findHomeTask();
@@ -931,7 +809,8 @@ public class TaskStack extends WindowContainer<Task> implements
// Calculate the home stack bounds when in docked mode and the home stack is
// resizeable.
getDisplayContent().mDividerControllerLocked
- .getHomeStackBoundsInDockedMode(outStackBounds);
+ .getHomeStackBoundsInDockedMode(parentConfig,
+ dockedSide, outStackBounds);
} else {
// Home stack isn't resizeable, so don't specify stack bounds.
outStackBounds.setEmpty();
@@ -948,59 +827,37 @@ public class TaskStack extends WindowContainer<Task> implements
return;
}
- if (!inSplitScreenWindowingMode() || mDisplayContent == null) {
- outStackBounds.set(getRawBounds());
- return;
- }
-
- final TaskStack dockedStack =
- mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
- if (dockedStack == null) {
- // Not sure why you are calling this method when there is no docked stack...
- throw new IllegalStateException(
- "Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
- }
- if (!ignoreVisibility && !dockedStack.isVisible()) {
- // The docked stack is being dismissed, but we caught before it finished being
- // dismissed. In that case we want to treat it as if it is not occupying any space and
- // let others occupy the whole display.
- mDisplayContent.getBounds(outStackBounds);
- return;
- }
-
- final int dockedSide = dockedStack.getDockSide();
if (dockedSide == DOCKED_INVALID) {
// Not sure how you got here...Only thing we can do is return current bounds.
- Slog.e(TAG_WM, "Failed to get valid docked side for docked stack=" + dockedStack);
+ Slog.e(TAG_WM, "Failed to get valid docked side for docked stack");
outStackBounds.set(getRawBounds());
return;
}
- mDisplayContent.getBounds(mTmpRect);
- dockedStack.getRawBounds(mTmpRect2);
final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
- getStackDockedModeBounds(mTmpRect, outStackBounds, mTmpRect2,
+ getStackDockedModeBounds(parentConfig,
+ false /* primary */, outStackBounds, dockedBounds,
mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
-
}
/**
* Outputs the bounds a stack should be given the presence of a docked stack on the display.
- * @param displayRect The bounds of the display the docked stack is on.
+ * @param parentConfig The parent configuration.
+ * @param primary {@code true} if getting the primary stack bounds.
* @param outBounds Output bounds that should be used for the stack.
* @param dockedBounds Bounds of the docked stack.
* @param dockDividerWidth We need to know the width of the divider make to the output bounds
* close to the side of the dock.
* @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen.
*/
- private void getStackDockedModeBounds(
- Rect displayRect, Rect outBounds, Rect dockedBounds, int dockDividerWidth,
+ private void getStackDockedModeBounds(Configuration parentConfig, boolean primary,
+ Rect outBounds, Rect dockedBounds, int dockDividerWidth,
boolean dockOnTopOrLeft) {
- final boolean dockedStack = inSplitScreenPrimaryWindowingMode();
+ final Rect displayRect = parentConfig.windowConfiguration.getBounds();
final boolean splitHorizontally = displayRect.width() > displayRect.height();
outBounds.set(displayRect);
- if (dockedStack) {
+ if (primary) {
if (mService.mDockedStackCreateBounds != null) {
outBounds.set(mService.mDockedStackCreateBounds);
return;
@@ -1009,14 +866,14 @@ public class TaskStack extends WindowContainer<Task> implements
// The initial bounds of the docked stack when it is created about half the screen space
// and its bounds can be adjusted after that. The bounds of all other stacks are
// adjusted to occupy whatever screen space the docked stack isn't occupying.
- final DisplayInfo di = mDisplayContent.getDisplayInfo();
- mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
- di.displayCutout, mTmpRect2);
+ final DisplayCutout displayCutout = mDisplayContent.getDisplayInfo().displayCutout;
+ mService.mPolicy.getStableInsetsLw(parentConfig.windowConfiguration.getRotation(),
+ displayRect.width(), displayRect.height(), displayCutout, mTmpRect2);
final int position = new DividerSnapAlgorithm(mService.mContext.getResources(),
- di.logicalWidth,
- di.logicalHeight,
+ displayRect.width(),
+ displayRect.height(),
dockDividerWidth,
- mDisplayContent.getConfiguration().orientation == ORIENTATION_PORTRAIT,
+ parentConfig.orientation == ORIENTATION_PORTRAIT,
mTmpRect2).getMiddleTarget().position;
if (dockOnTopOrLeft) {
@@ -1061,8 +918,11 @@ public class TaskStack extends WindowContainer<Task> implements
final Rect bounds = new Rect();
final Rect tempBounds = new Rect();
- getStackDockedModeBoundsLocked(null /* currentTempTaskBounds */, bounds, tempBounds,
- true /*ignoreVisibility*/);
+ TaskStack dockedStack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
+ Rect dockedBounds =
+ (dockedStack == null || dockedStack == this) ? null : dockedStack.getRawBounds();
+ getStackDockedModeBoundsLocked(mDisplayContent.getConfiguration(), dockedBounds,
+ null /* currentTempTaskBounds */, bounds, tempBounds);
getController().requestResize(bounds);
}
@@ -1520,9 +1380,6 @@ public class TaskStack extends WindowContainer<Task> implements
}
private int getDockSide(DisplayContent dc, Configuration parentConfig, Rect bounds) {
- if (!inSplitScreenWindowingMode()) {
- return DOCKED_INVALID;
- }
return dc.getDockedDividerController().getDockSide(bounds,
parentConfig.windowConfiguration.getBounds(),
parentConfig.orientation, parentConfig.windowConfiguration.getRotation());
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 228ece5ab136..43e10f0a5f06 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -16,10 +16,6 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -377,64 +373,6 @@ public class DisplayContentTests extends WindowTestsBase {
verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
}
- /**
- * This test enforces that alwaysOnTop stack is placed at proper position.
- */
- @Test
- public void testAlwaysOnTopStackLocation() {
- final TaskStack alwaysOnTopStack = createStackControllerOnStackOnDisplay(
- WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
- final Task task = createTaskInStack(alwaysOnTopStack, 0 /* userId */);
- alwaysOnTopStack.setAlwaysOnTop(true);
- mDisplayContent.positionStackAt(POSITION_TOP, alwaysOnTopStack,
- false /* includingParents */);
- assertTrue(alwaysOnTopStack.isAlwaysOnTop());
- // Ensure always on top state is synced to the children of the stack.
- assertTrue(alwaysOnTopStack.getTopChild().isAlwaysOnTop());
- assertEquals(alwaysOnTopStack, mDisplayContent.getTopStack());
-
- final TaskStack pinnedStack = createStackControllerOnStackOnDisplay(
- WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
- assertEquals(pinnedStack, mDisplayContent.getPinnedStack());
- assertEquals(pinnedStack, mDisplayContent.getTopStack());
-
- final TaskStack anotherAlwaysOnTopStack = createStackControllerOnStackOnDisplay(
- WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
- anotherAlwaysOnTopStack.setAlwaysOnTop(true);
- mDisplayContent.positionStackAt(POSITION_TOP, anotherAlwaysOnTopStack,
- false /* includingParents */);
- assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
- int topPosition = mDisplayContent.getStacks().size() - 1;
- // Ensure the new alwaysOnTop stack is put below the pinned stack, but on top of the
- // existing alwaysOnTop stack.
- assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 1));
-
- final TaskStack nonAlwaysOnTopStack = createStackControllerOnStackOnDisplay(
- WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
- assertEquals(mDisplayContent, nonAlwaysOnTopStack.getDisplayContent());
- topPosition = mDisplayContent.getStacks().size() - 1;
- // Ensure the non-alwaysOnTop stack is put below the three alwaysOnTop stacks, but above the
- // existing other non-alwaysOnTop stacks.
- assertEquals(nonAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 3));
-
- anotherAlwaysOnTopStack.setAlwaysOnTop(false);
- mDisplayContent.positionStackAt(POSITION_TOP, anotherAlwaysOnTopStack,
- false /* includingParents */);
- assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
- // Ensure, when always on top is turned off for a stack, the stack is put just below all
- // other always on top stacks.
- assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 2));
- anotherAlwaysOnTopStack.setAlwaysOnTop(true);
-
- // Ensure always on top state changes properly when windowing mode changes.
- anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
- assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 2));
- anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
- assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
- assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 1));
- }
-
@Test
public void testDisplayCutout_rot0() {
synchronized (mWm.getWindowManagerLock()) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 8119837f7c81..cb2a8ec8a274 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
@@ -31,6 +32,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -217,4 +219,61 @@ public class ActivityDisplayTests extends ActivityTestsBase {
assertEquals(top, display.topRunningActivity());
assertEquals(top, display.topRunningActivity(true /* considerKeyguardState */));
}
+
+ /**
+ * This test enforces that alwaysOnTop stack is placed at proper position.
+ */
+ @Test
+ public void testAlwaysOnTopStackLocation() {
+ final ActivityDisplay display = mSupervisor.getDefaultDisplay();
+ final ActivityStack alwaysOnTopStack = display.createStack(WINDOWING_MODE_FREEFORM,
+ ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
+ .setStack(alwaysOnTopStack).build();
+ alwaysOnTopStack.setAlwaysOnTop(true);
+ display.positionChildAtTop(alwaysOnTopStack, false /* includingParents */);
+ assertTrue(alwaysOnTopStack.isAlwaysOnTop());
+ // Ensure always on top state is synced to the children of the stack.
+ assertTrue(alwaysOnTopStack.getTopActivity().isAlwaysOnTop());
+ assertEquals(alwaysOnTopStack, display.getTopStack());
+
+ final ActivityStack pinnedStack = display.createStack(
+ WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ assertEquals(pinnedStack, display.getPinnedStack());
+ assertEquals(pinnedStack, display.getTopStack());
+
+ final ActivityStack anotherAlwaysOnTopStack = display.createStack(
+ WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ anotherAlwaysOnTopStack.setAlwaysOnTop(true);
+ display.positionChildAtTop(anotherAlwaysOnTopStack, false /* includingParents */);
+ assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
+ int topPosition = display.getChildCount() - 1;
+ // Ensure the new alwaysOnTop stack is put below the pinned stack, but on top of the
+ // existing alwaysOnTop stack.
+ assertEquals(anotherAlwaysOnTopStack, display.getChildAt(topPosition - 1));
+
+ final ActivityStack nonAlwaysOnTopStack = display.createStack(
+ WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ assertEquals(display, nonAlwaysOnTopStack.getDisplay());
+ topPosition = display.getChildCount() - 1;
+ // Ensure the non-alwaysOnTop stack is put below the three alwaysOnTop stacks, but above the
+ // existing other non-alwaysOnTop stacks.
+ assertEquals(nonAlwaysOnTopStack, display.getChildAt(topPosition - 3));
+
+ anotherAlwaysOnTopStack.setAlwaysOnTop(false);
+ display.positionChildAtTop(anotherAlwaysOnTopStack, false /* includingParents */);
+ assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
+ // Ensure, when always on top is turned off for a stack, the stack is put just below all
+ // other always on top stacks.
+ assertEquals(anotherAlwaysOnTopStack, display.getChildAt(topPosition - 2));
+ anotherAlwaysOnTopStack.setAlwaysOnTop(true);
+
+ // Ensure always on top state changes properly when windowing mode changes.
+ anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
+ assertEquals(anotherAlwaysOnTopStack, display.getChildAt(topPosition - 2));
+ anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
+ assertEquals(anotherAlwaysOnTopStack, display.getChildAt(topPosition - 1));
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 0a856efd96ae..caabdbd5640d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -622,7 +622,9 @@ class ActivityTestsBase {
@Override
protected DisplayWindowController createWindowContainerController() {
- return mock(DisplayWindowController.class);
+ DisplayWindowController out = mock(DisplayWindowController.class);
+ out.mContainer = WindowTestUtils.createTestDisplayContent();
+ return out;
}
void removeAllTasks() {
@@ -812,7 +814,10 @@ class ActivityTestsBase {
@Override
PinnedStackWindowController createStackWindowController(int displayId,
boolean onTop, Rect outBounds) {
- return mock(PinnedStackWindowController.class);
+ PinnedStackWindowController controller =
+ mock(PinnedStackWindowController.class);
+ controller.mContainer = mock(TaskStack.class);
+ return controller;
}
};
} else {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 99ec0a9e2fcb..cf34fe7f802f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -77,6 +77,15 @@ public class WindowTestUtils {
}
}
+ /** Create a mocked default {@link DisplayContent}. */
+ public static TestDisplayContent createTestDisplayContent() {
+ final TestDisplayContent displayContent = mock(TestDisplayContent.class);
+ DockedStackDividerController divider = mock(DockedStackDividerController.class);
+ when(displayContent.getDockedDividerController()).thenReturn(divider);
+
+ return displayContent;
+ }
+
/**
* Creates a mock instance of {@link StackWindowController}.
*/