From 5e04f4372ba6052a691228d9d69595c2cbf49ce6 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Fri, 11 Nov 2022 17:43:26 -0800 Subject: [PATCH] Change setFrameRatecompatibility for preferredRefreshRate When an app provides a preferredRefreshRate, it should be translated to a setFrameRate call with FRAME_RATE_COMPATIBILITY_DEFAULT instead of FRAME_RATE_COMPATIBILITY_EXACT as it can be any value, and not only a supported refresh rate. Test: atest RefreshRatePolicyTest Test: atest FrameRateSelectionPriorityTests Bug: 257071160 Change-Id: Ib8ee4ba74eac0ba16f7a2591d8aeb5f924224c1b --- .../android/server/wm/RefreshRatePolicy.java | 104 ++++++++-- .../com/android/server/wm/WindowState.java | 26 +-- .../wm/FrameRateSelectionPriorityTests.java | 62 +++--- .../server/wm/RefreshRatePolicyTest.java | 195 ++++++++++++++---- 4 files changed, 291 insertions(+), 96 deletions(-) diff --git a/services/core/java/com/android/server/wm/RefreshRatePolicy.java b/services/core/java/com/android/server/wm/RefreshRatePolicy.java index ccc71bb8c537b..de42c55be4b30 100644 --- a/services/core/java/com/android/server/wm/RefreshRatePolicy.java +++ b/services/core/java/com/android/server/wm/RefreshRatePolicy.java @@ -16,15 +16,21 @@ package com.android.server.wm; +import static android.hardware.display.DisplayManager.SWITCHING_TYPE_NONE; +import static android.hardware.display.DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY; + import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; +import android.hardware.display.DisplayManager; import android.view.Display; import android.view.Display.Mode; import android.view.DisplayInfo; +import android.view.Surface; import android.view.SurfaceControl.RefreshRateRange; import java.util.HashMap; +import java.util.Objects; /** * Policy to select a lower refresh rate for the display if applicable. @@ -154,39 +160,109 @@ class RefreshRatePolicy { return LAYER_PRIORITY_UNSET; } - float getPreferredRefreshRate(WindowState w) { + public static class FrameRateVote { + float mRefreshRate; + @Surface.FrameRateCompatibility int mCompatibility; + + FrameRateVote(float refreshRate, @Surface.FrameRateCompatibility int compatibility) { + update(refreshRate, compatibility); + } + + FrameRateVote() { + reset(); + } + + boolean update(float refreshRate, @Surface.FrameRateCompatibility int compatibility) { + if (!refreshRateEquals(refreshRate) || mCompatibility != compatibility) { + mRefreshRate = refreshRate; + mCompatibility = compatibility; + return true; + } + return false; + } + + boolean reset() { + return update(0, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof FrameRateVote)) { + return false; + } + + FrameRateVote other = (FrameRateVote) o; + return refreshRateEquals(other.mRefreshRate) + && mCompatibility == other.mCompatibility; + } + + @Override + public int hashCode() { + return Objects.hash(mRefreshRate, mCompatibility); + } + + @Override + public String toString() { + return "mRefreshRate=" + mRefreshRate + ", mCompatibility=" + mCompatibility; + } + + private boolean refreshRateEquals(float refreshRate) { + return mRefreshRate <= refreshRate + RefreshRateRange.FLOAT_TOLERANCE + && mRefreshRate >= refreshRate - RefreshRateRange.FLOAT_TOLERANCE; + } + } + + boolean updateFrameRateVote(WindowState w) { + @DisplayManager.SwitchingType int refreshRateSwitchingType = + mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType(); + + // If refresh rate switching is disabled there is no point to set the frame rate on the + // surface as the refresh rate will be limited by display manager to a single value + // and SurfaceFlinger wouldn't be able to change it anyways. + if (refreshRateSwitchingType == SWITCHING_TYPE_NONE) { + return w.mFrameRateVote.reset(); + } + // If app is animating, it's not able to control refresh rate because we want the animation // to run in default refresh rate. if (w.isAnimating(TRANSITION | PARENTS)) { - return 0; + return w.mFrameRateVote.reset(); } // If the app set a preferredDisplayModeId, the preferred refresh rate is the refresh rate // of that mode id. - final int preferredModeId = w.mAttrs.preferredDisplayModeId; - if (preferredModeId > 0) { - DisplayInfo info = w.getDisplayInfo(); - if (info != null) { - for (Display.Mode mode : info.supportedModes) { - if (preferredModeId == mode.getModeId()) { - return mode.getRefreshRate(); + if (refreshRateSwitchingType != SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY) { + final int preferredModeId = w.mAttrs.preferredDisplayModeId; + if (preferredModeId > 0) { + DisplayInfo info = w.getDisplayInfo(); + if (info != null) { + for (Display.Mode mode : info.supportedModes) { + if (preferredModeId == mode.getModeId()) { + return w.mFrameRateVote.update(mode.getRefreshRate(), + Surface.FRAME_RATE_COMPATIBILITY_EXACT); + + } } } } } if (w.mAttrs.preferredRefreshRate > 0) { - return w.mAttrs.preferredRefreshRate; + return w.mFrameRateVote.update(w.mAttrs.preferredRefreshRate, + Surface.FRAME_RATE_COMPATIBILITY_DEFAULT); } // If the app didn't set a preferred mode id or refresh rate, but it is part of the deny // list, we return the low refresh rate as the preferred one. - final String packageName = w.getOwningPackage(); - if (mHighRefreshRateDenylist.isDenylisted(packageName)) { - return mLowRefreshRateMode.getRefreshRate(); + if (refreshRateSwitchingType != SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY) { + final String packageName = w.getOwningPackage(); + if (mHighRefreshRateDenylist.isDenylisted(packageName)) { + return w.mFrameRateVote.update(mLowRefreshRateMode.getRefreshRate(), + Surface.FRAME_RATE_COMPATIBILITY_EXACT); + } } - return 0; + return w.mFrameRateVote.reset(); } float getPreferredMinRefreshRate(WindowState w) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 86dd0b5452b5f..659b04465fc86 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -24,8 +24,6 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.graphics.GraphicsProtos.dumpPointProto; -import static android.hardware.display.DisplayManager.SWITCHING_TYPE_NONE; -import static android.hardware.display.DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY; import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; import static android.os.PowerManager.DRAW_WAKE_LOCK; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; @@ -203,7 +201,6 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.gui.TouchOcclusionMode; -import android.hardware.display.DisplayManager; import android.os.Binder; import android.os.Build; import android.os.Debug; @@ -261,6 +258,7 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.ToBooleanFunction; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.LocalAnimationAdapter.AnimationSpec; +import com.android.server.wm.RefreshRatePolicy.FrameRateVote; import com.android.server.wm.SurfaceAnimator.AnimationType; import dalvik.annotation.optimization.NeverCompile; @@ -792,7 +790,7 @@ class WindowState extends WindowContainer implements WindowManagerP * preferredDisplayModeId or is part of the high refresh rate deny list. * The variable is cached, so we do not send too many updates to SF. */ - float mAppPreferredFrameRate = 0f; + FrameRateVote mFrameRateVote = new FrameRateVote(); static final int BLAST_TIMEOUT_DURATION = 5000; /* milliseconds */ @@ -5507,20 +5505,12 @@ class WindowState extends WindowContainer implements WindowManagerP mFrameRateSelectionPriority); } - // If refresh rate switching is disabled there is no point to set the frame rate on the - // surface as the refresh rate will be limited by display manager to a single value - // and SurfaceFlinger wouldn't be able to change it anyways. - @DisplayManager.SwitchingType int refreshRateSwitchingType = - mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType(); - if (refreshRateSwitchingType != SWITCHING_TYPE_NONE - && refreshRateSwitchingType != SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY) { - final float refreshRate = refreshRatePolicy.getPreferredRefreshRate(this); - if (mAppPreferredFrameRate != refreshRate) { - mAppPreferredFrameRate = refreshRate; - getPendingTransaction().setFrameRate( - mSurfaceControl, mAppPreferredFrameRate, - Surface.FRAME_RATE_COMPATIBILITY_EXACT, Surface.CHANGE_FRAME_RATE_ALWAYS); - } + boolean voteChanged = refreshRatePolicy.updateFrameRateVote(this); + if (voteChanged) { + getPendingTransaction().setFrameRate( + mSurfaceControl, mFrameRateVote.mRefreshRate, + mFrameRateVote.mCompatibility, Surface.CHANGE_FRAME_RATE_ALWAYS); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java b/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java index 13ebc932fcef3..0568b3893aa2d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java @@ -25,6 +25,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -36,6 +37,8 @@ import android.view.DisplayInfo; import android.view.Surface; import android.view.SurfaceControl; +import com.android.server.wm.RefreshRatePolicy.FrameRateVote; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -50,12 +53,18 @@ import org.junit.runner.RunWith; @Presubmit @RunWith(WindowTestRunner.class) public class FrameRateSelectionPriorityTests extends WindowTestsBase { - private static final float FLOAT_TOLERANCE = 0.01f; private static final int LOW_MODE_ID = 3; private DisplayPolicy mDisplayPolicy = mock(DisplayPolicy.class); private RefreshRatePolicy mRefreshRatePolicy; private HighRefreshRateDenylist mDenylist = mock(HighRefreshRateDenylist.class); + private FrameRateVote mTempFrameRateVote = new FrameRateVote(); + + private static final FrameRateVote FRAME_RATE_VOTE_NONE = new FrameRateVote(); + private static final FrameRateVote FRAME_RATE_VOTE_60_EXACT = + new FrameRateVote(60, Surface.FRAME_RATE_COMPATIBILITY_EXACT); + private static final FrameRateVote FRAME_RATE_VOTE_60_PREFERRED = + new FrameRateVote(60, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT); WindowState createWindow(String name) { WindowState window = createWindow(null, TYPE_APPLICATION, name); @@ -85,12 +94,12 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { assertNotNull("Window state is created", appWindow); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority doesn't change. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); // Call the function a few times. appWindow.updateFrameRateSelectionPriorityIfNeeded(); @@ -109,16 +118,15 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); assertEquals(appWindow.getDisplayContent().getDisplayPolicy().getRefreshRatePolicy() .getPreferredModeId(appWindow), 0); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); - assertEquals(appWindow.getDisplayContent().getDisplayPolicy().getRefreshRatePolicy() - .getPreferredRefreshRate(appWindow), 0, FLOAT_TOLERANCE); - - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); + assertFalse(appWindow.getDisplayContent().getDisplayPolicy().getRefreshRatePolicy() + .updateFrameRateVote(appWindow)); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority stays MAX_VALUE. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); @@ -127,7 +135,7 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes to 1. assertEquals(appWindow.mFrameRateSelectionPriority, 1); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), 1); verify(appWindow.getPendingTransaction(), never()).setFrameRate( @@ -138,27 +146,27 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { public void testApplicationInFocusWithModeId() { final WindowState appWindow = createWindow("appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); // Application is in focus. appWindow.mToken.mDisplayContent.mCurrentFocus = appWindow; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 1); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); // Update the mode ID to a requested number. appWindow.mAttrs.preferredDisplayModeId = 1; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 0); - assertEquals(appWindow.mAppPreferredFrameRate, 60, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_60_EXACT); // Remove the mode ID request. appWindow.mAttrs.preferredDisplayModeId = 0; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 1); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); // Verify we called actions on Transactions correctly. verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority( @@ -175,7 +183,7 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { public void testApplicationNotInFocusWithModeId() { final WindowState appWindow = createWindow("appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); final WindowState inFocusWindow = createWindow("inFocus"); appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow; @@ -183,14 +191,14 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { appWindow.updateFrameRateSelectionPriorityIfNeeded(); // The window is not in focus. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); // Update the mode ID to a requested number. appWindow.mAttrs.preferredDisplayModeId = 1; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 2); - assertEquals(appWindow.mAppPreferredFrameRate, 60, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_60_EXACT); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); @@ -204,7 +212,7 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { public void testApplicationNotInFocusWithoutModeId() { final WindowState appWindow = createWindow("appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); final WindowState inFocusWindow = createWindow("inFocus"); appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow; @@ -212,14 +220,14 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { appWindow.updateFrameRateSelectionPriorityIfNeeded(); // The window is not in focus. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); // Make sure that the mode ID is not set. appWindow.mAttrs.preferredDisplayModeId = 0; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority doesn't change. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); @@ -237,11 +245,10 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { when(mDenylist.isDenylisted("com.android.test")).thenReturn(true); assertEquals(0, mRefreshRatePolicy.getPreferredModeId(appWindow)); - assertEquals(60, mRefreshRatePolicy.getPreferredRefreshRate(appWindow), FLOAT_TOLERANCE); appWindow.updateFrameRateSelectionPriorityIfNeeded(); assertEquals(RefreshRatePolicy.LAYER_PRIORITY_UNSET, appWindow.mFrameRateSelectionPriority); - assertEquals(60, appWindow.mAppPreferredFrameRate, FLOAT_TOLERANCE); + assertEquals(FRAME_RATE_VOTE_60_EXACT, appWindow.mFrameRateVote); // Call the function a few times. appWindow.updateFrameRateSelectionPriorityIfNeeded(); @@ -262,19 +269,19 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { .thenReturn(DisplayManager.SWITCHING_TYPE_NONE); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); // Update the mode ID to a requested number. appWindow.mAttrs.preferredDisplayModeId = 1; appWindow.updateFrameRateSelectionPriorityIfNeeded(); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); // Remove the mode ID request. appWindow.mAttrs.preferredDisplayModeId = 0; appWindow.updateFrameRateSelectionPriorityIfNeeded(); - assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); @@ -292,11 +299,10 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { appWindow.mAttrs.preferredRefreshRate = 60; assertEquals(0, mRefreshRatePolicy.getPreferredModeId(appWindow)); - assertEquals(60, mRefreshRatePolicy.getPreferredRefreshRate(appWindow), FLOAT_TOLERANCE); appWindow.updateFrameRateSelectionPriorityIfNeeded(); assertEquals(RefreshRatePolicy.LAYER_PRIORITY_UNSET, appWindow.mFrameRateSelectionPriority); - assertEquals(60, appWindow.mAppPreferredFrameRate, FLOAT_TOLERANCE); + assertEquals(FRAME_RATE_VOTE_60_PREFERRED, appWindow.mFrameRateVote); // Call the function a few times. appWindow.updateFrameRateSelectionPriorityIfNeeded(); @@ -307,6 +313,6 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { any(SurfaceControl.class), anyInt()); verify(appWindow.getPendingTransaction(), times(1)).setFrameRate( appWindow.getSurfaceControl(), 60, - Surface.FRAME_RATE_COMPATIBILITY_EXACT, Surface.CHANGE_FRAME_RATE_ALWAYS); + Surface.FRAME_RATE_COMPATIBILITY_DEFAULT, Surface.CHANGE_FRAME_RATE_ALWAYS); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java index 9d2eb26f5f21f..bcaf8860b0722 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java @@ -16,22 +16,29 @@ package com.android.server.wm; +import static android.view.SurfaceControl.RefreshRateRange.FLOAT_TOLERANCE; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import android.hardware.display.DisplayManager; import android.os.Parcel; import android.platform.test.annotations.Presubmit; import android.view.Display.Mode; +import android.view.Surface; import android.view.WindowManager.LayoutParams; import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; +import com.android.server.wm.RefreshRatePolicy.FrameRateVote; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -45,7 +52,6 @@ import org.junit.runner.RunWith; @RunWith(WindowTestRunner.class) @FlakyTest public class RefreshRatePolicyTest extends WindowTestsBase { - private static final float FLOAT_TOLERANCE = 0.01f; private static final int HI_MODE_ID = 1; private static final float HI_REFRESH_RATE = 90; @@ -57,6 +63,19 @@ public class RefreshRatePolicyTest extends WindowTestsBase { private RefreshRatePolicy mPolicy; private HighRefreshRateDenylist mDenylist = mock(HighRefreshRateDenylist.class); + private FrameRateVote mTempFrameRateVote = new FrameRateVote(); + + private static final FrameRateVote FRAME_RATE_VOTE_NONE = new FrameRateVote(); + private static final FrameRateVote FRAME_RATE_VOTE_DENY_LIST = + new FrameRateVote(LOW_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_EXACT); + private static final FrameRateVote FRAME_RATE_VOTE_LOW_EXACT = + new FrameRateVote(LOW_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_EXACT); + private static final FrameRateVote FRAME_RATE_VOTE_HI_EXACT = + new FrameRateVote(HI_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_EXACT); + private static final FrameRateVote FRAME_RATE_VOTE_LOW_PREFERRED = + new FrameRateVote(LOW_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT); + private static final FrameRateVote FRAME_RATE_VOTE_HI_PREFERRED = + new FrameRateVote(HI_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT); // Parcel and Unparcel the LayoutParams in the window state to test the path the object // travels from the app's process to system server @@ -89,6 +108,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { WindowState createWindow(String name) { WindowState window = createWindow(null, TYPE_BASE_APPLICATION, name); when(window.getDisplayInfo()).thenReturn(mDisplayInfo); + when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) + .thenReturn(DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS); return window; } @@ -98,20 +119,23 @@ public class RefreshRatePolicyTest extends WindowTestsBase { cameraUsingWindow.mAttrs.packageName = "com.android.test"; parcelLayoutParams(cameraUsingWindow); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); - assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(cameraUsingWindow)); + assertEquals(FRAME_RATE_VOTE_NONE, cameraUsingWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); mPolicy.addRefreshRateRangeForPackage("com.android.test", LOW_REFRESH_RATE, LOW_REFRESH_RATE); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); - assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(cameraUsingWindow)); + assertEquals(FRAME_RATE_VOTE_NONE, cameraUsingWindow.mFrameRateVote); assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); mPolicy.removeRefreshRateRangeForPackage("com.android.test"); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); - assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(cameraUsingWindow)); + assertEquals(FRAME_RATE_VOTE_NONE, cameraUsingWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); } @@ -122,20 +146,23 @@ public class RefreshRatePolicyTest extends WindowTestsBase { cameraUsingWindow.mAttrs.packageName = "com.android.test"; parcelLayoutParams(cameraUsingWindow); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); - assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(cameraUsingWindow)); + assertEquals(FRAME_RATE_VOTE_NONE, cameraUsingWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); mPolicy.addRefreshRateRangeForPackage("com.android.test", LOW_REFRESH_RATE, MID_REFRESH_RATE); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); - assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(cameraUsingWindow)); + assertEquals(FRAME_RATE_VOTE_NONE, cameraUsingWindow.mFrameRateVote); assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(MID_REFRESH_RATE, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); mPolicy.removeRefreshRateRangeForPackage("com.android.test"); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); - assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(cameraUsingWindow)); + assertEquals(FRAME_RATE_VOTE_NONE, cameraUsingWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); } @@ -146,20 +173,23 @@ public class RefreshRatePolicyTest extends WindowTestsBase { cameraUsingWindow.mAttrs.packageName = "com.android.test"; parcelLayoutParams(cameraUsingWindow); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); - assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(cameraUsingWindow)); + assertEquals(FRAME_RATE_VOTE_NONE, cameraUsingWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); mPolicy.addRefreshRateRangeForPackage("com.android.test", LOW_REFRESH_RATE - 10, HI_REFRESH_RATE + 10); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); - assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(cameraUsingWindow)); + assertEquals(FRAME_RATE_VOTE_NONE, cameraUsingWindow.mFrameRateVote); assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(HI_REFRESH_RATE, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); mPolicy.removeRefreshRateRangeForPackage("com.android.test"); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); - assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(cameraUsingWindow)); + assertEquals(FRAME_RATE_VOTE_NONE, cameraUsingWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); } @@ -171,8 +201,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { parcelLayoutParams(denylistedWindow); when(mDenylist.isDenylisted("com.android.test")).thenReturn(true); assertEquals(0, mPolicy.getPreferredModeId(denylistedWindow)); - assertEquals(LOW_REFRESH_RATE, - mPolicy.getPreferredRefreshRate(denylistedWindow), FLOAT_TOLERANCE); + assertTrue(mPolicy.updateFrameRateVote(denylistedWindow)); + assertEquals(FRAME_RATE_VOTE_DENY_LIST, denylistedWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(denylistedWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(denylistedWindow), FLOAT_TOLERANCE); } @@ -185,8 +215,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { parcelLayoutParams(overrideWindow); when(mDenylist.isDenylisted("com.android.test")).thenReturn(true); assertEquals(HI_MODE_ID, mPolicy.getPreferredModeId(overrideWindow)); - assertEquals(HI_REFRESH_RATE, - mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); + assertTrue(mPolicy.updateFrameRateVote(overrideWindow)); + assertEquals(FRAME_RATE_VOTE_HI_EXACT, overrideWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE); } @@ -199,8 +229,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { parcelLayoutParams(overrideWindow); when(mDenylist.isDenylisted("com.android.test")).thenReturn(true); assertEquals(0, mPolicy.getPreferredModeId(overrideWindow)); - assertEquals(HI_REFRESH_RATE, - mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); + assertTrue(mPolicy.updateFrameRateVote(overrideWindow)); + assertEquals(FRAME_RATE_VOTE_HI_PREFERRED, overrideWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE); } @@ -214,8 +244,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { mPolicy.addRefreshRateRangeForPackage("com.android.test", LOW_REFRESH_RATE, LOW_REFRESH_RATE); assertEquals(HI_MODE_ID, mPolicy.getPreferredModeId(overrideWindow)); - assertEquals(HI_REFRESH_RATE, - mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); + assertTrue(mPolicy.updateFrameRateVote(overrideWindow)); + assertEquals(FRAME_RATE_VOTE_HI_EXACT, overrideWindow.mFrameRateVote); assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(LOW_REFRESH_RATE, @@ -231,8 +261,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { mPolicy.addRefreshRateRangeForPackage("com.android.test", LOW_REFRESH_RATE, LOW_REFRESH_RATE); assertEquals(0, mPolicy.getPreferredModeId(overrideWindow)); - assertEquals(HI_REFRESH_RATE, - mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); + assertTrue(mPolicy.updateFrameRateVote(overrideWindow)); + assertEquals(FRAME_RATE_VOTE_HI_PREFERRED, overrideWindow.mFrameRateVote); assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(LOW_REFRESH_RATE, @@ -246,8 +276,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { overrideWindow.mAttrs.preferredDisplayModeId = LOW_MODE_ID; parcelLayoutParams(overrideWindow); assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(overrideWindow)); - assertEquals(LOW_REFRESH_RATE, - mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); + assertTrue(mPolicy.updateFrameRateVote(overrideWindow)); + assertEquals(FRAME_RATE_VOTE_LOW_EXACT, overrideWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE); @@ -255,7 +285,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { overrideWindow.getPendingTransaction(), mock(AnimationAdapter.class), false /* hidden */, ANIMATION_TYPE_APP_TRANSITION); assertEquals(0, mPolicy.getPreferredModeId(overrideWindow)); - assertEquals(0, mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); + assertTrue(mPolicy.updateFrameRateVote(overrideWindow)); + assertEquals(FRAME_RATE_VOTE_NONE, overrideWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE); } @@ -267,8 +298,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { overrideWindow.mAttrs.preferredRefreshRate = LOW_REFRESH_RATE; parcelLayoutParams(overrideWindow); assertEquals(0, mPolicy.getPreferredModeId(overrideWindow)); - assertEquals(LOW_REFRESH_RATE, - mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); + assertTrue(mPolicy.updateFrameRateVote(overrideWindow)); + assertEquals(FRAME_RATE_VOTE_LOW_PREFERRED, overrideWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE); @@ -276,7 +307,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { overrideWindow.getPendingTransaction(), mock(AnimationAdapter.class), false /* hidden */, ANIMATION_TYPE_APP_TRANSITION); assertEquals(0, mPolicy.getPreferredModeId(overrideWindow)); - assertEquals(0, mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); + assertTrue(mPolicy.updateFrameRateVote(overrideWindow)); + assertEquals(FRAME_RATE_VOTE_NONE, overrideWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE); } @@ -288,8 +320,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { parcelLayoutParams(window); when(mDenylist.isDenylisted("com.android.test")).thenReturn(true); assertEquals(0, mPolicy.getPreferredModeId(window)); - assertEquals(LOW_REFRESH_RATE, - mPolicy.getPreferredRefreshRate(window), FLOAT_TOLERANCE); + assertTrue(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_DENY_LIST, window.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(window), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(window), FLOAT_TOLERANCE); @@ -297,7 +329,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { window.getPendingTransaction(), mock(AnimationAdapter.class), false /* hidden */, ANIMATION_TYPE_APP_TRANSITION); assertEquals(0, mPolicy.getPreferredModeId(window)); - assertEquals(0, mPolicy.getPreferredRefreshRate(window), FLOAT_TOLERANCE); + assertTrue(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_NONE, window.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(window), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(window), FLOAT_TOLERANCE); } @@ -311,7 +344,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { mPolicy.addRefreshRateRangeForPackage("com.android.test", LOW_REFRESH_RATE, LOW_REFRESH_RATE); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); - assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(cameraUsingWindow)); + assertEquals(FRAME_RATE_VOTE_NONE, cameraUsingWindow.mFrameRateVote); assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(LOW_REFRESH_RATE, @@ -321,7 +355,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { cameraUsingWindow.getPendingTransaction(), mock(AnimationAdapter.class), false /* hidden */, ANIMATION_TYPE_APP_TRANSITION); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); - assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(cameraUsingWindow)); + assertEquals(FRAME_RATE_VOTE_NONE, cameraUsingWindow.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); } @@ -332,7 +367,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { window.mAttrs.preferredMaxDisplayRefreshRate = LOW_REFRESH_RATE; parcelLayoutParams(window); assertEquals(0, mPolicy.getPreferredModeId(window)); - assertEquals(0, mPolicy.getPreferredRefreshRate(window), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_NONE, window.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(window), FLOAT_TOLERANCE); assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredMaxRefreshRate(window), FLOAT_TOLERANCE); @@ -340,7 +376,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { window.getPendingTransaction(), mock(AnimationAdapter.class), false /* hidden */, ANIMATION_TYPE_APP_TRANSITION); assertEquals(0, mPolicy.getPreferredModeId(window)); - assertEquals(0, mPolicy.getPreferredRefreshRate(window), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_NONE, window.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(window), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(window), FLOAT_TOLERANCE); } @@ -351,7 +388,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { window.mAttrs.preferredMinDisplayRefreshRate = LOW_REFRESH_RATE; parcelLayoutParams(window); assertEquals(0, mPolicy.getPreferredModeId(window)); - assertEquals(0, mPolicy.getPreferredRefreshRate(window), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_NONE, window.mFrameRateVote); assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredMinRefreshRate(window), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(window), FLOAT_TOLERANCE); @@ -359,7 +397,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { window.getPendingTransaction(), mock(AnimationAdapter.class), false /* hidden */, ANIMATION_TYPE_APP_TRANSITION); assertEquals(0, mPolicy.getPreferredModeId(window)); - assertEquals(0, mPolicy.getPreferredRefreshRate(window), FLOAT_TOLERANCE); + assertFalse(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_NONE, window.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(window), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(window), FLOAT_TOLERANCE); } @@ -370,8 +409,92 @@ public class RefreshRatePolicyTest extends WindowTestsBase { window.mAttrs.preferredRefreshRate = LOW_REFRESH_RATE; parcelLayoutParams(window); assertEquals(0, mPolicy.getPreferredModeId(window)); - assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredRefreshRate(window), FLOAT_TOLERANCE); + assertTrue(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_LOW_PREFERRED, window.mFrameRateVote); assertEquals(0, mPolicy.getPreferredMinRefreshRate(window), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(window), FLOAT_TOLERANCE); } + + @Test + public void testSwitchingTypeForExactVote() { + final WindowState window = createWindow("window"); + window.mAttrs.preferredDisplayModeId = HI_MODE_ID; + parcelLayoutParams(window); + + when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) + .thenReturn(DisplayManager.SWITCHING_TYPE_NONE); + assertFalse(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_NONE, window.mFrameRateVote); + + when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) + .thenReturn(DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS); + assertTrue(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_HI_EXACT, window.mFrameRateVote); + + when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) + .thenReturn(DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS); + assertFalse(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_HI_EXACT, window.mFrameRateVote); + + when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) + .thenReturn(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY); + assertTrue(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_NONE, window.mFrameRateVote); + } + + @Test + public void testSwitchingTypeForPreferredVote() { + final WindowState window = createWindow("window"); + window.mAttrs.preferredRefreshRate = HI_REFRESH_RATE; + parcelLayoutParams(window); + + when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) + .thenReturn(DisplayManager.SWITCHING_TYPE_NONE); + assertFalse(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_NONE, window.mFrameRateVote); + + when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) + .thenReturn(DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS); + assertTrue(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_HI_PREFERRED, window.mFrameRateVote); + + when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) + .thenReturn(DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS); + assertFalse(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_HI_PREFERRED, window.mFrameRateVote); + + when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) + .thenReturn(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY); + assertFalse(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_HI_PREFERRED, window.mFrameRateVote); + } + + @Test + public void testSwitchingTypeForDenylist() { + when(mDenylist.isDenylisted("com.android.test")).thenReturn(true); + + final WindowState window = createWindow("window"); + window.mAttrs.packageName = "com.android.test"; + parcelLayoutParams(window); + + when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) + .thenReturn(DisplayManager.SWITCHING_TYPE_NONE); + assertFalse(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_NONE, window.mFrameRateVote); + + when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) + .thenReturn(DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS); + assertTrue(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_LOW_EXACT, window.mFrameRateVote); + + when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) + .thenReturn(DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS); + assertFalse(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_LOW_EXACT, window.mFrameRateVote); + + when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) + .thenReturn(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY); + assertTrue(mPolicy.updateFrameRateVote(window)); + assertEquals(FRAME_RATE_VOTE_NONE, window.mFrameRateVote); + } }