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

Commit b9876970 authored by Evan Rosky's avatar Evan Rosky
Browse files

Drop sync buffers for subsequent sync requests

When making subsequent draw requests for the same window, drop
any existing buffers since they will be replaced by the new one.

Sometimes the "old" buffer will still be "in-flight" (either
drawing still or in binder). So, also drop incoming buffers
for seqIds that are earlier than the latest prepareSync.

Additionally, immediately apply any applyWithNextDraw that were
requested before the sync, but arrive after the sync started --
otherwise they can get put on pending (which waits for sync
apply) and thus also block the buffer queue.

Bug: 233625646
Test: run tests and check for ANRs
Change-Id: I156a9a73eea8346dc241b5d782a863b99127ca9f
parent 0d61ab9e
Loading
Loading
Loading
Loading
+12 −12
Original line number Diff line number Diff line
@@ -475,12 +475,6 @@
      "group": "WM_DEBUG_ADD_REMOVE",
      "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java"
    },
    "-1635750891": {
      "message": "Received remote change for Display[%d], applied: [%dx%d, rot = %d]",
      "level": "VERBOSE",
      "group": "WM_DEBUG_CONFIGURATION",
      "at": "com\/android\/server\/wm\/RemoteDisplayChangeController.java"
    },
    "-1633115609": {
      "message": "Key dispatch not paused for screen off",
      "level": "VERBOSE",
@@ -1711,6 +1705,12 @@
      "group": "WM_DEBUG_STATES",
      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
    },
    "-417730399": {
      "message": "Preparing to sync a window that was already in the sync, so try dropping buffer. win=%s",
      "level": "DEBUG",
      "group": "WM_DEBUG_SYNC_ENGINE",
      "at": "com\/android\/server\/wm\/WindowState.java"
    },
    "-415865166": {
      "message": "findFocusedWindow: Found new focus @ %s",
      "level": "VERBOSE",
@@ -2137,6 +2137,12 @@
      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
    },
    "-4263657": {
      "message": "Got a buffer for request id=%d but latest request is id=%d. Since the buffer is out-of-date, drop it. win=%s",
      "level": "DEBUG",
      "group": "WM_DEBUG_SYNC_ENGINE",
      "at": "com\/android\/server\/wm\/WindowState.java"
    },
    "3593205": {
      "message": "commitVisibility: %s: visible=%b mVisibleRequested=%b",
      "level": "VERBOSE",
@@ -3877,12 +3883,6 @@
      "group": "WM_DEBUG_ORIENTATION",
      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
    },
    "1764619787": {
      "message": "Remote change for Display[%d]: timeout reached",
      "level": "VERBOSE",
      "group": "WM_DEBUG_CONFIGURATION",
      "at": "com\/android\/server\/wm\/RemoteDisplayChangeController.java"
    },
    "1774661765": {
      "message": "Devices still not ready after waiting %d milliseconds before attempting to detect safe mode.",
      "level": "WARN",
+1 −7
Original line number Diff line number Diff line
@@ -122,7 +122,6 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainer.SYNC_STATE_NONE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
@@ -2252,7 +2251,7 @@ public class WindowManagerService extends IWindowManager.Stub
                return 0;
            }

            if (win.cancelAndRedraw()) {
            if (win.cancelAndRedraw() && win.mPrepareSyncSeqId <= win.mLastSeqIdSentToRelayout) {
                result |= RELAYOUT_RES_CANCEL_AND_REDRAW;
            }

@@ -2558,11 +2557,6 @@ public class WindowManagerService extends IWindowManager.Stub

                win.mLastSeqIdSentToRelayout = win.mSyncSeqId;
                outSyncIdBundle.putInt("seqid", win.mSyncSeqId);
                // Only mark mAlreadyRequestedSync if there's an explicit sync request, and not if
                // we're syncing due to mDrawHandlers
                if (win.mSyncState != SYNC_STATE_NONE) {
                    win.mAlreadyRequestedSync = true;
                }
            } else {
                outSyncIdBundle.putInt("seqid", -1);
            }
+52 −8
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RESIZE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SYNC_ENGINE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_INSETS;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER;
@@ -391,7 +392,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
     */
    int mSyncSeqId = 0;
    int mLastSeqIdSentToRelayout = 0;
    boolean mAlreadyRequestedSync;

    /** The last syncId associated with a prepareSync or 0 when no sync is active. */
    int mPrepareSyncSeqId = 0;

    /**
     * {@code true} when the client was still drawing for sync when the sync-set was finished or
@@ -4421,7 +4424,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
            }
        }

        pw.println(prefix + "mAlreadyRequestedSync=" + mAlreadyRequestedSync);
        pw.println(prefix + "mPrepareSyncSeqId=" + mPrepareSyncSeqId);
    }

    @Override
@@ -5913,6 +5916,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        return mWinAnimator.getSurfaceControl();
    }

    /** Drops a buffer for this window's view-root from a transaction */
    private void dropBufferFrom(Transaction t) {
        SurfaceControl viewSurface = getClientViewRootSurface();
        if (viewSurface == null) return;
        t.setBuffer(viewSurface, (android.hardware.HardwareBuffer) null);
    }

    @Override
    boolean prepareSync() {
        if (!mDrawHandlers.isEmpty()) {
@@ -5928,7 +5938,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        // to draw even if the children draw first or don't need to sync, so we start
        // in WAITING state rather than READY.
        mSyncState = SYNC_STATE_WAITING_FOR_DRAW;

        if (mPrepareSyncSeqId > 0) {
            // another prepareSync during existing sync (eg. reparented), so pre-emptively
            // drop buffer (if exists). If the buffer hasn't been received yet, it will be
            // dropped in finishDrawing.
            ProtoLog.d(WM_DEBUG_SYNC_ENGINE, "Preparing to sync a window that was already in the"
                            + " sync, so try dropping buffer. win=%s", this);
            dropBufferFrom(mSyncTransaction);
        }

        mSyncSeqId++;
        mPrepareSyncSeqId = mSyncSeqId;
        requestRedrawForSync();
        return true;
    }
@@ -5949,7 +5970,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        if (mSyncState == SYNC_STATE_WAITING_FOR_DRAW && mRedrawForSyncReported) {
            mClientWasDrawingForSync = true;
        }
        mAlreadyRequestedSync = false;
        mPrepareSyncSeqId = 0;
        if (cancel) {
            // This is leaving sync so any buffers left in the sync have a chance of
            // being applied out-of-order and can also block the buffer queue for this
            // window. To prevent this, drop the buffer.
            dropBufferFrom(mSyncTransaction);
        }
        super.finishSync(outMergedTransaction, cancel);
    }

@@ -5971,6 +5998,17 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
                    .notifyStartingWindowDrawn(mActivityRecord);
        }

        final boolean syncActive = mPrepareSyncSeqId > 0;
        final boolean syncStillPending = syncActive && mPrepareSyncSeqId > syncSeqId;
        if (syncStillPending && postDrawTransaction != null) {
            ProtoLog.d(WM_DEBUG_SYNC_ENGINE, "Got a buffer for request id=%d but latest request is"
                    + " id=%d. Since the buffer is out-of-date, drop it. win=%s", syncSeqId,
                    mPrepareSyncSeqId, this);
            // sync is waiting for a newer seqId, so this buffer is obsolete and can be dropped
            // to free up the buffer queue.
            dropBufferFrom(postDrawTransaction);
        }

        final boolean hasSyncHandlers = executeDrawHandlers(postDrawTransaction, syncSeqId);

        boolean skipLayout = false;
@@ -5983,11 +6021,16 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
            // Layout is not needed because the window will be hidden by the fade leash.
            postDrawTransaction = null;
            skipLayout = true;
        } else if (onSyncFinishedDrawing() && postDrawTransaction != null) {
        } else if (syncActive) {
            if (!syncStillPending) {
                onSyncFinishedDrawing();
            }
            if (postDrawTransaction != null) {
                mSyncTransaction.merge(postDrawTransaction);
                // Consume the transaction because the sync group will merge it.
                postDrawTransaction = null;
            }
        }

        final boolean layoutNeeded =
                mWinAnimator.finishDrawingLocked(postDrawTransaction, mClientWasDrawingForSync);
@@ -6218,6 +6261,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    }

    public boolean cancelAndRedraw() {
        return mSyncState != SYNC_STATE_NONE && mAlreadyRequestedSync;
        // Cancel any draw requests during a sync.
        return mPrepareSyncSeqId > 0;
    }
}