From aa47a68239c4c691359bd962b379a8773f3bbc75 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Thu, 7 Jan 2021 18:00:49 -0800 Subject: [PATCH] Use setFrameRate for high refresh rate deny list Add visibility to SurfaceFlinger into the high refresh rate deny list and let SurfaceFlinger handle it. Previously WM was setting the preferredDisplayModeId on the denied app's window. The old way prevented SurfaceFlinger to use the frame rate override feature as it didn't know that a specific app is causing the refresh rate spec to be limited. With this change, SurfaceFlinger will limit the display refresh rate based on the high refresh rate deny list, and if possible, will use the frame rate override feature to change the display rate to a multiple, allowing other animations to be smooth while the denied app remains in the low refresh rate. Bug: 170502573 Test: manual Change-Id: Ib75a3c229cea298b65aa56dc1c1b20ca016059c4 Merged-In: Ib75a3c229cea298b65aa56dc1c1b20ca016059c4 --- core/java/android/view/DisplayInfo.java | 7 +- core/java/android/view/Surface.java | 9 ++ .../server/display/DisplayManagerService.java | 2 +- .../android/server/wm/RefreshRatePolicy.java | 26 ++++-- .../com/android/server/wm/WindowState.java | 21 ++++- .../wm/FrameRateSelectionPriorityTests.java | 89 ++++++++++++++++++- .../server/wm/RefreshRatePolicyTest.java | 22 +++-- .../android/server/wm/StubTransaction.java | 6 ++ 8 files changed, 160 insertions(+), 22 deletions(-) diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index fc42cd07950ee..ab35af89f0b39 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -547,16 +547,17 @@ public final class DisplayInfo implements Parcelable { * Returns the id of the "default" mode with the given refresh rate, or {@code 0} if no suitable * mode could be found. */ - public int findDefaultModeByRefreshRate(float refreshRate) { + @Nullable + public Display.Mode findDefaultModeByRefreshRate(float refreshRate) { Display.Mode[] modes = supportedModes; Display.Mode defaultMode = getDefaultMode(); for (int i = 0; i < modes.length; i++) { if (modes[i].matches( defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), refreshRate)) { - return modes[i].getModeId(); + return modes[i]; } } - return 0; + return null; } /** diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index a2777fe985d50..24bc308743181 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -217,6 +217,15 @@ public class Surface implements Parcelable { */ public static final int FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1; + /** + * This surface belongs to an app on the High Refresh Rate Deny list, and needs the display + * to operate at the exact frame rate. + * + * This is used internally by the platform and should not be used by apps. + * @hide + */ + public static final int FRAME_RATE_COMPATIBILITY_EXACT = 100; + /** * Create an empty surface, which will later be filled in by readFromParcel(). * @hide diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 55103ca6cd1c9..481c3c7a5d967 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -1357,7 +1357,7 @@ public final class DisplayManagerService extends SystemService { // Scan supported modes returned by display.getInfo() to find a mode with the same // size as the default display mode but with the specified refresh rate instead. requestedModeId = display.getDisplayInfoLocked().findDefaultModeByRefreshRate( - requestedRefreshRate); + requestedRefreshRate).getModeId(); } mDisplayModeDirector.getAppRequestObserver().setAppRequestedMode( displayId, requestedModeId); diff --git a/services/core/java/com/android/server/wm/RefreshRatePolicy.java b/services/core/java/com/android/server/wm/RefreshRatePolicy.java index 91014aa698313..26871d130fbf0 100644 --- a/services/core/java/com/android/server/wm/RefreshRatePolicy.java +++ b/services/core/java/com/android/server/wm/RefreshRatePolicy.java @@ -28,7 +28,7 @@ import android.view.DisplayInfo; */ class RefreshRatePolicy { - private final int mLowRefreshRateId; + private final Mode mLowRefreshRateMode; private final ArraySet mNonHighRefreshRatePackages = new ArraySet<>(); private final HighRefreshRateDenylist mHighRefreshRateDenylist; private final WindowManagerService mWmService; @@ -56,7 +56,7 @@ class RefreshRatePolicy { RefreshRatePolicy(WindowManagerService wmService, DisplayInfo displayInfo, HighRefreshRateDenylist denylist) { - mLowRefreshRateId = findLowRefreshRateModeId(displayInfo); + mLowRefreshRateMode = findLowRefreshRateMode(displayInfo); mHighRefreshRateDenylist = denylist; mWmService = wmService; } @@ -65,7 +65,7 @@ class RefreshRatePolicy { * Finds the mode id with the lowest refresh rate which is >= 60hz and same resolution as the * default mode. */ - private int findLowRefreshRateModeId(DisplayInfo displayInfo) { + private Mode findLowRefreshRateMode(DisplayInfo displayInfo) { Mode mode = displayInfo.getDefaultMode(); float[] refreshRates = displayInfo.getDefaultRefreshRates(); float bestRefreshRate = mode.getRefreshRate(); @@ -104,13 +104,9 @@ class RefreshRatePolicy { // If app is using Camera, force it to default (lower) refresh rate. if (mNonHighRefreshRatePackages.contains(packageName)) { - return mLowRefreshRateId; + return mLowRefreshRateMode.getModeId(); } - // If app is denylisted using higher refresh rate, return default (lower) refresh rate - if (mHighRefreshRateDenylist.isDenylisted(packageName)) { - return mLowRefreshRateId; - } return 0; } @@ -137,4 +133,18 @@ class RefreshRatePolicy { } return LAYER_PRIORITY_UNSET; } + + float getPreferredRefreshRate(WindowState w) { + // 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; + } + + final String packageName = w.getOwningPackage(); + if (mHighRefreshRateDenylist.isDenylisted(packageName)) { + return mLowRefreshRateMode.getRefreshRate(); + } + return 0; + } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 3be4e78a122bc..d0afa2ae2a738 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -233,6 +233,7 @@ import android.view.InputWindowHandle; import android.view.InsetsSource; import android.view.InsetsState; import android.view.InsetsState.InternalInsetsType; +import android.view.Surface; import android.view.Surface.Rotation; import android.view.SurfaceControl; import android.view.SurfaceSession; @@ -730,6 +731,13 @@ class WindowState extends WindowContainer implements WindowManagerP */ int mFrameRateSelectionPriority = RefreshRatePolicy.LAYER_PRIORITY_UNSET; + /** + * This is the frame rate which is passed to SurfaceFlinger if the window is part of the + * high refresh rate deny list. The variable is cached, so we do not send too many updates to + * SF. + */ + float mDenyListFrameRate = 0f; + static final int BLAST_TIMEOUT_DURATION = 5000; /* milliseconds */ private final WindowProcessController mWpcForDisplayAreaConfigChanges; @@ -5233,7 +5241,6 @@ class WindowState extends WindowContainer implements WindowManagerP return (mAttrs.flags & FLAG_BLUR_BEHIND) != 0 && mOwnerCanUseBackgroundBlur; } - /** * Notifies SF about the priority of the window, if it changed. SF then uses this information * to decide which window's desired rendering rate should have a priority when deciding about @@ -5242,13 +5249,21 @@ class WindowState extends WindowContainer implements WindowManagerP */ @VisibleForTesting void updateFrameRateSelectionPriorityIfNeeded() { - final int priority = getDisplayContent().getDisplayPolicy().getRefreshRatePolicy() - .calculatePriority(this); + RefreshRatePolicy refreshRatePolicy = + getDisplayContent().getDisplayPolicy().getRefreshRatePolicy(); + final int priority = refreshRatePolicy.calculatePriority(this); if (mFrameRateSelectionPriority != priority) { mFrameRateSelectionPriority = priority; getPendingTransaction().setFrameRateSelectionPriority(mSurfaceControl, mFrameRateSelectionPriority); } + + final float refreshRate = refreshRatePolicy.getPreferredRefreshRate(this); + if (mDenyListFrameRate != refreshRate) { + mDenyListFrameRate = refreshRate; + getPendingTransaction().setFrameRate( + mSurfaceControl, mDenyListFrameRate, Surface.FRAME_RATE_COMPATIBILITY_EXACT); + } } private void updateGlobalScaleIfNeeded() { 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 032edde61becf..325bca418d130 100644 --- a/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java @@ -18,15 +18,24 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; 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.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import android.platform.test.annotations.Presubmit; +import android.view.Display.Mode; +import android.view.DisplayInfo; +import android.view.Surface; +import android.view.SurfaceControl; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -40,16 +49,40 @@ 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); + + @Before + public void setUp() { + DisplayInfo di = new DisplayInfo(mDisplayInfo); + Mode defaultMode = di.getDefaultMode(); + di.supportedModes = new Mode[] { + new Mode(1, defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), 90), + new Mode(2, defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), 70), + new Mode(LOW_MODE_ID, + defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), 60), + }; + di.defaultModeId = 1; + mRefreshRatePolicy = new RefreshRatePolicy(mWm, di, mDenylist); + when(mDisplayPolicy.getRefreshRatePolicy()).thenReturn(mRefreshRatePolicy); + } @Test public void basicTest() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertNotNull("Window state is created", appWindow); + assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority doesn't change. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); // Call the function a few times. appWindow.updateFrameRateSelectionPriorityIfNeeded(); @@ -57,7 +90,9 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { // Since nothing changed in the priority state, the transaction should not be updating. verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority( - appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); + any(SurfaceControl.class), anyInt()); + verify(appWindow.getPendingTransaction(), never()).setFrameRate( + any(SurfaceControl.class), anyInt(), anyInt()); } @Test @@ -66,10 +101,16 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); assertEquals(appWindow.getDisplayContent().getDisplayPolicy().getRefreshRatePolicy() .getPreferredModeId(appWindow), 0); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); + assertEquals(appWindow.getDisplayContent().getDisplayPolicy().getRefreshRatePolicy() + .getPreferredRefreshRate(appWindow), 0, FLOAT_TOLERANCE); + + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority stays MAX_VALUE. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); @@ -78,31 +119,38 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes to 1. assertEquals(appWindow.mFrameRateSelectionPriority, 1); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), 1); + verify(appWindow.getPendingTransaction(), never()).setFrameRate( + any(SurfaceControl.class), anyInt(), anyInt()); } @Test public void testApplicationInFocusWithModeId() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); // Application is in focus. appWindow.mToken.mDisplayContent.mCurrentFocus = appWindow; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 1); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); // Update the mode ID to a requested number. appWindow.mAttrs.preferredDisplayModeId = 1; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 0); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); // Remove the mode ID request. appWindow.mAttrs.preferredDisplayModeId = 0; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 1); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); // Verify we called actions on Transactions correctly. verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority( @@ -111,12 +159,15 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { appWindow.getSurfaceControl(), 0); verify(appWindow.getPendingTransaction(), times(2)).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), 1); + verify(appWindow.getPendingTransaction(), never()).setFrameRate( + any(SurfaceControl.class), anyInt(), anyInt()); } @Test public void testApplicationNotInFocusWithModeId() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); final WindowState inFocusWindow = createWindow(null, TYPE_APPLICATION, "inFocus"); appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow; @@ -124,23 +175,28 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { appWindow.updateFrameRateSelectionPriorityIfNeeded(); // The window is not in focus. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); // Update the mode ID to a requested number. appWindow.mAttrs.preferredDisplayModeId = 1; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 2); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), 2); + verify(appWindow.getPendingTransaction(), never()).setFrameRate( + any(SurfaceControl.class), anyInt(), anyInt()); } @Test public void testApplicationNotInFocusWithoutModeId() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); final WindowState inFocusWindow = createWindow(null, TYPE_APPLICATION, "inFocus"); appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow; @@ -148,14 +204,45 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { appWindow.updateFrameRateSelectionPriorityIfNeeded(); // The window is not in focus. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); + assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE); // 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.mDenyListFrameRate, 0, FLOAT_TOLERANCE); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); + verify(appWindow.getPendingTransaction(), never()).setFrameRate( + any(SurfaceControl.class), anyInt(), anyInt()); + } + + @Test + public void testPreferredRefreshRate() { + final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); + assertNotNull("Window state is created", appWindow); + when(appWindow.getDisplayContent().getDisplayPolicy()).thenReturn(mDisplayPolicy); + + appWindow.mAttrs.packageName = "com.android.test"; + 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.mDenyListFrameRate, FLOAT_TOLERANCE); + + // Call the function a few times. + appWindow.updateFrameRateSelectionPriorityIfNeeded(); + appWindow.updateFrameRateSelectionPriorityIfNeeded(); + + // Since nothing changed in the priority state, the transaction should not be updating. + verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority( + any(SurfaceControl.class), anyInt()); + verify(appWindow.getPendingTransaction(), times(1)).setFrameRate( + appWindow.getSurfaceControl(), 60, Surface.FRAME_RATE_COMPATIBILITY_EXACT); } } 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 77a4b0507a420..ef3c7ae91fedc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java @@ -44,7 +44,7 @@ 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 LOW_MODE_ID = 3; private RefreshRatePolicy mPolicy; @@ -70,28 +70,34 @@ public class RefreshRatePolicyTest extends WindowTestsBase { "cameraUsingWindow"); cameraUsingWindow.mAttrs.packageName = "com.android.test"; assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); + assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); mPolicy.addNonHighRefreshRatePackage("com.android.test"); assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(cameraUsingWindow)); + assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); mPolicy.removeNonHighRefreshRatePackage("com.android.test"); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); + assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); } @Test - public void testBlacklist() { - final WindowState blacklistedWindow = createWindow(null, TYPE_BASE_APPLICATION, - "blacklistedWindow"); - blacklistedWindow.mAttrs.packageName = "com.android.test"; + public void testDenyList() { + final WindowState denylistedWindow = createWindow(null, TYPE_BASE_APPLICATION, + "denylistedWindow"); + denylistedWindow.mAttrs.packageName = "com.android.test"; when(mDenylist.isDenylisted("com.android.test")).thenReturn(true); - assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(blacklistedWindow)); + assertEquals(0, mPolicy.getPreferredModeId(denylistedWindow)); + assertEquals(60, mPolicy.getPreferredRefreshRate(denylistedWindow), FLOAT_TOLERANCE); } @Test public void testAppOverride_blacklist() { final WindowState overrideWindow = createWindow(null, TYPE_BASE_APPLICATION, "overrideWindow"); + overrideWindow.mAttrs.packageName = "com.android.test"; overrideWindow.mAttrs.preferredDisplayModeId = LOW_MODE_ID; when(mDenylist.isDenylisted("com.android.test")).thenReturn(true); assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(overrideWindow)); + assertEquals(60, mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); } @Test @@ -102,6 +108,7 @@ public class RefreshRatePolicyTest extends WindowTestsBase { overrideWindow.mAttrs.preferredDisplayModeId = LOW_MODE_ID; mPolicy.addNonHighRefreshRatePackage("com.android.test"); assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(overrideWindow)); + assertEquals(0, mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); } @Test @@ -115,6 +122,7 @@ public class RefreshRatePolicyTest extends WindowTestsBase { false /* hidden */, ANIMATION_TYPE_APP_TRANSITION); mPolicy.addNonHighRefreshRatePackage("com.android.test"); assertEquals(0, mPolicy.getPreferredModeId(overrideWindow)); + assertEquals(0, mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); } @Test @@ -125,10 +133,12 @@ public class RefreshRatePolicyTest extends WindowTestsBase { mPolicy.addNonHighRefreshRatePackage("com.android.test"); assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(cameraUsingWindow)); + assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); cameraUsingWindow.mActivityRecord.mSurfaceAnimator.startAnimation( cameraUsingWindow.getPendingTransaction(), mock(AnimationAdapter.class), false /* hidden */, ANIMATION_TYPE_APP_TRANSITION); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); + assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java index c308fdbf84919..b8d44f605bca6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java +++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java @@ -244,6 +244,12 @@ public class StubTransaction extends SurfaceControl.Transaction { return this; } + @Override + public SurfaceControl.Transaction setFrameRate(SurfaceControl sc, float frameRate, + int compatibility) { + return this; + } + @Override public SurfaceControl.Transaction unsetColor(SurfaceControl sc) { return this;