Loading services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +10 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,11 @@ public class DisplayManagerFlags { Flags::useFusionProxSensor ); private final FlagState mPeakRefreshRatePhysicalLimit = new FlagState( Flags.FLAG_ENABLE_PEAK_REFRESH_RATE_PHYSICAL_LIMIT, Flags::enablePeakRefreshRatePhysicalLimit ); /** * @return {@code true} if 'port' is allowed in display layout configuration file. */ Loading Loading @@ -312,6 +317,10 @@ public class DisplayManagerFlags { return mUseFusionProxSensor.getName(); } public boolean isPeakRefreshRatePhysicalLimitEnabled() { return mPeakRefreshRatePhysicalLimit.isEnabled(); } /** * dumps all flagstates * @param pw printWriter Loading Loading @@ -343,6 +352,7 @@ public class DisplayManagerFlags { pw.println(" " + mRefactorDisplayPowerController); pw.println(" " + mResolutionBackupRestore); pw.println(" " + mUseFusionProxSensor); pw.println(" " + mPeakRefreshRatePhysicalLimit); } private static class FlagState { Loading services/core/java/com/android/server/display/feature/display_flags.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -244,3 +244,14 @@ flag { bug: "306203895" is_fixed_read_only: true } flag { name: "enable_peak_refresh_rate_physical_limit" namespace: "display_manager" description: "Flag for adding physical refresh rate limit if smooth display setting is on " bug: "332413475" is_fixed_read_only: true metadata { purpose: PURPOSE_BUGFIX } } services/core/java/com/android/server/display/mode/DisplayModeDirector.java +12 −2 Original line number Diff line number Diff line Loading @@ -940,6 +940,7 @@ public class DisplayModeDirector { Settings.Secure.getUriFor(Settings.Secure.MATCH_CONTENT_FRAME_RATE); private final boolean mVsynLowPowerVoteEnabled; private final boolean mPeakRefreshRatePhysicalLimitEnabled; private final Context mContext; private float mDefaultPeakRefreshRate; Loading @@ -950,6 +951,7 @@ public class DisplayModeDirector { super(handler); mContext = context; mVsynLowPowerVoteEnabled = flags.isVsyncLowPowerVoteEnabled(); mPeakRefreshRatePhysicalLimitEnabled = flags.isPeakRefreshRatePhysicalLimitEnabled(); // We don't want to load from the DeviceConfig while constructing since this leads to // a spike in the latency of DisplayManagerService startup. This happens because // reading from the DeviceConfig is an intensive IO operation and having it in the Loading Loading @@ -1127,11 +1129,19 @@ public class DisplayModeDirector { // used to predict if we're going to be doing frequent refresh rate switching, and if // so, enable the brightness observer. The logic here is more complicated and fragile // than necessary, and we should improve it. See b/156304339 for more info. if (mPeakRefreshRatePhysicalLimitEnabled) { Vote peakVote = peakRefreshRate == 0f ? null : Vote.forPhysicalRefreshRates(0f, Math.max(minRefreshRate, peakRefreshRate)); mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE, peakVote); } Vote peakRenderVote = peakRefreshRate == 0f ? null : Vote.forRenderFrameRates(0f, Math.max(minRefreshRate, peakRefreshRate)); mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE, peakVote); peakRenderVote); mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, Vote.forRenderFrameRates(minRefreshRate, Float.POSITIVE_INFINITY)); Vote defaultVote = Loading services/core/java/com/android/server/display/mode/Vote.java +19 −13 Original line number Diff line number Diff line Loading @@ -76,46 +76,52 @@ interface Vote { int PRIORITY_APP_REQUEST_SIZE = 7; // SETTING_PEAK_RENDER_FRAME_RATE has a high priority and will restrict the bounds of the // rest of low priority voters. It votes [0, max(PEAK, MIN)] int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 8; // PRIORITY_USER_SETTING_PEAK_REFRESH_RATE restricts physical refresh rate to // [0, max(PEAK, MIN)], depending on user settings peakRR/minRR values int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 8; // PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE has a higher priority than // PRIORITY_USER_SETTING_PEAK_REFRESH_RATE and will limit render rate to [0, max(PEAK, MIN)] // in case physical refresh rate vote is discarded (due to other high priority votes), // render rate vote can still apply int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 9; // Restrict all displays to 60Hz when external display is connected. It votes [59Hz, 61Hz]. int PRIORITY_SYNCHRONIZED_REFRESH_RATE = 9; int PRIORITY_SYNCHRONIZED_REFRESH_RATE = 10; // Restrict displays max available resolution and refresh rates. It votes [0, LIMIT] int PRIORITY_LIMIT_MODE = 10; int PRIORITY_LIMIT_MODE = 11; // To avoid delay in switching between 60HZ -> 90HZ when activating LHBM, set refresh // rate to max value (same as for PRIORITY_UDFPS) on lock screen int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 11; int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 12; // For concurrent displays we want to limit refresh rate on all displays int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 12; int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 13; // For internal application to limit display modes to specific ids int PRIORITY_SYSTEM_REQUESTED_MODES = 13; int PRIORITY_SYSTEM_REQUESTED_MODES = 14; // LOW_POWER_MODE force the render frame rate to [0, 60HZ] if // Settings.Global.LOW_POWER_MODE is on. int PRIORITY_LOW_POWER_MODE = 14; int PRIORITY_LOW_POWER_MODE = 15; // PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the // higher priority voters' result is a range, it will fix the rate to a single choice. // It's used to avoid refresh rate switches in certain conditions which may result in the // user seeing the display flickering when the switches occur. int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 15; int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 16; // Force display to [0, 60HZ] if skin temperature is at or above CRITICAL. int PRIORITY_SKIN_TEMPERATURE = 16; int PRIORITY_SKIN_TEMPERATURE = 17; // The proximity sensor needs the refresh rate to be locked in order to function, so this is // set to a high priority. int PRIORITY_PROXIMITY = 17; int PRIORITY_PROXIMITY = 18; // The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order // to function, so this needs to be the highest priority of all votes. int PRIORITY_UDFPS = 18; int PRIORITY_UDFPS = 19; // Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and // APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString. Loading services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java +0 −56 Original line number Diff line number Diff line Loading @@ -78,7 +78,6 @@ import android.view.DisplayInfo; import android.view.SurfaceControl; import android.view.SurfaceControl.IdleScreenRefreshRateConfig; import android.view.SurfaceControl.RefreshRateRange; import android.view.SurfaceControl.RefreshRateRanges; import androidx.test.core.app.ApplicationProvider; import androidx.test.filters.SmallTest; Loading Loading @@ -843,61 +842,6 @@ public class DisplayModeDirectorTest { assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(expectedAppRequestedRefreshRate); } void verifySpecsWithRefreshRateSettings(DisplayModeDirector director, float minFps, float peakFps, float defaultFps, RefreshRateRanges primary, RefreshRateRanges appRequest) { DesiredDisplayModeSpecs specs = director.getDesiredDisplayModeSpecsWithInjectedFpsSettings( minFps, peakFps, defaultFps); assertThat(specs.primary).isEqualTo(primary); assertThat(specs.appRequest).isEqualTo(appRequest); } @Test public void testSpecsFromRefreshRateSettings() { // Confirm that, with varying settings for min, peak, and default refresh rate, // DesiredDisplayModeSpecs is calculated correctly. float[] refreshRates = {30.f, 60.f, 90.f, 120.f, 150.f}; DisplayModeDirector director = createDirectorFromRefreshRateArray(refreshRates, /*baseModeId=*/0); float inf = Float.POSITIVE_INFINITY; RefreshRateRange rangeAll = new RefreshRateRange(0, inf); RefreshRateRange range0to60 = new RefreshRateRange(0, 60); RefreshRateRange range0to90 = new RefreshRateRange(0, 90); RefreshRateRange range0to120 = new RefreshRateRange(0, 120); RefreshRateRange range60to90 = new RefreshRateRange(60, 90); RefreshRateRange range90to90 = new RefreshRateRange(90, 90); RefreshRateRange range90to120 = new RefreshRateRange(90, 120); RefreshRateRange range60toInf = new RefreshRateRange(60, inf); RefreshRateRange range90toInf = new RefreshRateRange(90, inf); RefreshRateRanges frameRateAll = new RefreshRateRanges(rangeAll, rangeAll); RefreshRateRanges frameRate90toInf = new RefreshRateRanges(range90toInf, range90toInf); RefreshRateRanges frameRate0to60 = new RefreshRateRanges(rangeAll, range0to60); RefreshRateRanges frameRate0to90 = new RefreshRateRanges(rangeAll, range0to90); RefreshRateRanges frameRate0to120 = new RefreshRateRanges(rangeAll, range0to120); RefreshRateRanges frameRate60to90 = new RefreshRateRanges(range60toInf, range60to90); RefreshRateRanges frameRate90to90 = new RefreshRateRanges(range90toInf, range90to90); RefreshRateRanges frameRate90to120 = new RefreshRateRanges(range90toInf, range90to120); verifySpecsWithRefreshRateSettings(director, 0, 0, 0, frameRateAll, frameRateAll); verifySpecsWithRefreshRateSettings(director, 0, 0, 90, frameRate0to90, frameRateAll); verifySpecsWithRefreshRateSettings(director, 0, 90, 0, frameRate0to90, frameRate0to90); verifySpecsWithRefreshRateSettings(director, 0, 90, 60, frameRate0to60, frameRate0to90); verifySpecsWithRefreshRateSettings(director, 0, 90, 120, frameRate0to90, frameRate0to90); verifySpecsWithRefreshRateSettings(director, 90, 0, 0, frameRate90toInf, frameRateAll); verifySpecsWithRefreshRateSettings(director, 90, 0, 120, frameRate90to120, frameRateAll); verifySpecsWithRefreshRateSettings(director, 90, 0, 60, frameRate90toInf, frameRateAll); verifySpecsWithRefreshRateSettings(director, 90, 120, 0, frameRate90to120, frameRate0to120); verifySpecsWithRefreshRateSettings(director, 90, 60, 0, frameRate90to90, frameRate0to90); verifySpecsWithRefreshRateSettings(director, 60, 120, 90, frameRate60to90, frameRate0to120); } void verifyBrightnessObserverCall(DisplayModeDirector director, float minFps, float peakFps, float defaultFps, float brightnessObserverMin, float brightnessObserverMax) { BrightnessObserver brightnessObserver = mock(BrightnessObserver.class); Loading Loading
services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +10 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,11 @@ public class DisplayManagerFlags { Flags::useFusionProxSensor ); private final FlagState mPeakRefreshRatePhysicalLimit = new FlagState( Flags.FLAG_ENABLE_PEAK_REFRESH_RATE_PHYSICAL_LIMIT, Flags::enablePeakRefreshRatePhysicalLimit ); /** * @return {@code true} if 'port' is allowed in display layout configuration file. */ Loading Loading @@ -312,6 +317,10 @@ public class DisplayManagerFlags { return mUseFusionProxSensor.getName(); } public boolean isPeakRefreshRatePhysicalLimitEnabled() { return mPeakRefreshRatePhysicalLimit.isEnabled(); } /** * dumps all flagstates * @param pw printWriter Loading Loading @@ -343,6 +352,7 @@ public class DisplayManagerFlags { pw.println(" " + mRefactorDisplayPowerController); pw.println(" " + mResolutionBackupRestore); pw.println(" " + mUseFusionProxSensor); pw.println(" " + mPeakRefreshRatePhysicalLimit); } private static class FlagState { Loading
services/core/java/com/android/server/display/feature/display_flags.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -244,3 +244,14 @@ flag { bug: "306203895" is_fixed_read_only: true } flag { name: "enable_peak_refresh_rate_physical_limit" namespace: "display_manager" description: "Flag for adding physical refresh rate limit if smooth display setting is on " bug: "332413475" is_fixed_read_only: true metadata { purpose: PURPOSE_BUGFIX } }
services/core/java/com/android/server/display/mode/DisplayModeDirector.java +12 −2 Original line number Diff line number Diff line Loading @@ -940,6 +940,7 @@ public class DisplayModeDirector { Settings.Secure.getUriFor(Settings.Secure.MATCH_CONTENT_FRAME_RATE); private final boolean mVsynLowPowerVoteEnabled; private final boolean mPeakRefreshRatePhysicalLimitEnabled; private final Context mContext; private float mDefaultPeakRefreshRate; Loading @@ -950,6 +951,7 @@ public class DisplayModeDirector { super(handler); mContext = context; mVsynLowPowerVoteEnabled = flags.isVsyncLowPowerVoteEnabled(); mPeakRefreshRatePhysicalLimitEnabled = flags.isPeakRefreshRatePhysicalLimitEnabled(); // We don't want to load from the DeviceConfig while constructing since this leads to // a spike in the latency of DisplayManagerService startup. This happens because // reading from the DeviceConfig is an intensive IO operation and having it in the Loading Loading @@ -1127,11 +1129,19 @@ public class DisplayModeDirector { // used to predict if we're going to be doing frequent refresh rate switching, and if // so, enable the brightness observer. The logic here is more complicated and fragile // than necessary, and we should improve it. See b/156304339 for more info. if (mPeakRefreshRatePhysicalLimitEnabled) { Vote peakVote = peakRefreshRate == 0f ? null : Vote.forPhysicalRefreshRates(0f, Math.max(minRefreshRate, peakRefreshRate)); mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE, peakVote); } Vote peakRenderVote = peakRefreshRate == 0f ? null : Vote.forRenderFrameRates(0f, Math.max(minRefreshRate, peakRefreshRate)); mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE, peakVote); peakRenderVote); mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE, Vote.forRenderFrameRates(minRefreshRate, Float.POSITIVE_INFINITY)); Vote defaultVote = Loading
services/core/java/com/android/server/display/mode/Vote.java +19 −13 Original line number Diff line number Diff line Loading @@ -76,46 +76,52 @@ interface Vote { int PRIORITY_APP_REQUEST_SIZE = 7; // SETTING_PEAK_RENDER_FRAME_RATE has a high priority and will restrict the bounds of the // rest of low priority voters. It votes [0, max(PEAK, MIN)] int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 8; // PRIORITY_USER_SETTING_PEAK_REFRESH_RATE restricts physical refresh rate to // [0, max(PEAK, MIN)], depending on user settings peakRR/minRR values int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 8; // PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE has a higher priority than // PRIORITY_USER_SETTING_PEAK_REFRESH_RATE and will limit render rate to [0, max(PEAK, MIN)] // in case physical refresh rate vote is discarded (due to other high priority votes), // render rate vote can still apply int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 9; // Restrict all displays to 60Hz when external display is connected. It votes [59Hz, 61Hz]. int PRIORITY_SYNCHRONIZED_REFRESH_RATE = 9; int PRIORITY_SYNCHRONIZED_REFRESH_RATE = 10; // Restrict displays max available resolution and refresh rates. It votes [0, LIMIT] int PRIORITY_LIMIT_MODE = 10; int PRIORITY_LIMIT_MODE = 11; // To avoid delay in switching between 60HZ -> 90HZ when activating LHBM, set refresh // rate to max value (same as for PRIORITY_UDFPS) on lock screen int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 11; int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 12; // For concurrent displays we want to limit refresh rate on all displays int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 12; int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 13; // For internal application to limit display modes to specific ids int PRIORITY_SYSTEM_REQUESTED_MODES = 13; int PRIORITY_SYSTEM_REQUESTED_MODES = 14; // LOW_POWER_MODE force the render frame rate to [0, 60HZ] if // Settings.Global.LOW_POWER_MODE is on. int PRIORITY_LOW_POWER_MODE = 14; int PRIORITY_LOW_POWER_MODE = 15; // PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the // higher priority voters' result is a range, it will fix the rate to a single choice. // It's used to avoid refresh rate switches in certain conditions which may result in the // user seeing the display flickering when the switches occur. int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 15; int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 16; // Force display to [0, 60HZ] if skin temperature is at or above CRITICAL. int PRIORITY_SKIN_TEMPERATURE = 16; int PRIORITY_SKIN_TEMPERATURE = 17; // The proximity sensor needs the refresh rate to be locked in order to function, so this is // set to a high priority. int PRIORITY_PROXIMITY = 17; int PRIORITY_PROXIMITY = 18; // The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order // to function, so this needs to be the highest priority of all votes. int PRIORITY_UDFPS = 18; int PRIORITY_UDFPS = 19; // Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and // APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString. Loading
services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java +0 −56 Original line number Diff line number Diff line Loading @@ -78,7 +78,6 @@ import android.view.DisplayInfo; import android.view.SurfaceControl; import android.view.SurfaceControl.IdleScreenRefreshRateConfig; import android.view.SurfaceControl.RefreshRateRange; import android.view.SurfaceControl.RefreshRateRanges; import androidx.test.core.app.ApplicationProvider; import androidx.test.filters.SmallTest; Loading Loading @@ -843,61 +842,6 @@ public class DisplayModeDirectorTest { assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(expectedAppRequestedRefreshRate); } void verifySpecsWithRefreshRateSettings(DisplayModeDirector director, float minFps, float peakFps, float defaultFps, RefreshRateRanges primary, RefreshRateRanges appRequest) { DesiredDisplayModeSpecs specs = director.getDesiredDisplayModeSpecsWithInjectedFpsSettings( minFps, peakFps, defaultFps); assertThat(specs.primary).isEqualTo(primary); assertThat(specs.appRequest).isEqualTo(appRequest); } @Test public void testSpecsFromRefreshRateSettings() { // Confirm that, with varying settings for min, peak, and default refresh rate, // DesiredDisplayModeSpecs is calculated correctly. float[] refreshRates = {30.f, 60.f, 90.f, 120.f, 150.f}; DisplayModeDirector director = createDirectorFromRefreshRateArray(refreshRates, /*baseModeId=*/0); float inf = Float.POSITIVE_INFINITY; RefreshRateRange rangeAll = new RefreshRateRange(0, inf); RefreshRateRange range0to60 = new RefreshRateRange(0, 60); RefreshRateRange range0to90 = new RefreshRateRange(0, 90); RefreshRateRange range0to120 = new RefreshRateRange(0, 120); RefreshRateRange range60to90 = new RefreshRateRange(60, 90); RefreshRateRange range90to90 = new RefreshRateRange(90, 90); RefreshRateRange range90to120 = new RefreshRateRange(90, 120); RefreshRateRange range60toInf = new RefreshRateRange(60, inf); RefreshRateRange range90toInf = new RefreshRateRange(90, inf); RefreshRateRanges frameRateAll = new RefreshRateRanges(rangeAll, rangeAll); RefreshRateRanges frameRate90toInf = new RefreshRateRanges(range90toInf, range90toInf); RefreshRateRanges frameRate0to60 = new RefreshRateRanges(rangeAll, range0to60); RefreshRateRanges frameRate0to90 = new RefreshRateRanges(rangeAll, range0to90); RefreshRateRanges frameRate0to120 = new RefreshRateRanges(rangeAll, range0to120); RefreshRateRanges frameRate60to90 = new RefreshRateRanges(range60toInf, range60to90); RefreshRateRanges frameRate90to90 = new RefreshRateRanges(range90toInf, range90to90); RefreshRateRanges frameRate90to120 = new RefreshRateRanges(range90toInf, range90to120); verifySpecsWithRefreshRateSettings(director, 0, 0, 0, frameRateAll, frameRateAll); verifySpecsWithRefreshRateSettings(director, 0, 0, 90, frameRate0to90, frameRateAll); verifySpecsWithRefreshRateSettings(director, 0, 90, 0, frameRate0to90, frameRate0to90); verifySpecsWithRefreshRateSettings(director, 0, 90, 60, frameRate0to60, frameRate0to90); verifySpecsWithRefreshRateSettings(director, 0, 90, 120, frameRate0to90, frameRate0to90); verifySpecsWithRefreshRateSettings(director, 90, 0, 0, frameRate90toInf, frameRateAll); verifySpecsWithRefreshRateSettings(director, 90, 0, 120, frameRate90to120, frameRateAll); verifySpecsWithRefreshRateSettings(director, 90, 0, 60, frameRate90toInf, frameRateAll); verifySpecsWithRefreshRateSettings(director, 90, 120, 0, frameRate90to120, frameRate0to120); verifySpecsWithRefreshRateSettings(director, 90, 60, 0, frameRate90to90, frameRate0to90); verifySpecsWithRefreshRateSettings(director, 60, 120, 90, frameRate60to90, frameRate0to120); } void verifyBrightnessObserverCall(DisplayModeDirector director, float minFps, float peakFps, float defaultFps, float brightnessObserverMin, float brightnessObserverMax) { BrightnessObserver brightnessObserver = mock(BrightnessObserver.class); Loading