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

Commit 6fce2a69 authored by Shane's avatar Shane
Browse files

[ARR] Fix issues with apps that have internal rendering

This CL addresses two issues affecting apps with internal rendering. The root cause is that the value of mDrawnThisFrame is always set to false, preventing the calls to setFrameRate and setFrameRateCategory functions. This behavior results in two issues:

1. Touch boost never gets reset.
2. mSurfaceReplaced is never set to false, causing unnecessary setFrameRateCategory binder calls even when the previous and current frame rate categories are identical.

Solution:
1. When receiving the MSG_TOUCH_BOOST_TIMEOUT message and mDrawnThisFrame is false, call setPreferredFrameRateCategory(FRAME_RATE_CATEGORY_NO_PREFERENCE).
2. Always enforce a timeout to reset mSurfaceReplaced to false.

Bug: 374376214
Flag: EXEMPT bugfix
Test: atest ViewFrameRateTest and Manual test
Change-Id: I2e8c8b1f53e9ad38f4785bef9507b8d173e4f219
parent c4b3da52
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -1132,6 +1132,8 @@ public final class ViewRootImpl implements ViewParent,
    // time for evaluating the interval between current time and
    // the time when frame rate was set previously.
    private static final int FRAME_RATE_SETTING_REEVALUATE_TIME = 100;
    // timeout for surface replaced.
    private static final int FRAME_RATE_SURFACE_REPLACED_TIME = 3000;
    /*
     * The variables below are used to update frame rate category
@@ -3831,6 +3833,9 @@ public final class ViewRootImpl implements ViewParent,
                if (surfaceReplaced) {
                    mSurfaceReplaced = true;
                    mSurfaceSequenceId++;
                    mHandler.removeMessages(MSG_SURFACE_REPLACED_TIMEOUT);
                    mHandler.sendEmptyMessageDelayed(MSG_SURFACE_REPLACED_TIMEOUT,
                            FRAME_RATE_SURFACE_REPLACED_TIME);
                }
                if (alwaysConsumeSystemBarsChanged) {
                    mAttachInfo.mAlwaysConsumeSystemBars = mPendingAlwaysConsumeSystemBars;
@@ -6694,6 +6699,7 @@ public final class ViewRootImpl implements ViewParent,
    private static final int MSG_CHECK_INVALIDATION_IDLE = 40;
    private static final int MSG_REFRESH_POINTER_ICON = 41;
    private static final int MSG_FRAME_RATE_SETTING = 42;
    private static final int MSG_SURFACE_REPLACED_TIMEOUT = 43;
    final class ViewRootHandler extends Handler {
        @Override
@@ -6765,6 +6771,8 @@ public final class ViewRootImpl implements ViewParent,
                    return "MSG_TOUCH_BOOST_TIMEOUT";
                case MSG_FRAME_RATE_SETTING:
                    return "MSG_FRAME_RATE_SETTING";
                case MSG_SURFACE_REPLACED_TIMEOUT:
                    return "MSG_SURFACE_REPLACED_TIMEOUT";
            }
            return super.getMessageName(message);
        }
@@ -7036,6 +7044,9 @@ public final class ViewRootImpl implements ViewParent,
                     */
                    mIsFrameRateBoosting = false;
                    mIsTouchBoosting = false;
                    if (!mDrawnThisFrame) {
                        setPreferredFrameRateCategory(FRAME_RATE_CATEGORY_NO_PREFERENCE);
                    }
                    break;
                case MSG_REFRESH_POINTER_ICON:
                    if (mPointerIconEvent == null) {
@@ -7047,6 +7058,9 @@ public final class ViewRootImpl implements ViewParent,
                    mPreferredFrameRate = 0;
                    mFrameRateCompatibility = FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
                    break;
                case MSG_SURFACE_REPLACED_TIMEOUT:
                    mSurfaceReplaced = false;
                    break;
            }
        }
    }
@@ -13390,6 +13404,7 @@ public final class ViewRootImpl implements ViewParent,
    private void removeVrrMessages() {
        mHandler.removeMessages(MSG_TOUCH_BOOST_TIMEOUT);
        mHandler.removeMessages(MSG_FRAME_RATE_SETTING);
        mHandler.removeMessages(MSG_SURFACE_REPLACED_TIMEOUT);
        if (mInvalidationIdleMessagePosted && sSurfaceFlingerBugfixFlagValue) {
            mInvalidationIdleMessagePosted = false;
            mHandler.removeMessages(MSG_CHECK_INVALIDATION_IDLE);
+59 −0
Original line number Diff line number Diff line
@@ -891,6 +891,65 @@ public class ViewFrameRateTest {
        });
    }

    @Test
    @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY
    })
    public void testTouchBoostReset() throws Throwable {
        if (!ViewProperties.vrr_enabled().orElse(true)) {
            return;
        }
        mActivityRule.runOnUiThread(() -> {
            ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
            layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
            layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
            mMovingView.setLayoutParams(layoutParams);
            mMovingView.setOnClickListener((v) -> {});
        });
        waitForFrameRateCategoryToSettle();

        int[] position = new int[2];
        mActivityRule.runOnUiThread(() -> {
            mMovingView.getLocationOnScreen(position);
            position[0] += mMovingView.getWidth() / 2;
            position[1] += mMovingView.getHeight() / 2;
        });
        final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();

        long now = SystemClock.uptimeMillis();
        MotionEvent down = MotionEvent.obtain(
                now, // downTime
                now, // eventTime
                MotionEvent.ACTION_DOWN, // action
                position[0], // x
                position[1], // y
                0 // metaState
        );
        down.setSource(InputDevice.SOURCE_TOUCHSCREEN);
        instrumentation.sendPointerSync(down);
        assertEquals(FRAME_RATE_CATEGORY_HIGH_HINT, mViewRoot.getLastPreferredFrameRateCategory());

        MotionEvent up = MotionEvent.obtain(
                now, // downTime
                now, // eventTime
                MotionEvent.ACTION_UP, // action
                position[0], // x
                position[1], // y
                0 // metaState
        );
        up.setSource(InputDevice.SOURCE_TOUCHSCREEN);
        instrumentation.sendPointerSync(up);

        // Wait for idle timeout - 100 ms logner to avoid flaky
        Thread.sleep(3100);

        // Should not touch boost after the time out
        assertEquals(false, mViewRoot.getIsTouchBoosting());
        assertEquals(FRAME_RATE_CATEGORY_NO_PREFERENCE,
                mViewRoot.getLastPreferredFrameRateCategory());
    }


    @LargeTest
    @Test
    @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,