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

Commit 0f4a9597 authored by Shane's avatar Shane
Browse files

Update frame rate category changing logic

This CL is created to avoid the unnecessary (frequent) frame rate
category update. One observed scenario is that when a Video and an
animation have different invalidation intervals and sizes, it can cause
the frameRateCategory to be updated repeatedly.

To resolve this issue, we introudce counters for different category.
Everytime a category is voted, the value of the counter is set to 5 and
this value will be decrease by 1 every frame. When the value of a
counter is greater than 0, it will be taken into consideration when
determining the category to be set.

If the ViewRootImpl doesn't receive a vote of a category in 5 frames,
the category won't be taken into consideration anymore.

Test: atest ViewRootImplTest
Change-Id: I71e1f95381bc696865c50c2dc41a03f1646f5924
parent cb3aab75
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -53118,7 +53118,7 @@ package android.view {
    field protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
    field protected static final int[] PRESSED_STATE_SET;
    field protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
    field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = 0.0f;
    field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = (0.0f/0.0f);
    field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_HIGH = -4.0f;
    field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_LOW = -2.0f;
    field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_NORMAL = -3.0f;
+1 −2
Original line number Diff line number Diff line
@@ -5628,7 +5628,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    private int mLastFrameRateCategory = FRAME_RATE_CATEGORY_HIGH;
    @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
    public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = 0;
    public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = Float.NaN;
    @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
    public static final float REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE = -1;
    @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
@@ -33335,7 +33335,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (mInfrequentUpdateCount == INFREQUENT_UPDATE_COUNTS) {
            return FRAME_RATE_CATEGORY_NORMAL;
        }
        return mLastFrameRateCategory;
    }
+36 −1
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@ import static android.view.InputDevice.SOURCE_CLASS_NONE;
import static android.view.InsetsSource.ID_IME;
import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT;
import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
import static android.view.View.PFLAG_DRAW_ANIMATION;
import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
@@ -1032,6 +1034,15 @@ public final class ViewRootImpl implements ViewParent,
    // the time when frame rate was set previously.
    private static final int FRAME_RATE_SETTING_REEVALUATE_TIME = 100;
    /*
     * The variables below are used to update frame rate category
     */
    private static final int FRAME_RATE_CATEGORY_COUNT = 5;
    private int mFrameRateCategoryHighCount = 0;
    private int mFrameRateCategoryHighHintCount = 0;
    private int mFrameRateCategoryNormalCount = 0;
    private int mFrameRateCategoryLowCount = 0;
    /*
     * the variables below are used to determine whther a dVRR feature should be enabled
     */
@@ -4086,6 +4097,12 @@ public final class ViewRootImpl implements ViewParent,
        // when the values are applicable.
        setPreferredFrameRate(mPreferredFrameRate);
        setPreferredFrameRateCategory(mPreferredFrameRateCategory);
        mFrameRateCategoryHighCount = mFrameRateCategoryHighCount > 0
                ? mFrameRateCategoryHighCount - 1 : mFrameRateCategoryHighCount;
        mFrameRateCategoryNormalCount = mFrameRateCategoryNormalCount > 0
                ? mFrameRateCategoryNormalCount - 1 : mFrameRateCategoryNormalCount;
        mFrameRateCategoryLowCount = mFrameRateCategoryLowCount > 0
                ? mFrameRateCategoryLowCount - 1 : mFrameRateCategoryLowCount;
        mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
    }
@@ -12358,7 +12375,25 @@ public final class ViewRootImpl implements ViewParent,
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
    public void votePreferredFrameRateCategory(int frameRateCategory) {
        mPreferredFrameRateCategory = Math.max(mPreferredFrameRateCategory, frameRateCategory);
        if (frameRateCategory == FRAME_RATE_CATEGORY_HIGH) {
            mFrameRateCategoryHighCount = FRAME_RATE_CATEGORY_COUNT;
        } else if (frameRateCategory == FRAME_RATE_CATEGORY_HIGH_HINT) {
            mFrameRateCategoryHighHintCount = FRAME_RATE_CATEGORY_COUNT;
        } else if (frameRateCategory == FRAME_RATE_CATEGORY_NORMAL) {
            mFrameRateCategoryNormalCount = FRAME_RATE_CATEGORY_COUNT;
        } else if (frameRateCategory == FRAME_RATE_CATEGORY_LOW) {
            mFrameRateCategoryLowCount = FRAME_RATE_CATEGORY_COUNT;
        }
        if (mFrameRateCategoryHighCount > 0) {
            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_HIGH;
        } else if (mFrameRateCategoryHighHintCount > 0) {
            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_HIGH_HINT;
        } else if (mFrameRateCategoryNormalCount > 0) {
            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NORMAL;
        } else if (mFrameRateCategoryLowCount > 0) {
            mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_LOW;
        }
        mHasInvalidation = true;
    }
+51 −9
Original line number Diff line number Diff line
@@ -660,10 +660,22 @@ public class ViewRootImplTest {
    public void votePreferredFrameRate_voteFrameRateCategory_aggregate() {
        View view = new View(sContext);
        attachViewToWindow(view);
        sInstrumentation.runOnMainSync(() -> {
        ViewRootImpl viewRootImpl = view.getViewRootImpl();
        sInstrumentation.runOnMainSync(() -> {
            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
        });

        // reset the frame rate category counts
        for (int i = 0; i < 5; i++) {
            sInstrumentation.runOnMainSync(() -> {
                view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
                view.invalidate();
            });
            sInstrumentation.waitForIdleSync();
        }

        sInstrumentation.runOnMainSync(() -> {
            viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_LOW);
            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_LOW);
            viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_NORMAL);
@@ -721,6 +733,18 @@ public class ViewRootImplTest {
        sInstrumentation.runOnMainSync(() -> {
            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
        });

        // reset the frame rate category counts
        for (int i = 0; i < 5; i++) {
            sInstrumentation.runOnMainSync(() -> {
                view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
                view.invalidate();
            });
            sInstrumentation.waitForIdleSync();
        }

        sInstrumentation.runOnMainSync(() -> {
            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_LOW);
            view.invalidate();
            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_LOW);
@@ -847,7 +871,18 @@ public class ViewRootImplTest {
            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
            assertEquals(viewRootImpl.getPreferredFrameRate(), frameRate, 0.1);
        });

        // reset the frame rate category counts
        for (int i = 0; i < 5; i++) {
            sInstrumentation.runOnMainSync(() -> {
                view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
                view.invalidate();
            });
            sInstrumentation.waitForIdleSync();
        }

        sInstrumentation.runOnMainSync(() -> {
            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_LOW);
            view.invalidate();
            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_LOW);
@@ -882,28 +917,35 @@ public class ViewRootImplTest {

        ViewRootImpl viewRootImpl = view.getViewRootImpl();

        // Frequent update
        // In transistion from frequent update to infrequent update
        Thread.sleep(delay);
        sInstrumentation.runOnMainSync(() -> {
            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
            view.invalidate();
            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
            view.invalidate();
            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
        });

        // reset the frame rate category counts
        for (int i = 0; i < 5; i++) {
            sInstrumentation.runOnMainSync(() -> {
                view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
                view.invalidate();
            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
            });
            sInstrumentation.waitForIdleSync();
        }

        // In transistion from frequent update to infrequent update
        Thread.sleep(delay);
        sInstrumentation.runOnMainSync(() -> {
            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
            view.invalidate();
            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
            assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
                    FRAME_RATE_CATEGORY_NO_PREFERENCE);
        });

        // Infrequent update
        Thread.sleep(delay);
        sInstrumentation.runOnMainSync(() -> {
            view.setRequestedFrameRate(view.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT);
            view.invalidate();
            assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_NORMAL);
        });