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

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

Re-land: Make window stable while resizing

When the frame size and the frame position of the window are changed at
the same time, setPosition to the surface will be applied first, and
the client will draw on the new-size buffer later, which makes the
window flicker.

This CL uses applyWithNextDraw to make the new surface position can be
applied while the new frame is drawn. applyWithNextDraw is applied only
when
- the window doesn't have a move animation. So if a window needs to make
  resizing stable, it may need PRIVATE_FLAG_NO_MOVE_ANIMATION.
- it is visible, e.g., the surface is shown, and the window is OK to
  display -- for better performance.

If applyWithNextDraw is used while the window frame is changed to an
empty rectangle, e.g., Rect(10, 10 - 1000, 10), mNextDrawUseBlastSync
will stay true forever, because we don't draw while the dirty area is
empty, and ViewRootImpl would lose the only chance to clear the flag.
performTraversals will never be executed.

This CL makes mNextDrawUseBlastSync can be cleared in that case.

Bug: 182729646
Fix: 176874720
Test: steps in the bug
Change-Id: I81b0574ee8db7e4d9053639f56e04858d9feae90
parent 33d3819b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4293,7 +4293,7 @@ public final class ViewRootImpl implements ViewParent,
                mChoreographer.getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;

        boolean useAsyncReport = false;
        if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
        if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty || mNextDrawUseBlastSync) {
            if (isHardwareEnabled()) {
                // If accessibility focus moved, always invalidate the root.
                boolean invalidateRoot = accessibilityFocusDirty || mInvalidateRootRequested;
+2 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;

import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -2508,6 +2509,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
            if (mDecor.mForceWindowDrawsBarBackgrounds) {
                params.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
            }
            params.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
        }
        if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
            decor.setSystemUiVisibility(
+15 −28
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import static com.android.server.wm.InsetsSourceProviderProto.CONTROLLABLE;
import static com.android.server.wm.InsetsSourceProviderProto.CONTROL_TARGET;
import static com.android.server.wm.InsetsSourceProviderProto.FAKE_CONTROL;
import static com.android.server.wm.InsetsSourceProviderProto.FAKE_CONTROL_TARGET;
import static com.android.server.wm.InsetsSourceProviderProto.FINISH_SEAMLESS_ROTATE_FRAME_NUMBER;
import static com.android.server.wm.InsetsSourceProviderProto.FRAME;
import static com.android.server.wm.InsetsSourceProviderProto.IME_OVERRIDDEN_FRAME;
import static com.android.server.wm.InsetsSourceProviderProto.IS_LEASH_READY_FOR_DISPATCHING;
@@ -60,6 +59,7 @@ import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;

import java.io.PrintWriter;
import java.util.function.Consumer;

/**
 * Controller for a specific inset source on the server. It's called provider as it provides the
@@ -85,6 +85,16 @@ class InsetsSourceProvider {
    private final Rect mImeOverrideFrame = new Rect();
    private boolean mIsLeashReadyForDispatching;

    private final Consumer<Transaction> mSetLeashPositionConsumer = t -> {
        if (mControl != null) {
            final SurfaceControl leash = mControl.getLeash();
            if (leash != null) {
                final Point position = mControl.getSurfacePosition();
                t.setPosition(leash, position.x, position.y);
            }
        }
    };

    /** The visibility override from the current controlling window. */
    private boolean mClientVisible;

@@ -151,7 +161,6 @@ class InsetsSourceProvider {
            // TODO: Ideally, we should wait for the animation to finish so previous window can
            // animate-out as new one animates-in.
            mWin.cancelAnimation();
            mWin.mPendingPositionChanged = null;
            mWin.mProvidedInsetsSources.remove(mSource.getType());
        }
        ProtoLog.d(WM_DEBUG_IME, "InsetsSource setWin %s", win);
@@ -252,12 +261,11 @@ class InsetsSourceProvider {
            final Point position = getWindowFrameSurfacePosition();
            if (mControl.setSurfacePosition(position.x, position.y) && mControlTarget != null) {
                changed = true;
                if (!mWin.getWindowFrames().didFrameSizeChange()) {
                    updateLeashPosition(-1 /* frameNumber */);
                } else if (mWin.mInRelayout) {
                    updateLeashPosition(mWin.getFrameNumber());
                if (mWin.getWindowFrames().didFrameSizeChange() && mWin.mWinAnimator.getShown()
                        && mWin.okToDisplay()) {
                    mWin.applyWithNextDraw(mSetLeashPositionConsumer);
                } else {
                    mWin.mPendingPositionChanged = this;
                    mSetLeashPositionConsumer.accept(mWin.getPendingTransaction());
                }
            }
            final Insets insetsHint = mSource.calculateInsets(
@@ -272,19 +280,6 @@ class InsetsSourceProvider {
        }
    }

    void updateLeashPosition(long frameNumber) {
        if (mControl == null) {
            return;
        }
        final SurfaceControl leash = mControl.getLeash();
        if (leash != null) {
            final Transaction t = mDisplayContent.getPendingTransaction();
            final Point position = mControl.getSurfacePosition();
            t.setPosition(leash, position.x, position.y);
            deferTransactionUntil(t, leash, frameNumber);
        }
    }

    private Point getWindowFrameSurfacePosition() {
        final Rect frame = mWin.getFrame();
        final Point position = new Point();
@@ -292,14 +287,6 @@ class InsetsSourceProvider {
        return position;
    }

    private void deferTransactionUntil(Transaction t, SurfaceControl leash, long frameNumber) {
        if (frameNumber >= 0) {
            final SurfaceControl barrier = mWin.getClientViewRootSurface();
            t.deferTransactionUntil(mWin.getSurfaceControl(), barrier, frameNumber);
            t.deferTransactionUntil(leash, barrier, frameNumber);
        }
    }

    /**
     * @see InsetsStateController#onControlFakeTargetChanged(int, InsetsControlTarget)
     */
+8 −1
Original line number Diff line number Diff line
@@ -113,7 +113,7 @@ public class WindowFrames {
    }

    /**
     * @return true if the width or height has changed since last reported to the client.
     * @return true if the width or height has changed since last updating resizing window.
     */
    boolean didFrameSizeChange() {
        return (mLastFrame.width() != mFrame.width()) || (mLastFrame.height() != mFrame.height());
@@ -134,6 +134,13 @@ public class WindowFrames {
        return mLastForceReportingResized || mFrameSizeChanged;
    }

    /**
     * @return true if the width or height has changed since last reported to the client.
     */
    boolean isFrameSizeChangeReported() {
        return mFrameSizeChanged || didFrameSizeChange();
    }

    /**
     * Resets the size changed flags so they're all set to false again. This should be called
     * after the frames are reported to client.
+0 −7
Original line number Diff line number Diff line
@@ -2228,13 +2228,6 @@ public class WindowManagerService extends IWindowManager.Stub

            win.setFrameNumber(frameNumber);

            final DisplayContent dc = win.getDisplayContent();

            if (win.mPendingPositionChanged != null) {
                win.mPendingPositionChanged.updateLeashPosition(frameNumber);
                win.mPendingPositionChanged = null;
            }

            int attrChanges = 0;
            int flagChanges = 0;
            int privateFlagChanges = 0;
Loading