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

Commit 027b59d9 authored by Robert Carr's avatar Robert Carr
Browse files

WMS/ViewRoot: Prepare for Async BLAST Sync [1/N]

We would like to make relayoutWindow a non-blocking call,
and of course why not, who likes blocking. However it functions
as a critical path of BLASTSync. To understand why examine the
Guarantee described in BLASTSync.md.

In order to implement this guarantee we need to know
“Which frame has the client finished drawing” when it calls
finishDrawing. The current answer to this question is
“The frame reflecting the state observed in the last call
to relayoutWindow”. The comments on mPending and mCurrentDrawHandlers
also have a lot more context on how this works currently. Since
relayoutWindow has a critical section, it also ensures that changes
to syncable state and preparation of sync will be observed atomically
(since they are both observed over relayoutWindow, which is always
called before any frame drawing updated syncable state).

We design a new protocol described in BLASTSync.md, which uses a seqId
to track which call to finishDrawing reflects which syncable state.
We implement this seqId based system. Unfortunately the WindowManager
doesn’t quite conform to the requirements specified by the protocol,
and a follow up CL ensures that syncable state changes will
always be sent with the seqId.

This CL simply adds the protocol specification and makes some required
interface changes. It can be seen to be a no-op.

Bug: 161810301
Bug: 175861051
Bug: 175861127
Bug: 200285149
Change-Id: If2dea07121fe7de5d2524c5b63678dddf955d4b7
parent f1b86e8c
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.RemoteException;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
@@ -153,7 +154,8 @@ public class RelayoutPerfTest extends WindowManagerPerfTestBase
            while (state.keepRunning()) {
                session.relayout(mWindow, mParams, mWidth, mHeight,
                        mViewVisibility.getAsInt(), mFlags, mOutFrames,
                        mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls);
                        mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls,
                        new Bundle());
            }
        }
    }
+5 −3
Original line number Diff line number Diff line
@@ -252,6 +252,7 @@ public abstract class WallpaperService extends Service {
        final InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities();
        final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
        final MergedConfiguration mMergedConfiguration = new MergedConfiguration();
        final Bundle mSyncSeqIdBundle = new Bundle();
        private final Point mSurfaceSize = new Point();
        private final Point mLastSurfaceSize = new Point();
        private final Matrix mTmpMatrix = new Matrix();
@@ -391,7 +392,7 @@ public abstract class WallpaperService extends Service {
            @Override
            public void resized(ClientWindowFrames frames, boolean reportDraw,
                    MergedConfiguration mergedConfiguration, boolean forceLayout,
                    boolean alwaysConsumeSystemBars, int displayId) {
                    boolean alwaysConsumeSystemBars, int displayId, int syncSeqId) {
                Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED,
                        reportDraw ? 1 : 0,
                        mergedConfiguration);
@@ -1151,7 +1152,7 @@ public abstract class WallpaperService extends Service {
                    final int relayoutResult = mSession.relayout(
                            mWindow, mLayout, mWidth, mHeight,
                            View.VISIBLE, 0, mWinFrames, mMergedConfiguration, mSurfaceControl,
                            mInsetsState, mTempControls);
                            mInsetsState, mTempControls, mSyncSeqIdBundle);

                    final int transformHint = SurfaceControl.rotationToBufferTransform(
                            (mDisplayInstallOrientation + mDisplay.getRotation()) % 4);
@@ -1338,7 +1339,8 @@ public abstract class WallpaperService extends Service {
                        mSurfaceCreated = true;
                        if (redrawNeeded) {
                            resetWindowPages();
                            mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
                            mSession.finishDrawing(mWindow, null /* postDrawTransaction */,
                                                   Integer.MAX_VALUE);
                            processLocalColors(mPendingXOffset, mPendingXOffsetStep);
                            notifyColorsChanged();
                        }
+2 −1
Original line number Diff line number Diff line
@@ -55,7 +55,8 @@ oneway interface IWindow {

    void resized(in ClientWindowFrames frames, boolean reportDraw,
            in MergedConfiguration newMergedConfiguration,
            boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId);
            boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId,
            int syncSeqId);

    /**
     * Called when the window insets configuration has changed.
+4 −2
Original line number Diff line number Diff line
@@ -104,7 +104,8 @@ interface IWindowSession {
            int requestedWidth, int requestedHeight, int viewVisibility,
            int flags, out ClientWindowFrames outFrames,
            out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl,
            out InsetsState insetsState, out InsetsSourceControl[] activeControls);
            out InsetsState insetsState, out InsetsSourceControl[] activeControls,
            out Bundle bundle);

    /*
     * Notify the window manager that an application is relaunching and
@@ -142,7 +143,8 @@ interface IWindowSession {
     * is null if there is no sync required.
     */
    @UnsupportedAppUsage
    oneway void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction);
    oneway void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction,
            int seqId);

    @UnsupportedAppUsage
    oneway void setInTouchMode(boolean showFocus);
+26 −6
Original line number Diff line number Diff line
@@ -830,6 +830,24 @@ public final class ViewRootImpl implements ViewParent,

    private int mLastTransformHint = Integer.MIN_VALUE;

    /**
     * A temporary object used so relayoutWindow can return the latest SyncSeqId
     * system. The SyncSeqId system was designed to work without synchronous relayout
     * window, and actually synchronous relayout window presents a problem.  We could have
     * a sequence like this:
     *    1. We send MSG_RESIZED to the client with a new syncSeqId to begin a new sync
     *    2. Due to scheduling the client executes performTraversals before calling MSG_RESIZED
     *    3. Coincidentally for some random reason it also calls relayout
     *    4. It observes the new state from relayout, and so the next frame will contain the state
     * However it hasn't received the seqId yet, and so under the designed operation of
     * seqId flowing through MSG_RESIZED, the next frame wouldn't be synced. Since it
     * contains our target sync state, we need to sync it! This problem won't come up once
     * we get rid of synchronous relayout, until then, we use this bundle to channel the
     * integer back over relayout.
     */
    private Bundle mRelayoutBundle = new Bundle();
    private int mSyncSeqId;

    private String mTag = TAG;

    public ViewRootImpl(Context context, Display display) {
@@ -1711,6 +1729,7 @@ public final class ViewRootImpl implements ViewParent,
        mPendingBackDropFrame.set(backdropFrame);
        mForceNextWindowRelayout = forceNextWindowRelayout;
        mPendingAlwaysConsumeSystemBars = args.argi2 != 0;
        mSyncSeqId = args.argi4;

        if (msg == MSG_RESIZED_REPORT) {
            reportNextDraw();
@@ -4128,7 +4147,7 @@ public final class ViewRootImpl implements ViewParent,
        mDrawsNeededToReport = 0;

        try {
            mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction);
            mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction, Integer.MAX_VALUE);
        } catch (RemoteException e) {
            Log.e(mTag, "Unable to report draw finished", e);
            mSurfaceChangedTransaction.apply();
@@ -8071,7 +8090,7 @@ public final class ViewRootImpl implements ViewParent,
                requestedWidth, requestedHeight, viewVisibility,
                insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
                mTempControls);
                mTempControls, mRelayoutBundle);

        final int transformHint = SurfaceControl.rotationToBufferTransform(
                (mDisplayInstallOrientation + mDisplay.getRotation()) % 4);
@@ -8497,7 +8516,7 @@ public final class ViewRootImpl implements ViewParent,
                            if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
                                    & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
                                mWindowSession.finishDrawing(
                                        mWindow, null /* postDrawTransaction */);
                                    mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE);
                            }
                        } catch (RemoteException e) {
                        }
@@ -8571,7 +8590,7 @@ public final class ViewRootImpl implements ViewParent,
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private void dispatchResized(ClientWindowFrames frames, boolean reportDraw,
            MergedConfiguration mergedConfiguration, boolean forceLayout,
            boolean alwaysConsumeSystemBars, int displayId) {
                                 boolean alwaysConsumeSystemBars, int displayId, int seqId) {
        final Rect frame = frames.frame;
        final Rect backDropFrame = frames.backdropFrame;
        if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
@@ -8602,6 +8621,7 @@ public final class ViewRootImpl implements ViewParent,
        args.argi1 = forceLayout ? 1 : 0;
        args.argi2 = alwaysConsumeSystemBars ? 1 : 0;
        args.argi3 = displayId;
        args.argi4 = seqId;
        msg.obj = args;
        mHandler.sendMessage(msg);
    }
@@ -9986,11 +10006,11 @@ public final class ViewRootImpl implements ViewParent,
        @Override
        public void resized(ClientWindowFrames frames, boolean reportDraw,
                MergedConfiguration mergedConfiguration, boolean forceLayout,
                boolean alwaysConsumeSystemBars, int displayId) {
                boolean alwaysConsumeSystemBars, int displayId, int seqId) {
            final ViewRootImpl viewAncestor = mViewAncestor.get();
            if (viewAncestor != null) {
                viewAncestor.dispatchResized(frames, reportDraw, mergedConfiguration, forceLayout,
                        alwaysConsumeSystemBars, displayId);
                        alwaysConsumeSystemBars, displayId, seqId);
            }
        }

Loading