diff options
11 files changed, 315 insertions, 37 deletions
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 7b5cff739ba1..226bdf54ce3b 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -579,6 +579,14 @@ public class AutomaticBrightnessController { return mCurrentBrightnessMapper.getMode(); } + /** + * @return The preset for this mapping strategy. Presets are used on devices that allow users + * to choose from a set of predefined options in display auto-brightness settings. + */ + public int getPreset() { + return mCurrentBrightnessMapper.getPreset(); + } + public boolean isInIdleMode() { return mCurrentBrightnessMapper.getMode() == AUTO_BRIGHTNESS_MODE_IDLE; } diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java index 8405e0a52084..b0507fb78a41 100644 --- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java +++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java @@ -140,10 +140,10 @@ public abstract class BrightnessMappingStrategy { builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO); builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO); return new PhysicalMappingStrategy(builder.build(), nitsRange, brightnessRange, - autoBrightnessAdjustmentMaxGamma, mode, displayWhiteBalanceController); + autoBrightnessAdjustmentMaxGamma, mode, preset, displayWhiteBalanceController); } else if (isValidMapping(luxLevels, brightnessLevels)) { return new SimpleMappingStrategy(luxLevels, brightnessLevels, - autoBrightnessAdjustmentMaxGamma, shortTermModelTimeout, mode); + autoBrightnessAdjustmentMaxGamma, shortTermModelTimeout, mode, preset); } else { return null; } @@ -394,6 +394,12 @@ public abstract class BrightnessMappingStrategy { abstract int getMode(); /** + * @return The preset for this mapping strategy. Presets are used on devices that allow users + * to choose from a set of predefined options in display auto-brightness settings. + */ + abstract int getPreset(); + + /** * Check if the short term model should be reset given the anchor lux the last * brightness change was made at and the current ambient lux. */ @@ -598,6 +604,8 @@ public abstract class BrightnessMappingStrategy { @AutomaticBrightnessController.AutomaticBrightnessMode private final int mMode; + private final int mPreset; + private Spline mSpline; private float mMaxGamma; private float mAutoBrightnessAdjustment; @@ -606,7 +614,8 @@ public abstract class BrightnessMappingStrategy { private long mShortTermModelTimeout; private SimpleMappingStrategy(float[] lux, float[] brightness, float maxGamma, - long timeout, @AutomaticBrightnessController.AutomaticBrightnessMode int mode) { + long timeout, @AutomaticBrightnessController.AutomaticBrightnessMode int mode, + int preset) { Preconditions.checkArgument(lux.length != 0 && brightness.length != 0, "Lux and brightness arrays must not be empty!"); Preconditions.checkArgument(lux.length == brightness.length, @@ -633,6 +642,7 @@ public abstract class BrightnessMappingStrategy { computeSpline(); mShortTermModelTimeout = timeout; mMode = mode; + mPreset = preset; } @Override @@ -766,6 +776,11 @@ public abstract class BrightnessMappingStrategy { } @Override + int getPreset() { + return mPreset; + } + + @Override float getUserLux() { return mUserLux; } @@ -837,6 +852,8 @@ public abstract class BrightnessMappingStrategy { @AutomaticBrightnessController.AutomaticBrightnessMode private final int mMode; + private final int mPreset; + // Previous short-term models and the times that they were computed stored for debugging // purposes private List<Spline> mPreviousBrightnessSplines = new ArrayList<>(); @@ -846,7 +863,7 @@ public abstract class BrightnessMappingStrategy { public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits, float[] brightness, float maxGamma, - @AutomaticBrightnessController.AutomaticBrightnessMode int mode, + @AutomaticBrightnessController.AutomaticBrightnessMode int mode, int preset, @Nullable DisplayWhiteBalanceController displayWhiteBalanceController) { Preconditions.checkArgument(nits.length != 0 && brightness.length != 0, @@ -860,6 +877,7 @@ public abstract class BrightnessMappingStrategy { PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, "brightness"); mMode = mode; + mPreset = preset; mMaxGamma = maxGamma; mAutoBrightnessAdjustment = 0; mUserLux = INVALID_LUX; @@ -1073,6 +1091,11 @@ public abstract class BrightnessMappingStrategy { } @Override + int getPreset() { + return mPreset; + } + + @Override float getUserLux() { return mUserLux; } diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index ed6ed60a6806..cc115f13f5e3 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -588,22 +588,43 @@ import javax.xml.datatype.DatatypeConfigurationException; * <minorVersion>0</minorVersion> * </usiVersion> * <evenDimmer enabled="true"> - * <transitionPoint>0.1</transitionPoint> - * - * <nits>0.2</nits> - * <nits>2.0</nits> - * <nits>500.0</nits> - * <nits>1000.0</nits> - * - * <backlight>0</backlight> - * <backlight>0.0001</backlight> - * <backlight>0.5</backlight> - * <backlight>1.0</backlight> - * - * <brightness>0</brightness> - * <brightness>0.1</brightness> - * <brightness>0.5</brightness> - * <brightness>1.0</brightness> + * <transitionPoint>0.1</transitionPoint> + * <brightnessMapping> + * <brightnessPoint> + * <nits>0.2</nits> + * <backlight>0</backlight> + * <brightness>0</brightness> + * </brightnessPoint> + * <brightnessPoint> + * <nits>2.0</nits> + * <backlight>0.01</backlight> + * <brightness>0.002</brightness> + * </brightnessPoint> + * <brightnessPoint> + * <nits>500.0</nits> + * <backlight>0.5</backlight> + * <brightness>0.5</brightness> + * </brightnessPoint> + * <brightnessPoint> + * <nits>1000</nits> + * <backlight>1.0</backlight> + * <brightness>1.0</brightness> + * </brightnessPoint> + * </brightnessMapping> + * <luxToMinimumNitsMap> + * <point> + * <value>10</value> + * <nits>0.3</nits> + * </point> + * <point> + * <value>50</value> + * <nits>0.7</nits> + * </point> + * <point> + * <value>100</value> + * <nits>1.0</nits> + * </point> + * </luxToMinimumNitsMap> * </evenDimmer> * <screenBrightnessCapForWearBedtimeMode>0.1</screenBrightnessCapForWearBedtimeMode> * <idleScreenRefreshRateTimeout> diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 2cec869c290e..9e905abd78ed 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -722,6 +722,7 @@ public final class DisplayManagerService extends SystemService { if (userSwitching) { mCurrentUserId = newUserId; } + mDisplayModeDirector.onSwitchUser(); mLogicalDisplayMapper.forEachLocked(logicalDisplay -> { if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) { return; diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 1177be212222..4152fa005e94 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -702,6 +702,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private void handleOnSwitchUser(@UserIdInt int newUserId, int userSerial, float newBrightness) { Slog.i(mTag, "Switching user newUserId=" + newUserId + " userSerial=" + userSerial + " newBrightness=" + newBrightness); + + if (mAutomaticBrightnessController != null) { + int autoBrightnessPreset = Settings.System.getIntForUser(mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS_FOR_ALS, + Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_NORMAL, + UserHandle.USER_CURRENT); + if (autoBrightnessPreset != mAutomaticBrightnessController.getPreset()) { + setUpAutoBrightness(mContext, mHandler); + } + } + handleBrightnessModeChange(); if (mBrightnessTracker != null) { mBrightnessTracker.onSwitchUser(newUserId); @@ -714,6 +725,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (mAutomaticBrightnessController != null) { mAutomaticBrightnessController.resetShortTermModel(); } + mBrightnessClamperController.onUserSwitch(); sendUpdatePowerState(); } @@ -1009,7 +1021,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (mFlags.areAutoBrightnessModesEnabled()) { mContext.getContentResolver().registerContentObserver( Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_ALS), - /* notifyForDescendants= */ false, mSettingsObserver, UserHandle.USER_CURRENT); + /* notifyForDescendants= */ false, mSettingsObserver, UserHandle.USER_ALL); } handleBrightnessModeChange(); } diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java index 9324fc1c4e06..12c3197aba2a 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java @@ -71,6 +71,7 @@ public class BrightnessClamperController { private final List<DisplayDeviceDataListener> mDisplayDeviceDataListeners = new ArrayList<>(); private final List<StatefulModifier> mStatefulModifiers = new ArrayList<>(); + private final List<UserSwitchListener> mUserSwitchListeners = new ArrayList<>(); private ModifiersAggregatedState mModifiersAggregatedState = new ModifiersAggregatedState(); private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener; @@ -127,6 +128,9 @@ public class BrightnessClamperController { if (m instanceof StatefulModifier s) { mStatefulModifiers.add(s); } + if (m instanceof UserSwitchListener l) { + mUserSwitchListeners.add(l); + } }); mOnPropertiesChangedListener = properties -> mClampers.forEach(BrightnessClamper::onDeviceConfigChanged); @@ -209,6 +213,13 @@ public class BrightnessClamperController { } /** + * Called when the user switches. + */ + public void onUserSwitch() { + mUserSwitchListeners.forEach(listener -> listener.onSwitchUser()); + } + + /** * Used to dump ClampersController state. */ public void dump(PrintWriter writer) { @@ -466,6 +477,13 @@ public class BrightnessClamperController { } /** + * A clamper/modifier should implement this interface if it reads user-specific settings + */ + interface UserSwitchListener { + void onSwitchUser(); + } + + /** * StatefulModifiers contribute to AggregatedState, that is used to decide if brightness * adjustement is needed */ diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java index 951980adac8c..c3596c3e77fe 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessLowLuxModifier.java @@ -41,7 +41,8 @@ import java.io.PrintWriter; * Class used to prevent the screen brightness dipping below a certain value, based on current * lux conditions and user preferred minimum. */ -public class BrightnessLowLuxModifier extends BrightnessModifier { +public class BrightnessLowLuxModifier extends BrightnessModifier implements + BrightnessClamperController.UserSwitchListener { // To enable these logs, run: // 'adb shell setprop persist.log.tag.BrightnessLowLuxModifier DEBUG && adb reboot' @@ -81,10 +82,9 @@ public class BrightnessLowLuxModifier extends BrightnessModifier { */ @VisibleForTesting public void recalculateLowerBound() { - int userId = UserHandle.USER_CURRENT; float settingNitsLowerBound = Settings.Secure.getFloatForUser( mContentResolver, Settings.Secure.EVEN_DIMMER_MIN_NITS, - /* def= */ MIN_NITS_DEFAULT, userId); + /* def= */ MIN_NITS_DEFAULT, UserHandle.USER_CURRENT); boolean isActive = isSettingEnabled() && mAmbientLux != BrightnessMappingStrategy.INVALID_LUX; @@ -190,6 +190,11 @@ public class BrightnessLowLuxModifier extends BrightnessModifier { } @Override + public void onSwitchUser() { + recalculateLowerBound(); + } + + @Override public void dump(PrintWriter pw) { pw.println("BrightnessLowLuxModifier:"); pw.println(" mIsActive=" + mIsActive); @@ -221,10 +226,10 @@ public class BrightnessLowLuxModifier extends BrightnessModifier { super(handler); mContentResolver.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.EVEN_DIMMER_MIN_NITS), - false, this); + false, this, UserHandle.USER_ALL); mContentResolver.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.EVEN_DIMMER_ACTIVATED), - false, this); + false, this, UserHandle.USER_ALL); } @Override diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java index d610f086b3b5..5e471c82e108 100644 --- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java @@ -121,6 +121,7 @@ public class DisplayModeDirector { private static final int MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED = 6; private static final int MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED = 7; private static final int MSG_REFRESH_RATE_IN_HBM_HDR_CHANGED = 8; + private static final int MSG_SWITCH_USER = 9; private final Object mLock = new Object(); private final Context mContext; @@ -564,6 +565,13 @@ public class DisplayModeDirector { } /** + * Called when the user switches. + */ + public void onSwitchUser() { + mHandler.obtainMessage(MSG_SWITCH_USER).sendToTarget(); + } + + /** * Print the object's state and debug information into the given stream. * * @param pw The stream to dump information to. @@ -789,6 +797,13 @@ public class DisplayModeDirector { mHbmObserver.onDeviceConfigRefreshRateInHbmHdrChanged(refreshRateInHbmHdr); break; } + + case MSG_SWITCH_USER: { + synchronized (mLock) { + mSettingsObserver.updateRefreshRateSettingLocked(); + mSettingsObserver.updateModeSwitchingTypeSettingLocked(); + } + } } } } @@ -1012,10 +1027,10 @@ public class DisplayModeDirector { final ContentResolver cr = mContext.getContentResolver(); mInjector.registerPeakRefreshRateObserver(cr, this); mInjector.registerMinRefreshRateObserver(cr, this); - cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this, - UserHandle.USER_SYSTEM); - cr.registerContentObserver(mMatchContentFrameRateSetting, false /*notifyDescendants*/, - this); + cr.registerContentObserver(mLowPowerModeSetting, /* notifyDescendants= */ false, this, + UserHandle.USER_ALL); + cr.registerContentObserver(mMatchContentFrameRateSetting, + /* notifyDescendants= */ false, this, UserHandle.USER_ALL); mInjector.registerDisplayListener(mDisplayListener, mHandler); float deviceConfigDefaultPeakRefresh = @@ -1156,14 +1171,15 @@ public class DisplayModeDirector { float highestRefreshRate = getMaxRefreshRateLocked(displayId); float minRefreshRate = Settings.System.getFloatForUser(cr, - Settings.System.MIN_REFRESH_RATE, 0f, cr.getUserId()); + Settings.System.MIN_REFRESH_RATE, 0f, UserHandle.USER_CURRENT); if (Float.isInfinite(minRefreshRate)) { // Infinity means that we want the highest possible refresh rate minRefreshRate = highestRefreshRate; } float peakRefreshRate = Settings.System.getFloatForUser(cr, - Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate, cr.getUserId()); + Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate, + UserHandle.USER_CURRENT); if (Float.isInfinite(peakRefreshRate)) { // Infinity means that we want the highest possible refresh rate peakRefreshRate = highestRefreshRate; @@ -1234,9 +1250,9 @@ public class DisplayModeDirector { private void updateModeSwitchingTypeSettingLocked() { final ContentResolver cr = mContext.getContentResolver(); - int switchingType = Settings.Secure.getIntForUser( - cr, Settings.Secure.MATCH_CONTENT_FRAME_RATE, mModeSwitchingType /*default*/, - cr.getUserId()); + int switchingType = Settings.Secure.getIntForUser(cr, + Settings.Secure.MATCH_CONTENT_FRAME_RATE, /* default= */ mModeSwitchingType, + UserHandle.USER_CURRENT); if (switchingType != mModeSwitchingType) { mModeSwitchingType = switchingType; notifyDesiredDisplayModeSpecsChangedLocked(); @@ -3033,14 +3049,14 @@ public class DisplayModeDirector { public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, @NonNull ContentObserver observer) { cr.registerContentObserver(PEAK_REFRESH_RATE_URI, false /*notifyDescendants*/, - observer, UserHandle.USER_SYSTEM); + observer, UserHandle.USER_ALL); } @Override public void registerMinRefreshRateObserver(@NonNull ContentResolver cr, @NonNull ContentObserver observer) { cr.registerContentObserver(MIN_REFRESH_RATE_URI, false /*notifyDescendants*/, - observer, UserHandle.USER_SYSTEM); + observer, UserHandle.USER_ALL); } @Override diff --git a/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java index fb73aff44c64..f3cd0c960fca 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java @@ -693,6 +693,21 @@ public class BrightnessMappingStrategyTest { } @Test + public void testGetPreset() { + int preset = Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_DIM; + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS_FOR_ALS, preset); + setUpResources(); + DisplayDeviceConfig ddc = new DdcBuilder() + .setAutoBrightnessLevels(AUTO_BRIGHTNESS_MODE_DEFAULT, preset, DISPLAY_LEVELS) + .setAutoBrightnessLevelsLux(AUTO_BRIGHTNESS_MODE_DEFAULT, preset, LUX_LEVELS) + .build(); + BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(mContext, ddc, + AUTO_BRIGHTNESS_MODE_DEFAULT, /* displayWhiteBalanceController= */ null); + assertEquals(preset, strategy.getPreset()); + } + + @Test public void testAutoBrightnessModeAndPreset() { int mode = AUTO_BRIGHTNESS_MODE_DOZE; int preset = Settings.System.SCREEN_BRIGHTNESS_AUTOMATIC_DIM; diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt index d672435096b9..6929690baaf8 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessLowLuxModifierTest.kt @@ -225,5 +225,37 @@ class BrightnessLowLuxModifierTest { assertThat(modifier.brightnessReason).isEqualTo(BrightnessReason.MODIFIER_MIN_LUX) assertThat(modifier.brightnessLowerBound).isEqualTo(LOW_LUX_BRIGHTNESS) } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_EVEN_DIMMER) + fun testUserSwitch() { + // nits: 0.5 -> backlight 0.01 -> brightness -> 0.05 + whenever(mockDisplayDeviceConfig.getBacklightFromNits(/* nits= */ 0.5f)) + .thenReturn(0.01f) + whenever(mockDisplayDeviceConfig.getBrightnessFromBacklight(/* backlight = */ 0.01f)) + .thenReturn(0.05f) + + Settings.Secure.putIntForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_ACTIVATED, 0, USER_ID) // off + Settings.Secure.putFloatForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_MIN_NITS, 1.0f, USER_ID) + + modifier.recalculateLowerBound() + + assertThat(modifier.isActive).isFalse() + assertThat(modifier.brightnessLowerBound).isEqualTo(TRANSITION_POINT) + assertThat(modifier.brightnessReason).isEqualTo(0) // no reason - i.e. off + + Settings.Secure.putIntForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_ACTIVATED, 1, USER_ID) // on + Settings.Secure.putFloatForUser(context.contentResolver, + Settings.Secure.EVEN_DIMMER_MIN_NITS, 0.5f, USER_ID) + modifier.onSwitchUser() + + assertThat(modifier.isActive).isTrue() + assertThat(modifier.brightnessReason).isEqualTo( + BrightnessReason.MODIFIER_MIN_USER_SET_LOWER_BOUND) + assertThat(modifier.brightnessLowerBound).isEqualTo(0.05f) + } } diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java index 242d5593c3c8..62400ebed149 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java @@ -1088,6 +1088,21 @@ public class DisplayModeDirectorTest { } @Test + public void testModeSwitching_UserSwitch() { + DisplayModeDirector director = createDirectorFromFpsRange(0, 90); + assertThat(director.getModeSwitchingType()).isEqualTo( + DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS); + + int newModeSwitchingType = DisplayManager.SWITCHING_TYPE_NONE; + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.MATCH_CONTENT_FRAME_RATE, newModeSwitchingType); + director.onSwitchUser(); + waitForIdleSync(); + + assertThat(director.getModeSwitchingType()).isEqualTo(newModeSwitchingType); + } + + @Test public void testDefaultDisplayModeIsSelectedIfAvailable() { final float[] refreshRates = new float[]{24f, 25f, 30f, 60f, 90f}; final int defaultModeId = 3; @@ -1883,6 +1898,62 @@ public class DisplayModeDirectorTest { } @Test + public void testPeakRefreshRate_UserSwitch() { + when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled()) + .thenReturn(true); + DisplayModeDirector director = + new DisplayModeDirector(mContext, mHandler, mInjector, + mDisplayManagerFlags, mDisplayDeviceConfigProvider); + director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); + + Display.Mode[] modes1 = new Display.Mode[] { + new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 60), + new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 130), + }; + Display.Mode[] modes2 = new Display.Mode[] { + new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 60), + new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 140), + }; + SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>(); + supportedModesByDisplay.put(DISPLAY_ID, modes1); + supportedModesByDisplay.put(DISPLAY_ID_2, modes2); + + Sensor lightSensor = createLightSensor(); + SensorManager sensorManager = createMockSensorManager(lightSensor); + director.start(sensorManager); + director.injectSupportedModesByDisplay(supportedModesByDisplay); + + // Disable Smooth Display + setPeakRefreshRate(RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE); + + Vote vote1 = director.getVote(DISPLAY_ID, + Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE); + Vote vote2 = director.getVote(DISPLAY_ID_2, + Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote1, /* frameRateLow= */ 0, + /* frameRateHigh= */ RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE); + assertVoteForRenderFrameRateRange(vote2, /* frameRateLow= */ 0, + /* frameRateHigh= */ RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE); + + // Switch user to one that has Smooth Display Enabled + Settings.System.putFloat(mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE, + Float.POSITIVE_INFINITY); + director.onSwitchUser(); + waitForIdleSync(); + + vote1 = director.getVote(DISPLAY_ID, + Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE); + vote2 = director.getVote(DISPLAY_ID_2, + Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote1, /* frameRateLow= */ 0, /* frameRateHigh= */ 130); + assertVoteForRenderFrameRateRange(vote2, /* frameRateLow= */ 0, /* frameRateHigh= */ 140); + } + + @Test @Parameters({ "true, true, 60", "false, true, 50", @@ -2036,6 +2107,62 @@ public class DisplayModeDirectorTest { } @Test + public void testMinRefreshRate_UserSwitch() { + when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled()) + .thenReturn(true); + DisplayModeDirector director = + new DisplayModeDirector(mContext, mHandler, mInjector, + mDisplayManagerFlags, mDisplayDeviceConfigProvider); + director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); + + Display.Mode[] modes1 = new Display.Mode[] { + new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 60), + new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 130), + }; + Display.Mode[] modes2 = new Display.Mode[] { + new Display.Mode(/* modeId= */ 1, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 60), + new Display.Mode(/* modeId= */ 2, /* width= */ 1280, /* height= */ 720, + /* refreshRate= */ 140), + }; + SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>(); + supportedModesByDisplay.put(DISPLAY_ID, modes1); + supportedModesByDisplay.put(DISPLAY_ID_2, modes2); + + Sensor lightSensor = createLightSensor(); + SensorManager sensorManager = createMockSensorManager(lightSensor); + director.start(sensorManager); + director.injectSupportedModesByDisplay(supportedModesByDisplay); + + // Disable Force Peak Refresh Rate + setMinRefreshRate(0); + + Vote vote1 = director.getVote(DISPLAY_ID, Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE); + Vote vote2 = director.getVote(DISPLAY_ID_2, + Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote1, /* frameRateLow= */ 0, + /* frameRateHigh= */ Float.POSITIVE_INFINITY); + assertVoteForRenderFrameRateRange(vote2, /* frameRateLow= */ 0, + /* frameRateHigh= */ Float.POSITIVE_INFINITY); + + // Switch user to one that has Force Peak Refresh Rate enabled + Settings.System.putFloat(mContext.getContentResolver(), Settings.System.MIN_REFRESH_RATE, + Float.POSITIVE_INFINITY); + director.onSwitchUser(); + waitForIdleSync(); + + vote1 = director.getVote(DISPLAY_ID, Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE); + vote2 = director.getVote(DISPLAY_ID_2, + Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote1, /* frameRateLow= */ 130, + /* frameRateHigh= */ Float.POSITIVE_INFINITY); + assertVoteForRenderFrameRateRange(vote2, /* frameRateLow= */ 140, + /* frameRateHigh= */ Float.POSITIVE_INFINITY); + } + + @Test public void testPeakAndMinRefreshRate_FlagEnabled_DisplayWithOneMode() { when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled()) .thenReturn(true); |