Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54670769 authored by Tiger Huang's avatar Tiger Huang
Browse files

Refine simulateLayoutDisplay

Instead of calling into layoutWindowLw while simulateLayoutDisplay, this
CL invokes WindowLayout#computeWindowFrames directly. All windows will
compute their frame locally, so we don't need layoutWindowLw then.

Bug: 161810301
Test: atest DisplayPolicyLayoutTests SizeCompatTests
Change-Id: If123f4d56758078def8a7c50c218d75e0217633b
parent 7d16f0b5
Loading
Loading
Loading
Loading
+54 −113
Original line number Original line Diff line number Diff line
@@ -118,9 +118,9 @@ import android.os.Message;
import android.os.SystemClock;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.PrintWriterPrinter;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseArray;
import android.view.DisplayCutout;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.Gravity;
@@ -283,15 +283,12 @@ public class DisplayPolicy {
    @WindowManagerPolicy.AltBarPosition
    @WindowManagerPolicy.AltBarPosition
    private int mExtraNavBarAltPosition = ALT_BAR_UNKNOWN;
    private int mExtraNavBarAltPosition = ALT_BAR_UNKNOWN;


    /** See {@link #getNavigationBarFrameHeight} */
    private final ArraySet<WindowState> mInsetsSourceWindowsExceptIme = new ArraySet<>();
    private int[] mNavigationBarFrameHeightForRotationDefault = new int[4];


    private boolean mIsFreeformWindowOverlappingWithNavBar;
    private boolean mIsFreeformWindowOverlappingWithNavBar;


    private boolean mLastImmersiveMode;
    private boolean mLastImmersiveMode;


    private final SparseArray<Rect> mBarContentFrames = new SparseArray<>();

    // The windows we were told about in focusChanged.
    // The windows we were told about in focusChanged.
    private WindowState mFocusedWindow;
    private WindowState mFocusedWindow;
    private WindowState mLastFocusedWindow;
    private WindowState mLastFocusedWindow;
@@ -339,9 +336,11 @@ public class DisplayPolicy {
    private long mPendingPanicGestureUptime;
    private long mPendingPanicGestureUptime;


    private static final Rect sTmpRect = new Rect();
    private static final Rect sTmpRect = new Rect();
    private static final Rect sTmpDecorFrame = new Rect();
    private static final Rect sTmpLastParentFrame = new Rect();
    private static final Rect sTmpLastParentFrame = new Rect();
    private static final Rect sTmpDisplayFrameBounds = new Rect();
    private static final Rect sTmpDisplayCutoutSafe = new Rect();
    private static final Rect sTmpDisplayFrame = new Rect();
    private static final Rect sTmpParentFrame = new Rect();
    private static final Rect sTmpFrame = new Rect();


    private final WindowLayout mWindowLayout = new WindowLayout();
    private final WindowLayout mWindowLayout = new WindowLayout();


@@ -1093,6 +1092,7 @@ public class DisplayPolicy {
                mDisplayContent.setInsetProvider(
                mDisplayContent.setInsetProvider(
                        ITYPE_TOP_MANDATORY_GESTURES, win, gestureFrameProvider);
                        ITYPE_TOP_MANDATORY_GESTURES, win, gestureFrameProvider);
                mDisplayContent.setInsetProvider(ITYPE_TOP_TAPPABLE_ELEMENT, win, null);
                mDisplayContent.setInsetProvider(ITYPE_TOP_TAPPABLE_ELEMENT, win, null);
                mInsetsSourceWindowsExceptIme.add(win);
                break;
                break;
            case TYPE_NAVIGATION_BAR:
            case TYPE_NAVIGATION_BAR:
                mNavigationBar = win;
                mNavigationBar = win;
@@ -1137,6 +1137,7 @@ public class DisplayPolicy {
                                inOutFrame.setEmpty();
                                inOutFrame.setEmpty();
                            }
                            }
                        });
                        });
                mInsetsSourceWindowsExceptIme.add(win);
                if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
                if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
                break;
                break;
            default:
            default:
@@ -1170,6 +1171,7 @@ public class DisplayPolicy {
                                windowState, inOutFrame) -> inOutFrame.inset(
                                windowState, inOutFrame) -> inOutFrame.inset(
                                windowState.getLayoutingAttrs(displayFrames.mRotation)
                                windowState.getLayoutingAttrs(displayFrames.mRotation)
                                        .providedInternalInsets), imeFrameProvider);
                                        .providedInternalInsets), imeFrameProvider);
                        mInsetsSourceWindowsExceptIme.add(win);
                    }
                    }
                }
                }
                break;
                break;
@@ -1253,6 +1255,7 @@ public class DisplayPolicy {
        if (mLastFocusedWindow == win) {
        if (mLastFocusedWindow == win) {
            mLastFocusedWindow = null;
            mLastFocusedWindow = null;
        }
        }
        mInsetsSourceWindowsExceptIme.remove(win);
    }
    }


    private int getStatusBarHeight(DisplayFrames displayFrames) {
    private int getStatusBarHeight(DisplayFrames displayFrames) {
@@ -1433,49 +1436,22 @@ public class DisplayPolicy {
        return mForceShowSystemBars;
        return mForceShowSystemBars;
    }
    }


    private void simulateLayoutDecorWindow(WindowState win, DisplayFrames displayFrames,
            WindowFrames simulatedWindowFrames, Consumer<Rect> layout) {
        win.setSimulatedWindowFrames(simulatedWindowFrames);
        final int requestedHeight = win.mRequestedHeight;
        final int requestedWidth = win.mRequestedWidth;
        // Without a full layout process, in order to layout the system bars correctly, we need
        // to set the requested size and the initial display frames to the window.
        WindowManager.LayoutParams params = win.getLayoutingAttrs(displayFrames.mRotation);
        win.setRequestedSize(params.width, params.height);
        sTmpDecorFrame.set(0, 0, displayFrames.mDisplayWidth, displayFrames.mDisplayHeight);
        simulatedWindowFrames.setFrames(sTmpDecorFrame /* parentFrame */,
                sTmpDecorFrame /* displayFrame */);
        simulatedWindowFrames.mIsSimulatingDecorWindow = true;
        final Rect contentFrame = new Rect();
        try {
            layout.accept(contentFrame);
        } finally {
            win.setSimulatedWindowFrames(null);
            win.setRequestedSize(requestedWidth, requestedHeight);
        }
        mDisplayContent.getInsetsStateController().computeSimulatedState(
                win, displayFrames, simulatedWindowFrames);
    }

    /**
    /**
     * Computes the frames of display (its logical size, rotation and cutout should already be set)
     * Computes the frames of display (its logical size, rotation and cutout should already be set)
     * used to layout window. This method only changes the given display frames, insets state and
     * used to layout window. This method only changes the given display frames, insets state and
     * some temporal states, but doesn't change the window frames used to show on screen.
     * some temporal states, but doesn't change the window frames used to show on screen.
     */
     */
    void simulateLayoutDisplay(DisplayFrames displayFrames) {
    void simulateLayoutDisplay(DisplayFrames displayFrames) {
        final InsetsStateController insetsStateController =
        final InsetsStateController controller = mDisplayContent.getInsetsStateController();
                mDisplayContent.getInsetsStateController();
        for (int i = mInsetsSourceWindowsExceptIme.size() - 1; i >= 0; i--) {
        for (int type = 0; type < InsetsState.SIZE; type++) {
            final WindowState win = mInsetsSourceWindowsExceptIme.valueAt(i);
            final InsetsSourceProvider provider =
            mWindowLayout.computeWindowFrames(win.getLayoutingAttrs(displayFrames.mRotation),
                    insetsStateController.peekSourceProvider(type);
                    displayFrames.mInsetsState, displayFrames.mDisplayCutoutSafe,
            if (provider == null || !provider.hasWindow()
                    displayFrames.mUnrestricted, win.getWindowingMode(), UNSPECIFIED_LENGTH,
                    || provider.mWin.getControllableInsetProvider() != provider) {
                    UNSPECIFIED_LENGTH, win.getRequestedVisibilities(),
                continue;
                    null /* attachedWindowFrame */, win.mGlobalScale,
            }
                    sTmpDisplayFrame, sTmpParentFrame, sTmpFrame);
            final WindowFrames simulatedWindowFrames = new WindowFrames();
            controller.computeSimulatedState(win, displayFrames, sTmpFrame);
            simulateLayoutDecorWindow(provider.mWin, displayFrames, simulatedWindowFrames,
                    contentFrame -> simulateLayoutForContentFrame(displayFrames,
                            provider.mWin, contentFrame));
        }
        }
    }
    }


@@ -1483,25 +1459,6 @@ public class DisplayPolicy {
        mSystemGestures.onDisplayInfoChanged(info);
        mSystemGestures.onDisplayInfoChanged(info);
    }
    }


    private void simulateLayoutForContentFrame(DisplayFrames displayFrames, WindowState win,
            Rect simulatedContentFrame) {
        layoutWindowLw(win, null /* attached */, displayFrames);
        final Rect contentFrame = sTmpRect;
        contentFrame.set(win.getLayoutingWindowFrames().mFrame);
        // Excluding the display cutout before set to the simulated content frame.
        contentFrame.intersect(displayFrames.mDisplayCutoutSafe);
        simulatedContentFrame.set(contentFrame);
    }

    private boolean canReceiveInput(WindowState win) {
        boolean notFocusable =
                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
        boolean altFocusableIm =
                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
        boolean notFocusableForIm = notFocusable ^ altFocusableIm;
        return !notFocusableForIm;
    }

    /**
    /**
     * Called for each window attached to the window manager as layout is proceeding. The
     * Called for each window attached to the window manager as layout is proceeding. The
     * implementation of this function must take care of setting the window's frame, either here or
     * implementation of this function must take care of setting the window's frame, either here or
@@ -1514,51 +1471,37 @@ public class DisplayPolicy {
     * @param displayFrames The display frames.
     * @param displayFrames The display frames.
     */
     */
    public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {
    public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {
        final WindowManager.LayoutParams attrs = win.getLayoutingAttrs(displayFrames.mRotation);

        final int type = attrs.type;
        final int fl = attrs.flags;
        final int sim = attrs.softInputMode;


        // This window might be in the simulated environment.
        // We invoke this to get the proper DisplayFrames.
        displayFrames = win.getDisplayFrames(displayFrames);
        displayFrames = win.getDisplayFrames(displayFrames);
        final WindowFrames windowFrames = win.getLayoutingWindowFrames();


        final WindowManager.LayoutParams attrs = win.getLayoutingAttrs(displayFrames.mRotation);
        final WindowFrames windowFrames = win.getWindowFrames();
        final Rect pf = windowFrames.mParentFrame;
        final Rect pf = windowFrames.mParentFrame;
        final Rect df = windowFrames.mDisplayFrame;
        final Rect df = windowFrames.mDisplayFrame;
        final Rect f = windowFrames.mFrame;
        final Rect f = windowFrames.mFrame;
        final Rect attachedWindowFrame = attached != null ? attached.getFrame() : null;
        final Rect attachedWindowFrame = attached != null ? attached.getFrame() : null;
        sTmpLastParentFrame.set(pf);


        final Rect winBounds;
        // If this window has different LayoutParams for rotations, we cannot trust its requested
        final int requestedWidth;
        // size. Because it might have not sent its requested size for the new rotation.
        final int requestedHeight;
        final boolean trustedSize = attrs == win.mAttrs;
        if (windowFrames.mIsSimulatingDecorWindow) {
        final int requestedWidth = trustedSize ? win.mRequestedWidth : UNSPECIFIED_LENGTH;
            // Override the bounds in window token has many side effects. Directly use the display
        final int requestedHeight = trustedSize ? win.mRequestedHeight : UNSPECIFIED_LENGTH;
            // frame set for the simulated layout.

            winBounds = df;
        sTmpLastParentFrame.set(pf);

            // The view hierarchy has not been measured in the simulated layout. Use
            // UNSPECIFIED_LENGTH as the requested width and height so that WindowLayout will choose
            // the proper values in this case.
            requestedWidth = UNSPECIFIED_LENGTH;
            requestedHeight = UNSPECIFIED_LENGTH;
        } else {
            winBounds = win.getBounds();
            requestedWidth = win.mRequestedWidth;
            requestedHeight = win.mRequestedHeight;
        }


        final boolean clippedByDisplayCutout = mWindowLayout.computeWindowFrames(attrs,
        final boolean clippedByDisplayCutout = mWindowLayout.computeWindowFrames(attrs,
                win.getInsetsState(), displayFrames.mDisplayCutoutSafe,
                win.getInsetsState(), displayFrames.mDisplayCutoutSafe,
                winBounds, win.getWindowingMode(), requestedWidth, requestedHeight,
                win.getBounds(), win.getWindowingMode(), requestedWidth, requestedHeight,
                win.getRequestedVisibilities(), attachedWindowFrame, win.mGlobalScale,
                win.getRequestedVisibilities(), attachedWindowFrame, win.mGlobalScale,
                df, pf, f);
                df, pf, f);
        windowFrames.setParentFrameWasClippedByDisplayCutout(clippedByDisplayCutout);
        windowFrames.setParentFrameWasClippedByDisplayCutout(clippedByDisplayCutout);


        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
                + ": sim=#" + Integer.toHexString(sim)
                + ": sim=#" + Integer.toHexString(attrs.softInputMode)
                + " attach=" + attached + " type=" + type
                + " attach=" + attached + " type=" + attrs.type
                + " flags=" + ViewDebug.flagsToString(LayoutParams.class, "flags", fl)
                + " flags=" + ViewDebug.flagsToString(LayoutParams.class, "flags", attrs.flags)
                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
                + " f=" + f.toShortString());
                + " f=" + f.toShortString());


@@ -1566,10 +1509,8 @@ public class DisplayPolicy {
            windowFrames.setContentChanged(true);
            windowFrames.setContentChanged(true);
        }
        }


        if (!windowFrames.mIsSimulatingDecorWindow) {
        win.setFrame();
        win.setFrame();
    }
    }
    }


    WindowState getTopFullscreenOpaqueWindow() {
    WindowState getTopFullscreenOpaqueWindow() {
        return mTopFullscreenOpaqueWindowState;
        return mTopFullscreenOpaqueWindowState;
@@ -2510,22 +2451,22 @@ public class DisplayPolicy {
        return source != null && Rect.intersects(win.getFrame(), source.getFrame());
        return source != null && Rect.intersects(win.getFrame(), source.getFrame());
    }
    }


    private Rect getBarContentFrameForWindow(WindowState win, int windowType) {
    private Rect getBarContentFrameForWindow(WindowState win, @InternalInsetsType int type) {
        final Rect rotatedBarFrame = win.mToken.getFixedRotationBarContentFrame(windowType);
        final DisplayFrames displayFrames = win.getDisplayFrames(mDisplayContent.mDisplayFrames);
        if (rotatedBarFrame != null) {
        final InsetsState state = displayFrames.mInsetsState;
            return rotatedBarFrame;
        }
        // We only need a window specific information for the fixed rotation, use raw insets state
        // for all other cases.
        InsetsState insetsState = mDisplayContent.getInsetsStateController().getRawInsetsState();
        final Rect tmpRect = new Rect();
        final Rect tmpRect = new Rect();
        if (windowType == TYPE_NAVIGATION_BAR) {
        sTmpDisplayCutoutSafe.set(displayFrames.mDisplayCutoutSafe);
            tmpRect.set(insetsState.getSource(InsetsState.ITYPE_NAVIGATION_BAR).getFrame());
        if (type == ITYPE_STATUS_BAR) {
        }
            // The status bar content can extend into regular display cutout insets but not
        if (windowType == TYPE_STATUS_BAR) {
            // waterfall insets.
            tmpRect.set(insetsState.getSource(InsetsState.ITYPE_STATUS_BAR).getFrame());
            sTmpDisplayCutoutSafe.top =
                    Math.max(state.getDisplayCutout().getWaterfallInsets().top, 0);
        }
        final InsetsSource source = state.peekSource(type);
        if (source != null) {
            tmpRect.set(source.getFrame());
            tmpRect.intersect(sTmpDisplayCutoutSafe);
        }
        }
        tmpRect.intersect(mDisplayContent.mDisplayFrames.mDisplayCutoutSafe);
        return tmpRect;
        return tmpRect;
    }
    }


@@ -2539,11 +2480,11 @@ public class DisplayPolicy {
     * be drawn over letterboxed activity.
     * be drawn over letterboxed activity.
     */
     */
    @VisibleForTesting
    @VisibleForTesting
    boolean isFullyTransparentAllowed(WindowState win, int windowType) {
    boolean isFullyTransparentAllowed(WindowState win, @InternalInsetsType int type) {
        if (win == null) {
        if (win == null) {
            return true;
            return true;
        }
        }
        return win.isFullyTransparentBarAllowed(getBarContentFrameForWindow(win, windowType));
        return win.isFullyTransparentBarAllowed(getBarContentFrameForWindow(win, type));
    }
    }


    private boolean drawsBarBackground(WindowState win) {
    private boolean drawsBarBackground(WindowState win) {
@@ -2566,7 +2507,7 @@ public class DisplayPolicy {
        for (int i = mStatusBarBackgroundWindows.size() - 1; i >= 0; i--) {
        for (int i = mStatusBarBackgroundWindows.size() - 1; i >= 0; i--) {
            final WindowState window = mStatusBarBackgroundWindows.get(i);
            final WindowState window = mStatusBarBackgroundWindows.get(i);
            drawBackground &= drawsBarBackground(window);
            drawBackground &= drawsBarBackground(window);
            isFullyTransparentAllowed &= isFullyTransparentAllowed(window, TYPE_STATUS_BAR);
            isFullyTransparentAllowed &= isFullyTransparentAllowed(window, ITYPE_STATUS_BAR);
        }
        }


        if (drawBackground) {
        if (drawBackground) {
@@ -2606,7 +2547,7 @@ public class DisplayPolicy {
            }
            }
        }
        }


        if (!isFullyTransparentAllowed(mNavBarBackgroundWindow, TYPE_NAVIGATION_BAR)) {
        if (!isFullyTransparentAllowed(mNavBarBackgroundWindow, ITYPE_NAVIGATION_BAR)) {
            appearance |= APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS;
            appearance |= APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS;
        }
        }


+2 −2
Original line number Original line Diff line number Diff line
@@ -236,12 +236,12 @@ class InsetsSourceProvider {
    }
    }


    /** @return A new source computed by the specified window frame in the given display frames. */
    /** @return A new source computed by the specified window frame in the given display frames. */
    InsetsSource createSimulatedSource(DisplayFrames displayFrames, WindowFrames windowFrames) {
    InsetsSource createSimulatedSource(DisplayFrames displayFrames, Rect winFrame) {
        // Don't copy visible frame because it might not be calculated in the provided display
        // Don't copy visible frame because it might not be calculated in the provided display
        // frames and it is not significant for this usage.
        // frames and it is not significant for this usage.
        final InsetsSource source = new InsetsSource(mSource.getType());
        final InsetsSource source = new InsetsSource(mSource.getType());
        source.setVisible(mSource.isVisible());
        source.setVisible(mSource.isVisible());
        mTmpRect.set(windowFrames.mFrame);
        mTmpRect.set(winFrame);
        if (mFrameProvider != null) {
        if (mFrameProvider != null) {
            mFrameProvider.accept(displayFrames, mWin, mTmpRect);
            mFrameProvider.accept(displayFrames, mWin, mTmpRect);
        }
        }
+4 −4
Original line number Original line Diff line number Diff line
@@ -40,6 +40,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.WindowingMode;
import android.app.WindowConfiguration.WindowingMode;
import android.graphics.Rect;
import android.os.Trace;
import android.os.Trace;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.ArraySet;
@@ -385,15 +386,14 @@ class InsetsStateController {
     *
     *
     * @param win The owner window of insets provider.
     * @param win The owner window of insets provider.
     * @param displayFrames The display frames to create insets source.
     * @param displayFrames The display frames to create insets source.
     * @param windowFrames The specified frames to represent the owner window.
     * @param winFrame The frame of the insets source window.
     */
     */
    void computeSimulatedState(WindowState win, DisplayFrames displayFrames,
    void computeSimulatedState(WindowState win, DisplayFrames displayFrames, Rect winFrame) {
            WindowFrames windowFrames) {
        final InsetsState state = displayFrames.mInsetsState;
        final InsetsState state = displayFrames.mInsetsState;
        for (int i = mProviders.size() - 1; i >= 0; i--) {
        for (int i = mProviders.size() - 1; i >= 0; i--) {
            final InsetsSourceProvider provider = mProviders.valueAt(i);
            final InsetsSourceProvider provider = mProviders.valueAt(i);
            if (provider.mWin == win) {
            if (provider.mWin == win) {
                state.addSource(provider.createSimulatedSource(displayFrames, windowFrames));
                state.addSource(provider.createSimulatedSource(displayFrames, winFrame));
            }
            }
        }
        }
    }
    }
+0 −5
Original line number Original line Diff line number Diff line
@@ -71,11 +71,6 @@ public class WindowFrames {
    // screen size compatibility mode.
    // screen size compatibility mode.
    final Rect mCompatFrame = new Rect();
    final Rect mCompatFrame = new Rect();


    /**
     * {@code true} if the window frame is a simulated frame and attached to a decor window.
     */
    boolean mIsSimulatingDecorWindow = false;

    /**
    /**
     * Whether the parent frame would have been different if there was no display cutout.
     * Whether the parent frame would have been different if there was no display cutout.
     */
     */
+3 −22
Original line number Original line Diff line number Diff line
@@ -466,9 +466,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP


    private final ClientWindowFrames mClientWindowFrames = new ClientWindowFrames();
    private final ClientWindowFrames mClientWindowFrames = new ClientWindowFrames();


    /** The frames used to compute a temporal layout appearance. */
    private WindowFrames mSimulatedWindowFrames;

    /**
    /**
     * List of rects where system gestures should be ignored.
     * List of rects where system gestures should be ignored.
     *
     *
@@ -1513,9 +1510,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP


    /** @return The display frames in use by this window. */
    /** @return The display frames in use by this window. */
    DisplayFrames getDisplayFrames(DisplayFrames originalFrames) {
    DisplayFrames getDisplayFrames(DisplayFrames originalFrames) {
        final DisplayFrames diplayFrames = mToken.getFixedRotationTransformDisplayFrames();
        final DisplayFrames displayFrames = mToken.getFixedRotationTransformDisplayFrames();
        if (diplayFrames != null) {
        if (displayFrames != null) {
            return diplayFrames;
            return displayFrames;
        }
        }
        return originalFrames;
        return originalFrames;
    }
    }
@@ -5502,22 +5499,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        return mWindowFrames;
        return mWindowFrames;
    }
    }


    /**
     * If the simulated frame is set, the computed result won't be used in real layout. So this
     * frames must be cleared when the simulated computation is done.
     */
    void setSimulatedWindowFrames(WindowFrames windowFrames) {
        mSimulatedWindowFrames = windowFrames;
    }

    /**
     * Use this method only when the simulated frames may be set, so it is clearer that the calling
     * path may be used to simulate layout.
     */
    WindowFrames getLayoutingWindowFrames() {
        return mSimulatedWindowFrames != null ? mSimulatedWindowFrames : mWindowFrames;
    }

    void resetContentChanged() {
    void resetContentChanged() {
        mWindowFrames.setContentChanged(false);
        mWindowFrames.setContentChanged(false);
    }
    }
Loading