Merge "Removed global windowFrames from PWM"
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 3b19beb..91fd8d0 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -125,6 +125,7 @@
 import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION;
 import static android.view.WindowManagerGlobal.ADD_OKAY;
 import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
+
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
@@ -631,9 +632,11 @@
 
     InputConsumer mInputConsumer = null;
 
-    private final WindowFrames mWindowFrames = new WindowFrames();
-    private static final Rect mTmpDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
-    private static final Rect mTmpRect = new Rect();
+    private static final Rect sTmpDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
+    private static final Rect sTmpRect = new Rect();
+    private static final Rect sTmpDockedFrame = new Rect();
+    private static final Rect sTmpNavFrame = new Rect();
+    private static final Rect sTmpLastParentFrame = new Rect();
 
     WindowState mTopFullscreenOpaqueWindowState;
     WindowState mTopFullscreenOpaqueOrDimmingWindowState;
@@ -4308,9 +4311,6 @@
         mDockLayer = 0x10000000;
         mStatusBarLayer = -1;
 
-        mWindowFrames.setDisplayCutout(displayFrames.mDisplayCutout);
-        mWindowFrames.setParentFrameWasClippedByDisplayCutout(false);
-
         if (displayFrames.mDisplayId == DEFAULT_DISPLAY) {
             // For purposes of putting out fake window up to steal focus, we will
             // drive nav being hidden only by whether it is requested.
@@ -4377,12 +4377,8 @@
             return;
         }
 
-        mTmpRect.setEmpty();
-        mWindowFrames.setFrames(displayFrames.mDock /* parentFrame */,
-                displayFrames.mDock /* displayFrame */, displayFrames.mDock /* overscanFrame */,
-                displayFrames.mDock /* contentFrame */, displayFrames.mDock /* visibleFrame */,
-                mTmpRect /* decorFrame */, displayFrames.mDock /* stableFrame */,
-                displayFrames.mDock /* outsetFrame */);
+        sTmpRect.setEmpty();
+        sTmpDockedFrame.set(displayFrames.mDock);
 
         final int displayId = displayFrames.mDisplayId;
         final Rect dockFrame = displayFrames.mDock;
@@ -4396,7 +4392,13 @@
                 continue;
             }
 
-            w.computeFrameLw(mWindowFrames);
+            w.getWindowFrames().setFrames(sTmpDockedFrame /* parentFrame */,
+                    sTmpDockedFrame /* displayFrame */, sTmpDockedFrame /* overscanFrame */,
+                    sTmpDockedFrame /* contentFrame */, sTmpDockedFrame /* visibleFrame */,
+                    sTmpRect /* decorFrame */, sTmpDockedFrame /* stableFrame */,
+                    sTmpDockedFrame /* outsetFrame */);
+            w.getWindowFrames().setDisplayCutout(displayFrames.mDisplayCutout);
+            w.computeFrameLw();
             final Rect frame = w.getFrameLw();
 
             if (frame.left <= 0 && frame.top <= 0) {
@@ -4448,17 +4450,17 @@
             return false;
         }
         // apply any navigation bar insets
-        mTmpRect.setEmpty();
-        mWindowFrames.setFrames(displayFrames.mUnrestricted /* parentFrame */,
+        sTmpRect.setEmpty();
+        mStatusBar.getWindowFrames().setFrames(displayFrames.mUnrestricted /* parentFrame */,
                 displayFrames.mUnrestricted /* displayFrame */,
                 displayFrames.mStable /* overscanFrame */, displayFrames.mStable /* contentFrame */,
-                displayFrames.mStable /* visibleFrame */, mTmpRect /* decorFrame */,
+                displayFrames.mStable /* visibleFrame */, sTmpRect /* decorFrame */,
                 displayFrames.mStable /* stableFrame */, displayFrames.mStable /* outsetFrame */);
-
+        mStatusBar.getWindowFrames().setDisplayCutout(displayFrames.mDisplayCutout);
         mStatusBarLayer = mStatusBar.getSurfaceLayer();
 
         // Let the status bar determine its size.
-        mStatusBar.computeFrameLw(mWindowFrames);
+        mStatusBar.computeFrameLw();
 
         // For layout, the status bar is always at the top with our fixed height.
         displayFrames.mStable.top = displayFrames.mUnrestricted.top
@@ -4468,11 +4470,11 @@
                 displayFrames.mDisplayCutoutSafe.top);
 
         // Tell the bar controller where the collapsed status bar content is
-        mTmpRect.set(mStatusBar.getContentFrameLw());
-        mTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
-        mTmpRect.top = mStatusBar.getContentFrameLw().top;  // Ignore top display cutout inset
-        mTmpRect.bottom = displayFrames.mStable.top;  // Use collapsed status bar size
-        mStatusBarController.setContentFrame(mTmpRect);
+        sTmpRect.set(mStatusBar.getContentFrameLw());
+        sTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
+        sTmpRect.top = mStatusBar.getContentFrameLw().top;  // Ignore top display cutout inset
+        sTmpRect.bottom = displayFrames.mStable.top;  // Use collapsed status bar size
+        mStatusBarController.setContentFrame(sTmpRect);
 
         boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
         boolean statusBarTranslucent = (sysui
@@ -4512,7 +4514,7 @@
             return false;
         }
 
-        final Rect navigationFrame = mWindowFrames.mParentFrame;
+        final Rect navigationFrame = sTmpNavFrame;
         boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
         // Force the navigation bar to its appropriate place and size. We need to do this directly,
         // instead of relying on it to bubble up from the nav bar, because this needs to change
@@ -4523,7 +4525,7 @@
         final Rect dockFrame = displayFrames.mDock;
         mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight, rotation);
 
-        final Rect cutoutSafeUnrestricted = mTmpRect;
+        final Rect cutoutSafeUnrestricted = sTmpRect;
         cutoutSafeUnrestricted.set(displayFrames.mUnrestricted);
         cutoutSafeUnrestricted.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
 
@@ -4605,15 +4607,15 @@
         displayFrames.mContent.set(dockFrame);
         mStatusBarLayer = mNavigationBar.getSurfaceLayer();
         // And compute the final frame.
-        mTmpRect.setEmpty();
-        mWindowFrames.setFrames(navigationFrame /* parentFrame */,
+        sTmpRect.setEmpty();
+        mNavigationBar.getWindowFrames().setFrames(navigationFrame /* parentFrame */,
                 navigationFrame /* displayFrame */, navigationFrame /* overscanFrame */,
                 displayFrames.mDisplayCutoutSafe /* contentFrame */,
-                navigationFrame /* visibleFrame */, mTmpRect /* decorFrame */,
+                navigationFrame /* visibleFrame */, sTmpRect /* decorFrame */,
                 navigationFrame /* stableFrame */,
                 displayFrames.mDisplayCutoutSafe /* outsetFrame */);
-
-        mNavigationBar.computeFrameLw(mWindowFrames);
+        mNavigationBar.getWindowFrames().setDisplayCutout(displayFrames.mDisplayCutout);
+        mNavigationBar.computeFrameLw();
         mNavigationBarController.setContentFrame(mNavigationBar.getContentFrameLw());
 
         if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + navigationFrame);
@@ -4744,17 +4746,20 @@
         final int requestedSysUiFl = PolicyControl.getSystemUiVisibility(null, attrs);
         final int sysUiFl = requestedSysUiFl | getImpliedSysUiFlagsForLayout(attrs);
 
-        final Rect pf = mWindowFrames.mParentFrame;
-        final Rect df = mWindowFrames.mDisplayFrame;
-        final Rect of = mWindowFrames.mOverscanFrame;
-        final Rect cf = mWindowFrames.mContentFrame;
-        final Rect vf = mWindowFrames.mVisibleFrame;
-        final Rect dcf = mWindowFrames.mDecorFrame;
-        final Rect sf = mWindowFrames.mStableFrame;
+        final WindowFrames windowFrames = win.getWindowFrames();
+
+        windowFrames.setHasOutsets(false);
+        sTmpLastParentFrame.set(windowFrames.mParentFrame);
+        final Rect pf = windowFrames.mParentFrame;
+        final Rect df = windowFrames.mDisplayFrame;
+        final Rect of = windowFrames.mOverscanFrame;
+        final Rect cf = windowFrames.mContentFrame;
+        final Rect vf = windowFrames.mVisibleFrame;
+        final Rect dcf = windowFrames.mDecorFrame;
+        final Rect sf = windowFrames.mStableFrame;
         dcf.setEmpty();
-        mWindowFrames.mOutsetFrame.setEmpty();
-        mWindowFrames.setParentFrameWasClippedByDisplayCutout(false);
-        mWindowFrames.setDisplayCutout(displayFrames.mDisplayCutout);
+        windowFrames.setParentFrameWasClippedByDisplayCutout(false);
+        windowFrames.setDisplayCutout(displayFrames.mDisplayCutout);
 
         final boolean hasNavBar = (isDefaultDisplay && mDefaultDisplayPolicy.hasNavigationBar()
                 && mNavigationBar != null && mNavigationBar.isVisibleLw());
@@ -4774,7 +4779,7 @@
             cf.set(displayFrames.mDock);
             of.set(displayFrames.mDock);
             df.set(displayFrames.mDock);
-            pf.set(displayFrames.mDock);
+            windowFrames.mParentFrame.set(displayFrames.mDock);
             // IM dock windows layout below the nav bar...
             pf.bottom = df.bottom = of.bottom = displayFrames.mUnrestricted.bottom;
             // ...with content insets above the nav bar
@@ -4876,9 +4881,7 @@
                                 ? displayFrames.mRestricted.bottom
                                 : displayFrames.mUnrestricted.bottom;
 
-                        if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
-                                        "Laying out status bar window: (%d,%d - %d,%d)",
-                                        pf.left, pf.top, pf.right, pf.bottom));
+                        if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out status bar window: " + pf);
                     } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
                             && type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW) {
                         // Asking to layout into the overscan region, so give it that pure
@@ -4950,17 +4953,13 @@
                         pf.bottom = df.bottom = of.bottom = cf.bottom =
                                 displayFrames.mRestricted.bottom;
                     }
-                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
-                            "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
-                            pf.left, pf.top, pf.right, pf.bottom));
+                    if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out IN_SCREEN status bar window: " + pf);
                 } else if (type == TYPE_NAVIGATION_BAR || type == TYPE_NAVIGATION_BAR_PANEL) {
                     // The navigation bar has Real Ultimate Power.
                     of.set(displayFrames.mUnrestricted);
                     df.set(displayFrames.mUnrestricted);
                     pf.set(displayFrames.mUnrestricted);
-                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
-                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
-                                    pf.left, pf.top, pf.right, pf.bottom));
+                    if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out navigation bar window: " + pf);
                 } else if ((type == TYPE_SECURE_SYSTEM_OVERLAY || type == TYPE_SCREENSHOT)
                         && ((fl & FLAG_FULLSCREEN) != 0)) {
                     // Fullscreen secure system overlays get what they ask for. Screenshot region
@@ -5087,7 +5086,7 @@
         // Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
         // the cutout safe zone.
         if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
-            final Rect displayCutoutSafeExceptMaybeBars = mTmpDisplayCutoutSafeExceptMaybeBarsRect;
+            final Rect displayCutoutSafeExceptMaybeBars = sTmpDisplayCutoutSafeExceptMaybeBarsRect;
             displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe);
             if (layoutInScreen && layoutInsetDecor && !requestedFullscreen
                     && cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {
@@ -5122,9 +5121,9 @@
             // They will later be cropped or shifted using the displayFrame in WindowState,
             // which prevents overlap with the DisplayCutout.
             if (!attachedInParent && !floatingInScreenWindow) {
-                mTmpRect.set(pf);
+                sTmpRect.set(pf);
                 pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
-                mWindowFrames.setParentFrameWasClippedByDisplayCutout(!mTmpRect.equals(pf));
+                windowFrames.setParentFrameWasClippedByDisplayCutout(!sTmpRect.equals(pf));
             }
             // Make sure that NO_LIMITS windows clipped to the display don't extend under the
             // cutout.
@@ -5152,8 +5151,9 @@
         // apply the outsets to floating dialogs, because they wouldn't make sense there.
         final boolean useOutsets = shouldUseOutsets(attrs, fl);
         if (isDefaultDisplay && useOutsets) {
-            final Rect osf = mWindowFrames.mOutsetFrame;
+            final Rect osf = windowFrames.mOutsetFrame;
             osf.set(cf.left, cf.top, cf.right, cf.bottom);
+            windowFrames.setHasOutsets(true);
             int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
             if (outset > 0) {
                 int rotation = displayFrames.mRotation;
@@ -5180,9 +5180,13 @@
                 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
                 + " dcf=" + dcf.toShortString()
                 + " sf=" + sf.toShortString()
-                + " osf=" + mWindowFrames.mOutsetFrame.toShortString());
+                + " osf=" + windowFrames.mOutsetFrame.toShortString() + " " + win);
 
-        win.computeFrameLw(mWindowFrames);
+        if (!sTmpLastParentFrame.equals(pf)) {
+            windowFrames.setContentChanged(true);
+        }
+
+        win.computeFrameLw();
         // Dock windows carve out the bottom of the screen, so normal windows
         // can't appear underneath them.
         if (type == TYPE_INPUT_METHOD && win.isVisibleLw()
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index b55adeb..1fcdd63 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -63,12 +63,10 @@
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
-import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.Context;
-import android.content.pm.ActivityInfo;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
@@ -95,7 +93,6 @@
 import com.android.server.wm.DisplayFrames;
 import com.android.server.wm.DisplayRotation;
 import com.android.server.wm.WindowFrames;
-import com.android.server.wm.utils.WmDisplayCutout;
 
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -201,10 +198,8 @@
          * getFrame() if so desired.  Must be called with the window manager
          * lock held.
          *
-         * @param windowFrames Container for all the window frames that affect how the window is
-         *                     laid out.
          */
-        public void computeFrameLw(WindowFrames windowFrames);
+        public void computeFrameLw();
 
         /**
          * Retrieve the current frame of the window that has been assigned by
@@ -477,6 +472,11 @@
          * Writes {@link com.android.server.wm.IdentifierProto} to stream.
          */
         void writeIdentifierToProto(ProtoOutputStream proto, long fieldId);
+
+        /**
+         * @return The {@link WindowFrames} associated with this {@link WindowState}
+         */
+        WindowFrames getWindowFrames();
     }
 
     /**
@@ -1167,7 +1167,6 @@
     default void layoutWindowLw(
             WindowState win, WindowState attached, DisplayFrames displayFrames) {}
 
-
     /**
      * Return the layout hints for a newly added window. These values are computed on the
      * most recent layout, so they are not guaranteed to be correct.
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index d518549..984ebe1 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -571,7 +571,7 @@
             if (!w.mLayoutAttached) {
                 if (mTmpInitial) {
                     //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
-                    w.mContentChanged = false;
+                    w.resetContentChanged();
                 }
                 if (w.mAttrs.type == TYPE_DREAM) {
                     // Don't layout windows behind a dream, so that if it does stuff like hide
@@ -616,7 +616,7 @@
                     || w.mLayoutNeeded) {
                 if (mTmpInitial) {
                     //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
-                    w.mContentChanged = false;
+                    w.resetContentChanged();
                 }
                 w.mLayoutNeeded = false;
                 w.prelayout();
@@ -699,7 +699,7 @@
         final WindowStateAnimator winAnimator = w.mWinAnimator;
 
         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
-        w.mContentChanged = false;
+        w.resetContentChanged();
 
         // Moved from updateWindowsAndWallpaperLocked().
         if (w.mHasSurface) {
diff --git a/services/core/java/com/android/server/wm/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java
index cbe7d9d..20a874b 100644
--- a/services/core/java/com/android/server/wm/WindowFrames.java
+++ b/services/core/java/com/android/server/wm/WindowFrames.java
@@ -36,7 +36,6 @@
 import android.graphics.Rect;
 import android.util.proto.ProtoOutputStream;
 import android.view.DisplayCutout;
-import android.view.WindowManager;
 
 import com.android.server.wm.utils.InsetUtils;
 import com.android.server.wm.utils.WmDisplayCutout;
@@ -191,6 +190,10 @@
 
     private final Rect mTmpRect = new Rect();
 
+    private boolean mHasOutsets;
+
+    private boolean mContentChanged;
+
     public WindowFrames() {
     }
 
@@ -237,11 +240,9 @@
      * Calculates the outsets for this windowFrame. The outsets are calculated by the area between
      * the {@link #mOutsetFrame} and the {@link #mContentFrame}. If there are no outsets, then
      * {@link #mOutsets} is set to empty.
-     *
-     * @param hasOutsets Whether this frame has outsets.
      */
-    void calculateOutsets(boolean hasOutsets) {
-        if (hasOutsets) {
+    void calculateOutsets() {
+        if (mHasOutsets) {
             InsetUtils.insetsBetweenFrames(mOutsetFrame, mContentFrame, mOutsets);
         } else {
             mOutsets.setEmpty();
@@ -249,7 +250,8 @@
     }
 
     /**
-     * Calculate the insets for the type {@link WindowManager.LayoutParams#TYPE_DOCK_DIVIDER}
+     * Calculate the insets for the type
+     * {@link android.view.WindowManager.LayoutParams#TYPE_DOCK_DIVIDER}
      *
      * @param cutoutInsets The insets for the cutout.
      */
@@ -367,6 +369,28 @@
         mLastContentInsets.set(-1, -1, -1, -1);
     }
 
+    /**
+     * Sets whether the frame has outsets.
+     */
+    public void setHasOutsets(boolean hasOutsets) {
+        mHasOutsets = hasOutsets;
+    }
+
+    /**
+     * Sets whether the content has changed. This means that either the size or parent frame has
+     * changed.
+     */
+    public void setContentChanged(boolean contentChanged) {
+        mContentChanged = contentChanged;
+    }
+
+    /**
+     * @see #setContentChanged(boolean)
+     */
+    boolean hasContentChanged() {
+        return mContentChanged;
+    }
+
     public void writeToProto(@NonNull ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
         mParentFrame.writeToProto(proto, PARENT_FRAME);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 5272b66..f1ddda7 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -359,8 +359,6 @@
      */
     private final Rect mInsetFrame = new Rect();
 
-    boolean mContentChanged;
-
     // If a window showing a wallpaper: the requested offset for the
     // wallpaper; if a wallpaper window: the currently applied offset.
     float mWallpaperX = -1;
@@ -787,7 +785,7 @@
     }
 
     @Override
-    public void computeFrameLw(WindowFrames windowFrames) {
+    public void computeFrameLw() {
         if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) {
             // This window is being replaced and either already got information that it's being
             // removed or we are still waiting for some information. Because of this we don't
@@ -796,8 +794,6 @@
             return;
         }
         mHaveFrame = true;
-        mWindowFrames.setParentFrameWasClippedByDisplayCutout(
-                windowFrames.parentFrameWasClippedByDisplayCutout());
 
         final Task task = getTask();
         final boolean inFullscreenContainer = inFullscreenContainer();
@@ -827,10 +823,9 @@
         final int layoutYDiff;
         if (inFullscreenContainer || layoutInParentFrame()) {
             // We use the parent frame as the containing frame for fullscreen and child windows
-            mWindowFrames.mContainingFrame.set(windowFrames.mParentFrame);
-            mWindowFrames.mDisplayFrame.set(windowFrames.mDisplayFrame);
-            layoutDisplayFrame = windowFrames.mDisplayFrame;
-            layoutContainingFrame = windowFrames.mParentFrame;
+            mWindowFrames.mContainingFrame.set(mWindowFrames.mParentFrame);
+            layoutDisplayFrame = mWindowFrames.mDisplayFrame;
+            layoutContainingFrame = mWindowFrames.mParentFrame;
             layoutXDiff = 0;
             layoutYDiff = 0;
         } else {
@@ -849,17 +844,17 @@
             // IME is up and obscuring this window. Adjust the window position so it is visible.
             if (imeWin != null && imeWin.isVisibleNow() && isInputMethodTarget()) {
                 if (inFreeformWindowingMode() && mWindowFrames.mContainingFrame.bottom
-                        > windowFrames.mContentFrame.bottom) {
+                        > mWindowFrames.mContentFrame.bottom) {
                     // In freeform we want to move the top up directly.
                     // TODO: Investigate why this is contentFrame not parentFrame.
                     mWindowFrames.mContainingFrame.top -= mWindowFrames.mContainingFrame.bottom
-                            - windowFrames.mContentFrame.bottom;
+                            - mWindowFrames.mContentFrame.bottom;
                 } else if (!inPinnedWindowingMode() && mWindowFrames.mContainingFrame.bottom
-                        > windowFrames.mParentFrame.bottom) {
+                        > mWindowFrames.mParentFrame.bottom) {
                     // But in docked we want to behave like fullscreen and behave as if the task
                     // were given smaller bounds for the purposes of layout. Skip adjustments for
                     // the pinned stack, they are handled separately in the PinnedStackController.
-                    mWindowFrames.mContainingFrame.bottom = windowFrames.mParentFrame.bottom;
+                    mWindowFrames.mContainingFrame.bottom = mWindowFrames.mParentFrame.bottom;
                 }
             }
 
@@ -868,7 +863,7 @@
                 // if it wasn't set already. No need to intersect it with the (visible)
                 // "content frame" since it is allowed to be outside the visible desktop.
                 if (mWindowFrames.mContainingFrame.isEmpty()) {
-                    mWindowFrames.mContainingFrame.set(windowFrames.mContentFrame);
+                    mWindowFrames.mContainingFrame.set(mWindowFrames.mContentFrame);
                 }
             }
 
@@ -878,10 +873,11 @@
                 // PIP edge case: When going from pinned to fullscreen, we apply a
                 // tempInsetFrame for the full task - but we're still at the start of the animation.
                 // To prevent a jump if there's a letterbox, restrict to the parent frame.
-                mInsetFrame.intersectUnchecked(windowFrames.mParentFrame);
-                mWindowFrames.mContainingFrame.intersectUnchecked(windowFrames.mParentFrame);
+                mInsetFrame.intersectUnchecked(mWindowFrames.mParentFrame);
+                mWindowFrames.mContainingFrame.intersectUnchecked(mWindowFrames.mParentFrame);
             }
 
+            layoutDisplayFrame = new Rect(mWindowFrames.mDisplayFrame);
             mWindowFrames.mDisplayFrame.set(mWindowFrames.mContainingFrame);
             layoutXDiff =
                     !mInsetFrame.isEmpty() ? mInsetFrame.left - mWindowFrames.mContainingFrame.left
@@ -892,41 +888,24 @@
             layoutContainingFrame =
                     !mInsetFrame.isEmpty() ? mInsetFrame : mWindowFrames.mContainingFrame;
             mTmpRect.set(0, 0, dc.getDisplayInfo().logicalWidth, dc.getDisplayInfo().logicalHeight);
-            subtractInsets(mWindowFrames.mDisplayFrame, layoutContainingFrame,
-                    windowFrames.mDisplayFrame, mTmpRect);
+            subtractInsets(mWindowFrames.mDisplayFrame, layoutContainingFrame, layoutDisplayFrame,
+                    mTmpRect);
             if (!layoutInParentFrame()) {
                 subtractInsets(mWindowFrames.mContainingFrame, layoutContainingFrame,
-                        windowFrames.mParentFrame, mTmpRect);
-                subtractInsets(mInsetFrame, layoutContainingFrame, windowFrames.mParentFrame,
+                        mWindowFrames.mParentFrame, mTmpRect);
+                subtractInsets(mInsetFrame, layoutContainingFrame, mWindowFrames.mParentFrame,
                         mTmpRect);
             }
-            layoutDisplayFrame = windowFrames.mDisplayFrame;
             layoutDisplayFrame.intersect(layoutContainingFrame);
         }
 
         final int pw = mWindowFrames.mContainingFrame.width();
         final int ph = mWindowFrames.mContainingFrame.height();
 
-        if (!mWindowFrames.mParentFrame.equals(windowFrames.mParentFrame)) {
-            //Slog.i(TAG_WM, "Window " + this + " content frame from " + mParentFrame
-            //        + " to " + parentFrame);
-            mWindowFrames.mParentFrame.set(windowFrames.mParentFrame);
-            mContentChanged = true;
-        }
         if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
             mLastRequestedWidth = mRequestedWidth;
             mLastRequestedHeight = mRequestedHeight;
-            mContentChanged = true;
-        }
-
-        mWindowFrames.mOverscanFrame.set(windowFrames.mOverscanFrame);
-        mWindowFrames.mContentFrame.set(windowFrames.mContentFrame);
-        mWindowFrames.mVisibleFrame.set(windowFrames.mVisibleFrame);
-        mWindowFrames.mDecorFrame.set(windowFrames.mDecorFrame);
-        mWindowFrames.mStableFrame.set(windowFrames.mStableFrame);
-        final boolean hasOutsets = !windowFrames.mOutsetFrame.isEmpty();
-        if (hasOutsets) {
-            mWindowFrames.mOutsetFrame.set(windowFrames.mOutsetFrame);
+            mWindowFrames.setContentChanged(true);
         }
 
         final int fw = mWindowFrames.mFrame.width();
@@ -935,7 +914,7 @@
         applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame);
 
         // Calculate the outsets before the content frame gets shrinked to the window frame.
-        mWindowFrames.calculateOutsets(hasOutsets);
+        mWindowFrames.calculateOutsets();
 
         // Make sure the content and visible frames are inside of the
         // final window frame.
@@ -997,7 +976,7 @@
         }
 
         if (mAttrs.type == TYPE_DOCK_DIVIDER) {
-            final WmDisplayCutout c = windowFrames.mDisplayCutout.calculateRelativeTo(
+            final WmDisplayCutout c = mWindowFrames.mDisplayCutout.calculateRelativeTo(
                     mWindowFrames.mDisplayFrame);
             mWindowFrames.calculateDockedDividerInsets(c.getDisplayCutout().getSafeInsets());
         } else {
@@ -1006,7 +985,7 @@
         }
 
         mWindowFrames.setDisplayCutout(
-                windowFrames.mDisplayCutout.calculateRelativeTo(mWindowFrames.mFrame));
+                mWindowFrames.mDisplayCutout.calculateRelativeTo(mWindowFrames.mFrame));
 
         // Offset the actual frame by the amount layout frame is off.
         mWindowFrames.offsetFrames(-layoutXDiff, -layoutYDiff);
@@ -1733,7 +1712,7 @@
      * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
      */
     private boolean hasMoved() {
-        return mHasSurface && (mContentChanged || mMovedByResize)
+        return mHasSurface && (mWindowFrames.hasContentChanged() || mMovedByResize)
                 && !mAnimatingExit
                 && (mWindowFrames.mFrame.top != mWindowFrames.mLastFrame.top
                     || mWindowFrames.mFrame.left != mWindowFrames.mLastFrame.left)
@@ -4762,6 +4741,15 @@
         return mWindowFrames.mVisibleInsets;
     }
 
+    @Override
+    public WindowFrames getWindowFrames() {
+        return mWindowFrames;
+    }
+
+    void resetContentChanged() {
+        mWindowFrames.setContentChanged(false);
+    }
+
     private final class MoveAnimationSpec implements AnimationSpec {
 
         private final long mDuration;
diff --git a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
index b238e43..d34f951 100644
--- a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
+++ b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
@@ -30,7 +30,7 @@
 
 public class FakeWindowState implements WindowManagerPolicy.WindowState {
 
-    private WindowFrames windowFrames;
+    private WindowFrames mWindowFrames = new WindowFrames();
 
     public WindowManager.LayoutParams attrs;
     public int displayId;
@@ -53,41 +53,40 @@
     }
 
     @Override
-    public void computeFrameLw(WindowFrames windowFrames) {
-        this.windowFrames = windowFrames;
+    public void computeFrameLw() {
     }
 
     @Override
     public Rect getFrameLw() {
-        return windowFrames.mParentFrame;
+        return mWindowFrames.mParentFrame;
     }
 
     @Override
     public Rect getDisplayFrameLw() {
-        return windowFrames.mDisplayFrame;
+        return mWindowFrames.mDisplayFrame;
     }
 
     @Override
     public Rect getOverscanFrameLw() {
-        return windowFrames.mOverscanFrame;
+        return mWindowFrames.mOverscanFrame;
     }
 
     @Override
     public Rect getContentFrameLw() {
-        return windowFrames.mContentFrame;
+        return mWindowFrames.mContentFrame;
     }
 
     @Override
     public Rect getVisibleFrameLw() {
-        return windowFrames.mVisibleFrame;
+        return mWindowFrames.mVisibleFrame;
     }
 
     public Rect getStableFrame() {
-        return windowFrames.mStableFrame;
+        return mWindowFrames.mStableFrame;
     }
 
     public Rect getDecorFrame() {
-        return windowFrames.mDecorFrame;
+        return mWindowFrames.mDecorFrame;
     }
 
     @Override
@@ -252,6 +251,11 @@
     }
 
     @Override
+    public WindowFrames getWindowFrames() {
+        return mWindowFrames;
+    }
+
+    @Override
     public boolean isInputMethodTarget() {
         return false;
     }
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 e648230..0886729 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -202,8 +202,8 @@
         // When mFrame extends past cf, the content insets are
         // the difference between mFrame and ContentFrame. Visible
         // and stable frames work the same way.
-        final WindowFrames windowFrames = new WindowFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
-        w.computeFrameLw(windowFrames);
+        w.getWindowFrames().setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
+        w.computeFrameLw();
         assertFrame(w, 0, 0, 1000, 1000);
         assertContentInset(w, 0, topContentInset, 0, bottomContentInset);
         assertVisibleInset(w, 0, topVisibleInset, 0, bottomVisibleInset);
@@ -217,7 +217,7 @@
         w.mAttrs.width = 100; w.mAttrs.height = 100; //have to clear MATCH_PARENT
         w.mRequestedWidth = 100;
         w.mRequestedHeight = 100;
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
         assertFrame(w, 100, 100, 200, 200);
         assertContentInset(w, 0, 0, 0, 0);
         // In this case the frames are shrunk to the window frame.
@@ -238,8 +238,8 @@
 
         // Here the window has FILL_PARENT, FILL_PARENT
         // so we expect it to fill the entire available frame.
-        final WindowFrames windowFrames = new WindowFrames(pf, pf, pf, pf, pf, pf, pf, pf);
-        w.computeFrameLw(windowFrames);
+        w.getWindowFrames().setFrames(pf, pf, pf, pf, pf, pf, pf, pf);
+        w.computeFrameLw();
         assertFrame(w, 0, 0, 1000, 1000);
 
         // It can select various widths and heights within the bounds.
@@ -247,14 +247,14 @@
         // and we use mRequestedWidth/mRequestedHeight
         w.mAttrs.width = 300;
         w.mAttrs.height = 300;
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
         // Explicit width and height without requested width/height
         // gets us nothing.
         assertFrame(w, 0, 0, 0, 0);
 
         w.mRequestedWidth = 300;
         w.mRequestedHeight = 300;
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
         // With requestedWidth/Height we can freely choose our size within the
         // parent bounds.
         assertFrame(w, 0, 0, 300, 300);
@@ -267,14 +267,14 @@
         w.mRequestedWidth = -1;
         w.mAttrs.width = 100;
         w.mAttrs.height = 100;
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
         assertFrame(w, 0, 0, 100, 100);
         w.mAttrs.flags = 0;
 
         // But sizes too large will be clipped to the containing frame
         w.mRequestedWidth = 1200;
         w.mRequestedHeight = 1200;
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
         assertFrame(w, 0, 0, 1000, 1000);
 
         // Before they are clipped though windows will be shifted
@@ -282,7 +282,7 @@
         w.mAttrs.y = 300;
         w.mRequestedWidth = 1000;
         w.mRequestedHeight = 1000;
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
         assertFrame(w, 0, 0, 1000, 1000);
 
         // If there is room to move around in the parent frame the window will be shifted according
@@ -292,16 +292,16 @@
         w.mRequestedWidth = 300;
         w.mRequestedHeight = 300;
         w.mAttrs.gravity = Gravity.RIGHT | Gravity.TOP;
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
          assertFrame(w, 700, 0, 1000, 300);
         w.mAttrs.gravity = Gravity.RIGHT | Gravity.BOTTOM;
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
         assertFrame(w, 700, 700, 1000, 1000);
         // Window specified  x and y are interpreted as offsets in the opposite
         // direction of gravity
         w.mAttrs.x = 100;
         w.mAttrs.y = 100;
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
         assertFrame(w, 600, 600, 900, 900);
     }
 
@@ -322,8 +322,9 @@
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
-        final WindowFrames windowFrames = new WindowFrames(pf, pf, pf, pf, pf, pf, pf, mEmptyRect);
-        w.computeFrameLw(windowFrames);
+        final WindowFrames windowFrames = w.getWindowFrames();
+        windowFrames.setFrames(pf, pf, pf, pf, pf, pf, pf, mEmptyRect);
+        w.computeFrameLw();
         // For non fullscreen tasks the containing frame is based off the
         // task bounds not the parent frame.
         assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
@@ -336,7 +337,7 @@
         final int cfBottom = logicalHeight / 2;
         final Rect cf = new Rect(0, 0, cfRight, cfBottom);
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
         assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
         int contentInsetRight = taskRight - cfRight;
         int contentInsetBottom = taskBottom - cfBottom;
@@ -354,7 +355,7 @@
         final int insetBottom = insetTop + (taskBottom - taskTop);
         task.mInsetBounds.set(insetLeft, insetTop, insetRight, insetBottom);
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
         assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
         contentInsetRight = insetRight - cfRight;
         contentInsetBottom = insetBottom - cfBottom;
@@ -384,13 +385,14 @@
         // We use a decor content frame with insets to produce cropping.
         Rect dcf = new Rect(cf);
 
-        final WindowFrames windowFrames = new WindowFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
-        w.computeFrameLw(windowFrames);
+        final WindowFrames windowFrames = w.getWindowFrames();
+        windowFrames.setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
+        w.computeFrameLw();
         assertPolicyCrop(w, 0, cf.top, logicalWidth, cf.bottom);
 
         windowFrames.mDecorFrame.setEmpty();
         // Likewise with no decor frame we would get no crop
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
         assertPolicyCrop(w, 0, 0, logicalWidth, logicalHeight);
 
         // Now we set up a window which doesn't fill the entire decor frame.
@@ -404,7 +406,7 @@
         w.mAttrs.height = logicalHeight / 2;
         w.mRequestedWidth = logicalWidth / 2;
         w.mRequestedHeight = logicalHeight / 2;
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
 
         // Normally the crop is shrunk from the decor frame
         // to the computed window frame.
@@ -437,8 +439,9 @@
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
-        final WindowFrames windowFrames = new WindowFrames(pf, pf, pf, pf, pf, pf, pf, mEmptyRect);
-        w.computeFrameLw(windowFrames);
+        final WindowFrames windowFrames = w.getWindowFrames();
+        windowFrames.setFrames(pf, pf, pf, pf, pf, pf, pf, mEmptyRect);
+        w.computeFrameLw();
         // For non fullscreen tasks the containing frame is based off the
         // task bounds not the parent frame.
         assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
@@ -455,7 +458,7 @@
         pf.set(0, 0, logicalWidth, logicalHeight);
         task.mFullscreenForTest = true;
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
         assertFrame(w, cf.left, cf.top, cf.right, cf.bottom);
         assertContentFrame(w, cf);
         assertContentInset(w, 0, 0, 0, 0);
@@ -473,9 +476,10 @@
         final WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
                 fromBoundingRect(500, 0, 550, 50), pf.width(), pf.height());
 
-        final WindowFrames windowFrames = new WindowFrames(pf, pf, pf, pf, pf, pf, pf, pf);
+        final WindowFrames windowFrames = w.getWindowFrames();
+        windowFrames.setFrames(pf, pf, pf, pf, pf, pf, pf, pf);
         windowFrames.setDisplayCutout(cutout);
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
 
         assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetTop(), 50);
         assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetBottom(), 0);
@@ -497,9 +501,10 @@
         final WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
                 fromBoundingRect(500, 0, 550, 50), pf.width(), pf.height());
 
-        final WindowFrames windowFrames = new WindowFrames(pf, pf, pf, pf, pf, pf, pf, pf);
+        final WindowFrames windowFrames = w.getWindowFrames();
+        windowFrames.setFrames(pf, pf, pf, pf, pf, pf, pf, pf);
         windowFrames.setDisplayCutout(cutout);
-        w.computeFrameLw(windowFrames);
+        w.computeFrameLw();
 
         assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetTop(), 50);
         assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetBottom(), 0);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index b43d9a6..6af3ea7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -391,14 +391,14 @@
     @Test
     public void testDisplayCutoutIsCalculatedRelativeToFrame() {
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        WindowFrames wf = new WindowFrames();
+        WindowFrames wf = app.getWindowFrames();
         wf.mParentFrame.set(7, 10, 185, 380);
         wf.mDisplayFrame.set(wf.mParentFrame);
         final DisplayCutout cutout = new DisplayCutout(new Rect(0, 15, 0, 22),
                 Arrays.asList(new Rect(95, 0, 105, 15), new Rect(95, 378, 105, 400)));
         wf.setDisplayCutout(new WmDisplayCutout(cutout, new Size(200, 400)));
 
-        app.computeFrameLw(wf);
+        app.computeFrameLw();
         assertThat(app.getWmDisplayCutout().getDisplayCutout(), is(cutout.inset(7, 10, 5, 20)));
     }