Merge "Move policy handling into ATM hierarchy [4/n]"
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 257122d..2990b57 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -673,6 +673,15 @@
}
/**
+ * Returns true if the windowingMode represents a split window.
+ * @hide
+ */
+ public static boolean isSplitScreenWindowingMode(int windowingMode) {
+ return windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+ }
+
+ /**
* Returns true if the windows associated with this window configuration can receive input keys.
* @hide
*/
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 54e3dee..608e450 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -717,8 +717,12 @@
// to forcing the update of the picture-in-picture mode as a part of the PiP animation.
mLastReportedPictureInPictureMode = inPictureInPictureMode;
mLastReportedMultiWindowMode = inPictureInPictureMode;
- final Configuration newConfig = task.computeNewOverrideConfigurationForBounds(
- targetStackBounds, null);
+ final Configuration newConfig = new Configuration();
+ if (targetStackBounds != null && !targetStackBounds.isEmpty()) {
+ task.computeResolvedOverrideConfiguration(newConfig,
+ task.getParent().getConfiguration(),
+ task.getRequestedOverrideConfiguration());
+ }
schedulePictureInPictureModeChanged(newConfig);
scheduleMultiWindowModeChanged(newConfig);
}
@@ -2558,12 +2562,10 @@
setBounds(mTmpBounds);
- final Rect updatedBounds = getRequestedOverrideBounds();
-
// Bounds changed...update configuration to match.
if (!matchParentBounds()) {
- task.computeOverrideConfiguration(mTmpConfig, updatedBounds,
- false /* overrideWidth */, false /* overrideHeight */);
+ task.computeResolvedOverrideConfiguration(mTmpConfig,
+ task.getParent().getConfiguration(), getRequestedOverrideConfiguration());
}
onRequestedOverrideConfigurationChanged(mTmpConfig);
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 1a6ae3e..2663d99 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -294,13 +294,6 @@
// stack and the new stack will be on top of all stacks.
static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2;
- // The height/width divide used when fitting a task within a bounds with method
- // {@link #fitWithinBounds}.
- // We always want the task to to be visible in the bounds without affecting its size when
- // fitting. To make sure this is the case, we don't adjust the task left or top side pass
- // the input bounds right or bottom side minus the width or height divided by this value.
- private static final int FIT_WITHIN_BOUNDS_DIVIDER = 3;
-
final ActivityTaskManagerService mService;
private final WindowManagerService mWindowManager;
T mWindowContainerController;
@@ -365,9 +358,9 @@
private boolean mUpdateBoundsDeferred;
private boolean mUpdateBoundsDeferredCalled;
+ private boolean mUpdateDisplayedBoundsDeferredCalled;
private final Rect mDeferredBounds = new Rect();
- private final Rect mDeferredTaskBounds = new Rect();
- private final Rect mDeferredTaskInsetBounds = new Rect();
+ private final Rect mDeferredDisplayedBounds = new Rect();
int mCurrentUser;
@@ -605,7 +598,9 @@
if (getRequestedOverrideWindowingMode() == 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 */);
+ setTaskDisplayedBounds(null);
+ setTaskBounds(mTmpRect2);
+ setBounds(mTmpRect2);
} else if (
getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
Rect dockedBounds = display.getSplitScreenPrimaryStack().getBounds();
@@ -949,17 +944,19 @@
* be resized to that bounds.
*/
void continueUpdateBounds() {
- final boolean wasDeferred = mUpdateBoundsDeferred;
- mUpdateBoundsDeferred = false;
- if (wasDeferred && mUpdateBoundsDeferredCalled) {
- resize(mDeferredBounds.isEmpty() ? null : mDeferredBounds,
- mDeferredTaskBounds.isEmpty() ? null : mDeferredTaskBounds,
- mDeferredTaskInsetBounds.isEmpty() ? null : mDeferredTaskInsetBounds);
+ if (mUpdateBoundsDeferred) {
+ mUpdateBoundsDeferred = false;
+ if (mUpdateBoundsDeferredCalled) {
+ setTaskBounds(mDeferredBounds);
+ setBounds(mDeferredBounds);
+ }
+ if (mUpdateDisplayedBoundsDeferredCalled) {
+ setTaskDisplayedBounds(mDeferredDisplayedBounds);
+ }
}
}
- boolean updateBoundsAllowed(Rect bounds, Rect tempTaskBounds,
- Rect tempTaskInsetBounds) {
+ boolean updateBoundsAllowed(Rect bounds) {
if (!mUpdateBoundsDeferred) {
return true;
}
@@ -968,20 +965,23 @@
} else {
mDeferredBounds.setEmpty();
}
- if (tempTaskBounds != null) {
- mDeferredTaskBounds.set(tempTaskBounds);
- } else {
- mDeferredTaskBounds.setEmpty();
- }
- if (tempTaskInsetBounds != null) {
- mDeferredTaskInsetBounds.set(tempTaskInsetBounds);
- } else {
- mDeferredTaskInsetBounds.setEmpty();
- }
mUpdateBoundsDeferredCalled = true;
return false;
}
+ boolean updateDisplayedBoundsAllowed(Rect bounds) {
+ if (!mUpdateBoundsDeferred) {
+ return true;
+ }
+ if (bounds != null) {
+ mDeferredDisplayedBounds.set(bounds);
+ } else {
+ mDeferredDisplayedBounds.setEmpty();
+ }
+ mUpdateDisplayedBoundsDeferredCalled = true;
+ return false;
+ }
+
@Override
public int setBounds(Rect bounds) {
return super.setBounds(!inMultiWindowMode() ? null : bounds);
@@ -4908,7 +4908,7 @@
// TODO: Can only be called from special methods in ActivityStackSupervisor.
// Need to consolidate those calls points into this resize method so anyone can call directly.
void resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds) {
- if (!updateBoundsAllowed(bounds, tempTaskBounds, tempTaskInsetBounds)) {
+ if (!updateBoundsAllowed(bounds)) {
return;
}
@@ -4922,20 +4922,7 @@
for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
final TaskRecord task = mTaskHistory.get(i);
if (task.isResizeable()) {
- if (inFreeformWindowingMode()) {
- // TODO(b/71028874): Can be removed since each freeform task is its own
- // stack.
- // For freeform stack we don't adjust the size of the tasks to match that
- // of the stack, but we do try to make sure the tasks are still contained
- // with the bounds of the stack.
- if (task.getRequestedOverrideBounds() != null) {
- mTmpRect2.set(task.getRequestedOverrideBounds());
- fitWithinBounds(mTmpRect2, bounds);
- task.updateOverrideConfiguration(mTmpRect2);
- }
- } else {
- task.updateOverrideConfiguration(taskBounds, insetBounds);
- }
+ task.updateOverrideConfiguration(taskBounds, insetBounds);
}
if (task.hasDisplayedBounds()) {
@@ -4947,7 +4934,6 @@
}
}
- mWindowContainerController.resize(bounds, mTmpBounds, mTmpInsetBounds);
setBounds(bounds);
}
@@ -4957,41 +4943,37 @@
/**
- * Adjust bounds to stay within stack bounds.
- *
- * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
- * that keep them unchanged, but be contained within the stack bounds.
- *
- * @param bounds Bounds to be adjusted.
- * @param stackBounds Bounds within which the other bounds should remain.
+ * Until we can break this "set task bounds to same as stack bounds" behavior, this
+ * basically resizes both stack and task bounds to the same bounds.
*/
- private static void fitWithinBounds(Rect bounds, Rect stackBounds) {
- if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) {
+ void setTaskBounds(Rect bounds) {
+ if (!updateBoundsAllowed(bounds)) {
return;
}
- if (bounds.left < stackBounds.left || bounds.right > stackBounds.right) {
- final int maxRight = stackBounds.right
- - (stackBounds.width() / FIT_WITHIN_BOUNDS_DIVIDER);
- int horizontalDiff = stackBounds.left - bounds.left;
- if ((horizontalDiff < 0 && bounds.left >= maxRight)
- || (bounds.left + horizontalDiff >= maxRight)) {
- horizontalDiff = maxRight - bounds.left;
+ for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
+ final TaskRecord task = mTaskHistory.get(i);
+ if (task.isResizeable()) {
+ task.setBounds(bounds);
+ } else {
+ task.setBounds(null);
}
- bounds.left += horizontalDiff;
- bounds.right += horizontalDiff;
+ }
+ }
+
+ /** Helper to setDisplayedBounds on all child tasks */
+ void setTaskDisplayedBounds(Rect bounds) {
+ if (!updateDisplayedBoundsAllowed(bounds)) {
+ return;
}
- if (bounds.top < stackBounds.top || bounds.bottom > stackBounds.bottom) {
- final int maxBottom = stackBounds.bottom
- - (stackBounds.height() / FIT_WITHIN_BOUNDS_DIVIDER);
- int verticalDiff = stackBounds.top - bounds.top;
- if ((verticalDiff < 0 && bounds.top >= maxBottom)
- || (bounds.top + verticalDiff >= maxBottom)) {
- verticalDiff = maxBottom - bounds.top;
+ for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
+ final TaskRecord task = mTaskHistory.get(i);
+ if (bounds == null || bounds.isEmpty()) {
+ task.setDisplayedBounds(null);
+ } else if (task.isResizeable()) {
+ task.setDisplayedBounds(bounds);
}
- bounds.top += verticalDiff;
- bounds.bottom += verticalDiff;
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 46ee08f..9861157 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3799,7 +3799,7 @@
// changed, so we should reflect that check here as well.
final PinnedActivityStack stack = r.getActivityStack();
final PinnedStackWindowController windowController = stack.getWindowContainerController();
- return !windowController.isAnimatingBoundsToFullscreen();
+ return !windowController.mContainer.isAnimatingBoundsToFullscreen();
}
@Override
diff --git a/services/core/java/com/android/server/wm/PinnedActivityStack.java b/services/core/java/com/android/server/wm/PinnedActivityStack.java
index 1c7ebd6..2a05af4 100644
--- a/services/core/java/com/android/server/wm/PinnedActivityStack.java
+++ b/services/core/java/com/android/server/wm/PinnedActivityStack.java
@@ -77,7 +77,7 @@
}
boolean isAnimatingBoundsToFullscreen() {
- return getWindowContainerController().isAnimatingBoundsToFullscreen();
+ return getWindowContainerController().mContainer.isAnimatingBoundsToFullscreen();
}
/**
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowController.java b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
index bbdcc62..518e39b 100644
--- a/services/core/java/com/android/server/wm/PinnedStackWindowController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
@@ -18,6 +18,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
@@ -180,15 +181,6 @@
}
/**
- * @return whether the bounds are currently animating to fullscreen.
- */
- public boolean isAnimatingBoundsToFullscreen() {
- synchronized (mGlobalLock) {
- return mContainer.isAnimatingBoundsToFullscreen();
- }
- }
-
- /**
* @return whether the stack can be resized from the bounds animation.
*/
public boolean pinnedStackResizeDisallowed() {
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index 0452977..ada807b 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -21,7 +21,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import android.app.WindowConfiguration;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Handler;
@@ -29,8 +28,6 @@
import android.os.Message;
import android.util.Slog;
import android.util.SparseArray;
-import android.view.DisplayCutout;
-import android.view.DisplayInfo;
import com.android.internal.annotations.VisibleForTesting;
@@ -49,11 +46,7 @@
private final H mHandler;
- // Temp bounds only used in adjustConfigurationForBounds()
- private final Rect mTmpRect = new Rect();
- private final Rect mTmpStableInsets = new Rect();
- private final Rect mTmpNonDecorInsets = new Rect();
- private final Rect mTmpDisplayBounds = new Rect();
+ final Rect mTmpBounds = new Rect();
public StackWindowController(int stackId, StackWindowListener listener, int displayId,
boolean onTop, Rect outBounds) {
@@ -214,126 +207,6 @@
outBounds.setEmpty();
}
- /**
- * Adjusts the screen size in dp's for the {@param config} for the given params. The provided
- * params represent the desired state of a configuration change. Since this utility is used
- * before mContainer has been updated, any relevant properties (like {@param windowingMode})
- * need to be passed in.
- */
- public void adjustConfigurationForBounds(Rect bounds,
- Rect nonDecorBounds, Rect stableBounds, boolean overrideWidth,
- boolean overrideHeight, float density, Configuration config,
- Configuration parentConfig, int windowingMode) {
- final TaskStack stack = mContainer;
- final DisplayContent displayContent = stack.getDisplayContent();
- final DisplayInfo di = displayContent.getDisplayInfo();
- final DisplayCutout displayCutout = di.displayCutout;
- final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
-
- // Get the insets and display bounds
- displayPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
- displayCutout, mTmpStableInsets);
- displayPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
- displayCutout, mTmpNonDecorInsets);
- mTmpDisplayBounds.set(0, 0, di.logicalWidth, di.logicalHeight);
-
- int width;
- int height;
-
- final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
-
- config.windowConfiguration.setBounds(bounds);
- config.windowConfiguration.setAppBounds(!bounds.isEmpty() ? bounds : null);
- boolean intersectParentBounds = false;
-
- if (WindowConfiguration.isFloating(windowingMode)) {
- // Floating tasks should not be resized to the screen's bounds.
-
- if (windowingMode == WindowConfiguration.WINDOWING_MODE_PINNED
- && bounds.width() == mTmpDisplayBounds.width()
- && bounds.height() == mTmpDisplayBounds.height()) {
- // If the bounds we are animating is the same as the fullscreen stack
- // dimensions, then apply the same inset calculations that we normally do for
- // the fullscreen stack, without intersecting it with the display bounds
- stableBounds.inset(mTmpStableInsets);
- nonDecorBounds.inset(mTmpNonDecorInsets);
- // Move app bounds to zero to apply intersection with parent correctly. They are
- // used only for evaluating width and height, so it's OK to move them around.
- config.windowConfiguration.getAppBounds().offsetTo(0, 0);
- intersectParentBounds = true;
- }
- width = (int) (stableBounds.width() / density);
- height = (int) (stableBounds.height() / density);
- } else {
- // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
- // area, i.e. the screen area without the system bars.
- // Additionally task dimensions should not be bigger than its parents dimensions.
- // The non decor inset are areas that could never be removed in Honeycomb. See
- // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
- intersectDisplayBoundsExcludeInsets(nonDecorBounds, bounds, mTmpNonDecorInsets,
- mTmpDisplayBounds, overrideWidth, overrideHeight);
- intersectDisplayBoundsExcludeInsets(stableBounds, bounds, mTmpStableInsets,
- mTmpDisplayBounds, overrideWidth, overrideHeight);
- width = Math.min((int) (stableBounds.width() / density),
- parentConfig.screenWidthDp);
- height = Math.min((int) (stableBounds.height() / density),
- parentConfig.screenHeightDp);
- intersectParentBounds = true;
- }
-
- if (intersectParentBounds && config.windowConfiguration.getAppBounds() != null) {
- config.windowConfiguration.getAppBounds().intersect(parentAppBounds);
- }
-
- config.screenWidthDp = width;
- config.screenHeightDp = height;
- config.smallestScreenWidthDp = getSmallestWidthForTaskBounds(
- bounds, density, windowingMode);
- }
-
- /**
- * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
- * inset areas.
- *
- * @param inOutBounds The inOutBounds to subtract the stable inset areas from.
- */
- private void intersectDisplayBoundsExcludeInsets(Rect inOutBounds, Rect inInsetBounds,
- Rect stableInsets, Rect displayBounds, boolean overrideWidth, boolean overrideHeight) {
- mTmpRect.set(inInsetBounds);
- mService.intersectDisplayInsetBounds(displayBounds, stableInsets, mTmpRect);
- int leftInset = mTmpRect.left - inInsetBounds.left;
- int topInset = mTmpRect.top - inInsetBounds.top;
- int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect.right;
- int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect.bottom;
- inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
- }
-
- /**
- * Calculates the smallest width for a task given the target {@param bounds} and
- * {@param windowingMode}. Avoid using values from mContainer since they can be out-of-date.
- *
- * @return the smallest width to be used in the Configuration, in dips
- */
- private int getSmallestWidthForTaskBounds(Rect bounds, float density, int windowingMode) {
- final DisplayContent displayContent = mContainer.getDisplayContent();
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-
- if (bounds == null || (bounds.width() == displayInfo.logicalWidth &&
- bounds.height() == displayInfo.logicalHeight)) {
- // If the bounds are fullscreen, return the value of the fullscreen configuration
- return displayContent.getConfiguration().smallestScreenWidthDp;
- } else if (WindowConfiguration.isFloating(windowingMode)) {
- // For floating tasks, calculate the smallest width from the bounds of the task
- return (int) (Math.min(bounds.width(), bounds.height()) / density);
- } else {
- // Iterating across all screen orientations, and return the minimum of the task
- // width taking into account that the bounds might change because the snap algorithm
- // snaps to a different value
- return displayContent.getDockedDividerController()
- .getSmallestWidthDpForBounds(bounds);
- }
- }
-
void requestResize(Rect bounds) {
mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 56e634a..5bb6440 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -27,6 +27,7 @@
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.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
@@ -85,6 +86,7 @@
import static java.lang.Integer.MAX_VALUE;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
@@ -114,6 +116,7 @@
import android.util.EventLog;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import android.view.DisplayInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
@@ -195,6 +198,13 @@
// Do not move the stack as a part of reparenting
static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
+ // The height/width divide used when fitting a task within a bounds with method
+ // {@link #fitWithinBounds}.
+ // We always want the task to to be visible in the bounds without affecting its size when
+ // fitting. To make sure this is the case, we don't adjust the task left or top side pass
+ // the input bounds right or bottom side minus the width or height divided by this value.
+ private static final int FIT_WITHIN_BOUNDS_DIVIDER = 3;
+
/**
* The factory used to create {@link TaskRecord}. This allows OEM subclass {@link TaskRecord}.
*/
@@ -300,7 +310,8 @@
private final Rect mTmpStableBounds = new Rect();
private final Rect mTmpNonDecorBounds = new Rect();
- private final Rect mTmpRect = new Rect();
+ private final Rect mTmpBounds = new Rect();
+ private final Rect mTmpInsets = new Rect();
// Last non-fullscreen bounds the task was launched in or resized to.
// The information is persisted and used to determine the appropriate stack to launch the
@@ -1714,7 +1725,7 @@
// If the task has no requested minimal size, we'd like to enforce a minimal size
// so that the user can not render the task too small to manipulate. We don't need
// to do this for the pinned stack as the bounds are controlled by the system.
- if (!inPinnedWindowingMode()) {
+ if (!inPinnedWindowingMode() && mStack != null) {
final int defaultMinSizeDp =
mService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp;
final ActivityDisplay display =
@@ -1758,31 +1769,6 @@
}
/**
- * @return a new Configuration for this Task, given the provided {@param bounds} and
- * {@param insetBounds}.
- */
- Configuration computeNewOverrideConfigurationForBounds(Rect bounds, Rect insetBounds) {
- // Compute a new override configuration for the given bounds, if fullscreen bounds
- // (bounds == null), then leave the override config unset
- final Configuration newOverrideConfig = new Configuration();
- if (bounds != null) {
- newOverrideConfig.setTo(getRequestedOverrideConfiguration());
- if (insetBounds != null && !insetBounds.isEmpty()) {
- mTmpRect.set(insetBounds);
- setDisplayedBounds(bounds);
- } else {
- mTmpRect.set(bounds);
- setDisplayedBounds(null);
- }
- adjustForMinimalTaskDimensions(mTmpRect);
- computeOverrideConfiguration(newOverrideConfig, mTmpRect,
- mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
- }
-
- return newOverrideConfig;
- }
-
- /**
* Update task's override configuration based on the bounds.
* @param bounds The bounds of the task.
* @return True if the override configuration was updated.
@@ -1808,42 +1794,21 @@
* @return True if the override configuration was updated.
*/
boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
- if (equivalentRequestedOverrideBounds(bounds)) {
+ final boolean hasSetDisplayedBounds = (insetBounds != null && !insetBounds.isEmpty());
+ if (hasSetDisplayedBounds) {
+ setDisplayedBounds(bounds);
+ } else {
+ setDisplayedBounds(null);
+ }
+ // "steady" bounds do not include any temporary offsets from animation or interaction.
+ Rect steadyBounds = hasSetDisplayedBounds ? insetBounds : bounds;
+ if (equivalentRequestedOverrideBounds(steadyBounds)) {
return false;
}
- final Rect currentBounds = getRequestedOverrideBounds();
- mTmpConfig.setTo(getRequestedOverrideConfiguration());
- final Configuration newConfig = getRequestedOverrideConfiguration();
-
- final boolean matchParentBounds = bounds == null || bounds.isEmpty();
- final boolean persistBounds = getWindowConfiguration().persistTaskBounds();
- if (matchParentBounds) {
- if (!currentBounds.isEmpty() && persistBounds) {
- setLastNonFullscreenBounds(currentBounds);
- }
- setBounds(null);
- setDisplayedBounds(null);
- newConfig.unset();
- } else {
- if (insetBounds != null && !insetBounds.isEmpty()) {
- mTmpRect.set(insetBounds);
- setDisplayedBounds(bounds);
- } else {
- mTmpRect.set(bounds);
- setDisplayedBounds(null);
- }
- adjustForMinimalTaskDimensions(mTmpRect);
- setBounds(mTmpRect);
-
- if (mStack == null || persistBounds) {
- setLastNonFullscreenBounds(getRequestedOverrideBounds());
- }
- computeOverrideConfiguration(newConfig, mTmpRect,
- mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
- }
- onRequestedOverrideConfigurationChanged(newConfig);
- return !mTmpConfig.equals(newConfig);
+ mTmpConfig.setTo(getResolvedOverrideConfiguration());
+ setBounds(steadyBounds);
+ return !mTmpConfig.equals(getResolvedOverrideConfiguration());
}
/**
@@ -1869,6 +1834,12 @@
if (wasInMultiWindowMode != inMultiWindowMode()) {
mService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
}
+ if (getWindowConfiguration().persistTaskBounds()) {
+ final Rect currentBounds = getRequestedOverrideBounds();
+ if (!currentBounds.isEmpty()) {
+ setLastNonFullscreenBounds(currentBounds);
+ }
+ }
// TODO: Should also take care of Pip mode changes here.
saveLaunchingStateIfNeeded();
@@ -1896,6 +1867,45 @@
}
/**
+ * Adjust bounds to stay within stack bounds.
+ *
+ * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
+ * that keep them unchanged, but be contained within the stack bounds.
+ *
+ * @param bounds Bounds to be adjusted.
+ * @param stackBounds Bounds within which the other bounds should remain.
+ */
+ private static void fitWithinBounds(Rect bounds, Rect stackBounds) {
+ if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) {
+ return;
+ }
+
+ if (bounds.left < stackBounds.left || bounds.right > stackBounds.right) {
+ final int maxRight = stackBounds.right
+ - (stackBounds.width() / FIT_WITHIN_BOUNDS_DIVIDER);
+ int horizontalDiff = stackBounds.left - bounds.left;
+ if ((horizontalDiff < 0 && bounds.left >= maxRight)
+ || (bounds.left + horizontalDiff >= maxRight)) {
+ horizontalDiff = maxRight - bounds.left;
+ }
+ bounds.left += horizontalDiff;
+ bounds.right += horizontalDiff;
+ }
+
+ if (bounds.top < stackBounds.top || bounds.bottom > stackBounds.bottom) {
+ final int maxBottom = stackBounds.bottom
+ - (stackBounds.height() / FIT_WITHIN_BOUNDS_DIVIDER);
+ int verticalDiff = stackBounds.top - bounds.top;
+ if ((verticalDiff < 0 && bounds.top >= maxBottom)
+ || (bounds.top + verticalDiff >= maxBottom)) {
+ verticalDiff = maxBottom - bounds.top;
+ }
+ bounds.top += verticalDiff;
+ bounds.bottom += verticalDiff;
+ }
+ }
+
+ /**
* Displayed bounds are used to set where the task is drawn at any given time. This is
* separate from its actual bounds so that the app doesn't see any meaningful configuration
* changes during transitionary periods.
@@ -1927,46 +1937,205 @@
return !mDisplayedBounds.isEmpty();
}
- /** Clears passed config and fills it with new override values. */
- // TODO(b/36505427): TaskRecord.computeOverrideConfiguration() is a utility method that doesn't
- // depend on task or stacks, but uses those object to get the display to base the calculation
- // on. Probably best to centralize calculations like this in ConfigurationContainer.
- void computeOverrideConfiguration(Configuration config, Rect bounds,
- boolean overrideWidth, boolean overrideHeight) {
- mTmpNonDecorBounds.set(bounds);
- mTmpStableBounds.set(bounds);
+ /**
+ * Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
+ * intersectBounds on a side, then the respective side will not be intersected.
+ *
+ * The assumption is that if inOutBounds is initially larger than intersectBounds, then the
+ * inset on that side is no-longer applicable. This scenario happens when a task's minimal
+ * bounds are larger than the provided parent/display bounds.
+ *
+ * @param inOutBounds the bounds to intersect.
+ * @param intersectBounds the bounds to intersect with.
+ * @param intersectInsets insets to apply to intersectBounds before intersecting.
+ */
+ private static void intersectWithInsetsIfFits(
+ Rect inOutBounds, Rect intersectBounds, Rect intersectInsets) {
+ if (inOutBounds.right <= intersectBounds.right) {
+ inOutBounds.right =
+ Math.min(intersectBounds.right - intersectInsets.right, inOutBounds.right);
+ }
+ if (inOutBounds.bottom <= intersectBounds.bottom) {
+ inOutBounds.bottom =
+ Math.min(intersectBounds.bottom - intersectInsets.bottom, inOutBounds.bottom);
+ }
+ if (inOutBounds.left >= intersectBounds.left) {
+ inOutBounds.left =
+ Math.max(intersectBounds.left + intersectInsets.left, inOutBounds.left);
+ }
+ if (inOutBounds.top >= intersectBounds.top) {
+ inOutBounds.top =
+ Math.max(intersectBounds.top + intersectInsets.top, inOutBounds.top);
+ }
+ }
- config.unset();
- final Configuration parentConfig = getParent().getConfiguration();
+ /**
+ * Gets bounds with non-decor and stable insets applied respectively.
+ *
+ * If bounds overhangs the display, those edges will not get insets. See
+ * {@link #intersectWithInsetsIfFits}
+ *
+ * @param outNonDecorBounds where to place bounds with non-decor insets applied.
+ * @param outStableBounds where to place bounds with stable insets applied.
+ * @param bounds the bounds to inset.
+ */
+ private void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds,
+ DisplayInfo displayInfo) {
+ outNonDecorBounds.set(bounds);
+ outStableBounds.set(bounds);
+ if (getStack() == null || getStack().getDisplay() == null) {
+ return;
+ }
+ DisplayPolicy policy = getStack().getDisplay().mDisplayContent.getDisplayPolicy();
+ if (policy == null) {
+ return;
+ }
+ mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
- final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+ policy.getStableInsetsLw(displayInfo.rotation,
+ displayInfo.logicalWidth, displayInfo.logicalHeight, displayInfo.displayCutout,
+ mTmpInsets);
+ intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);
- if (mStack != null) {
- final StackWindowController stackController = mStack.getWindowContainerController();
- stackController.adjustConfigurationForBounds(bounds,
- mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
- config, parentConfig, getWindowingMode());
- } else {
- throw new IllegalArgumentException("Expected stack when calculating override config");
+ policy.getNonDecorInsetsLw(displayInfo.rotation,
+ displayInfo.logicalWidth, displayInfo.logicalHeight, displayInfo.displayCutout,
+ mTmpInsets);
+ intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, mTmpInsets);
+ }
+
+ /**
+ * Asks docked-divider controller for the smallestwidthdp given bounds.
+ * @param bounds bounds to calculate smallestwidthdp for.
+ */
+ private int getSmallestScreenWidthDpForDockedBounds(Rect bounds) {
+ DisplayContent dc = mStack.getDisplay().mDisplayContent;
+ if (dc != null) {
+ return dc.getDockedDividerController().getSmallestWidthDpForBounds(bounds);
+ }
+ return Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
+ }
+
+ /**
+ * Calculates configuration values used by the client to get resources. This should be run
+ * using app-facing bounds (bounds unmodified by animations or transient interactions).
+ *
+ * This assumes bounds are non-empty/null. For the null-bounds case, the caller is likely
+ * configuring an "inherit-bounds" window which means that all configuration settings would
+ * just be inherited from the parent configuration.
+ **/
+ void computeConfigResourceOverrides(@NonNull Configuration inOutConfig, @NonNull Rect bounds,
+ @NonNull Configuration parentConfig) {
+ int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
+ if (windowingMode == WINDOWING_MODE_UNDEFINED) {
+ windowingMode = parentConfig.windowConfiguration.getWindowingMode();
}
- config.orientation = (config.screenWidthDp <= config.screenHeightDp)
- ? Configuration.ORIENTATION_PORTRAIT
- : Configuration.ORIENTATION_LANDSCAPE;
+ float density = inOutConfig.densityDpi;
+ if (density == Configuration.DENSITY_DPI_UNDEFINED) {
+ density = parentConfig.densityDpi;
+ }
+ density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
- // For calculating screen layout, we need to use the non-decor inset screen area for the
- // calculation for compatibility reasons, i.e. screen area without system bars that could
- // never go away in Honeycomb.
- final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
- final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
- // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start override
- // calculation with partial default.
- // Reducing the screen layout starting from its parent config.
- final int sl = parentConfig.screenLayout &
- (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
- final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
- final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
- config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
+ Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
+ if (outAppBounds == null || outAppBounds.isEmpty()) {
+ inOutConfig.windowConfiguration.setAppBounds(bounds);
+ outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
+ }
+ if (windowingMode != WINDOWING_MODE_FREEFORM) {
+ final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
+ if (parentAppBounds != null && !parentAppBounds.isEmpty()) {
+ outAppBounds.intersect(parentAppBounds);
+ }
+ }
+
+ if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
+ || inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
+ if (mStack != null) {
+ final DisplayInfo di = new DisplayInfo();
+ mStack.getDisplay().mDisplay.getDisplayInfo(di);
+
+ // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
+ // area, i.e. the screen area without the system bars.
+ // The non decor inset are areas that could never be removed in Honeycomb. See
+ // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
+ calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, bounds, di);
+ } else {
+ mTmpNonDecorBounds.set(bounds);
+ mTmpStableBounds.set(bounds);
+ }
+
+ if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
+ inOutConfig.screenWidthDp = Math.min((int) (mTmpStableBounds.width() / density),
+ parentConfig.screenWidthDp);
+ }
+ if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
+ inOutConfig.screenHeightDp = Math.min((int) (mTmpStableBounds.height() / density),
+ parentConfig.screenHeightDp);
+ }
+
+ if (inOutConfig.smallestScreenWidthDp
+ == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
+ if (WindowConfiguration.isFloating(windowingMode)) {
+ // For floating tasks, calculate the smallest width from the bounds of the task
+ inOutConfig.smallestScreenWidthDp = (int) (
+ Math.min(bounds.width(), bounds.height()) / density);
+ } else if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) {
+ // Iterating across all screen orientations, and return the minimum of the task
+ // width taking into account that the bounds might change because the snap
+ // algorithm snaps to a different value
+ getSmallestScreenWidthDpForDockedBounds(bounds);
+ }
+ // otherwise, it will just inherit
+ }
+ }
+
+ if (inOutConfig.orientation == Configuration.ORIENTATION_UNDEFINED) {
+ inOutConfig.orientation = (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
+ ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE;
+ }
+ if (inOutConfig.screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
+ // For calculating screen layout, we need to use the non-decor inset screen area for the
+ // calculation for compatibility reasons, i.e. screen area without system bars that
+ // could never go away in Honeycomb.
+ final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
+ final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
+ // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start
+ // override calculation with partial default.
+ // Reducing the screen layout starting from its parent config.
+ final int sl = parentConfig.screenLayout
+ & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
+ final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
+ final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
+ inOutConfig.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
+ }
+ }
+
+ // TODO(b/113900640): remove this once ActivityRecord is changed to not need it anymore.
+ void computeResolvedOverrideConfiguration(Configuration inOutConfig, Configuration parentConfig,
+ Configuration overrideConfig) {
+ inOutConfig.setTo(overrideConfig);
+
+ Rect outOverrideBounds = inOutConfig.windowConfiguration.getBounds();
+ if (outOverrideBounds != null && !outOverrideBounds.isEmpty()) {
+ adjustForMinimalTaskDimensions(outOverrideBounds);
+
+ int windowingMode = overrideConfig.windowConfiguration.getWindowingMode();
+ if (windowingMode == WINDOWING_MODE_UNDEFINED) {
+ windowingMode = parentConfig.windowConfiguration.getWindowingMode();
+ }
+ if (windowingMode == WINDOWING_MODE_FREEFORM) {
+ // by policy, make sure the window remains within parent
+ fitWithinBounds(outOverrideBounds, parentConfig.windowConfiguration.getBounds());
+ }
+
+ computeConfigResourceOverrides(inOutConfig, outOverrideBounds, parentConfig);
+ }
+ }
+
+ @Override
+ void resolveOverrideConfiguration(Configuration newParentConfig) {
+ computeResolvedOverrideConfiguration(getResolvedOverrideConfiguration(), newParentConfig,
+ getRequestedOverrideConfiguration());
}
Rect updateOverrideConfigurationFromLaunchBounds() {
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 630a8bf..6b6b33c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -16,6 +16,9 @@
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.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
@@ -31,10 +34,12 @@
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.service.voice.IVoiceInteractionSession;
import android.util.Xml;
+import android.view.DisplayInfo;
import androidx.test.filters.MediumTest;
@@ -66,10 +71,13 @@
private static final String TASK_TAG = "task";
+ private Rect mParentBounds;
+
@Before
public void setUp() throws Exception {
TaskRecord.setTaskRecordFactory(null);
setupActivityTaskManagerService();
+ mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/);
}
@Test
@@ -124,6 +132,72 @@
assertTrue(task.returnsToHomeStack());
}
+ /** Ensures that bounds are clipped to their parent. */
+ @Test
+ public void testAppBounds_BoundsClipping() {
+ final Rect shiftedBounds = new Rect(mParentBounds);
+ shiftedBounds.offset(10, 10);
+ final Rect expectedBounds = new Rect(mParentBounds);
+ expectedBounds.intersect(shiftedBounds);
+ testStackBoundsConfiguration(WINDOWING_MODE_FULLSCREEN, mParentBounds, shiftedBounds,
+ expectedBounds);
+ }
+
+ /** Ensures that empty bounds are not propagated to the configuration. */
+ @Test
+ public void testAppBounds_EmptyBounds() {
+ final Rect emptyBounds = new Rect();
+ testStackBoundsConfiguration(WINDOWING_MODE_FULLSCREEN, mParentBounds, emptyBounds,
+ null /*ExpectedBounds*/);
+ }
+
+ /** Ensures that bounds on freeform stacks are not clipped. */
+ @Test
+ public void testAppBounds_FreeFormBounds() {
+ final Rect freeFormBounds = new Rect(mParentBounds);
+ freeFormBounds.offset(10, 10);
+ testStackBoundsConfiguration(WINDOWING_MODE_FREEFORM, mParentBounds, freeFormBounds,
+ freeFormBounds);
+ }
+
+ /** Ensures that fully contained bounds are not clipped. */
+ @Test
+ public void testAppBounds_ContainedBounds() {
+ final Rect insetBounds = new Rect(mParentBounds);
+ insetBounds.inset(5, 5, 5, 5);
+ testStackBoundsConfiguration(
+ WINDOWING_MODE_FULLSCREEN, mParentBounds, insetBounds, insetBounds);
+ }
+
+ /** Ensures that full screen free form bounds are clipped */
+ @Test
+ public void testAppBounds_FullScreenFreeFormBounds() {
+ ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
+ DisplayInfo info = new DisplayInfo();
+ display.mDisplay.getDisplayInfo(info);
+ final Rect fullScreenBounds = new Rect(0, 0, info.logicalWidth, info.logicalHeight);
+ testStackBoundsConfiguration(WINDOWING_MODE_FULLSCREEN, mParentBounds, fullScreenBounds,
+ mParentBounds);
+ }
+
+ private void testStackBoundsConfiguration(int windowingMode, Rect parentBounds, Rect bounds,
+ Rect expectedConfigBounds) {
+
+ ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
+ ActivityStack stack = display.createStack(windowingMode, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
+
+ final Configuration parentConfig = stack.getConfiguration();
+ parentConfig.windowConfiguration.setAppBounds(parentBounds);
+ task.setBounds(bounds);
+
+ task.resolveOverrideConfiguration(parentConfig);
+ // Assert that both expected and actual are null or are equal to each other
+ assertEquals(expectedConfigBounds,
+ task.getResolvedOverrideConfiguration().windowConfiguration.getAppBounds());
+ }
+
private byte[] serializeToBytes(TaskRecord r) throws IOException, XmlPullParserException {
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
final XmlSerializer serializer = Xml.newSerializer();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
index 885a7e0..c653762f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
@@ -19,7 +19,6 @@
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.WINDOW_CONFIG_ALWAYS_ON_TOP;
import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
import static android.app.WindowConfiguration.WINDOW_CONFIG_ROTATION;
@@ -174,70 +173,4 @@
assertEquals(appBounds.width(), info.appWidth);
assertEquals(appBounds.height(), info.appHeight);
}
-
- /** Ensures that bounds are clipped to their parent. */
- @Test
- public void testAppBounds_BoundsClipping() {
- final Rect shiftedBounds = new Rect(mParentBounds);
- shiftedBounds.offset(10, 10);
- final Rect expectedBounds = new Rect(mParentBounds);
- expectedBounds.intersect(shiftedBounds);
- testStackBoundsConfiguration(WINDOWING_MODE_FULLSCREEN, mParentBounds, shiftedBounds,
- expectedBounds);
- }
-
- /** Ensures that empty bounds are not propagated to the configuration. */
- @Test
- public void testAppBounds_EmptyBounds() {
- final Rect emptyBounds = new Rect();
- testStackBoundsConfiguration(WINDOWING_MODE_FULLSCREEN, mParentBounds, emptyBounds,
- null /*ExpectedBounds*/);
- }
-
- /** Ensures that bounds on freeform stacks are not clipped. */
- @Test
- public void testAppBounds_FreeFormBounds() {
- final Rect freeFormBounds = new Rect(mParentBounds);
- freeFormBounds.offset(10, 10);
- testStackBoundsConfiguration(WINDOWING_MODE_FREEFORM, mParentBounds, freeFormBounds,
- freeFormBounds);
- }
-
- /** Ensures that fully contained bounds are not clipped. */
- @Test
- public void testAppBounds_ContainedBounds() {
- final Rect insetBounds = new Rect(mParentBounds);
- insetBounds.inset(5, 5, 5, 5);
- testStackBoundsConfiguration(
- WINDOWING_MODE_FULLSCREEN, mParentBounds, insetBounds, insetBounds);
- }
-
- /** Ensures that full screen free form bounds are clipped */
- @Test
- public void testAppBounds_FullScreenFreeFormBounds() {
- final Rect fullScreenBounds = new Rect(0, 0, mDisplayInfo.logicalWidth,
- mDisplayInfo.logicalHeight);
- testStackBoundsConfiguration(WINDOWING_MODE_FULLSCREEN, mParentBounds, fullScreenBounds,
- mParentBounds);
- }
-
- private void testStackBoundsConfiguration(int windowingMode, Rect parentBounds, Rect bounds,
- Rect expectedConfigBounds) {
- final StackWindowController stackController = createStackControllerOnStackOnDisplay(
- windowingMode, ACTIVITY_TYPE_STANDARD, mDisplayContent);
-
- final Configuration parentConfig = mDisplayContent.getConfiguration();
- parentConfig.windowConfiguration.setAppBounds(parentBounds);
-
- final Configuration config = new Configuration();
- final WindowConfiguration winConfig = config.windowConfiguration;
- stackController.adjustConfigurationForBounds(bounds,
- new Rect() /*nonDecorBounds*/, new Rect() /*stableBounds*/, false /*overrideWidth*/,
- false /*overrideHeight*/, mDisplayInfo.logicalDensityDpi, config, parentConfig,
- windowingMode);
- // Assert that both expected and actual are null or are equal to each other
-
- assertEquals(expectedConfigBounds, winConfig.getAppBounds());
- }
-
}
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 3170f5a..65cde77 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -19,11 +19,6 @@
import static android.app.AppOpsManager.OP_NONE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyFloat;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -34,8 +29,6 @@
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
import android.view.Display;
@@ -45,8 +38,6 @@
import android.view.SurfaceControl.Transaction;
import android.view.WindowManager;
-import org.mockito.invocation.InvocationOnMock;
-
/**
* A collection of static functions that can be referenced by other test packages to provide access
* to WindowManager related test functionality.
@@ -116,17 +107,6 @@
public static StackWindowController createMockStackWindowContainerController() {
StackWindowController controller = mock(StackWindowController.class);
controller.mContainer = mock(TestTaskStack.class);
-
- // many components rely on the {@link StackWindowController#adjustConfigurationForBounds}
- // to properly set bounds values in the configuration. We must mimick those actions here.
- doAnswer((InvocationOnMock invocationOnMock) -> {
- final Configuration config = invocationOnMock.<Configuration>getArgument(6);
- final Rect bounds = invocationOnMock.<Rect>getArgument(0);
- config.windowConfiguration.setBounds(bounds);
- return null;
- }).when(controller).adjustConfigurationForBounds(any(), any(), any(),
- anyBoolean(), anyBoolean(), anyFloat(), any(), any(), anyInt());
-
return controller;
}