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

Commit ac7d6387 authored by Rob Carr's avatar Rob Carr Committed by Android (Google) Code Review
Browse files

Merge "WindowState: applyWithNextDraw fixes" into sc-dev

parents ced0e5a1 6f4f2c72
Loading
Loading
Loading
Loading
+6 −5
Original line number Original line Diff line number Diff line
@@ -2235,11 +2235,6 @@ public class WindowManagerService extends IWindowManager.Stub
                win.mPendingPositionChanged = null;
                win.mPendingPositionChanged = null;
            }
            }


            if (mUseBLASTSync && win.useBLASTSync() && viewVisibility != View.GONE) {
                win.prepareDrawHandlers();
                result |= RELAYOUT_RES_BLAST_SYNC;
            }

            int attrChanges = 0;
            int attrChanges = 0;
            int flagChanges = 0;
            int flagChanges = 0;
            int privateFlagChanges = 0;
            int privateFlagChanges = 0;
@@ -2512,6 +2507,12 @@ public class WindowManagerService extends IWindowManager.Stub
            }
            }
            win.mInRelayout = false;
            win.mInRelayout = false;


            if (mUseBLASTSync && win.useBLASTSync() && viewVisibility != View.GONE) {
                win.prepareDrawHandlers();
                win.markRedrawForSyncReported();
                result |= RELAYOUT_RES_BLAST_SYNC;
            }

            if (configChanged) {
            if (configChanged) {
                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                        "relayoutWindow: postNewConfigurationToHandler");
                        "relayoutWindow: postNewConfigurationToHandler");
+70 −6
Original line number Original line Diff line number Diff line
@@ -763,6 +763,56 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
     * into mReadyDrawHandlers. Finally once we get to finishDrawing we know everything in
     * into mReadyDrawHandlers. Finally once we get to finishDrawing we know everything in
     * mReadyDrawHandlers corresponds to state which was observed by the client and we can
     * mReadyDrawHandlers corresponds to state which was observed by the client and we can
     * invoke the consumers.
     * invoke the consumers.
     *
     * To see in more detail that this works, we can look at it like this:
     *
     * The client is in one of these states:
     *
     * 1. Asleep
     * 2. Traversal scheduled
     * 3. Starting traversal
     * 4. In relayout
     * 5. Already drawing
     *
     * The property we want to implement with the draw handlers is:
     *   If WM code makes a change to client observable state (e.g. configuration),
     *   and registers a draw handler (without releasing the WM lock in between),
     *   the FIRST frame reflecting that change, will be in the Transaction passed
     *   to the draw handler.
     *
     * We describe the expected sequencing in each of the possible client states.
     * We aim to "prove" that the WM can call applyWithNextDraw() with the client
     * starting in any state, and achieve the desired result.
     *
     * 1. Asleep: The client will wake up in response to MSG_RESIZED, call relayout,
     * observe the changes. Relayout will return BLAST_SYNC, and the client will
     * send the transaction to finishDrawing. Since the client was asleep. This
     * will be the first finishDrawing reflecting the change.
     * 2, 3: traversal scheduled/starting traversal: These two states can be considered
     *    together. Each has two sub-states:
     *       a) Traversal will call relayout. In this case we proceed like the starting
     *          from asleep case.
     *       b) Traversal will not call relayout. In this case, the client produced
     *       frame will not include the change. Because there is no call to relayout
     *       there is no call to prepareDrawHandlers() and even if the client calls
     *       finish drawing the draw handler will not be invoked. We have to wait
     *       on the client to receive MSG_RESIZED, and will sync on the next frame
     * 4. In relayout. In this case we are careful to prepare draw handlers and check
     *    whether to return the BLAST flag at the end of relayoutWindow. This means if you
     *    add a draw handler while the client is in relayout, BLAST_SYNC will be
     *    immediately returned, and the client will submit the frame corresponding
     *    to what returns from layout. When we prepare the draw handlers we clear the
     *    flag which would later cause us to report draw for sync. Since we reported
     *    sync through relayout (by luck the client was calling relayout perhaps)
     *    there is no need for a MSG_RESIZED.
     * 5. Already drawing. This works much like cases 2 and 3. If there is no call to
     *    finishDrawing then of course the draw handlers will not be invoked and we just
     *    wait on the next frame for sync. If there is a call to finishDrawing,
     *    the draw handler will not have been prepared (since we did not call relayout)
     *    and we will have to wait on the next frame.
     *
     * By this logic we can see no matter which of the client states we are in when the
     * draw handler is added, it will always execute on the expected frame.
     */
     */
    private final List<Consumer<SurfaceControl.Transaction>> mPendingDrawHandlers
    private final List<Consumer<SurfaceControl.Transaction>> mPendingDrawHandlers
        = new ArrayList<>();
        = new ArrayList<>();
@@ -3706,7 +3756,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        final int displayId = getDisplayId();
        final int displayId = getDisplayId();
        fillClientWindowFrames(mClientWindowFrames);
        fillClientWindowFrames(mClientWindowFrames);


        mRedrawForSyncReported = true;
        markRedrawForSyncReported();


        try {
        try {
            mClient.resized(mClientWindowFrames, reportDraw, mergedConfiguration, forceRelayout,
            mClient.resized(mClientWindowFrames, reportDraw, mergedConfiguration, forceRelayout,
@@ -5850,7 +5900,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
     * "in relayout", the results may be undefined but at all other times the function
     * "in relayout", the results may be undefined but at all other times the function
     * should sort of transparently work like this:
     * should sort of transparently work like this:
     *    1. Make changes to WM hierarchy (say change app configuration)
     *    1. Make changes to WM hierarchy (say change app configuration)
     *    2. Call apply with next draw.
     *    2. Call applyWithNextDraw
     *    3. After finishDrawing, our consumer will be passed the Transaction
     *    3. After finishDrawing, our consumer will be passed the Transaction
     *    containing the buffer, and we can merge in additional operations.
     *    containing the buffer, and we can merge in additional operations.
     * See {@link WindowState#mPendingDrawHandlers}
     * See {@link WindowState#mPendingDrawHandlers}
@@ -5879,16 +5929,26 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
     * See {@link WindowState#mPendingDrawHandlers}
     * See {@link WindowState#mPendingDrawHandlers}
     */
     */
    boolean executeDrawHandlers(SurfaceControl.Transaction t) {
    boolean executeDrawHandlers(SurfaceControl.Transaction t) {
        if (t == null) t = mTmpTransaction;
        boolean hadHandlers = false;
        boolean hadHandlers = false;
        boolean applyHere = false;
        if (t == null) {
            t = mTmpTransaction;
            applyHere = true;
        }

        for (int i = 0; i < mReadyDrawHandlers.size(); i++) {
        for (int i = 0; i < mReadyDrawHandlers.size(); i++) {
            mReadyDrawHandlers.get(i).accept(t);
            mReadyDrawHandlers.get(i).accept(t);
            hadHandlers = true;
            hadHandlers = true;
        }
        }

        if (hadHandlers) {
            mReadyDrawHandlers.clear();
            mReadyDrawHandlers.clear();
            mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
            mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
        }


        if (applyHere) {
            t.apply();
            t.apply();
        }


        return hadHandlers;
        return hadHandlers;
    }
    }
@@ -5906,4 +5966,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    @WindowManager.LayoutParams.WindowType int getWindowType() {
    @WindowManager.LayoutParams.WindowType int getWindowType() {
        return mAttrs.type;
        return mAttrs.type;
    }
    }

    void markRedrawForSyncReported() {
       mRedrawForSyncReported = true;
    }
}
}
+6 −5
Original line number Original line Diff line number Diff line
@@ -272,15 +272,16 @@ class WindowStateAnimator {
            }
            }
            mDrawState = COMMIT_DRAW_PENDING;
            mDrawState = COMMIT_DRAW_PENDING;
            layoutNeeded = true;
            layoutNeeded = true;
        }


        if (postDrawTransaction != null) {
        if (postDrawTransaction != null) {
            if (mLastHidden) {
                mPostDrawTransaction.merge(postDrawTransaction);
                mPostDrawTransaction.merge(postDrawTransaction);
            }
                layoutNeeded = true;
        } else if (postDrawTransaction != null) {
            } else {
            // If draw state is not pending we may delay applying this transaction from the client,
            // so apply it now.
                postDrawTransaction.apply();
                postDrawTransaction.apply();
            }
            }
        }


        return layoutNeeded;
        return layoutNeeded;
    }
    }