diff options
| author | 2024-06-18 13:54:50 -0700 | |
|---|---|---|
| committer | 2024-06-21 00:57:19 +0000 | |
| commit | 54617d39152af88825954e94538d6d2106bb7f44 (patch) | |
| tree | 127d90b1e967281b28540f4c4cd145418142f7fe | |
| parent | 43f6df87b92f2feb1d7ffb81d3ff617d22109e90 (diff) | |
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
| -rw-r--r-- | core/java/android/view/View.java | 15 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/view/ViewRootImplTest.java | 75 |
2 files changed, 88 insertions, 2 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 9bc15112debc..0960dfd84511 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -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; diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java index 06cb0eea811b..b15370049176 100644 --- a/core/tests/coretests/src/android/view/ViewRootImplTest.java +++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java @@ -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 */ |