summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Haoyu Zhang <haoyuchang@google.com> 2024-06-18 13:54:50 -0700
committer Haoyu Zhang <haoyuchang@google.com> 2024-06-21 00:57:19 +0000
commit54617d39152af88825954e94538d6d2106bb7f44 (patch)
tree127d90b1e967281b28540f4c4cd145418142f7fe
parent43f6df87b92f2feb1d7ffb81d3ff617d22109e90 (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.java15
-rw-r--r--core/tests/coretests/src/android/view/ViewRootImplTest.java75
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
*/