Support for setting stack windowing mode
We currently create a in stack in the windowing mode we want anytime we
want to change the windowing mode of a task which isn't optimal.
We now change the current stack windowing mode for some cases vs.
creating a new stack.
Test: go/wm-smoke
Bug: 64146578
Fixes: 68948655
Fixes: 65739235
Fixes: 29068935
Change-Id: I9fceb7d608e86610c1fb5ba59b15087a96e7401e
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c4b810f..4d839d0 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
@@ -1488,7 +1489,7 @@
* Returns the topmost stack on the display that is compatible with the input windowing mode.
* Null is no compatible stack on the display.
*/
- TaskStack getStack(int windowingMode) {
+ TaskStack getTopStackInWindowingMode(int windowingMode) {
return getStack(windowingMode, ACTIVITY_TYPE_UNDEFINED);
}
@@ -1764,10 +1765,6 @@
final TaskStack stack = new TaskStack(mService, stackId, controller);
mTaskStackContainers.addStackToDisplay(stack, onTop);
-
- if (stack.inSplitScreenPrimaryWindowingMode()) {
- mDividerControllerLocked.notifyDockedStackExistsChanged(true);
- }
return stack;
}
@@ -2274,7 +2271,7 @@
/** Returns true if the stack in the windowing mode is visible. */
boolean isStackVisible(int windowingMode) {
- final TaskStack stack = getStack(windowingMode);
+ final TaskStack stack = getTopStackInWindowingMode(windowingMode);
return stack != null && stack.isVisible();
}
@@ -3391,6 +3388,12 @@
}
for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
final TaskStack stack = mTaskStackContainers.getChildAt(i);
+ if (activityType == ACTIVITY_TYPE_UNDEFINED
+ && windowingMode == stack.getWindowingMode()) {
+ // Passing in undefined type means we want to match the topmost stack with the
+ // windowing mode.
+ return stack;
+ }
if (stack.isCompatible(windowingMode, activityType)) {
return stack;
}
@@ -3461,6 +3464,7 @@
+ " already exist on display=" + this + " stack=" + stack);
}
mSplitScreenPrimaryStack = stack;
+ mDividerControllerLocked.notifyDockedStackExistsChanged(true);
}
}
@@ -3471,6 +3475,10 @@
mPinnedStack = null;
} else if (stack == mSplitScreenPrimaryStack) {
mSplitScreenPrimaryStack = null;
+ // Re-set the split-screen create mode whenever the split-screen stack is removed.
+ mService.setDockedStackCreateStateLocked(
+ SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */);
+ mDividerControllerLocked.notifyDockedStackExistsChanged(false);
}
}
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index e693e5a..d79ba89 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -559,7 +559,7 @@
void setResizeDimLayer(boolean visible, int targetWindowingMode, float alpha) {
// TODO: Maybe only allow split-screen windowing modes?
final TaskStack stack = targetWindowingMode != WINDOWING_MODE_UNDEFINED
- ? mDisplayContent.getStack(targetWindowingMode)
+ ? mDisplayContent.getTopStackInWindowingMode(targetWindowingMode)
: null;
final TaskStack dockedStack = mDisplayContent.getSplitScreenPrimaryStack();
boolean visibleAndValid = visible && stack != null && dockedStack != null;
@@ -663,11 +663,15 @@
if (mMinimizedDock && mService.mPolicy.isKeyguardShowingAndNotOccluded()) {
return;
}
- final TaskStack fullscreenStack = mDisplayContent.getStack(
+ final TaskStack topSecondaryStack = mDisplayContent.getTopStackInWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
- final boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
- final boolean homeBehind = fullscreenStack != null && fullscreenStack.isVisible();
- setMinimizedDockedStack(homeVisible && !homeBehind, animate);
+ boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
+ if (homeVisible && topSecondaryStack != null) {
+ // Home should only be considered visible if it is greater or equal to the top secondary
+ // stack in terms of z-order.
+ homeVisible = homeStack.compareTo(topSecondaryStack) >= 0;
+ }
+ setMinimizedDockedStack(homeVisible, animate);
}
private boolean isWithinDisplay(Task task) {
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index aff1bc6..95c1d53 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -225,11 +225,13 @@
}
}
- private void getRawBounds(Rect outBounds) {
- if (mContainer.getRawFullscreen()) {
- outBounds.setEmpty();
- } else {
- mContainer.getRawBounds(outBounds);
+ public void getRawBounds(Rect outBounds) {
+ synchronized (mWindowMap) {
+ if (mContainer.getRawFullscreen()) {
+ outBounds.setEmpty();
+ } else {
+ mContainer.getRawBounds(outBounds);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index dde7946..053fb47 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -685,9 +685,12 @@
public void onConfigurationChanged(Configuration newParentConfig) {
final int prevWindowingMode = getWindowingMode();
super.onConfigurationChanged(newParentConfig);
- if (mDisplayContent != null && prevWindowingMode != getWindowingMode()) {
- mDisplayContent.onStackWindowingModeChanged(this);
+ final int windowingMode = getWindowingMode();
+ if (mDisplayContent == null || prevWindowingMode == windowingMode) {
+ return;
}
+ mDisplayContent.onStackWindowingModeChanged(this);
+ updateBoundsForWindowModeChange();
}
@Override
@@ -699,39 +702,41 @@
mDisplayContent = dc;
mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId(),
"animation background stackId=" + mStackId);
+ updateBoundsForWindowModeChange();
+ super.onDisplayChanged(dc);
+ }
+ private void updateBoundsForWindowModeChange() {
Rect bounds = null;
- final TaskStack dockedStack = dc.getSplitScreenPrimaryStackIgnoringVisibility();
- if (inSplitScreenPrimaryWindowingMode()
- || (dockedStack != null && inSplitScreenSecondaryWindowingMode()
- && !dockedStack.fillsParent())) {
+ 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.
bounds = new Rect();
- dc.getLogicalDisplayRect(mTmpRect);
+ mDisplayContent.getLogicalDisplayRect(mTmpRect);
mTmpRect2.setEmpty();
- if (dockedStack != null) {
- dockedStack.getRawBounds(mTmpRect2);
+ if (splitScreenStack != null) {
+ splitScreenStack.getRawBounds(mTmpRect2);
}
final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
== SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
getStackDockedModeBounds(mTmpRect, bounds, mTmpRect2,
- mDisplayContent.mDividerControllerLocked.getContentWidth(),
- dockedOnTopOrLeft);
+ mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
} else if (inPinnedWindowingMode()) {
// Update the bounds based on any changes to the display info
getAnimationOrCurrentBounds(mTmpRect2);
- boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
- mTmpRect2, mTmpRect3);
- if (updated) {
+ if (mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
+ mTmpRect2, mTmpRect3)) {
bounds = new Rect(mTmpRect3);
}
}
updateDisplayInfo(bounds);
- super.onDisplayChanged(dc);
}
/**
@@ -922,10 +927,6 @@
mAnimationBackgroundSurface = null;
}
- if (inSplitScreenPrimaryWindowingMode()) {
- mDisplayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(false);
- }
-
mDisplayContent = null;
mService.mWindowPlacerLocked.requestTraversal();
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index df51be1..723b888 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -6860,11 +6860,16 @@
public void setWillReplaceWindow(IBinder token, boolean animate) {
synchronized (mWindowMap) {
final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
- if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) {
+ if (appWindowToken == null) {
Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
+ token);
return;
}
+ if (!appWindowToken.hasContentToDisplay()) {
+ Slog.w(TAG_WM, "Attempted to set replacing window on app token with no content"
+ + token);
+ return;
+ }
appWindowToken.setWillReplaceWindows(animate);
}
}
@@ -6884,11 +6889,16 @@
void setWillReplaceWindows(IBinder token, boolean childrenOnly) {
synchronized (mWindowMap) {
final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
- if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) {
+ if (appWindowToken == null) {
Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
+ token);
return;
}
+ if (!appWindowToken.hasContentToDisplay()) {
+ Slog.w(TAG_WM, "Attempted to set replacing window on app token with no content"
+ + token);
+ return;
+ }
if (childrenOnly) {
appWindowToken.setWillReplaceChildWindows();