Merge "Store bounds in WindowConfiguration."
diff --git a/api/test-current.txt b/api/test-current.txt
index 2e6c40a..8647ed3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -75,9 +75,11 @@
     method public int describeContents();
     method public int getActivityType();
     method public android.graphics.Rect getAppBounds();
+    method public android.graphics.Rect getBounds();
     method public int getWindowingMode();
     method public void setActivityType(int);
     method public void setAppBounds(android.graphics.Rect);
+    method public void setBounds(android.graphics.Rect);
     method public void setTo(android.app.WindowConfiguration);
     method public void setWindowingMode(int);
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 2c1fad1..80399ae 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -40,6 +40,13 @@
  */
 @TestApi
 public class WindowConfiguration implements Parcelable, Comparable<WindowConfiguration> {
+    /**
+     * bounds that can differ from app bounds, which may include things such as insets.
+     *
+     * TODO: Investigate combining with {@link mAppBounds}. Can the latter be a product of the
+     * former?
+     */
+    private Rect mBounds = new Rect();
 
     /**
      * {@link android.graphics.Rect} defining app bounds. The dimensions override usages of
@@ -117,22 +124,26 @@
     })
     public @interface ActivityType {}
 
+    /** Bit that indicates that the {@link #mBounds} changed.
+     * @hide */
+    public static final int WINDOW_CONFIG_BOUNDS = 1 << 0;
     /** Bit that indicates that the {@link #mAppBounds} changed.
      * @hide */
-    public static final int WINDOW_CONFIG_APP_BOUNDS = 1 << 0;
+    public static final int WINDOW_CONFIG_APP_BOUNDS = 1 << 1;
     /** Bit that indicates that the {@link #mWindowingMode} changed.
      * @hide */
-    public static final int WINDOW_CONFIG_WINDOWING_MODE = 1 << 1;
+    public static final int WINDOW_CONFIG_WINDOWING_MODE = 1 << 2;
     /** Bit that indicates that the {@link #mActivityType} changed.
      * @hide */
-    public static final int WINDOW_CONFIG_ACTIVITY_TYPE = 1 << 2;
+    public static final int WINDOW_CONFIG_ACTIVITY_TYPE = 1 << 3;
 
     /** @hide */
     @IntDef(flag = true,
             value = {
+                    WINDOW_CONFIG_BOUNDS,
                     WINDOW_CONFIG_APP_BOUNDS,
                     WINDOW_CONFIG_WINDOWING_MODE,
-                    WINDOW_CONFIG_ACTIVITY_TYPE,
+                    WINDOW_CONFIG_ACTIVITY_TYPE
             })
     public @interface WindowConfig {}
 
@@ -151,12 +162,14 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mBounds, flags);
         dest.writeParcelable(mAppBounds, flags);
         dest.writeInt(mWindowingMode);
         dest.writeInt(mActivityType);
     }
 
     private void readFromParcel(Parcel source) {
+        mBounds = source.readParcelable(Rect.class.getClassLoader());
         mAppBounds = source.readParcelable(Rect.class.getClassLoader());
         mWindowingMode = source.readInt();
         mActivityType = source.readInt();
@@ -181,6 +194,19 @@
     };
 
     /**
+     * Sets the bounds to the provided {@link Rect}.
+     * @param rect the new bounds value.
+     */
+    public void setBounds(Rect rect) {
+        if (rect == null) {
+            mBounds.setEmpty();
+            return;
+        }
+
+        mBounds.set(rect);
+    }
+
+    /**
      * Set {@link #mAppBounds} to the input Rect.
      * @param rect The rect value to set {@link #mAppBounds} to.
      * @see #getAppBounds()
@@ -212,6 +238,11 @@
         return mAppBounds;
     }
 
+    /** @see #setBounds(Rect) */
+    public Rect getBounds() {
+        return mBounds;
+    }
+
     public void setWindowingMode(@WindowingMode int windowingMode) {
         mWindowingMode = windowingMode;
     }
@@ -244,6 +275,7 @@
     }
 
     public void setTo(WindowConfiguration other) {
+        setBounds(other.mBounds);
         setAppBounds(other.mAppBounds);
         setWindowingMode(other.mWindowingMode);
         setActivityType(other.mActivityType);
@@ -258,6 +290,7 @@
     /** @hide */
     public void setToDefaults() {
         setAppBounds(null);
+        setBounds(null);
         setWindowingMode(WINDOWING_MODE_UNDEFINED);
         setActivityType(ACTIVITY_TYPE_UNDEFINED);
     }
@@ -272,6 +305,11 @@
      */
     public @WindowConfig int updateFrom(@NonNull WindowConfiguration delta) {
         int changed = 0;
+        // Only allow override if bounds is not empty
+        if (!delta.mBounds.isEmpty() && !delta.mBounds.equals(mBounds)) {
+            changed |= WINDOW_CONFIG_BOUNDS;
+            setBounds(delta.mBounds);
+        }
         if (delta.mAppBounds != null && !delta.mAppBounds.equals(mAppBounds)) {
             changed |= WINDOW_CONFIG_APP_BOUNDS;
             setAppBounds(delta.mAppBounds);
@@ -303,6 +341,10 @@
     public @WindowConfig long diff(WindowConfiguration other, boolean compareUndefined) {
         long changes = 0;
 
+        if (!mBounds.equals(other.mBounds)) {
+            changes |= WINDOW_CONFIG_BOUNDS;
+        }
+
         // Make sure that one of the values is not null and that they are not equal.
         if ((compareUndefined || other.mAppBounds != null)
                 && mAppBounds != other.mAppBounds
@@ -340,6 +382,16 @@
             n = mAppBounds.bottom - that.mAppBounds.bottom;
             if (n != 0) return n;
         }
+
+        n = mBounds.left - that.mBounds.left;
+        if (n != 0) return n;
+        n = mBounds.top - that.mBounds.top;
+        if (n != 0) return n;
+        n = mBounds.right - that.mBounds.right;
+        if (n != 0) return n;
+        n = mBounds.bottom - that.mBounds.bottom;
+        if (n != 0) return n;
+
         n = mWindowingMode - that.mWindowingMode;
         if (n != 0) return n;
         n = mActivityType - that.mActivityType;
@@ -367,6 +419,8 @@
         if (mAppBounds != null) {
             result = 31 * result + mAppBounds.hashCode();
         }
+        result = 31 * result + mBounds.hashCode();
+
         result = 31 * result + mWindowingMode;
         result = 31 * result + mActivityType;
         return result;
@@ -375,7 +429,8 @@
     /** @hide */
     @Override
     public String toString() {
-        return "{mAppBounds=" + mAppBounds
+        return "{ mBounds=" + mBounds
+                + " mAppBounds=" + mAppBounds
                 + " mWindowingMode=" + windowingModeToString(mWindowingMode)
                 + " mActivityType=" + activityTypeToString(mActivityType) + "}";
     }
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 2289f85..3dbee42 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -42,6 +42,8 @@
 import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
 import android.app.WindowConfiguration;
+import android.graphics.Point;
+import android.graphics.Rect;
 import android.util.IntArray;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
@@ -89,6 +91,9 @@
     private ActivityStack mPinnedStack = null;
     private ActivityStack mSplitScreenPrimaryStack = null;
 
+    // Used in updating the display size
+    private Point mTmpDisplaySize = new Point();
+
     ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
         mSupervisor = supervisor;
         mDisplayId = displayId;
@@ -97,6 +102,13 @@
             throw new IllegalStateException("Display does not exist displayId=" + displayId);
         }
         mDisplay = display;
+
+        updateBounds();
+    }
+
+    void updateBounds() {
+        mDisplay.getSize(mTmpDisplaySize);
+        setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
     }
 
     void addChild(ActivityStack stack, int position) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index aa8a366..083d306 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8098,7 +8098,7 @@
                     return false;
                 }
                 // An activity is consider to be in multi-window mode if its task isn't fullscreen.
-                return !r.getTask().mFullscreen;
+                return r.inMultiWindowMode();
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -10117,8 +10117,8 @@
                 } else {
                     // Task isn't in window manager yet since it isn't associated with a stack.
                     // Return the persist value from activity manager
-                    if (task.mBounds != null) {
-                        rect.set(task.mBounds);
+                    if (!task.matchParentBounds()) {
+                        rect.set(task.getBounds());
                     } else if (task.mLastNonFullscreenBounds != null) {
                         rect.set(task.mLastNonFullscreenBounds);
                     }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index a2c46f1..11590d6 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -165,7 +165,6 @@
 import android.view.WindowManager.LayoutParams;
 
 import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.content.ReferrerIntent;
 import com.android.internal.util.XmlUtils;
@@ -343,12 +342,6 @@
     // on the window.
     int mRotationAnimationHint = -1;
 
-    // The bounds of this activity. Mainly used for aspect-ratio compatibility.
-    // TODO(b/36505427): Every level on ConfigurationContainer now has bounds information, which
-    // directly affects the configuration. We should probably move this into that class and have it
-    // handle calculating override configuration from the bounds.
-    private final Rect mBounds = new Rect();
-
     private boolean mShowWhenLocked;
     private boolean mTurnScreenOn;
 
@@ -414,8 +407,8 @@
         if (!getOverrideConfiguration().equals(EMPTY)) {
             pw.println(prefix + "OverrideConfiguration=" + getOverrideConfiguration());
         }
-        if (!mBounds.isEmpty()) {
-            pw.println(prefix + "mBounds=" + mBounds);
+        if (!matchParentBounds()) {
+            pw.println(prefix + "bounds=" + getBounds());
         }
         if (resultTo != null || resultWho != null) {
             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
@@ -648,7 +641,7 @@
         }
 
         // An activity is considered to be in multi-window mode if its task isn't fullscreen.
-        final boolean inMultiWindowMode = !task.mFullscreen;
+        final boolean inMultiWindowMode = task.inMultiWindowMode();
         if (inMultiWindowMode != mLastReportedMultiWindowMode) {
             mLastReportedMultiWindowMode = inMultiWindowMode;
             scheduleMultiWindowModeChanged(getConfiguration());
@@ -966,14 +959,14 @@
                 (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, info.configChanges,
                 task.voiceSession != null, mLaunchTaskBehind, isAlwaysFocusable(),
                 appInfo.targetSdkVersion, mRotationAnimationHint,
-                ActivityManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L, mBounds);
+                ActivityManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L);
 
         task.addActivityToTop(this);
 
         // When an activity is started directly into a split-screen fullscreen stack, we need to
         // update the initial multi-window modes so that the callbacks are scheduled correctly when
         // the user leaves that mode.
-        mLastReportedMultiWindowMode = !task.mFullscreen;
+        mLastReportedMultiWindowMode = inMultiWindowMode();
         mLastReportedPictureInPictureMode = inPinnedWindowingMode();
     }
 
@@ -2172,33 +2165,25 @@
         mLastReportedConfiguration.setConfiguration(global, override);
     }
 
-    @Override
-    public void onOverrideConfigurationChanged(Configuration newConfig) {
-        final Configuration currentConfig = getOverrideConfiguration();
-        if (currentConfig.equals(newConfig)) {
-            return;
-        }
-        super.onOverrideConfigurationChanged(newConfig);
-        if (mWindowContainerController == null) {
-            return;
-        }
-        mWindowContainerController.onOverrideConfigurationChanged(newConfig, mBounds);
-    }
-
     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
     private void updateOverrideConfiguration() {
         mTmpConfig.unset();
         computeBounds(mTmpBounds);
-        if (mTmpBounds.equals(mBounds)) {
+
+        if (mTmpBounds.equals(getOverrideBounds())) {
             return;
         }
 
-        mBounds.set(mTmpBounds);
+        setBounds(mTmpBounds);
+
+        final Rect updatedBounds = getOverrideBounds();
+
         // Bounds changed...update configuration to match.
-        if (!mBounds.isEmpty()) {
-            task.computeOverrideConfiguration(mTmpConfig, mBounds, null /* insetBounds */,
+        if (!matchParentBounds()) {
+            task.computeOverrideConfiguration(mTmpConfig, updatedBounds, null /* insetBounds */,
                     false /* overrideWidth */, false /* overrideHeight */);
         }
+
         onOverrideConfigurationChanged(mTmpConfig);
     }
 
@@ -2225,7 +2210,7 @@
         outBounds.setEmpty();
         final float maxAspectRatio = info.maxAspectRatio;
         final ActivityStack stack = getStack();
-        if (task == null || stack == null || !task.mFullscreen || maxAspectRatio == 0
+        if (task == null || stack == null || task.inMultiWindowMode() || maxAspectRatio == 0
                 || isInVrUiMode(getConfiguration())) {
             // We don't set override configuration if that activity task isn't fullscreen. I.e. the
             // activity is in multi-window mode. Or, there isn't a max aspect ratio specified for
@@ -2256,11 +2241,11 @@
         if (containingAppWidth <= maxActivityWidth && containingAppHeight <= maxActivityHeight) {
             // The display matches or is less than the activity aspect ratio, so nothing else to do.
             // Return the existing bounds. If this method is running for the first time,
-            // {@link mBounds} will be empty (representing no override). If the method has run
-            // before, then effect of {@link mBounds} will already have been applied to the
+            // {@link #getOverrideBounds()} will be empty (representing no override). If the method has run
+            // before, then effect of {@link #getOverrideBounds()} will already have been applied to the
             // value returned from {@link getConfiguration}. Refer to
             // {@link TaskRecord#computeOverrideConfiguration}.
-            outBounds.set(mBounds);
+            outBounds.set(getOverrideBounds());
             return;
         }
 
@@ -2272,12 +2257,6 @@
         outBounds.offsetTo(left, 0 /* top */);
     }
 
-    /** Get bounds of the activity. */
-    @VisibleForTesting
-    Rect getBounds() {
-        return new Rect(mBounds);
-    }
-
     /**
      * Make sure the given activity matches the current configuration. Returns false if the activity
      * had to be destroyed.  Returns true if the configuration is the same, or the activity will
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 6985d6e..4816998 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -156,7 +156,6 @@
  */
 class ActivityStack<T extends StackWindowController> extends ConfigurationContainer
         implements StackWindowListener {
-
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_AM;
     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
     private static final String TAG_APP = TAG + POSTFIX_APP;
@@ -322,11 +321,6 @@
      */
     boolean mForceHidden = false;
 
-    // Whether or not this stack covers the entire screen; by default stacks are fullscreen
-    boolean mFullscreen = true;
-    // Current bounds of the stack or null if fullscreen.
-    Rect mBounds = null;
-
     private boolean mUpdateBoundsDeferred;
     private boolean mUpdateBoundsDeferredCalled;
     private final Rect mDeferredBounds = new Rect();
@@ -342,8 +336,6 @@
     /** The attached Display's unique identifier, or -1 if detached */
     int mDisplayId;
 
-    /** Temp variables used during override configuration update. */
-    private final SparseArray<Configuration> mTmpConfigs = new SparseArray<>();
     private final SparseArray<Rect> mTmpBounds = new SparseArray<>();
     private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>();
     private final Rect mTmpRect2 = new Rect();
@@ -574,7 +566,7 @@
                 }
             }
 
-            if (!Objects.equals(mBounds, mTmpRect2)) {
+            if (!Objects.equals(getOverrideBounds(), mTmpRect2)) {
                 resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */);
             }
         } finally {
@@ -641,9 +633,7 @@
      */
     private void postAddToDisplay(ActivityDisplay activityDisplay, Rect bounds, boolean onTop) {
         mDisplayId = activityDisplay.mDisplayId;
-        mBounds = bounds != null ? new Rect(bounds) : null;
-        mFullscreen = mBounds == null;
-
+        setBounds(bounds);
         onParentChanged();
 
         activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
@@ -651,7 +641,7 @@
             // If we created a docked stack we want to resize it so it resizes all other stacks
             // in the system.
             mStackSupervisor.resizeDockedStackLocked(
-                    mBounds, null, null, null, null, PRESERVE_WINDOWS);
+                    getOverrideBounds(), null, null, null, null, PRESERVE_WINDOWS);
         }
     }
 
@@ -766,8 +756,9 @@
         return false;
     }
 
-    void setBounds(Rect bounds) {
-        mBounds = mFullscreen ? null : new Rect(bounds);
+    @Override
+    public int setBounds(Rect bounds) {
+        return super.setBounds(!inMultiWindowMode() ? null : bounds);
     }
 
     ActivityRecord topRunningActivityLocked() {
@@ -2495,7 +2486,7 @@
             // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
             // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
             final boolean lastActivityTranslucent = lastStack != null
-                    && (!lastStack.mFullscreen
+                    && (lastStack.inMultiWindowMode()
                     || (lastStack.mLastPausedActivity != null
                     && !lastStack.mLastPausedActivity.fullscreen));
 
@@ -2739,8 +2730,7 @@
         position = getAdjustedPositionForTask(task, position, null /* starting */);
         mTaskHistory.remove(task);
         mTaskHistory.add(position, task);
-        mWindowContainerController.positionChildAt(task.getWindowContainerController(), position,
-                task.mBounds, task.getOverrideConfiguration());
+        mWindowContainerController.positionChildAt(task.getWindowContainerController(), position);
         updateTaskMovement(task, true);
     }
 
@@ -4602,8 +4592,6 @@
     // 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) {
-        bounds = TaskRecord.validateBounds(bounds);
-
         if (!updateBoundsAllowed(bounds, tempTaskBounds, tempTaskInsetBounds)) {
             return;
         }
@@ -4613,7 +4601,6 @@
         final Rect insetBounds = tempTaskInsetBounds != null ? tempTaskInsetBounds : taskBounds;
 
         mTmpBounds.clear();
-        mTmpConfigs.clear();
         mTmpInsetBounds.clear();
 
         for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
@@ -4624,7 +4611,7 @@
                     // 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.
-                    mTmpRect2.set(task.mBounds);
+                    mTmpRect2.set(task.getOverrideBounds());
                     fitWithinBounds(mTmpRect2, bounds);
                     task.updateOverrideConfiguration(mTmpRect2);
                 } else {
@@ -4632,15 +4619,13 @@
                 }
             }
 
-            mTmpConfigs.put(task.taskId, task.getOverrideConfiguration());
-            mTmpBounds.put(task.taskId, task.mBounds);
+            mTmpBounds.put(task.taskId, task.getOverrideBounds());
             if (tempTaskInsetBounds != null) {
                 mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds);
             }
         }
 
-        mFullscreen = mWindowContainerController.resize(bounds, mTmpConfigs, mTmpBounds,
-                mTmpInsetBounds);
+        mWindowContainerController.resize(bounds, mTmpBounds, mTmpInsetBounds);
         setBounds(bounds);
     }
 
@@ -4655,7 +4640,7 @@
      * @param stackBounds Bounds within which the other bounds should remain.
      */
     private static void fitWithinBounds(Rect bounds, Rect stackBounds) {
-        if (stackBounds == null || stackBounds.contains(bounds)) {
+        if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) {
             return;
         }
 
@@ -4873,8 +4858,7 @@
                 pw.println("");
             }
             pw.println(prefix + "Task id #" + task.taskId);
-            pw.println(prefix + "mFullscreen=" + task.mFullscreen);
-            pw.println(prefix + "mBounds=" + task.mBounds);
+            pw.println(prefix + "mBounds=" + task.getOverrideBounds());
             pw.println(prefix + "mMinWidth=" + task.mMinWidth);
             pw.println(prefix + "mMinHeight=" + task.mMinHeight);
             pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds);
@@ -4981,7 +4965,7 @@
             if (isOnHomeDisplay() && mode != REMOVE_TASK_MODE_MOVING_TO_TOP
                     && mStackSupervisor.isFocusedStack(this)) {
                 String myReason = reason + " leftTaskHistoryEmpty";
-                if (mFullscreen || !adjustFocusToNextFocusableStack(myReason)) {
+                if (!inMultiWindowMode() || !adjustFocusToNextFocusableStack(myReason)) {
                     mStackSupervisor.moveHomeStackToFront(myReason);
                 }
             }
@@ -5011,8 +4995,8 @@
         final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController()
                 .isKeyguardShowing(mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
         if (!mStackSupervisor.getLaunchingBoundsController().layoutTask(task, info.windowLayout)
-                && mBounds != null && task.isResizeable() && !isLockscreenShown) {
-            task.updateOverrideConfiguration(mBounds);
+                && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
+            task.updateOverrideConfiguration(getOverrideBounds());
         }
         task.createWindowContainer(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
         return task;
@@ -5174,10 +5158,13 @@
             mResumedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
         }
         proto.write(DISPLAY_ID, mDisplayId);
-        if (mBounds != null) {
-            mBounds.writeToProto(proto, BOUNDS);
+        if (!matchParentBounds()) {
+            final Rect bounds = getOverrideBounds();
+            bounds.writeToProto(proto, BOUNDS);
         }
-        proto.write(FULLSCREEN, mFullscreen);
+
+        // TODO: Remove, no longer needed with windowingMode.
+        proto.write(FULLSCREEN, matchParentBounds());
         proto.end(token);
     }
 }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index ddde4bc..5525cdb 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2118,7 +2118,7 @@
         }
 
         if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) {
-            final Rect bounds = TaskRecord.validateBounds(options.getLaunchBounds());
+            final Rect bounds = options.getLaunchBounds();
             task.updateOverrideConfiguration(bounds);
 
             ActivityStack stack = getLaunchStack(null, options, task, ON_TOP);
@@ -2626,7 +2626,8 @@
 
             // TODO: Checking for isAttached might not be needed as if the user passes in null
             // dockedBounds then they want the docked stack to be dismissed.
-            if (stack.mFullscreen || (dockedBounds == null && !stack.isAttached())) {
+            if (stack.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
+                    || (dockedBounds == null && !stack.isAttached())) {
                 // The dock stack either was dismissed or went fullscreen, which is kinda the same.
                 // In this case we make all other static stacks fullscreen and move all
                 // docked stack tasks to the fullscreen stack.
@@ -3058,7 +3059,7 @@
             // Resize the pinned stack to match the current size of the task the activity we are
             // going to be moving is currently contained in. We do this to have the right starting
             // animation bounds for the pinned stack to the desired bounds the caller wants.
-            resizeStackLocked(stack, task.mBounds, null /* tempTaskBounds */,
+            resizeStackLocked(stack, task.getOverrideBounds(), null /* tempTaskBounds */,
                     null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS,
                     true /* allowResizeInDockedMode */, !DEFER_RESUME);
 
@@ -3782,9 +3783,8 @@
                 pw.println("  Stack #" + stack.mStackId
                         + ": type=" + activityTypeToString(stack.getActivityType())
                         + " mode=" + windowingModeToString(stack.getWindowingMode()));
-                pw.println("  mFullscreen=" + stack.mFullscreen);
                 pw.println("  isSleeping=" + stack.shouldSleepActivities());
-                pw.println("  mBounds=" + stack.mBounds);
+                pw.println("  mBounds=" + stack.getOverrideBounds());
 
                 printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage,
                         needSep);
@@ -4054,6 +4054,7 @@
     private void handleDisplayChanged(int displayId) {
         synchronized (mService) {
             ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+            // TODO: The following code block should be moved into {@link ActivityDisplay}.
             if (activityDisplay != null) {
                 // The window policy is responsible for stopping activities on the default display
                 if (displayId != Display.DEFAULT_DISPLAY) {
@@ -4067,7 +4068,8 @@
                         activityDisplay.mOffToken = null;
                     }
                 }
-                // TODO: Update the bounds.
+
+                activityDisplay.updateBounds();
             }
             mWindowManager.onDisplayChanged(displayId);
         }
@@ -4289,7 +4291,7 @@
             return;
         }
 
-        scheduleUpdatePictureInPictureModeIfNeeded(task, stack.mBounds);
+        scheduleUpdatePictureInPictureModeIfNeeded(task, stack.getOverrideBounds());
     }
 
     void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, Rect targetStackBounds) {
diff --git a/services/core/java/com/android/server/am/LaunchingActivityPositioner.java b/services/core/java/com/android/server/am/LaunchingActivityPositioner.java
index d5f9cf3..793884d 100644
--- a/services/core/java/com/android/server/am/LaunchingActivityPositioner.java
+++ b/services/core/java/com/android/server/am/LaunchingActivityPositioner.java
@@ -47,10 +47,10 @@
             return RESULT_SKIP;
         }
 
-        final Rect bounds = TaskRecord.validateBounds(options.getLaunchBounds());
+        final Rect bounds = options.getLaunchBounds();
 
         // Bounds weren't valid.
-        if (bounds == null) {
+        if (bounds == null || bounds.isEmpty()) {
             return RESULT_SKIP;
         }
 
diff --git a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
index c958fca..d89568e 100644
--- a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
+++ b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
@@ -88,7 +88,7 @@
 
         final ArrayList<TaskRecord> tasks = task.getStack().getAllTasks();
 
-        updateAvailableRect(task, mAvailableRect);
+        mAvailableRect.set(task.getParent().getBounds());
 
         if (layout == null) {
             positionCenter(tasks, mAvailableRect, getFreeformWidth(mAvailableRect),
@@ -123,17 +123,6 @@
         return RESULT_CONTINUE;
     }
 
-    private void updateAvailableRect(TaskRecord task, Rect availableRect) {
-        final Rect stackBounds = task.getStack().mBounds;
-
-        if (stackBounds != null) {
-            availableRect.set(stackBounds);
-        } else {
-            task.getStack().getDisplay().mDisplay.getSize(mDisplaySize);
-            availableRect.set(0, 0, mDisplaySize.x, mDisplaySize.y);
-        }
-    }
-
     @VisibleForTesting
     static int getFreeformStartLeft(Rect bounds) {
         return bounds.left + bounds.width() / MARGIN_SIZE_DENOMINATOR;
@@ -294,9 +283,9 @@
 
     private static boolean boundsConflict(Rect proposal, ArrayList<TaskRecord> tasks) {
         for (int i = tasks.size() - 1; i >= 0; i--) {
-            TaskRecord task = tasks.get(i);
-            if (!task.mActivities.isEmpty() && task.mBounds != null) {
-                Rect bounds = task.mBounds;
+            final TaskRecord task = tasks.get(i);
+            if (!task.mActivities.isEmpty() && !task.matchParentBounds()) {
+                final Rect bounds = task.getOverrideBounds();
                 if (closeLeftTopCorner(proposal, bounds) || closeRightTopCorner(proposal, bounds)
                         || closeLeftBottomCorner(proposal, bounds)
                         || closeRightBottomCorner(proposal, bounds)) {
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index d35c37b..cecdc5c 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -1444,8 +1444,8 @@
         rti.affiliatedTaskId = tr.mAffiliatedTaskId;
         rti.affiliatedTaskColor = tr.mAffiliatedTaskColor;
         rti.numActivities = 0;
-        if (tr.mBounds != null) {
-            rti.bounds = new Rect(tr.mBounds);
+        if (!tr.matchParentBounds()) {
+            rti.bounds = new Rect(tr.getOverrideBounds());
         }
         rti.supportsSplitScreenMultiWindow = tr.supportsSplitScreenWindowingMode();
         rti.resizeMode = tr.mResizeMode;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index a9c6eee..b69cad4 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -19,9 +19,6 @@
 import static android.app.ActivityManager.RESIZE_MODE_FORCED;
 import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
@@ -293,11 +290,6 @@
 
     final ActivityManagerService mService;
 
-    // Whether or not this task covers the entire screen; by default tasks are fullscreen.
-    boolean mFullscreen = true;
-
-    // Bounds of the Task. null for fullscreen tasks.
-    Rect mBounds = null;
     private final Rect mTmpStableBounds = new Rect();
     private final Rect mTmpNonDecorBounds = new Rect();
     private final Rect mTmpRect = new Rect();
@@ -480,68 +472,76 @@
     }
 
     boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
-        if (!isResizeable()) {
-            Slog.w(TAG, "resizeTask: task " + this + " not resizeable.");
-            return true;
-        }
+        mService.mWindowManager.deferSurfaceLayout();
 
-        // If this is a forced resize, let it go through even if the bounds is not changing,
-        // as we might need a relayout due to surface size change (to/from fullscreen).
-        final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
-        if (Objects.equals(mBounds, bounds) && !forced) {
-            // Nothing to do here...
-            return true;
-        }
-        bounds = validateBounds(bounds);
-
-        if (mWindowContainerController == null) {
-            // Task doesn't exist in window manager yet (e.g. was restored from recents).
-            // All we can do for now is update the bounds so it can be used when the task is
-            // added to window manager.
-            updateOverrideConfiguration(bounds);
-            if (!inFreeformWindowingMode()) {
-                // re-restore the task so it can have the proper stack association.
-                mService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
+        try {
+            if (!isResizeable()) {
+                Slog.w(TAG, "resizeTask: task " + this + " not resizeable.");
+                return true;
             }
-            return true;
-        }
 
-        if (!canResizeToBounds(bounds)) {
-            throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
-                    + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
-        }
+            // If this is a forced resize, let it go through even if the bounds is not changing,
+            // as we might need a relayout due to surface size change (to/from fullscreen).
+            final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
+            if (equivalentOverrideBounds(bounds) && !forced) {
+                // Nothing to do here...
+                return true;
+            }
 
-        // Do not move the task to another stack here.
-        // This method assumes that the task is already placed in the right stack.
-        // we do not mess with that decision and we only do the resize!
+            if (mWindowContainerController == null) {
+                // Task doesn't exist in window manager yet (e.g. was restored from recents).
+                // All we can do for now is update the bounds so it can be used when the task is
+                // added to window manager.
+                updateOverrideConfiguration(bounds);
+                if (!inFreeformWindowingMode()) {
+                    // re-restore the task so it can have the proper stack association.
+                    mService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
+                }
+                return true;
+            }
 
-        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId);
+            if (!canResizeToBounds(bounds)) {
+                throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
+                        + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
+            }
 
-        final boolean updatedConfig = updateOverrideConfiguration(bounds);
-        // This variable holds information whether the configuration didn't change in a significant
-        // way and the activity was kept the way it was. If it's false, it means the activity had
-        // to be relaunched due to configuration change.
-        boolean kept = true;
-        if (updatedConfig) {
-            final ActivityRecord r = topRunningActivityLocked();
-            if (r != null && !deferResume) {
-                kept = r.ensureActivityConfigurationLocked(0 /* globalChanges */, preserveWindow);
-                mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS);
-                if (!kept) {
-                    mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
+            // Do not move the task to another stack here.
+            // This method assumes that the task is already placed in the right stack.
+            // we do not mess with that decision and we only do the resize!
+
+            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId);
+
+            final boolean updatedConfig = updateOverrideConfiguration(bounds);
+            // This variable holds information whether the configuration didn't change in a significant
+
+            // way and the activity was kept the way it was. If it's false, it means the activity
+            // had
+            // to be relaunched due to configuration change.
+            boolean kept = true;
+            if (updatedConfig) {
+                final ActivityRecord r = topRunningActivityLocked();
+                if (r != null && !deferResume) {
+                    kept = r.ensureActivityConfigurationLocked(0 /* globalChanges */,
+                            preserveWindow);
+                    mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0,
+                            !PRESERVE_WINDOWS);
+                    if (!kept) {
+                        mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                    }
                 }
             }
-        }
-        mWindowContainerController.resize(mBounds, getOverrideConfiguration(), kept, forced);
+            mWindowContainerController.resize(kept, forced);
 
-        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
-        return kept;
+            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+            return kept;
+        } finally {
+            mService.mWindowManager.continueSurfaceLayout();
+        }
     }
 
     // TODO: Investigate combining with the resize() method above.
     void resizeWindowContainer() {
-        mWindowContainerController.resize(mBounds, getOverrideConfiguration(), false /* relayout */,
-                false /* forced */);
+        mWindowContainerController.resize(false /* relayout */, false /* forced */);
     }
 
     void getWindowContainerBounds(Rect bounds) {
@@ -686,16 +686,17 @@
             // Make sure the task has the appropriate bounds/size for the stack it is in.
             final boolean toStackSplitScreenPrimary =
                     toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+            final Rect configBounds = getOverrideBounds();
             if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
                     || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
-                    && !Objects.equals(mBounds, toStack.mBounds)) {
-                kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
+                    && !Objects.equals(configBounds, toStack.getOverrideBounds())) {
+                kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
                         deferResume);
             } else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
                 Rect bounds = getLaunchBounds();
                 if (bounds == null) {
                     mService.mStackSupervisor.getLaunchingBoundsController().layoutTask(this, null);
-                    bounds = mBounds;
+                    bounds = configBounds;
                 }
                 kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
             } else if (toStackSplitScreenPrimary || toStackWindowingMode == WINDOWING_MODE_PINNED) {
@@ -704,7 +705,7 @@
                     // mode
                     mService.mStackSupervisor.moveRecentsStackToFront(reason);
                 }
-                kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
+                kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
                         deferResume);
             }
         } finally {
@@ -1501,8 +1502,10 @@
             return true;
         }
         final boolean landscape = bounds.width() > bounds.height();
+        final Rect configBounds = getOverrideBounds();
         if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
-            return mBounds == null || landscape == (mBounds.width() > mBounds.height());
+            return configBounds.isEmpty()
+                    || landscape == (configBounds.width() > configBounds.height());
         }
         return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
                 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
@@ -1920,8 +1923,9 @@
             return;
         }
 
+        final Rect configBounds = getOverrideBounds();
         if (adjustWidth) {
-            if (mBounds != null && bounds.right == mBounds.right) {
+            if (!configBounds.isEmpty() && bounds.right == configBounds.right) {
                 bounds.left = bounds.right - minWidth;
             } else {
                 // Either left bounds match, or neither match, or the previous bounds were
@@ -1930,7 +1934,7 @@
             }
         }
         if (adjustHeight) {
-            if (mBounds != null && bounds.bottom == mBounds.bottom) {
+            if (!configBounds.isEmpty() && bounds.bottom == configBounds.bottom) {
                 bounds.top = bounds.bottom - minHeight;
             } else {
                 // Either top bounds match, or neither match, or the previous bounds were
@@ -1977,38 +1981,37 @@
      * @return True if the override configuration was updated.
      */
     boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
-        if (Objects.equals(mBounds, bounds)) {
+        if (equivalentOverrideBounds(bounds)) {
             return false;
         }
+        final Rect currentBounds = getOverrideBounds();
+
         mTmpConfig.setTo(getOverrideConfiguration());
-        final boolean oldFullscreen = mFullscreen;
+        final boolean oldMatchParentBounds = matchParentBounds();
         final Configuration newConfig = getOverrideConfiguration();
 
-        mFullscreen = bounds == null;
+        final boolean matchParentBounds = bounds == null || bounds.isEmpty();
         final boolean persistBounds = getWindowConfiguration().persistTaskBounds();
-        if (mFullscreen) {
-            if (mBounds != null && persistBounds) {
-                mLastNonFullscreenBounds = mBounds;
+        if (matchParentBounds) {
+            if (!currentBounds.isEmpty() && persistBounds) {
+                mLastNonFullscreenBounds = currentBounds;
             }
-            mBounds = null;
+            setBounds(null);
             newConfig.unset();
         } else {
             mTmpRect.set(bounds);
             adjustForMinimalTaskDimensions(mTmpRect);
-            if (mBounds == null) {
-                mBounds = new Rect(mTmpRect);
-            } else {
-                mBounds.set(mTmpRect);
-            }
+            setBounds(mTmpRect);
+
             if (mStack == null || persistBounds) {
-                mLastNonFullscreenBounds = mBounds;
+                mLastNonFullscreenBounds = getOverrideBounds();
             }
             computeOverrideConfiguration(newConfig, mTmpRect, insetBounds,
                     mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
         }
         onOverrideConfigurationChanged(newConfig);
 
-        if (mFullscreen != oldFullscreen) {
+        if (matchParentBounds != oldMatchParentBounds) {
             mService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
         }
 
@@ -2053,23 +2056,19 @@
         final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
         final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
         config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
-
     }
 
     Rect updateOverrideConfigurationFromLaunchBounds() {
-        final Rect bounds = validateBounds(getLaunchBounds());
+        final Rect bounds = getLaunchBounds();
         updateOverrideConfiguration(bounds);
-        if (bounds != null) {
-            bounds.set(mBounds);
+        if (bounds != null && !bounds.isEmpty()) {
+            // TODO: Review if we actually want to do this - we are setting the launch bounds
+            // directly here.
+            bounds.set(getOverrideBounds());
         }
         return bounds;
     }
 
-    static Rect validateBounds(Rect bounds) {
-        // TODO: Not needed once we have bounds in WindowConfiguration.
-        return (bounds != null && bounds.isEmpty()) ? null : bounds;
-    }
-
     /** Updates the task's bounds and override configuration to match what is expected for the
      * input stack. */
     void updateOverrideConfigurationForStack(ActivityStack inStack) {
@@ -2082,7 +2081,7 @@
                 throw new IllegalArgumentException("Can not position non-resizeable task="
                         + this + " in stack=" + inStack);
             }
-            if (mBounds != null) {
+            if (!matchParentBounds()) {
                 return;
             }
             if (mLastNonFullscreenBounds != null) {
@@ -2091,7 +2090,7 @@
                 mService.mStackSupervisor.getLaunchingBoundsController().layoutTask(this, null);
             }
         } else {
-            updateOverrideConfiguration(inStack.mBounds);
+            updateOverrideConfiguration(inStack.getOverrideBounds());
         }
     }
 
@@ -2105,9 +2104,9 @@
         if (!isActivityTypeStandardOrUndefined()
                 || windowingMode == WINDOWING_MODE_FULLSCREEN
                 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
-            return isResizeable() ? mStack.mBounds : null;
+            return isResizeable() ? mStack.getOverrideBounds() : null;
         } else if (!getWindowConfiguration().persistTaskBounds()) {
-            return mStack.mBounds;
+            return mStack.getOverrideBounds();
         }
         return mLastNonFullscreenBounds;
     }
@@ -2287,9 +2286,12 @@
         }
         proto.write(ACTIVITY_TYPE, getActivityType());
         proto.write(RESIZE_MODE, mResizeMode);
-        proto.write(FULLSCREEN, mFullscreen);
-        if (mBounds != null) {
-            mBounds.writeToProto(proto, BOUNDS);
+        // TODO: Remove, no longer needed with windowingMode.
+        proto.write(FULLSCREEN, matchParentBounds());
+
+        if (!matchParentBounds()) {
+            final Rect bounds = getOverrideBounds();
+            bounds.writeToProto(proto, BOUNDS);
         }
         proto.write(MIN_WIDTH, mMinWidth);
         proto.write(MIN_HEIGHT, mMinHeight);
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index a528ecd..00a0d3d 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -181,13 +181,12 @@
             IApplicationToken token, AppWindowContainerListener listener, int index,
             int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges,
             boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
-            int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos,
-            Rect bounds) {
+            int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos) {
         this(taskController, token, listener, index, requestedOrientation, fullscreen,
                 showForAllUsers,
                 configChanges, voiceInteraction, launchTaskBehind, alwaysFocusable,
                 targetSdkVersion, rotationAnimationHint, inputDispatchingTimeoutNanos,
-                WindowManagerService.getInstance(), bounds);
+                WindowManagerService.getInstance());
     }
 
     public AppWindowContainerController(TaskWindowContainerController taskController,
@@ -195,7 +194,7 @@
             int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges,
             boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
             int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos,
-            WindowManagerService service, Rect bounds) {
+            WindowManagerService service) {
         super(listener, service);
         mHandler = new H(service.mH.getLooper());
         mToken = token;
@@ -216,7 +215,7 @@
             atoken = createAppWindow(mService, token, voiceInteraction, task.getDisplayContent(),
                     inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdkVersion,
                     requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind,
-                    alwaysFocusable, this, bounds);
+                    alwaysFocusable, this);
             if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
                     + " controller=" + taskController + " at " + index);
             task.addChild(atoken, index);
@@ -228,11 +227,11 @@
             boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
             boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
             int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
-            boolean alwaysFocusable, AppWindowContainerController controller, Rect bounds) {
+            boolean alwaysFocusable, AppWindowContainerController controller) {
         return new AppWindowToken(service, token, voiceInteraction, dc,
                 inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
                 rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
-                controller, bounds);
+                controller);
     }
 
     public void removeContainer(int displayId) {
@@ -299,17 +298,6 @@
         }
     }
 
-    // TODO(b/36505427): Maybe move to WindowContainerController so other sub-classes can use it as
-    // a generic way to set override config. Need to untangle current ways the override config is
-    // currently set for tasks and displays before we are doing that though.
-    public void onOverrideConfigurationChanged(Configuration overrideConfiguration, Rect bounds) {
-        synchronized(mWindowMap) {
-            if (mContainer != null) {
-                mContainer.onOverrideConfigurationChanged(overrideConfiguration, bounds);
-            }
-        }
-    }
-
     public void setDisablePreviewScreenshots(boolean disable) {
         synchronized (mWindowMap) {
             if (mContainer == null) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 627f8ce..c39ce98 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -175,11 +175,6 @@
     private boolean mLastContainsShowWhenLockedWindow;
     private boolean mLastContainsDismissKeyguardWindow;
 
-    // The bounds of this activity. Mainly used for aspect-ratio compatibility.
-    // TODO(b/36505427): Every level on WindowContainer now has bounds information, which directly
-    // affects the configuration. We should probably move this into that class.
-    private final Rect mBounds = new Rect();
-
     ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
     ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
 
@@ -196,8 +191,8 @@
             DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen,
             boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint,
             int configChanges, boolean launchTaskBehind, boolean alwaysFocusable,
-            AppWindowContainerController controller, Rect bounds) {
-        this(service, token, voiceInteraction, dc, fullscreen, bounds);
+            AppWindowContainerController controller) {
+        this(service, token, voiceInteraction, dc, fullscreen);
         setController(controller);
         mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
         mShowForAllUsers = showForAllUsers;
@@ -214,7 +209,7 @@
     }
 
     AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
-            DisplayContent dc, boolean fillsParent, Rect bounds) {
+            DisplayContent dc, boolean fillsParent) {
         super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
                 false /* ownerCanManageAppTokens */);
         appToken = token;
@@ -222,27 +217,6 @@
         mFillsParent = fillsParent;
         mInputApplicationHandle = new InputApplicationHandle(this);
         mAppAnimator = new AppWindowAnimator(this, service);
-        if (bounds != null) {
-            mBounds.set(bounds);
-        }
-    }
-
-    void onOverrideConfigurationChanged(Configuration overrideConfiguration, Rect bounds) {
-        onOverrideConfigurationChanged(overrideConfiguration);
-        if (mBounds.equals(bounds)) {
-            return;
-        }
-        // TODO(b/36505427): If bounds is in WC, then we can automatically call onResize() when set.
-        mBounds.set(bounds);
-        onResize();
-    }
-
-    void getBounds(Rect outBounds) {
-        outBounds.set(mBounds);
-    }
-
-    boolean hasBounds() {
-        return !mBounds.isEmpty();
     }
 
     void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index b534b8a..d340923 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -36,6 +36,7 @@
 import android.annotation.CallSuper;
 import android.app.WindowConfiguration;
 import android.content.res.Configuration;
+import android.graphics.Rect;
 import android.util.proto.ProtoOutputStream;
 
 import java.io.PrintWriter;
@@ -46,6 +47,11 @@
  * hierarchy.
  */
 public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
+    /**
+     * {@link #Rect} returned from {@link #getOverrideBounds()} to prevent original value from being
+     * set directly.
+     */
+    private Rect mReturnBounds = new Rect();
 
     /** Contains override configuration settings applied to this configuration container. */
     private Configuration mOverrideConfiguration = new Configuration();
@@ -71,6 +77,16 @@
     // TODO: Can't have ag/2592611 soon enough!
     private final Configuration mTmpConfig = new Configuration();
 
+    // Used for setting bounds
+    private final Rect mTmpRect = new Rect();
+
+    static final int BOUNDS_CHANGE_NONE = 0;
+    // Return value from {@link setBounds} indicating the position of the override bounds changed.
+    static final int BOUNDS_CHANGE_POSITION = 1;
+    // Return value from {@link setBounds} indicating the size of the override bounds changed.
+    static final int BOUNDS_CHANGE_SIZE = 1 << 1;
+
+
     /**
      * Returns full configuration applied to this configuration container.
      * This method should be used for getting settings applied in each particular level of the
@@ -148,6 +164,118 @@
         }
     }
 
+    /**
+     * Indicates whether this container has not specified any bounds different from its parent. In
+     * this case, it will inherit the bounds of the first ancestor which specifies a bounds.
+     * @return {@code true} if no explicit bounds have been set at this container level.
+     *         {@code false} otherwise.
+     */
+    public boolean matchParentBounds() {
+        return getOverrideBounds().isEmpty();
+    }
+
+    /**
+     * Returns whether the bounds specified is considered the same as the existing override bounds.
+     * This is either when the two bounds are equal or the override bounds is empty and the
+     * specified bounds is null.
+     *
+     * @return {@code true} if the bounds are equivalent, {@code false} otherwise
+     */
+    public boolean equivalentOverrideBounds(Rect bounds) {
+        return equivalentBounds(getOverrideBounds(),  bounds);
+    }
+
+    /**
+     * Returns whether the two bounds are equal to each other or are a combination of null or empty.
+     */
+    public static boolean equivalentBounds(Rect bounds, Rect other) {
+        return bounds == other
+                || (bounds != null && (bounds.equals(other) || (bounds.isEmpty() && other == null)))
+                || (other != null && other.isEmpty() && bounds == null);
+    }
+
+    /**
+     * Returns the effective bounds of this container, inheriting the first non-empty bounds set in
+     * its ancestral hierarchy, including itself.
+     * @return
+     */
+    public Rect getBounds() {
+        mReturnBounds.set(getConfiguration().windowConfiguration.getBounds());
+        return mReturnBounds;
+    }
+
+    public void getBounds(Rect outBounds) {
+        outBounds.set(getBounds());
+    }
+
+    /**
+     * Returns the current bounds explicitly set on this container. The {@link Rect} handed back is
+     * shared for all calls to this method and should not be modified.
+     */
+    public Rect getOverrideBounds() {
+        mReturnBounds.set(getOverrideConfiguration().windowConfiguration.getBounds());
+
+        return mReturnBounds;
+    }
+
+    /**
+     * Sets the passed in {@link Rect} to the current bounds.
+     * @see {@link #getOverrideBounds()}.
+     */
+    public void getOverrideBounds(Rect outBounds) {
+        outBounds.set(getOverrideBounds());
+    }
+
+    /**
+     * Sets the bounds at the current hierarchy level, overriding any bounds set on an ancestor.
+     * This value will be reported when {@link #getBounds()} and {@link #getOverrideBounds()}. If
+     * an empty {@link Rect} or null is specified, this container will be considered to match its
+     * parent bounds {@see #matchParentBounds} and will inherit bounds from its parent.
+     * @param bounds The bounds defining the container size.
+     * @return a bitmask representing the types of changes made to the bounds.
+     */
+    public int setBounds(Rect bounds) {
+        int boundsChange = diffOverrideBounds(bounds);
+
+        if (boundsChange == BOUNDS_CHANGE_NONE) {
+            return boundsChange;
+        }
+
+
+        mTmpConfig.setTo(getOverrideConfiguration());
+        mTmpConfig.windowConfiguration.setBounds(bounds);
+        onOverrideConfigurationChanged(mTmpConfig);
+
+        return boundsChange;
+    }
+
+    public int setBounds(int left, int top, int right, int bottom) {
+        mTmpRect.set(left, top, right, bottom);
+        return setBounds(mTmpRect);
+    }
+
+    int diffOverrideBounds(Rect bounds) {
+        if (equivalentOverrideBounds(bounds)) {
+            return BOUNDS_CHANGE_NONE;
+        }
+
+        int boundsChange = BOUNDS_CHANGE_NONE;
+
+        final Rect existingBounds = getOverrideBounds();
+
+        if (bounds == null || existingBounds.left != bounds.left
+                || existingBounds.top != bounds.top) {
+            boundsChange |= BOUNDS_CHANGE_POSITION;
+        }
+
+        if (bounds == null || existingBounds.width() != bounds.width()
+                || existingBounds.height() != bounds.height()) {
+            boundsChange |= BOUNDS_CHANGE_SIZE;
+        }
+
+        return boundsChange;
+    }
+
     public WindowConfiguration getWindowConfiguration() {
         return mFullConfiguration.windowConfiguration;
     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 44dfa07..3fb3773 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -314,6 +314,9 @@
     private final Matrix mTmpMatrix = new Matrix();
     private final Region mTmpRegion = new Region();
 
+    /** Used for handing back size of display */
+    private final Rect mTmpBounds = new Rect();
+
     WindowManagerService mService;
 
     /** Remove this display when animation on it has completed. */
@@ -1223,6 +1226,8 @@
             mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
                     mCompatDisplayMetrics);
         }
+
+        updateBounds();
         return mDisplayInfo;
     }
 
@@ -1541,8 +1546,17 @@
         // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
         mService.reconfigureDisplayLocked(this);
 
-        getDockedDividerController().onConfigurationChanged();
-        getPinnedStackController().onConfigurationChanged();
+        final DockedStackDividerController dividerController = getDockedDividerController();
+
+        if (dividerController != null) {
+            getDockedDividerController().onConfigurationChanged();
+        }
+
+        final PinnedStackController pinnedStackController = getPinnedStackController();
+
+        if (pinnedStackController != null) {
+            getPinnedStackController().onConfigurationChanged();
+        }
     }
 
     /**
@@ -1681,33 +1695,6 @@
         mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
     }
 
-    void getLogicalDisplayRect(Rect out) {
-        // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
-        final int orientation = mDisplayInfo.rotation;
-        boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
-        final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
-        final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
-        int width = mDisplayInfo.logicalWidth;
-        int left = (physWidth - width) / 2;
-        int height = mDisplayInfo.logicalHeight;
-        int top = (physHeight - height) / 2;
-        out.set(left, top, left + width, top + height);
-    }
-
-    private void getLogicalDisplayRect(Rect out, int orientation) {
-        getLogicalDisplayRect(out);
-
-        // Rotate the Rect if needed.
-        final int currentRotation = mDisplayInfo.rotation;
-        final int rotationDelta = deltaRotation(currentRotation, orientation);
-        if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
-            createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
-            mTmpRectF.set(out);
-            mTmpMatrix.mapRect(mTmpRectF);
-            mTmpRectF.round(out);
-        }
-    }
-
     /**
      * If display metrics changed, overrides are not set and it's not just a rotation - update base
      * values.
@@ -1775,6 +1762,8 @@
         }
 
         mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
+
+        updateBounds();
     }
 
     void getContentRect(Rect out) {
@@ -2104,7 +2093,7 @@
     }
 
     void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
-        getLogicalDisplayRect(mTmpRect, newRotation);
+        getBounds(mTmpRect, newRotation);
 
         // Compute a transform matrix to undo the coordinate space transformation,
         // and present the window at the same physical position it previously occupied.
@@ -2881,6 +2870,44 @@
         return mTmpApplySurfaceChangesTransactionState.focusDisplayed;
     }
 
+    private void updateBounds() {
+        calculateBounds(mTmpBounds);
+        setBounds(mTmpBounds);
+    }
+
+    // Determines the current display bounds based on the current state
+    private void calculateBounds(Rect out) {
+        // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
+        final int orientation = mDisplayInfo.rotation;
+        boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
+        final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
+        final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
+        int width = mDisplayInfo.logicalWidth;
+        int left = (physWidth - width) / 2;
+        int height = mDisplayInfo.logicalHeight;
+        int top = (physHeight - height) / 2;
+        out.set(left, top, left + width, top + height);
+    }
+
+    @Override
+    public void getBounds(Rect out) {
+        calculateBounds(out);
+    }
+
+    private void getBounds(Rect out, int orientation) {
+        getBounds(out);
+
+        // Rotate the Rect if needed.
+        final int currentRotation = mDisplayInfo.rotation;
+        final int rotationDelta = deltaRotation(currentRotation, orientation);
+        if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
+            createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
+            mTmpRectF.set(out);
+            mTmpMatrix.mapRect(mTmpRectF);
+            mTmpRectF.round(out);
+        }
+    }
+
     void performLayout(boolean initial, boolean updateInputWindows) {
         if (!isLayoutNeeded()) {
             return;
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 8308417..a37598e 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -655,8 +655,8 @@
     }
 
     private boolean isWithinDisplay(Task task) {
-        task.mStack.getBounds(mTmpRect);
-        mDisplayContent.getLogicalDisplayRect(mTmpRect2);
+        task.getBounds(mTmpRect);
+        mDisplayContent.getBounds(mTmpRect2);
         return mTmpRect.intersect(mTmpRect2);
     }
 
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 18b0f97..7e29a3a 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -661,8 +661,8 @@
             if (w.inPinnedWindowingMode()) {
                 if (mAddPipInputConsumerHandle
                         && (inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer)) {
-                    // Update the bounds of the Pip input consumer to match the Pinned stack
-                    w.getStack().getBounds(pipTouchableBounds);
+                    // Update the bounds of the Pip input consumer to match the window bounds.
+                    w.getBounds(pipTouchableBounds);
                     pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
                     addInputWindowHandle(pipInputConsumer.mWindowHandle);
                     mAddPipInputConsumerHandle = false;
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowController.java b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
index 41f076d..b021a72 100644
--- a/services/core/java/com/android/server/wm/PinnedStackWindowController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
@@ -106,7 +106,7 @@
                 } else {
                     // Otherwise, use the display bounds
                     toBounds = new Rect();
-                    mContainer.getDisplayContent().getLogicalDisplayRect(toBounds);
+                    mContainer.getDisplayContent().getBounds(toBounds);
                 }
             } else if (fromFullscreen) {
                 schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 70bf15c..5a39de5 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -28,7 +28,6 @@
 
 import android.content.Context;
 import android.graphics.Matrix;
-import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
@@ -230,7 +229,7 @@
         mService = service;
         mContext = context;
         mDisplayContent = displayContent;
-        displayContent.getLogicalDisplayRect(mOriginalDisplayRect);
+        displayContent.getBounds(mOriginalDisplayRect);
 
         // Screenshot does NOT include rotation!
         final Display display = displayContent.getDisplay();
@@ -312,7 +311,7 @@
             float x = mTmpFloats[Matrix.MTRANS_X];
             float y = mTmpFloats[Matrix.MTRANS_Y];
             if (mForceDefaultOrientation) {
-                mDisplayContent.getLogicalDisplayRect(mCurrentDisplayRect);
+                mDisplayContent.getBounds(mCurrentDisplayRect);
                 x -= mCurrentDisplayRect.left;
                 y -= mCurrentDisplayRect.top;
             }
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index 95c1d53..c2a4be5 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -111,8 +111,7 @@
         }
     }
 
-    public void positionChildAt(TaskWindowContainerController child, int position, Rect bounds,
-            Configuration overrideConfig) {
+    public void positionChildAt(TaskWindowContainerController child, int position) {
         synchronized (mWindowMap) {
             if (DEBUG_STACK) Slog.i(TAG_WM, "positionChildAt: positioning task=" + child
                     + " at " + position);
@@ -126,7 +125,7 @@
                         "positionChildAt: could not find stack for task=" + mContainer);
                 return;
             }
-            child.mContainer.positionAt(position, bounds, overrideConfig);
+            child.mContainer.positionAt(position);
             mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
         }
     }
@@ -178,24 +177,22 @@
      * Re-sizes a stack and its containing tasks.
      *
      * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen.
-     * @param configs Configurations for tasks in the resized stack, keyed by task id.
      * @param taskBounds Bounds for tasks in the resized stack, keyed by task id.
-     * @return True if the stack is now fullscreen.
+     * @param taskTempInsetBounds Inset bounds for individual tasks, keyed by task id.
      */
-    public boolean resize(Rect bounds, SparseArray<Configuration> configs,
-            SparseArray<Rect> taskBounds, SparseArray<Rect> taskTempInsetBounds) {
+    public void resize(Rect bounds, SparseArray<Rect> taskBounds,
+            SparseArray<Rect> taskTempInsetBounds) {
         synchronized (mWindowMap) {
             if (mContainer == null) {
                 throw new IllegalArgumentException("resizeStack: stack " + this + " not found.");
             }
             // We might trigger a configuration change. Save the current task bounds for freezing.
             mContainer.prepareFreezingTaskBounds();
-            if (mContainer.setBounds(bounds, configs, taskBounds, taskTempInsetBounds)
+            if (mContainer.setBounds(bounds, taskBounds, taskTempInsetBounds)
                     && mContainer.isVisible()) {
                 mContainer.getDisplayContent().setLayoutNeeded();
                 mService.mWindowPlacerLocked.performSurfacePlacement();
             }
-            return mContainer.getRawFullscreen();
         }
     }
 
@@ -227,7 +224,7 @@
 
     public void getRawBounds(Rect outBounds) {
         synchronized (mWindowMap) {
-            if (mContainer.getRawFullscreen()) {
+            if (mContainer.matchParentBounds()) {
                 outBounds.setEmpty();
             } else {
                 mContainer.getRawBounds(outBounds);
@@ -275,6 +272,7 @@
 
             final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
 
+            config.windowConfiguration.setBounds(bounds);
             config.windowConfiguration.setAppBounds(!bounds.isEmpty() ? bounds : null);
             boolean intersectParentBounds = false;
 
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index f70845e..8aa129a 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -53,12 +53,6 @@
 
 class Task extends WindowContainer<AppWindowToken> {
     static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_WM;
-    // Return value from {@link setBounds} indicating no change was made to the Task bounds.
-    private static final int BOUNDS_CHANGE_NONE = 0;
-    // Return value from {@link setBounds} indicating the position of the Task bounds changed.
-    private static final int BOUNDS_CHANGE_POSITION = 1;
-    // Return value from {@link setBounds} indicating the size of the Task bounds changed.
-    private static final int BOUNDS_CHANGE_SIZE = 1 << 1;
 
     // TODO: Track parent marks like this in WindowContainer.
     TaskStack mStack;
@@ -67,8 +61,6 @@
     private boolean mDeferRemoval = false;
     final WindowManagerService mService;
 
-    // Content limits relative to the DisplayContent this sits in.
-    private Rect mBounds = new Rect();
     final Rect mPreparedFrozenBounds = new Rect();
     final Configuration mPreparedFrozenMergedConfig = new Configuration();
 
@@ -78,13 +70,12 @@
     // Device rotation as of the last time {@link #mBounds} was set.
     private int mRotation;
 
-    // Whether mBounds is fullscreen
-    private boolean mFillsParent = true;
-
     // For comparison with DisplayContent bounds.
     private Rect mTmpRect = new Rect();
     // For handling display rotations.
     private Rect mTmpRect2 = new Rect();
+    // For retrieving dim bounds
+    private Rect mTmpRect3 = new Rect();
 
     // Resize mode of the task. See {@link ActivityInfo#resizeMode}
     private int mResizeMode;
@@ -108,8 +99,8 @@
     private Dimmer mDimmer = new Dimmer(this);
     private final Rect mTmpDimBoundsRect = new Rect();
 
-    Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
-            int resizeMode, boolean supportsPictureInPicture, TaskDescription taskDescription,
+    Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode,
+            boolean supportsPictureInPicture, TaskDescription taskDescription,
             TaskWindowContainerController controller) {
         mTaskId = taskId;
         mStack = stack;
@@ -118,7 +109,7 @@
         mResizeMode = resizeMode;
         mSupportsPictureInPicture = supportsPictureInPicture;
         setController(controller);
-        setBounds(bounds, getOverrideConfiguration());
+        setBounds(getOverrideBounds());
         mTaskDescription = taskDescription;
 
         // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
@@ -227,9 +218,8 @@
     }
 
     /** @see com.android.server.am.ActivityManagerService#positionTaskInStack(int, int, int). */
-    void positionAt(int position, Rect bounds, Configuration overrideConfig) {
+    void positionAt(int position) {
         mStack.positionChildAt(position, this, false /* includingParents */);
-        resizeLocked(bounds, overrideConfig, false /* force */);
     }
 
     @Override
@@ -271,48 +261,37 @@
         }
     }
 
-    /** Set the task bounds. Passing in null sets the bounds to fullscreen. */
-    // TODO: There is probably not a need to pass in overrideConfig anymore since any change to it
-    // will be automatically propagated from the AM. Also, mBound is going to be in
-    // WindowConfiguration long term.
-    private int setBounds(Rect bounds, Configuration overrideConfig) {
-        if (overrideConfig == null) {
-            overrideConfig = EMPTY;
+    public int setBounds(Rect bounds, boolean forceResize) {
+        final int boundsChanged = setBounds(bounds);
+
+        if (forceResize && (boundsChanged & BOUNDS_CHANGE_SIZE) != BOUNDS_CHANGE_SIZE) {
+            onResize();
+            return BOUNDS_CHANGE_SIZE | boundsChanged;
         }
 
-        boolean oldFullscreen = mFillsParent;
+        return boundsChanged;
+    }
+
+    /** Set the task bounds. Passing in null sets the bounds to fullscreen. */
+    @Override
+    public int setBounds(Rect bounds) {
         int rotation = Surface.ROTATION_0;
         final DisplayContent displayContent = mStack.getDisplayContent();
         if (displayContent != null) {
-            displayContent.getLogicalDisplayRect(mTmpRect);
             rotation = displayContent.getDisplayInfo().rotation;
-            mFillsParent = bounds == null;
-            if (mFillsParent) {
-                bounds = mTmpRect;
-            }
-        }
-
-        if (bounds == null) {
+        } else if (bounds == null) {
             // Can't set to fullscreen if we don't have a display to get bounds from...
             return BOUNDS_CHANGE_NONE;
         }
-        if (mBounds.equals(bounds) && oldFullscreen == mFillsParent && mRotation == rotation) {
+
+        if (equivalentOverrideBounds(bounds)) {
             return BOUNDS_CHANGE_NONE;
         }
 
-        int boundsChange = BOUNDS_CHANGE_NONE;
-        if (mBounds.left != bounds.left || mBounds.top != bounds.top) {
-            boundsChange |= BOUNDS_CHANGE_POSITION;
-        }
-        if (mBounds.width() != bounds.width() || mBounds.height() != bounds.height()) {
-            boundsChange |= BOUNDS_CHANGE_SIZE;
-        }
-
-        mBounds.set(bounds);
+        final int boundsChange = super.setBounds(bounds);
 
         mRotation = rotation;
 
-        onOverrideConfigurationChanged(overrideConfig);
         return boundsChange;
     }
 
@@ -360,28 +339,12 @@
         return isResizeable();
     }
 
-    boolean resizeLocked(Rect bounds, Configuration overrideConfig, boolean forced) {
-        int boundsChanged = setBounds(bounds, overrideConfig);
-        if (forced) {
-            boundsChanged |= BOUNDS_CHANGE_SIZE;
-        }
-        if (boundsChanged == BOUNDS_CHANGE_NONE) {
-            return false;
-        }
-        if ((boundsChanged & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
-            onResize();
-        } else {
-            onMovedByResize();
-        }
-        return true;
-    }
-
     /**
      * Prepares the task bounds to be frozen with the current size. See
      * {@link AppWindowToken#freezeBounds}.
      */
     void prepareFreezingBounds() {
-        mPreparedFrozenBounds.set(mBounds);
+        mPreparedFrozenBounds.set(getBounds());
         mPreparedFrozenMergedConfig.setTo(getConfiguration());
     }
 
@@ -407,30 +370,30 @@
             mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top);
         }
         setTempInsetBounds(tempInsetBounds);
-        resizeLocked(mTmpRect2, getOverrideConfiguration(), false /* forced */);
+        setBounds(mTmpRect2, false /* forced */);
     }
 
     /** Return true if the current bound can get outputted to the rest of the system as-is. */
     private boolean useCurrentBounds() {
         final DisplayContent displayContent = getDisplayContent();
-        return mFillsParent
+        return matchParentBounds()
                 || !inSplitScreenSecondaryWindowingMode()
                 || displayContent == null
                 || displayContent.getSplitScreenPrimaryStackIgnoringVisibility() != null;
     }
 
-    /** Original bounds of the task if applicable, otherwise fullscreen rect. */
-    void getBounds(Rect out) {
+    @Override
+    public void getBounds(Rect out) {
         if (useCurrentBounds()) {
             // No need to adjust the output bounds if fullscreen or the docked stack is visible
             // since it is already what we want to represent to the rest of the system.
-            out.set(mBounds);
+            super.getBounds(out);
             return;
         }
 
         // The bounds has been adjusted to accommodate for a docked stack, but the docked stack is
         // not currently visible. Go ahead a represent it as fullscreen to the rest of the system.
-        mStack.getDisplayContent().getLogicalDisplayRect(out);
+        mStack.getDisplayContent().getBounds(out);
     }
 
     /**
@@ -490,7 +453,7 @@
                 return;
             }
 
-            if (!mFillsParent) {
+            if (!matchParentBounds()) {
                 // When minimizing the docked stack when going home, we don't adjust the task bounds
                 // so we need to intersect the task bounds with the stack bounds here.
                 //
@@ -501,11 +464,11 @@
                     mStack.getBounds(out);
                 } else {
                     mStack.getBounds(mTmpRect);
-                    mTmpRect.intersect(mBounds);
+                    mTmpRect.intersect(getBounds());
                 }
                 out.set(mTmpRect);
             } else {
-                out.set(mBounds);
+                out.set(getBounds());
             }
             return;
         }
@@ -513,7 +476,7 @@
         // The bounds has been adjusted to accommodate for a docked stack, but the docked stack is
         // not currently visible. Go ahead a represent it as fullscreen to the rest of the system.
         if (displayContent != null) {
-            displayContent.getLogicalDisplayRect(out);
+            displayContent.getBounds(out);
         }
     }
 
@@ -541,10 +504,10 @@
         if (displayContent == null) {
             return;
         }
-        if (mFillsParent) {
+        if (matchParentBounds()) {
             // TODO: Yeah...not sure if this works with WindowConfiguration, but shouldn't be a
             // problem once we move mBounds into WindowConfiguration.
-            setBounds(null, getOverrideConfiguration());
+            setBounds(null);
             return;
         }
         final int newRotation = displayContent.getDisplayInfo().rotation;
@@ -557,18 +520,18 @@
         //   task bounds so it stays in the same place.
         // - Rotate the bounds and notify activity manager if the task can be resized independently
         //   from its stack. The stack will take care of task rotation for the other case.
-        mTmpRect2.set(mBounds);
+        mTmpRect2.set(getBounds());
 
         if (!getWindowConfiguration().canResizeTask()) {
-            setBounds(mTmpRect2, getOverrideConfiguration());
+            setBounds(mTmpRect2);
             return;
         }
 
         displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
-        if (setBounds(mTmpRect2, getOverrideConfiguration()) != BOUNDS_CHANGE_NONE) {
+        if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) {
             final TaskWindowContainerController controller = getController();
             if (controller != null) {
-                controller.requestResize(mBounds, RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
+                controller.requestResize(getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
             }
         }
     }
@@ -632,7 +595,7 @@
 
     boolean isFullscreen() {
         if (useCurrentBounds()) {
-            return mFillsParent;
+            return matchParentBounds();
         }
         // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
         // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
@@ -661,7 +624,7 @@
 
     @Override
     boolean fillsParent() {
-        return mFillsParent || !getWindowConfiguration().canResizeTask();
+        return matchParentBounds() || !getWindowConfiguration().canResizeTask();
     }
 
     @Override
@@ -711,8 +674,8 @@
             final AppWindowToken appWindowToken = mChildren.get(i);
             appWindowToken.writeToProto(proto, APP_WINDOW_TOKENS, trim);
         }
-        proto.write(FILLS_PARENT, mFillsParent);
-        mBounds.writeToProto(proto, BOUNDS);
+        proto.write(FILLS_PARENT, matchParentBounds());
+        getBounds().writeToProto(proto, BOUNDS);
         mTempInsetBounds.writeToProto(proto, TEMP_INSET_BOUNDS);
         proto.end(token);
     }
@@ -721,8 +684,7 @@
         final String doublePrefix = prefix + "  ";
 
         pw.println(prefix + "taskId=" + mTaskId);
-        pw.println(doublePrefix + "mFillsParent=" + mFillsParent);
-        pw.println(doublePrefix + "mBounds=" + mBounds.toShortString());
+        pw.println(doublePrefix + "mBounds=" + getBounds().toShortString());
         pw.println(doublePrefix + "mdr=" + mDeferRemoval);
         pw.println(doublePrefix + "appTokens=" + mChildren);
         pw.println(doublePrefix + "mTempInsetBounds=" + mTempInsetBounds.toShortString());
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index e3c7515..41915a3 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -18,9 +18,7 @@
 
 import static android.graphics.Color.WHITE;
 import static android.graphics.Color.alpha;
-import static android.view.SurfaceControl.HIDDEN;
 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
 import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
 import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
 import static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 8a930ef..4a3a3fc 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -36,7 +36,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.LAYER_OFFSET_DIM;
 import static com.android.server.wm.proto.StackProto.ANIMATION_BACKGROUND_SURFACE_IS_DIMMING;
 import static com.android.server.wm.proto.StackProto.BOUNDS;
 import static com.android.server.wm.proto.StackProto.FILLS_PARENT;
@@ -88,9 +87,6 @@
     private Rect mTmpRect2 = new Rect();
     private Rect mTmpRect3 = new Rect();
 
-    /** Content limits relative to the DisplayContent this sits in. */
-    private Rect mBounds = new Rect();
-
     /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
     private final Rect mAdjustedBounds = new Rect();
 
@@ -100,9 +96,6 @@
      */
     private final Rect mFullyAdjustedImeBounds = new Rect();
 
-    /** Whether mBounds is fullscreen */
-    private boolean mFillsParent = true;
-
     // Device rotation as of the last time {@link #mBounds} was set.
     private int mRotation;
 
@@ -180,27 +173,20 @@
     /**
      * Set the bounds of the stack and its containing tasks.
      * @param stackBounds New stack bounds. Passing in null sets the bounds to fullscreen.
-     * @param configs Configuration for individual tasks, keyed by task id.
      * @param taskBounds Bounds for individual tasks, keyed by task id.
+     * @param taskTempInsetBounds Inset bounds for individual tasks, keyed by task id.
      * @return True if the stack bounds was changed.
      * */
     boolean setBounds(
-            Rect stackBounds, SparseArray<Configuration> configs, SparseArray<Rect> taskBounds,
-            SparseArray<Rect> taskTempInsetBounds) {
+            Rect stackBounds, SparseArray<Rect> taskBounds, SparseArray<Rect> taskTempInsetBounds) {
         setBounds(stackBounds);
 
         // Update bounds of containing tasks.
         for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
             final Task task = mChildren.get(taskNdx);
-            Configuration config = configs.get(task.mTaskId);
-            if (config != null) {
-                Rect bounds = taskBounds.get(task.mTaskId);
-                task.resizeLocked(bounds, config, false /* forced */);
-                task.setTempInsetBounds(taskTempInsetBounds != null ?
-                        taskTempInsetBounds.get(task.mTaskId) : null);
-            } else {
-                Slog.wtf(TAG_WM, "No config for task: " + task + ", is there a mismatch with AM?");
-            }
+            task.setBounds(taskBounds.get(task.mTaskId), false /* forced */);
+            task.setTempInsetBounds(taskTempInsetBounds != null ?
+                    taskTempInsetBounds.get(task.mTaskId) : null);
         }
         return true;
     }
@@ -227,20 +213,20 @@
         final boolean adjusted = !mAdjustedBounds.isEmpty();
         Rect insetBounds = null;
         if (adjusted && isAdjustedForMinimizedDockedStack()) {
-            insetBounds = mBounds;
+            insetBounds = getRawBounds();
         } else if (adjusted && mAdjustedForIme) {
             if (mImeGoingAway) {
-                insetBounds = mBounds;
+                insetBounds = getRawBounds();
             } else {
                 insetBounds = mFullyAdjustedImeBounds;
             }
         }
-        alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : mBounds, insetBounds);
+        alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : getRawBounds(), insetBounds);
         mDisplayContent.setLayoutNeeded();
     }
 
     private void alignTasksToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds) {
-        if (mFillsParent) {
+        if (matchParentBounds()) {
             return;
         }
 
@@ -253,13 +239,15 @@
         }
     }
 
-    private void setAnimationBackgroundBounds(Rect bounds) {
+    private void updateAnimationBackgroundBounds() {
         if (mAnimationBackgroundSurface == null) {
             return;
         }
+        getRawBounds(mTmpRect);
         // TODO: Should be in relative coordinates.
-        getPendingTransaction().setSize(mAnimationBackgroundSurface, bounds.width(), bounds.height())
-                .setPosition(mAnimationBackgroundSurface, bounds.left, bounds.top);
+        getPendingTransaction().setSize(mAnimationBackgroundSurface, mTmpRect.width(),
+                mTmpRect.height()).setPosition(mAnimationBackgroundSurface, mTmpRect.left,
+                mTmpRect.top);
         scheduleAnimation();
     }
 
@@ -283,50 +271,53 @@
         scheduleAnimation();
     }
 
-    private boolean setBounds(Rect bounds) {
-        boolean oldFullscreen = mFillsParent;
+    @Override
+    public int setBounds(Rect bounds) {
+        return setBounds(getOverrideBounds(), bounds);
+    }
+
+    private int setBounds(Rect existing, Rect bounds) {
         int rotation = Surface.ROTATION_0;
         int density = DENSITY_DPI_UNDEFINED;
         if (mDisplayContent != null) {
-            mDisplayContent.getLogicalDisplayRect(mTmpRect);
+            mDisplayContent.getBounds(mTmpRect);
             rotation = mDisplayContent.getDisplayInfo().rotation;
             density = mDisplayContent.getDisplayInfo().logicalDensityDpi;
-            mFillsParent = bounds == null;
-            if (mFillsParent) {
-                bounds = mTmpRect;
-            }
         }
 
-        if (bounds == null) {
-            // Can't set to fullscreen if we don't have a display to get bounds from...
-            return false;
-        }
-        if (mBounds.equals(bounds) && oldFullscreen == mFillsParent && mRotation == rotation) {
-            return false;
+        if (equivalentBounds(existing, bounds) && mRotation == rotation) {
+            return BOUNDS_CHANGE_NONE;
         }
 
-        setAnimationBackgroundBounds(bounds);
+        final int result = super.setBounds(bounds);
 
-        mBounds.set(bounds);
+        if (mDisplayContent != null) {
+            updateAnimationBackgroundBounds();
+        }
+
         mRotation = rotation;
         mDensity = density;
 
         updateAdjustedBounds();
 
-        return true;
+        return result;
     }
 
     /** Bounds of the stack without adjusting for other factors in the system like visibility
      * of docked stack.
-     * Most callers should be using {@link #getBounds} as it take into consideration other system
-     * factors. */
+     * Most callers should be using {@link ConfigurationContainer#getOverrideBounds} as it take into
+     * consideration other system factors. */
     void getRawBounds(Rect out) {
-        out.set(mBounds);
+        out.set(getRawBounds());
+    }
+
+    Rect getRawBounds() {
+        return super.getBounds();
     }
 
     /** Return true if the current bound can get outputted to the rest of the system as-is. */
     private boolean useCurrentBounds() {
-        if (mFillsParent
+        if (matchParentBounds()
                 || !inSplitScreenSecondaryWindowingMode()
                 || mDisplayContent == null
                 || mDisplayContent.getSplitScreenPrimaryStack() != null) {
@@ -335,24 +326,29 @@
         return false;
     }
 
-    public void getBounds(Rect out) {
+    @Override
+    public void getBounds(Rect bounds) {
+        bounds.set(getBounds());
+    }
+
+    @Override
+    public Rect getBounds() {
         if (useCurrentBounds()) {
             // If we're currently adjusting for IME or minimized docked stack, we use the adjusted
             // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked
             // stack is visible since it is already what we want to represent to the rest of the
             // system.
             if (!mAdjustedBounds.isEmpty()) {
-                out.set(mAdjustedBounds);
+                return mAdjustedBounds;
             } else {
-                out.set(mBounds);
+                return super.getBounds();
             }
-            return;
         }
 
         // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
         // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
         // system.
-        mDisplayContent.getLogicalDisplayRect(out);
+        return mDisplayContent.getBounds();
     }
 
     /**
@@ -373,7 +369,7 @@
             mBoundsAnimationSourceHintBounds.setEmpty();
         }
 
-        mPreAnimationBounds.set(mBounds);
+        mPreAnimationBounds.set(getRawBounds());
     }
 
     /**
@@ -418,12 +414,12 @@
         if (bounds != null) {
             setBounds(bounds);
             return;
-        } else if (mFillsParent) {
+        } else if (matchParentBounds()) {
             setBounds(null);
             return;
         }
 
-        mTmpRect2.set(mBounds);
+        mTmpRect2.set(getRawBounds());
         final int newRotation = mDisplayContent.getDisplayInfo().rotation;
         final int newDensity = mDisplayContent.getDisplayInfo().logicalDensityDpi;
         if (mRotation == newRotation && mDensity == newDensity) {
@@ -466,14 +462,14 @@
             return false;
         }
 
-        if (mFillsParent) {
+        if (matchParentBounds()) {
             // Update stack bounds again since rotation changed since updateDisplayInfo().
             setBounds(null);
             // Return false since we don't need the client to resize.
             return false;
         }
 
-        mTmpRect2.set(mBounds);
+        mTmpRect2.set(getRawBounds());
         mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
         if (inSplitScreenPrimaryWindowingMode()) {
             repositionPrimarySplitScreenStackAfterRotation(mTmpRect2);
@@ -510,7 +506,7 @@
         if (mDisplayContent.getDockedDividerController().canPrimaryStackDockTo(dockSide)) {
             return;
         }
-        mDisplayContent.getLogicalDisplayRect(mTmpRect);
+        mDisplayContent.getBounds(mTmpRect);
         dockSide = DockedDividerUtils.invertDockSide(dockSide);
         switch (dockSide) {
             case DOCKED_LEFT:
@@ -755,7 +751,7 @@
             // 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();
-            mDisplayContent.getLogicalDisplayRect(mTmpRect);
+            mDisplayContent.getBounds(mTmpRect);
             mTmpRect2.setEmpty();
             if (splitScreenStack != null) {
                 splitScreenStack.getRawBounds(mTmpRect2);
@@ -818,7 +814,7 @@
         }
 
         if (!inSplitScreenWindowingMode() || mDisplayContent == null) {
-            outStackBounds.set(mBounds);
+            outStackBounds.set(getRawBounds());
             return;
         }
 
@@ -833,7 +829,7 @@
             // 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.getLogicalDisplayRect(outStackBounds);
+            mDisplayContent.getBounds(outStackBounds);
             return;
         }
 
@@ -841,11 +837,11 @@
         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);
-            outStackBounds.set(mBounds);
+            outStackBounds.set(getRawBounds());
             return;
         }
 
-        mDisplayContent.getLogicalDisplayRect(mTmpRect);
+        mDisplayContent.getBounds(mTmpRect);
         dockedStack.getRawBounds(mTmpRect2);
         final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
         getStackDockedModeBounds(mTmpRect, outStackBounds, mTmpRect2,
@@ -1146,14 +1142,14 @@
             // occluded by IME. We shift its bottom up by the height of the IME, but
             // leaves at least 30% of the top stack visible.
             final int minTopStackBottom =
-                    getMinTopStackBottom(displayContentRect, mBounds.bottom);
+                    getMinTopStackBottom(displayContentRect, getRawBounds().bottom);
             final int bottom = Math.max(
-                    mBounds.bottom - yOffset + dividerWidth - dividerWidthInactive,
+                    getRawBounds().bottom - yOffset + dividerWidth - dividerWidthInactive,
                     minTopStackBottom);
-            mTmpAdjustedBounds.set(mBounds);
-            mTmpAdjustedBounds.bottom =
-                    (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount) * mBounds.bottom);
-            mFullyAdjustedImeBounds.set(mBounds);
+            mTmpAdjustedBounds.set(getRawBounds());
+            mTmpAdjustedBounds.bottom = (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount)
+                    * getRawBounds().bottom);
+            mFullyAdjustedImeBounds.set(getRawBounds());
         } else {
             // When the stack is on bottom and has no focus, it's only adjusted for divider width.
             final int dividerWidthDelta = dividerWidthInactive - dividerWidth;
@@ -1163,22 +1159,24 @@
             // We try to move it up by the height of the IME window, but only to the extent
             // that leaves at least 30% of the top stack visible.
             // 'top' is where the top of bottom stack will move to in this case.
-            final int topBeforeImeAdjust = mBounds.top - dividerWidth + dividerWidthInactive;
+            final int topBeforeImeAdjust =
+                    getRawBounds().top - dividerWidth + dividerWidthInactive;
             final int minTopStackBottom =
-                    getMinTopStackBottom(displayContentRect, mBounds.top - dividerWidth);
+                    getMinTopStackBottom(displayContentRect,
+                            getRawBounds().top - dividerWidth);
             final int top = Math.max(
-                    mBounds.top - yOffset, minTopStackBottom + dividerWidthInactive);
+                    getRawBounds().top - yOffset, minTopStackBottom + dividerWidthInactive);
 
-            mTmpAdjustedBounds.set(mBounds);
+            mTmpAdjustedBounds.set(getRawBounds());
             // Account for the adjustment for IME and divider width separately.
             // (top - topBeforeImeAdjust) is the amount of movement due to IME only,
             // and dividerWidthDelta is due to divider width change only.
-            mTmpAdjustedBounds.top = mBounds.top +
+            mTmpAdjustedBounds.top = getRawBounds().top +
                     (int) (mAdjustImeAmount * (top - topBeforeImeAdjust) +
                             mAdjustDividerAmount * dividerWidthDelta);
-            mFullyAdjustedImeBounds.set(mBounds);
+            mFullyAdjustedImeBounds.set(getRawBounds());
             mFullyAdjustedImeBounds.top = top;
-            mFullyAdjustedImeBounds.bottom = top + mBounds.height();
+            mFullyAdjustedImeBounds.bottom = top + getRawBounds().height();
         }
         return true;
     }
@@ -1192,21 +1190,21 @@
         if (dockSide == DOCKED_TOP) {
             mService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
             int topInset = mTmpRect.top;
-            mTmpAdjustedBounds.set(mBounds);
-            mTmpAdjustedBounds.bottom =
-                    (int) (minimizeAmount * topInset + (1 - minimizeAmount) * mBounds.bottom);
+            mTmpAdjustedBounds.set(getRawBounds());
+            mTmpAdjustedBounds.bottom = (int) (minimizeAmount * topInset + (1 - minimizeAmount)
+                    * getRawBounds().bottom);
         } else if (dockSide == DOCKED_LEFT) {
-            mTmpAdjustedBounds.set(mBounds);
-            final int width = mBounds.width();
+            mTmpAdjustedBounds.set(getRawBounds());
+            final int width = getRawBounds().width();
             mTmpAdjustedBounds.right =
                     (int) (minimizeAmount * mDockedStackMinimizeThickness
-                            + (1 - minimizeAmount) * mBounds.right);
+                            + (1 - minimizeAmount) * getRawBounds().right);
             mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width;
         } else if (dockSide == DOCKED_RIGHT) {
-            mTmpAdjustedBounds.set(mBounds);
-            mTmpAdjustedBounds.left =
-                    (int) (minimizeAmount * (mBounds.right - mDockedStackMinimizeThickness)
-                            + (1 - minimizeAmount) * mBounds.left);
+            mTmpAdjustedBounds.set(getRawBounds());
+            mTmpAdjustedBounds.left = (int) (minimizeAmount *
+                    (getRawBounds().right - mDockedStackMinimizeThickness)
+                            + (1 - minimizeAmount) * getRawBounds().left);
         }
         return true;
     }
@@ -1228,9 +1226,9 @@
         if (dockSide == DOCKED_TOP) {
             mService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
             int topInset = mTmpRect.top;
-            return mBounds.bottom - topInset;
+            return getRawBounds().bottom - topInset;
         } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
-            return mBounds.width() - mDockedStackMinimizeThickness;
+            return getRawBounds().width() - mDockedStackMinimizeThickness;
         } else {
             return 0;
         }
@@ -1264,11 +1262,12 @@
             return;
         }
 
-        final Rect insetBounds = mImeGoingAway ? mBounds : mFullyAdjustedImeBounds;
+        final Rect insetBounds = mImeGoingAway ? getRawBounds() : mFullyAdjustedImeBounds;
         task.alignToAdjustedBounds(mAdjustedBounds, insetBounds, getDockSide() == DOCKED_TOP);
         mDisplayContent.setLayoutNeeded();
     }
 
+
     boolean isAdjustedForMinimizedDockedStack() {
         return mMinimizeAmount != 0f;
     }
@@ -1282,8 +1281,8 @@
         for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
             mChildren.get(taskNdx).writeToProto(proto, TASKS, trim);
         }
-        proto.write(FILLS_PARENT, mFillsParent);
-        mBounds.writeToProto(proto, BOUNDS);
+        proto.write(FILLS_PARENT, matchParentBounds());
+        getRawBounds().writeToProto(proto, BOUNDS);
         proto.write(ANIMATION_BACKGROUND_SURFACE_IS_DIMMING, mAnimationBackgroundSurfaceIsShown);
         proto.end(token);
     }
@@ -1291,8 +1290,7 @@
     public void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + "mStackId=" + mStackId);
         pw.println(prefix + "mDeferRemoval=" + mDeferRemoval);
-        pw.println(prefix + "mFillsParent=" + mFillsParent);
-        pw.println(prefix + "mBounds=" + mBounds.toShortString());
+        pw.println(prefix + "mBounds=" + getRawBounds().toShortString());
         if (mMinimizeAmount != 0f) {
             pw.println(prefix + "mMinimizeAmount=" + mMinimizeAmount);
         }
@@ -1323,18 +1321,10 @@
         }
     }
 
-    /** Fullscreen status of the stack without adjusting for other factors in the system like
-     * visibility of docked stack.
-     * Most callers should be using {@link #fillsParent} as it take into consideration other
-     * system factors. */
-    boolean getRawFullscreen() {
-        return mFillsParent;
-    }
-
     @Override
     boolean fillsParent() {
         if (useCurrentBounds()) {
-            return mFillsParent;
+            return matchParentBounds();
         }
         // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
         // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
@@ -1360,7 +1350,7 @@
      * information which side of the screen was the dock anchored.
      */
     int getDockSide() {
-        return getDockSide(mBounds);
+        return getDockSide(getRawBounds());
     }
 
     private int getDockSide(Rect bounds) {
@@ -1370,7 +1360,7 @@
         if (mDisplayContent == null) {
             return DOCKED_INVALID;
         }
-        mDisplayContent.getLogicalDisplayRect(mTmpRect);
+        mDisplayContent.getBounds(mTmpRect);
         final int orientation = mDisplayContent.getConfiguration().orientation;
         return getDockSideUnchecked(bounds, mTmpRect, orientation);
     }
@@ -1490,7 +1480,7 @@
              */
 
             if (task.isActivityTypeHome() && isMinimizedDockAndHomeStackResizable()) {
-                mDisplayContent.getLogicalDisplayRect(mTmpRect);
+                mDisplayContent.getBounds(mTmpRect);
             } else {
                 task.getDimBounds(mTmpRect);
             }
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
index b3bb0b7..5caae32 100644
--- a/services/core/java/com/android/server/wm/TaskWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
@@ -18,7 +18,6 @@
 
 import android.app.ActivityManager.TaskDescription;
 import android.app.ActivityManager.TaskSnapshot;
-import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Looper;
@@ -30,6 +29,7 @@
 import java.lang.ref.WeakReference;
 
 import static com.android.server.EventLogTags.WM_TASK_CREATED;
+import static com.android.server.wm.ConfigurationContainer.BOUNDS_CHANGE_NONE;
 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
 import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -75,7 +75,7 @@
                         + stackController);
             }
             EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId);
-            final Task task = createTask(taskId, stack, userId, bounds, resizeMode,
+            final Task task = createTask(taskId, stack, userId, resizeMode,
                     supportsPictureInPicture, taskDescription);
             final int position = toTop ? POSITION_TOP : POSITION_BOTTOM;
             // We only want to move the parents to the parents if we are creating this task at the
@@ -85,10 +85,10 @@
     }
 
     @VisibleForTesting
-    Task createTask(int taskId, TaskStack stack, int userId, Rect bounds, int resizeMode,
+    Task createTask(int taskId, TaskStack stack, int userId, int resizeMode,
             boolean supportsPictureInPicture, TaskDescription taskDescription) {
-        return new Task(taskId, stack, userId, mService, bounds, resizeMode,
-                supportsPictureInPicture, taskDescription, this);
+        return new Task(taskId, stack, userId, mService, resizeMode, supportsPictureInPicture,
+                taskDescription, this);
     }
 
     @Override
@@ -151,14 +151,14 @@
         }
     }
 
-    public void resize(Rect bounds, Configuration overrideConfig, boolean relayout,
-            boolean forced) {
+    public void resize(boolean relayout, boolean forced) {
         synchronized (mWindowMap) {
             if (mContainer == null) {
                 throw new IllegalArgumentException("resizeTask: taskId " + mTaskId + " not found.");
             }
 
-            if (mContainer.resizeLocked(bounds, overrideConfig, forced) && relayout) {
+            if (mContainer.setBounds(mContainer.getOverrideBounds(), forced) != BOUNDS_CHANGE_NONE
+                    && relayout) {
                 mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
             }
         }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index a5e6288..610453e 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -318,11 +318,24 @@
      * @see #mFullConfiguration
      */
     @Override
-    final public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+    public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+        // We must diff before the configuration is applied so that we can capture the change
+        // against the existing bounds.
+        final int diff = diffOverrideBounds(overrideConfiguration.windowConfiguration.getBounds());
         super.onOverrideConfigurationChanged(overrideConfiguration);
         if (mParent != null) {
             mParent.onDescendantOverrideConfigurationChanged();
         }
+
+        if (diff == BOUNDS_CHANGE_NONE) {
+            return;
+        }
+
+        if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
+            onResize();
+        } else {
+            onMovedByResize();
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d88cf4d..1cd4080 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -126,7 +126,6 @@
 import android.app.IActivityManager;
 import android.app.IAssistDataReceiver;
 import android.content.BroadcastReceiver;
-import android.content.ClipData;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -5517,7 +5516,7 @@
     }
 
     void reconfigureDisplayLocked(@NonNull DisplayContent displayContent) {
-        if (!mDisplayReady) {
+        if (!displayContent.isReady()) {
             return;
         }
         displayContent.configureDisplayPolicy();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e53fccf..90e9c23 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -814,7 +814,7 @@
             layoutXDiff = 0;
             layoutYDiff = 0;
         } else {
-            getContainerBounds(mContainingFrame);
+            getBounds(mContainingFrame);
             if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) {
 
                 // If the bounds are frozen, we still want to translate the window freely and only
@@ -972,7 +972,7 @@
             mContentInsets.setEmpty();
             mVisibleInsets.setEmpty();
         } else {
-            getDisplayContent().getLogicalDisplayRect(mTmpRect);
+            getDisplayContent().getBounds(mTmpRect);
             // Override right and/or bottom insets in case if the frame doesn't fit the screen in
             // non-fullscreen mode.
             boolean overrideRightInset = !windowsAreFloating && !inFullscreenContainer
@@ -1044,6 +1044,18 @@
                 + " of=" + mOutsets.toShortString());
     }
 
+    // TODO: Look into whether this override is still necessary.
+    @Override
+    public Rect getBounds() {
+        if (isInMultiWindowMode()) {
+            return getTask().getBounds();
+        } else if (mAppToken != null){
+            return mAppToken.getBounds();
+        } else {
+            return super.getBounds();
+        }
+    }
+
     @Override
     public Rect getFrameLw() {
         return mFrame;
@@ -2951,33 +2963,12 @@
 
     /** Is this window in a container that takes up the entire screen space? */
     private boolean inFullscreenContainer() {
-        if (mAppToken == null) {
-            return true;
-        }
-        if (mAppToken.hasBounds()) {
-            return false;
-        }
-        return !isInMultiWindowMode();
+        return mAppToken == null || (mAppToken.matchParentBounds() && !isInMultiWindowMode());
     }
 
     /** @return true when the window is in fullscreen task, but has non-fullscreen bounds set. */
     boolean isLetterboxedAppWindow() {
-        final Task task = getTask();
-        final boolean taskIsFullscreen = task != null && task.isFullscreen();
-        final boolean appWindowIsFullscreen = mAppToken != null && !mAppToken.hasBounds();
-
-        return taskIsFullscreen && !appWindowIsFullscreen;
-    }
-
-    /** Returns the appropriate bounds to use for computing frames. */
-    private void getContainerBounds(Rect outBounds) {
-        if (isInMultiWindowMode()) {
-            getTask().getBounds(outBounds);
-        } else if (mAppToken != null){
-            mAppToken.getBounds(outBounds);
-        } else {
-            outBounds.setEmpty();
-        }
+        return !isInMultiWindowMode() && mAppToken != null && !mAppToken.matchParentBounds();
     }
 
     boolean isDragResizeChanged() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index d11b0db..d2b3748 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1971,7 +1971,7 @@
         final float width = w.mFrame.width();
         final float height = w.mFrame.height();
 
-        mService.getDefaultDisplayContentLocked().getLogicalDisplayRect(displayRect);
+        mService.getDefaultDisplayContentLocked().getBounds(displayRect);
         final float displayWidth = displayRect.width();
         final float displayHeight = displayRect.height();
 
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index d90e284..ee45595 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -37,7 +37,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.content.ComponentName;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.MediumTest;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index bc503c4..b4919b6 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -28,7 +28,6 @@
 
 import android.app.ActivityOptions;
 import android.app.IApplicationThread;
-import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -108,8 +107,8 @@
         final Rect bounds = new Rect(10, 10, 100, 100);
 
         mStarter.updateBounds(task, bounds);
-        assertEquals(task.mBounds, bounds);
-        assertEquals(task.getStack().mBounds, null);
+        assertEquals(task.getOverrideBounds(), bounds);
+        assertEquals(new Rect(), task.getStack().getOverrideBounds());
 
         // When in a resizeable stack, the stack bounds should be updated as well.
         final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor)
@@ -124,10 +123,10 @@
 
         // In the case of no animation, the stack and task bounds should be set immediately.
         if (!ANIMATE) {
-            assertEquals(task2.getStack().mBounds, bounds);
-            assertEquals(task2.mBounds, bounds);
+            assertEquals(task2.getStack().getOverrideBounds(), bounds);
+            assertEquals(task2.getOverrideBounds(), bounds);
         } else {
-            assertEquals(task2.mBounds, null);
+            assertEquals(task2.getOverrideBounds(), new Rect());
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 9683e22..2fffb89 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -19,6 +19,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 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.view.Display.DEFAULT_DISPLAY;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.doNothing;
@@ -415,6 +416,12 @@
         @Override
         protected T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
             mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController();
+
+            // Primary pinned stacks require a non-empty out bounds to be set or else all tasks
+            // will be moved to the full screen stack.
+            if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+                outBounds.set(0, 0, 100, 100);
+            }
             return mContainerController;
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java b/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java
index 01e2da6..13daf3e 100644
--- a/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java
@@ -16,7 +16,6 @@
 
 package com.android.server.am;
 
-import android.content.ComponentName;
 import android.content.pm.ActivityInfo.WindowLayout;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
@@ -93,8 +92,8 @@
      */
     @Test
     public void testInitialBounds() throws Exception {
-        assertEquals(mStack.mBounds, STACK_BOUNDS);
-        assertEquals(mTask.mBounds, null);
+        assertEquals(mStack.getOverrideBounds(), STACK_BOUNDS);
+        assertEquals(mTask.getOverrideBounds(), new Rect());
     }
 
     /**
@@ -182,7 +181,7 @@
         mService.mStackSupervisor.getLaunchingBoundsController().layoutTask(mTask, layout);
 
         // Second task will be laid out on top of the first so starting bounds is the same.
-        final Rect expectedBounds = new Rect(mTask.mBounds);
+        final Rect expectedBounds = new Rect(mTask.getOverrideBounds());
 
         ActivityRecord activity = null;
         TaskRecord secondTask = null;
@@ -203,14 +202,16 @@
             if ((gravity & (Gravity.TOP | Gravity.RIGHT)) == (Gravity.TOP | Gravity.RIGHT)
                     || (gravity & (Gravity.BOTTOM | Gravity.RIGHT))
                     == (Gravity.BOTTOM | Gravity.RIGHT)) {
-                expectedBounds.offset(-LaunchingTaskPositioner.getHorizontalStep(mStack.mBounds),
-                        0);
+                expectedBounds.offset(-LaunchingTaskPositioner.getHorizontalStep(
+                        mStack.getOverrideBounds()), 0);
             } else if ((gravity & Gravity.TOP) == Gravity.TOP
                     || (gravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
-                expectedBounds.offset(LaunchingTaskPositioner.getHorizontalStep(mStack.mBounds), 0);
+                expectedBounds.offset(
+                        LaunchingTaskPositioner.getHorizontalStep(mStack.getOverrideBounds()), 0);
             } else {
-                expectedBounds.offset(LaunchingTaskPositioner.getHorizontalStep(mStack.mBounds),
-                        LaunchingTaskPositioner.getVerticalStep(mStack.mBounds));
+                expectedBounds.offset(
+                        LaunchingTaskPositioner.getHorizontalStep(mStack.getOverrideBounds()),
+                        LaunchingTaskPositioner.getVerticalStep(mStack.getOverrideBounds()));
             }
 
             assertEquals(mResult, expectedBounds);
@@ -228,10 +229,12 @@
 
     private Rect getDefaultBounds(int gravity) {
         final Rect bounds = new Rect();
-        bounds.set(mStack.mBounds);
+        bounds.set(mStack.getOverrideBounds());
 
-        final int verticalInset = LaunchingTaskPositioner.getFreeformStartTop(mStack.mBounds);
-        final int horizontalInset = LaunchingTaskPositioner.getFreeformStartLeft(mStack.mBounds);
+        final int verticalInset =
+                LaunchingTaskPositioner.getFreeformStartTop(mStack.getOverrideBounds());
+        final int horizontalInset =
+                LaunchingTaskPositioner.getFreeformStartLeft(mStack.getOverrideBounds());
 
         bounds.inset(horizontalInset, verticalInset);
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index 5d2bb4d..503e1ac 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -21,7 +21,7 @@
 import org.junit.runner.RunWith;
 
 import android.app.ActivityManager.TaskDescription;
-import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.InstrumentationRegistry;
@@ -75,11 +75,23 @@
         final Rect mInsetBounds = new Rect();
         boolean mFullscreenForTest = true;
         TaskWithBounds(Rect bounds) {
-            super(0, mStubStack, 0, sWm, null, 0, false, new TaskDescription(), null);
+            super(0, mStubStack, 0, sWm, 0, false, new TaskDescription(), null);
             mBounds = bounds;
+            setBounds(bounds);
         }
+
         @Override
-        void getBounds(Rect outBounds) {
+        public Rect getBounds() {
+            return mBounds;
+        }
+
+        @Override
+        public void getBounds(Rect out) {
+            out.set(mBounds);
+        }
+
+        @Override
+        public void getOverrideBounds(Rect outBounds) {
             outBounds.set(mBounds);
         }
         @Override
@@ -395,7 +407,9 @@
         final int xInset = logicalWidth / 10;
         final int yInset = logicalWidth / 10;
         final Rect cf = new Rect(xInset, yInset, logicalWidth - xInset, logicalHeight - yInset);
-        w.mAppToken.onOverrideConfigurationChanged(w.mAppToken.getOverrideConfiguration(), cf);
+        Configuration config = new Configuration(w.mAppToken.getOverrideConfiguration());
+        config.windowConfiguration.setBounds(cf);
+        w.mAppToken.onOverrideConfigurationChanged(config);
         pf.set(0, 0, logicalWidth, logicalHeight);
         task.mFullscreenForTest = true;
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index 1aafac6..b2334e8 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -29,11 +29,17 @@
 import static android.app.AppOpsManager.OP_NONE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.res.Configuration.EMPTY;
+
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyFloat;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+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.
@@ -64,13 +70,24 @@
     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(7);
+            final Rect bounds = invocationOnMock.<Rect>getArgument(0);
+            config.windowConfiguration.setBounds(bounds);
+            return null;
+        }).when(controller).adjustConfigurationForBounds(any(), any(), any(), any(),
+                anyBoolean(), anyBoolean(), anyFloat(), any(), any());
+
         return controller;
     }
 
     /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
     public static Task createTaskInStack(WindowManagerService service, TaskStack stack,
             int userId) {
-        final Task newTask = new Task(sNextTaskId++, stack, userId, service, null, 0, false,
+        final Task newTask = new Task(sNextTaskId++, stack, userId, service, 0, false,
                 new ActivityManager.TaskDescription(), null);
         stack.addTask(newTask, POSITION_TOP);
         return newTask;
@@ -98,17 +115,17 @@
         TestAppWindowToken(DisplayContent dc) {
             super(dc.mService, new IApplicationToken.Stub() {
                 public String getName() {return null;}
-                }, false, dc, true /* fillsParent */, null /* bounds */);
+                }, false, dc, true /* fillsParent */);
         }
 
         TestAppWindowToken(WindowManagerService service, IApplicationToken token,
                 boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
                 boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
                 int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
-                boolean alwaysFocusable, AppWindowContainerController controller, Rect bounds) {
+                boolean alwaysFocusable, AppWindowContainerController controller) {
             super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen,
                     showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges,
-                    launchTaskBehind, alwaysFocusable, controller, bounds);
+                    launchTaskBehind, alwaysFocusable, controller);
         }
 
         int getWindowsCount() {
@@ -175,10 +192,10 @@
         private boolean mUseLocalIsAnimating = false;
         private boolean mIsAnimating = false;
 
-        TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
+        TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service,
                 int resizeMode, boolean supportsPictureInPicture,
                 TaskWindowContainerController controller) {
-            super(taskId, stack, userId, service, bounds, resizeMode, supportsPictureInPicture,
+            super(taskId, stack, userId, service, resizeMode, supportsPictureInPicture,
                     new ActivityManager.TaskDescription(), controller);
         }
 
@@ -247,9 +264,9 @@
         }
 
         @Override
-        TestTask createTask(int taskId, TaskStack stack, int userId, Rect bounds, int resizeMode,
+        TestTask createTask(int taskId, TaskStack stack, int userId, int resizeMode,
                 boolean supportsPictureInPicture, ActivityManager.TaskDescription taskDescription) {
-            return new TestTask(taskId, stack, userId, mService, bounds, resizeMode,
+            return new TestTask(taskId, stack, userId, mService, resizeMode,
                     supportsPictureInPicture, this);
         }
     }
@@ -269,8 +286,7 @@
                     true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */,
                     false /* launchTaskBehind */, false /* alwaysFocusable */,
                     0 /* targetSdkVersion */, 0 /* rotationAnimationHint */,
-                    0 /* inputDispatchingTimeoutNanos */, taskController.mService,
-                    null /* bounds */);
+                    0 /* inputDispatchingTimeoutNanos */, taskController.mService);
             mToken = token;
         }
 
@@ -279,12 +295,12 @@
                 boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
                 boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
                 int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
-                boolean alwaysFocusable, AppWindowContainerController controller, Rect bounds) {
+                boolean alwaysFocusable, AppWindowContainerController controller) {
             return new TestAppWindowToken(service, token, voiceInteraction, dc,
                     inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
                     orientation,
                     rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
-                    controller, bounds);
+                    controller);
         }
 
         AppWindowToken getAppWindowToken(DisplayContent dc) {