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

Commit b67596d1 authored by Chris Li's avatar Chris Li
Browse files

Fix seq not update when it is not from system server

When the View is attached through WindowlessWindowManager or other
implementation of IWindowSession, it won't get seq update as it is
from the system server.

Don't treat it as stale in such case instead of updating
WindowlessWindowManager since this can happen to other device
implementation of IWindowSession as well.

Bug: 339380439
Test: atest FrameworksCoreTests:SequenceUtilsTest
Flag: com.android.window.flags.insets_control_seq
Change-Id: I561b08880c273e53fe9d996888f72715fb200347
parent 0ecbc703
Loading
Loading
Loading
Loading
+15 −8
Original line number Diff line number Diff line
@@ -25,8 +25,8 @@ package android.util;
 * {@link #getInitSeq}.
 * 2. Whenever a newer info needs to be sent to the client side, the system server should first
 * update its seq with {@link #getNextSeq}, then send the new info with the new seq to the client.
 * 3. On the client side, when receiving a new info, it should only consume it if it is newer than
 * the last received info seq by checking {@link #isIncomingSeqNewer}.
 * 3. On the client side, when receiving a new info, it should only consume it if it is not stale by
 * checking {@link #isIncomingSeqStale}.
 *
 * @hide
 */
@@ -36,15 +36,22 @@ public final class SequenceUtils {
    }

    /**
     * Returns {@code true} if the incomingSeq is newer than the curSeq.
     * Returns {@code true} if the incomingSeq is stale, which means the client should not consume
     * it.
     */
    public static boolean isIncomingSeqNewer(int curSeq, int incomingSeq) {
    public static boolean isIncomingSeqStale(int curSeq, int incomingSeq) {
        if (curSeq == getInitSeq()) {
            // curSeq can be set to the initial seq in the following cases:
            // 1. The client process/field is newly created/recreated.
            // 2. The field is not managed by the system server, such as WindowlessWindowManager.
            // The client should always consume the incoming in these cases.
            return false;
        }
        // Convert to long for comparison.
        final long diff = (long) incomingSeq - curSeq;
        // If there has been a sufficiently large jump, assume the sequence has wrapped around.
        // For example, when the last seq is MAX_VALUE, the incoming seq will be MIN_VALUE + 1.
        // diff = MIN_VALUE + 1 - MAX_VALUE. It is smaller than 0, but should be treated as newer.
        return diff > 0 || diff < Integer.MIN_VALUE;
        // When diff is 0, allow client to consume.
        // When there has been a sufficiently large jump, assume the sequence has wrapped around.
        return (diff < 0 && diff > Integer.MIN_VALUE) || diff > Integer.MAX_VALUE;
    }

    /** Returns the initial seq. */
+13 −13
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ import static android.graphics.HardwareRenderer.SYNC_LOST_SURFACE_REWARD_IF_FOUN
import static android.os.IInputConstants.INVALID_INPUT_EVENT_ID;
import static android.os.Trace.TRACE_TAG_VIEW;
import static android.util.SequenceUtils.getInitSeq;
import static android.util.SequenceUtils.isIncomingSeqNewer;
import static android.util.SequenceUtils.isIncomingSeqStale;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.DragEvent.ACTION_DRAG_LOCATION;
@@ -2329,23 +2329,23 @@ public final class ViewRootImpl implements ViewParent,
        if (mLastReportedFrames == null) {
            return;
        }
        if (isIncomingSeqNewer(mLastReportedFrames.seq, inOutFrames.seq)) {
        if (isIncomingSeqStale(mLastReportedFrames.seq, inOutFrames.seq)) {
            // If the incoming is stale, use the last reported instead.
            inOutFrames.setTo(mLastReportedFrames);
        } else {
            // Keep track of the latest.
            mLastReportedFrames.setTo(inOutFrames);
        } else {
            // If the last reported frames is newer, use the last reported instead.
            inOutFrames.setTo(mLastReportedFrames);
        }
    }
    private void onInsetsStateChanged(@NonNull InsetsState insetsState) {
        if (insetsControlSeq()) {
            if (isIncomingSeqNewer(mLastReportedInsetsStateSeq, insetsState.getSeq())) {
                mLastReportedInsetsStateSeq = insetsState.getSeq();
            } else {
                // The last reported InsetsState is newer. Skip.
            if (isIncomingSeqStale(mLastReportedInsetsStateSeq, insetsState.getSeq())) {
                // The incoming is stale. Skip.
                return;
            }
            // Keep track of the latest.
            mLastReportedInsetsStateSeq = insetsState.getSeq();
        }
        if (mTranslator != null) {
@@ -2362,13 +2362,13 @@ public final class ViewRootImpl implements ViewParent,
        }
        if (insetsControlSeq()) {
            if (isIncomingSeqNewer(mLastReportedActiveControlsSeq, activeControls.getSeq())) {
                mLastReportedActiveControlsSeq = activeControls.getSeq();
            } else {
                // The last reported controls is newer. Skip.
            if (isIncomingSeqStale(mLastReportedActiveControlsSeq, activeControls.getSeq())) {
                // The incoming is stale. Skip.
                activeControls.release();
                return;
            }
            // Keep track of the latest.
            mLastReportedActiveControlsSeq = activeControls.getSeq();
        }
        final InsetsSourceControl[] controls = activeControls.get();
+26 −21
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package android.util;

import static android.util.SequenceUtils.getInitSeq;
import static android.util.SequenceUtils.getNextSeq;
import static android.util.SequenceUtils.isIncomingSeqNewer;
import static android.util.SequenceUtils.isIncomingSeqStale;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -60,30 +60,35 @@ public class SequenceUtilsTest {
    }

    @Test
    public void testIsIncomingSeqNewer() {
        assertTrue(isIncomingSeqNewer(getInitSeq() + 1, getInitSeq() + 10));
        assertFalse(isIncomingSeqNewer(getInitSeq() + 10, getInitSeq() + 1));
        assertTrue(isIncomingSeqNewer(-100, 100));
        assertFalse(isIncomingSeqNewer(100, -100));
        assertTrue(isIncomingSeqNewer(1, 2));
        assertFalse(isIncomingSeqNewer(2, 1));
    public void testIsIncomingSeqStale() {
        assertFalse(isIncomingSeqStale(getInitSeq() + 1, getInitSeq() + 10));
        assertTrue(isIncomingSeqStale(getInitSeq() + 10, getInitSeq() + 1));
        assertFalse(isIncomingSeqStale(-100, 100));
        assertTrue(isIncomingSeqStale(100, -100));
        assertFalse(isIncomingSeqStale(1, 2));
        assertTrue(isIncomingSeqStale(2, 1));

        // Possible incoming seq are all newer than the initial seq.
        assertTrue(isIncomingSeqNewer(getInitSeq(), getInitSeq() + 1));
        assertTrue(isIncomingSeqNewer(getInitSeq(), -100));
        assertTrue(isIncomingSeqNewer(getInitSeq(), 0));
        assertTrue(isIncomingSeqNewer(getInitSeq(), 100));
        assertTrue(isIncomingSeqNewer(getInitSeq(), Integer.MAX_VALUE));
        assertTrue(isIncomingSeqNewer(getInitSeq(), getNextSeq(Integer.MAX_VALUE)));
        assertFalse(isIncomingSeqStale(getInitSeq(), getInitSeq()));
        assertFalse(isIncomingSeqStale(getInitSeq(), getInitSeq() + 1));
        assertFalse(isIncomingSeqStale(getInitSeq(), -100));
        assertFalse(isIncomingSeqStale(getInitSeq(), 0));
        assertFalse(isIncomingSeqStale(getInitSeq(), 100));
        assertFalse(isIncomingSeqStale(getInitSeq(), Integer.MAX_VALUE));
        assertFalse(isIncomingSeqStale(getInitSeq(), getNextSeq(Integer.MAX_VALUE)));

        // False for the same seq.
        assertFalse(isIncomingSeqNewer(getInitSeq(), getInitSeq()));
        assertFalse(isIncomingSeqNewer(100, 100));
        assertFalse(isIncomingSeqNewer(Integer.MAX_VALUE, Integer.MAX_VALUE));
        assertFalse(isIncomingSeqStale(100, 100));
        assertFalse(isIncomingSeqStale(Integer.MAX_VALUE, Integer.MAX_VALUE));

        // True when there is a large jump (overflow).
        assertTrue(isIncomingSeqNewer(Integer.MAX_VALUE, getInitSeq() + 1));
        assertTrue(isIncomingSeqNewer(Integer.MAX_VALUE, getInitSeq() + 100));
        assertTrue(isIncomingSeqNewer(Integer.MAX_VALUE, getNextSeq(Integer.MAX_VALUE)));
        // False when there is a large jump (overflow).
        assertFalse(isIncomingSeqStale(Integer.MAX_VALUE, getInitSeq() + 1));
        assertFalse(isIncomingSeqStale(Integer.MAX_VALUE, getInitSeq() + 100));
        assertFalse(isIncomingSeqStale(Integer.MAX_VALUE, getNextSeq(Integer.MAX_VALUE)));

        // True when the large jump is opposite (curSeq is newer).
        assertTrue(isIncomingSeqStale(getInitSeq() + 1, Integer.MAX_VALUE));
        assertTrue(isIncomingSeqStale(getInitSeq() + 100, Integer.MAX_VALUE));
        assertTrue(isIncomingSeqStale(getNextSeq(Integer.MAX_VALUE), Integer.MAX_VALUE));
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.view;

import static android.util.SequenceUtils.getInitSeq;
import static android.view.Surface.FRAME_RATE_CATEGORY_DEFAULT;
import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT;
@@ -1555,9 +1556,9 @@ public class ViewRootImplTest {
        final InsetsState state0 = new InsetsState();
        final InsetsState state1 = new InsetsState();
        state0.setDisplayFrame(new Rect(0, 0, 500, 1000));
        state0.setSeq(10000);
        state0.setSeq(getInitSeq() + 10000);
        state1.setDisplayFrame(new Rect(0, 0, 1500, 2000));
        state1.setSeq(10001);
        state1.setSeq(getInitSeq() + 10001);
        final InsetsSourceControl.Array array = new InsetsSourceControl.Array();

        sInstrumentation.runOnMainSync(() -> {