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

Commit 54617d39 authored by Haoyu Zhang's avatar Haoyu Zhang
Browse files

Vote for frame rate low for small view in intermittent

We've previously change the default frame rate category of intermittent
state to normal. However, small views that should vote for low frame rate will
now vote for normal in intermittent state.

To fix that, view will always vote based on their size now. This is
also the first step to remove the intermittent state.

Flag: android.view.flags.toolkit_frame_rate_by_size_read_only
Bug: 346123132
Test: ViewRootImplTest, ViewFrameRateTest
Change-Id: If7fe290f64657ec79e9ad2fe23893fc18e3ad3ae
parent 43f6df87
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -33898,8 +33898,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    protected int calculateFrameRateCategory() {
        int category;
        switch (getViewRootImpl().intermittentUpdateState()) {
            case ViewRootImpl.INTERMITTENT_STATE_INTERMITTENT -> category =
                    FRAME_RATE_CATEGORY_NORMAL | FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
            case ViewRootImpl.INTERMITTENT_STATE_INTERMITTENT -> {
                if (!sToolkitFrameRateBySizeReadOnlyFlagValue) {
                    category = FRAME_RATE_CATEGORY_NORMAL;
                } else {
                    // The size based frame rate category can only be LOW or NORMAL. If the size
                    // based frame rate category is LOW, we shouldn't vote for NORMAL for
                    // intermittent.
                    category = Math.min(
                            mSizeBasedFrameRateCategoryAndReason & ~FRAME_RATE_CATEGORY_REASON_MASK,
                            FRAME_RATE_CATEGORY_NORMAL);
                }
                category |= FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
            }
            case ViewRootImpl.INTERMITTENT_STATE_NOT_INTERMITTENT ->
                    category = mSizeBasedFrameRateCategoryAndReason;
            default -> category = mLastFrameRateCategory;
+75 −0
Original line number Diff line number Diff line
@@ -1250,6 +1250,81 @@ public class ViewRootImplTest {
        });
    }

    @Test
    @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
            FLAG_TOOLKIT_FRAME_RATE_FUNCTION_ENABLING_READ_ONLY,
            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY,
            FLAG_TOOLKIT_FRAME_RATE_BY_SIZE_READ_ONLY})
    public void votePreferredFrameRate_infrequentLayer_smallView_voteForLow() throws Throwable {
        if (!ViewProperties.vrr_enabled().orElse(true)) {
            return;
        }
        final long delay = 200L;

        mView = new View(sContext);
        WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
        wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
        wmlp.width = 1;
        wmlp.height = 1;

        // The view is a small view, and it should vote for category low only.
        int expected = FRAME_RATE_CATEGORY_LOW;

        sInstrumentation.runOnMainSync(() -> {
            WindowManager wm = sContext.getSystemService(WindowManager.class);
            wm.addView(mView, wmlp);
        });
        sInstrumentation.waitForIdleSync();

        mViewRootImpl = mView.getViewRootImpl();
        waitForFrameRateCategoryToSettle(mView);

        // In transition from frequent update to infrequent update
        Thread.sleep(delay);
        sInstrumentation.runOnMainSync(() -> {
            mView.invalidate();
            runAfterDraw(() -> assertEquals(expected,
                    mViewRootImpl.getLastPreferredFrameRateCategory()));
        });
        waitForAfterDraw();

        // In transition from frequent update to infrequent update
        Thread.sleep(delay);
        sInstrumentation.runOnMainSync(() -> {
            mView.invalidate();
            runAfterDraw(() -> assertEquals(expected,
                    mViewRootImpl.getLastPreferredFrameRateCategory()));
        });

        // Infrequent update
        Thread.sleep(delay);

        // The view is small, the expected category is still low for intermittent.
        int intermittentExpected = FRAME_RATE_CATEGORY_LOW;

        sInstrumentation.runOnMainSync(() -> {
            mView.invalidate();
            runAfterDraw(() -> assertEquals(intermittentExpected,
                    mViewRootImpl.getLastPreferredFrameRateCategory()));
        });
        waitForAfterDraw();

        // When the View vote, it's still considered as intermittent update state
        sInstrumentation.runOnMainSync(() -> {
            mView.invalidate();
            runAfterDraw(() -> assertEquals(intermittentExpected,
                    mViewRootImpl.getLastPreferredFrameRateCategory()));
        });
        waitForAfterDraw();

        // Becomes frequent update state
        sInstrumentation.runOnMainSync(() -> {
            mView.invalidate();
            runAfterDraw(() -> assertEquals(expected,
                    mViewRootImpl.getLastPreferredFrameRateCategory()));
        });
    }

    /**
     * Test the IsFrameRatePowerSavingsBalanced values are properly set
     */