diff options
| -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 3df72e8b142a..7a1ab7bca6c0 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 */ |