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

Commit fed10074 authored by Robert Carr's avatar Robert Carr
Browse files

Ensure surfaces only resize during relayout.

For clients which use an indeterminate measure spec in their
layout params (MATCH_PARENT). We could try and change their window size
due to a stack resize, before the client calls relayout. This isn't
safe as the client never had an opportunity to pause rendering, so it
could be in the middle of producing a frame for the old size to suddenly
find the buffer size change underneath it.

Bug: 28559097
Change-Id: I3982936fdf85c22def2f9c754d5508e029e4a84d
parent 15818e11
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -2834,6 +2834,8 @@ public class WindowManagerService extends IWindowManager.Stub
            }

            win.mRelayoutCalled = true;
            win.mInRelayout = true;

            final int oldVisibility = win.mViewVisibility;
            win.mViewVisibility = viewVisibility;
            if (DEBUG_SCREEN_ON) {
@@ -2974,6 +2976,7 @@ public class WindowManagerService extends IWindowManager.Stub
            if (DEBUG_LAYOUT) {
                Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
            }
            win.mInRelayout = false;
        }

        if (configChanged) {
+8 −0
Original line number Diff line number Diff line
@@ -362,6 +362,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
     */
    boolean mRelayoutCalled;

    boolean mInRelayout;

    /**
     * If the application has called relayout() with changes that can
     * impact its window's size, we need to perform a layout pass on it
@@ -1630,6 +1632,12 @@ final class WindowState implements WindowManagerPolicy.WindowState {
        return task != null && task.inDockedWorkspace();
    }

    // TODO: Strange usage of word workspace here and above.
    boolean inPinnedWorkspace() {
        final Task task = getTask();
        return task != null && task.inPinnedWorkspace();
    }

    boolean isDockedInEffect() {
        final Task task = getTask();
        return task != null && task.isDockedInEffect();
+23 −5
Original line number Diff line number Diff line
@@ -1428,8 +1428,24 @@ class WindowStateAnimator {
        float extraHScale = (float) 1.0;
        float extraVScale = (float) 1.0;

        // Once relayout has been called at least once, we need to make sure
        // we only resize the client surface during calls to relayout. For
        // clients which use indeterminate measure specs (MATCH_PARENT),
        // we may try and change their window size without a call to relayout.
        // However, this would be unsafe, as the client may be in the middle
        // of producing a frame at the old size, having just completed layout
        // to find the surface size changed underneath it.
        //
        // TODO: For N we only apply this fix to the pinned workspace. As we
        // aren't observing known issues here outside of PiP resizing. (Typically
        // the other windows that use -1 are PopupWindows which aren't likely
        // to be rendering while we resize).
        if (!w.inPinnedWorkspace() || (!w.mRelayoutCalled || w.mInRelayout)) {
            mSurfaceResized = mSurfaceController.setSizeInTransaction(
                    mTmpSize.width(), mTmpSize.height(), recoveringMemory);
        } else {
            mSurfaceResized = false;
        }
        mForceScaleUntilResize = mForceScaleUntilResize && !mSurfaceResized;


@@ -1437,10 +1453,12 @@ class WindowStateAnimator {
        if ((task != null && task.mStack.getForceScaleToCrop()) || mForceScaleUntilResize) {
            int hInsets = w.getAttrs().surfaceInsets.left + w.getAttrs().surfaceInsets.right;
            int vInsets = w.getAttrs().surfaceInsets.top + w.getAttrs().surfaceInsets.bottom;
            float surfaceWidth = mSurfaceController.getWidth();
            float surfaceHeight = mSurfaceController.getHeight();
            // We want to calculate the scaling based on the content area, not based on
            // the entire surface, so that we scale in sync with windows that don't have insets.
            extraHScale = (mTmpClipRect.width() - hInsets) / (float)(mTmpSize.width() - hInsets);
            extraVScale = (mTmpClipRect.height() - vInsets) / (float)(mTmpSize.height() - vInsets);
            extraHScale = (mTmpClipRect.width() - hInsets) / (float)(surfaceWidth - hInsets);
            extraVScale = (mTmpClipRect.height() - vInsets) / (float)(surfaceHeight - vInsets);

            // In the case of ForceScaleToCrop we scale entire tasks together,
            // and so we need to scale our offsets relative to the task bounds
@@ -1462,7 +1480,7 @@ class WindowStateAnimator {
            // Since we are scaled to fit in our previously desired crop, we can now
            // expose the whole window in buffer space, and not risk extending
            // past where the system would have cropped us
            mTmpClipRect.set(0, 0, mTmpSize.width(), mTmpSize.height());
            mTmpClipRect.set(0, 0, (int)surfaceWidth, (int)surfaceHeight);
            mTmpFinalClipRect.setEmpty();

            // Various surfaces in the scaled stack may resize at different times.
+9 −0
Original line number Diff line number Diff line
@@ -454,6 +454,15 @@ class WindowSurfaceController {
        return mSurfaceY;
    }

    float getWidth() {
        return mSurfaceW;
    }

    float getHeight() {
        return mSurfaceH;
    }


    public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
        if (dumpAll) {
            pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl);