Loading services/core/java/com/android/server/display/AutomaticBrightnessController.java +0 −1 Original line number Diff line number Diff line Loading @@ -778,7 +778,6 @@ class AutomaticBrightnessController { mScreenBrightnessThresholds.getBrighteningThreshold(newScreenAutoBrightness)); mScreenDarkeningThreshold = clampScreenBrightness( mScreenBrightnessThresholds.getDarkeningThreshold(newScreenAutoBrightness)); mHbmController.onAutoBrightnessChanged(mScreenAutoBrightness); if (sendUpdate) { mCallbacks.updateBrightness(); Loading services/core/java/com/android/server/display/DisplayManagerService.java +5 −5 Original line number Diff line number Diff line Loading @@ -1281,6 +1281,11 @@ public final class DisplayManagerService extends SystemService { sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); scheduleTraversalLocked(false); mPersistentDataStore.saveIfNeeded(); DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); if (dpc != null) { dpc.onDisplayChanged(); } } private void handleLogicalDisplayFrameRateOverridesChangedLocked( Loading Loading @@ -1312,11 +1317,6 @@ public final class DisplayManagerService extends SystemService { if (work != null) { mHandler.post(work); } final int displayId = display.getDisplayIdLocked(); DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); if (dpc != null) { dpc.onDisplayChanged(); } handleLogicalDisplayChangedLocked(display); } Loading services/core/java/com/android/server/display/DisplayPowerController.java +14 −10 Original line number Diff line number Diff line Loading @@ -511,7 +511,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mSkipScreenOnBrightnessRamp = resources.getBoolean( com.android.internal.R.bool.config_skipScreenOnBrightnessRamp); mHbmController = createHbmController(); mHbmController = createHbmControllerLocked(); // Seed the cached brightness saveBrightnessInfo(getScreenBrightnessSetting()); Loading Loading @@ -717,6 +717,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call final String uniqueId = device.getUniqueId(); final DisplayDeviceConfig config = device.getDisplayDeviceConfig(); final IBinder token = device.getDisplayTokenLocked(); final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); mHandler.post(() -> { if (mDisplayDevice == device) { return; Loading @@ -724,7 +725,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mDisplayDevice = device; mUniqueDisplayId = uniqueId; mDisplayDeviceConfig = config; loadFromDisplayDeviceConfig(token); loadFromDisplayDeviceConfig(token, info); }); } Loading Loading @@ -765,7 +766,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } private void loadFromDisplayDeviceConfig(IBinder token) { private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info) { // All properties that depend on the associated DisplayDevice and the DDC must be // updated here. loadAmbientLightSensor(); Loading @@ -774,7 +775,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call loadNitsRange(mContext.getResources()); setUpAutoBrightness(mContext.getResources(), mHandler); reloadReduceBrightColours(); mHbmController.resetHbmData(token, mDisplayDeviceConfig.getHighBrightnessModeData()); mHbmController.resetHbmData(info.width, info.height, token, mDisplayDeviceConfig.getHighBrightnessModeData(), mBrightnessSetting); } private void sendUpdatePowerState() { Loading Loading @@ -1343,6 +1345,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR && ((mBrightnessReason.modifier & BrightnessReason.MODIFIER_DIMMED) == 0 || (mBrightnessReason.modifier & BrightnessReason.MODIFIER_LOW_POWER) == 0)) { // We want to scale HDR brightness level with the SDR level animateValue = mHbmController.getHdrBrightnessValue(); } Loading Loading @@ -1514,21 +1517,22 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } private HighBrightnessModeController createHbmController() { final DisplayDeviceConfig ddConfig = mLogicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig(); private HighBrightnessModeController createHbmControllerLocked() { final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked(); final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig(); final IBinder displayToken = mLogicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayTokenLocked(); final DisplayDeviceConfig.HighBrightnessModeData hbmData = ddConfig != null ? ddConfig.getHighBrightnessModeData() : null; return new HighBrightnessModeController(mHandler, displayToken, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, hbmData, final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); return new HighBrightnessModeController(mHandler, info.width, info.height, displayToken, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, hbmData, () -> { sendUpdatePowerStateLocked(); mHandler.post(mOnBrightnessChangeRunnable); // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern. mAutomaticBrightnessController.update(); }, mContext); }, mContext, mBrightnessSetting); } private void blockScreenOn() { Loading services/core/java/com/android/server/display/HighBrightnessModeController.java +80 −34 Original line number Diff line number Diff line Loading @@ -31,11 +31,13 @@ import android.os.SystemClock; import android.os.Temperature; import android.os.UserHandle; import android.provider.Settings; import android.util.MathUtils; import android.util.Slog; import android.util.TimeUtils; import android.view.SurfaceControlHdrLayerInfoListener; import com.android.internal.annotations.VisibleForTesting; import com.android.server.display.BrightnessSetting.BrightnessSettingListener; import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData; import com.android.server.display.DisplayManagerService.Clock; Loading @@ -56,6 +58,8 @@ class HighBrightnessModeController { private static final boolean DEBUG = false; private static final float HDR_PERCENT_OF_SCREEN_REQUIRED = 0.50f; private final float mBrightnessMin; private final float mBrightnessMax; private final Handler mHandler; Loading @@ -66,6 +70,7 @@ class HighBrightnessModeController { private final Context mContext; private final SettingsObserver mSettingsObserver; private final Injector mInjector; private final BrightnessSettingListener mBrightnessSettingListener = this::onBrightnessChanged; private SurfaceControlHdrLayerInfoListener mHdrListener; private HighBrightnessModeData mHbmData; Loading @@ -74,11 +79,15 @@ class HighBrightnessModeController { private boolean mIsInAllowedAmbientRange = false; private boolean mIsTimeAvailable = false; private boolean mIsAutoBrightnessEnabled = false; private float mAutoBrightness; private float mBrightness; private int mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF; private boolean mIsHdrLayerPresent = false; private boolean mIsThermalStatusWithinLimit = true; private boolean mIsBlockedByLowPowerMode = false; private int mWidth; private int mHeight; private BrightnessSetting mBrightnessSetting; private float mAmbientLux; /** * If HBM is currently running, this is the start time for the current HBM session. Loading @@ -92,30 +101,32 @@ class HighBrightnessModeController { */ private LinkedList<HbmEvent> mEvents = new LinkedList<>(); HighBrightnessModeController(Handler handler, IBinder displayToken, float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback, Context context) { this(new Injector(), handler, displayToken, brightnessMin, brightnessMax, hbmData, hbmChangeCallback, context); HighBrightnessModeController(Handler handler, int width, int height, IBinder displayToken, float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback, Context context, BrightnessSetting brightnessSetting) { this(new Injector(), handler, width, height, displayToken, brightnessMin, brightnessMax, hbmData, hbmChangeCallback, context, brightnessSetting); } @VisibleForTesting HighBrightnessModeController(Injector injector, Handler handler, IBinder displayToken, float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback, Context context) { HighBrightnessModeController(Injector injector, Handler handler, int width, int height, IBinder displayToken, float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback, Context context, BrightnessSetting brightnessSetting) { mInjector = injector; mContext = context; mClock = injector.getClock(); mHandler = handler; mBrightnessMin = brightnessMin; mBrightnessMax = brightnessMax; mBrightness = brightnessSetting.getBrightness(); mHbmChangeCallback = hbmChangeCallback; mContext = context; mAutoBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT; mRecalcRunnable = this::recalculateTimeAllowance; mHdrListener = new HdrListener(); mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler); mSettingsObserver = new SettingsObserver(mHandler); resetHbmData(displayToken, hbmData); mRecalcRunnable = this::recalculateTimeAllowance; mHdrListener = new HdrListener(); resetHbmData(width, height, displayToken, hbmData, brightnessSetting); } void setAutoBrightnessEnabled(boolean isEnabled) { Loading @@ -123,7 +134,7 @@ class HighBrightnessModeController { return; } if (DEBUG) { Slog.d(TAG, "setAutoBrightness( " + isEnabled + " )"); Slog.d(TAG, "setAutoBrightnessEnabled( " + isEnabled + " )"); } mIsAutoBrightnessEnabled = isEnabled; mIsInAllowedAmbientRange = false; // reset when auto-brightness switches Loading @@ -147,11 +158,22 @@ class HighBrightnessModeController { } } float getNormalBrightnessMax() { return deviceSupportsHbm() ? mHbmData.transitionPoint : mBrightnessMax; } float getHdrBrightnessValue() { return mBrightnessMax; // For HDR brightness, we take the current brightness and scale it to the max. The reason // we do this is because we want brightness to go to HBM max when it would normally go // to normal max, meaning it should not wait to go to 10000 lux (or whatever the transition // point happens to be) in order to go full HDR. Likewise, HDR on manual brightness should // automatically scale the brightness without forcing the user to adjust to higher values. return MathUtils.map(getCurrentBrightnessMin(), getCurrentBrightnessMax(), mBrightnessMin, mBrightnessMax, mBrightness); } void onAmbientLuxChange(float ambientLux) { mAmbientLux = ambientLux; if (!deviceSupportsHbm() || !mIsAutoBrightnessEnabled) { return; } Loading @@ -163,17 +185,17 @@ class HighBrightnessModeController { } } void onAutoBrightnessChanged(float autoBrightness) { @VisibleForTesting void onBrightnessChanged(float brightness) { if (!deviceSupportsHbm()) { return; } final float oldAutoBrightness = mAutoBrightness; mAutoBrightness = autoBrightness; mBrightness = brightness; // If we are starting or ending a high brightness mode session, store the current // session in mRunningStartTimeMillis, or the old one in mEvents. final boolean wasHbmDrainingAvailableTime = mRunningStartTimeMillis != -1; final boolean shouldHbmDrainAvailableTime = mAutoBrightness > mHbmData.transitionPoint final boolean shouldHbmDrainAvailableTime = mBrightness > mHbmData.transitionPoint && !mIsHdrLayerPresent; if (wasHbmDrainingAvailableTime != shouldHbmDrainAvailableTime) { final long currentTime = mClock.uptimeMillis(); Loading Loading @@ -202,8 +224,12 @@ class HighBrightnessModeController { mSettingsObserver.stopObserving(); } void resetHbmData(IBinder displayToken, HighBrightnessModeData hbmData) { void resetHbmData(int width, int height, IBinder displayToken, HighBrightnessModeData hbmData, BrightnessSetting brightnessSetting) { mWidth = width; mHeight = height; mHbmData = hbmData; resetBrightnessSetting(brightnessSetting); unregisterHdrListener(); mSkinThermalStatusObserver.stopObserving(); mSettingsObserver.stopObserving(); Loading @@ -227,21 +253,23 @@ class HighBrightnessModeController { private void dumpLocal(PrintWriter pw) { pw.println("HighBrightnessModeController:"); pw.println(" mBrightness=" + mBrightness); pw.println(" mCurrentMin=" + getCurrentBrightnessMin()); pw.println(" mCurrentMax=" + getCurrentBrightnessMax()); pw.println(" mHbmMode=" + BrightnessInfo.hbmToString(mHbmMode)); pw.println(" remainingTime=" + calculateRemainingTime(mClock.uptimeMillis())); pw.println(" mHbmData=" + mHbmData); pw.println(" mAmbientLux=" + mAmbientLux); pw.println(" mIsInAllowedAmbientRange=" + mIsInAllowedAmbientRange); pw.println(" mIsTimeAvailable= " + mIsTimeAvailable); pw.println(" mIsAutoBrightnessEnabled=" + mIsAutoBrightnessEnabled); pw.println(" mAutoBrightness=" + mAutoBrightness); pw.println(" mIsHdrLayerPresent=" + mIsHdrLayerPresent); pw.println(" mBrightnessMin=" + mBrightnessMin); pw.println(" mBrightnessMax=" + mBrightnessMax); pw.println(" remainingTime=" + calculateRemainingTime(mClock.uptimeMillis())); pw.println(" mIsTimeAvailable= " + mIsTimeAvailable); pw.println(" mRunningStartTimeMillis=" + TimeUtils.formatUptime(mRunningStartTimeMillis)); pw.println(" mIsThermalStatusWithinLimit=" + mIsThermalStatusWithinLimit); pw.println(" mIsBlockedByLowPowerMode=" + mIsBlockedByLowPowerMode); pw.println(" width*height=" + mWidth + "*" + mHeight); pw.println(" mEvents="); final long currentTime = mClock.uptimeMillis(); long lastStartTime = currentTime; Loading @@ -268,9 +296,26 @@ class HighBrightnessModeController { return event.startTimeMillis; } private void resetBrightnessSetting(BrightnessSetting brightnessSetting) { if (mBrightnessSetting != null) { mBrightnessSetting.unregisterListener(mBrightnessSettingListener); } mBrightnessSetting = brightnessSetting; if (mBrightnessSetting != null) { mBrightnessSetting.registerListener(mBrightnessSettingListener); } } private boolean isCurrentlyAllowed() { return mIsHdrLayerPresent || (mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange // Returns true if HBM is allowed (above the ambient lux threshold) and there's still // time within the current window for additional HBM usage. We return false if there is an // HDR layer because we don't want the brightness MAX to change for HDR, which has its // brightness scaled in a different way than sunlight HBM that doesn't require changing // the MAX. HDR also needs to work under manual brightness which never adjusts the // brightness maximum; so we implement HDR-HBM in a way that doesn't adjust the max. // See {@link #getHdrBrightnessValue}. return !mIsHdrLayerPresent && (mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange && mIsThermalStatusWithinLimit && !mIsBlockedByLowPowerMode); } Loading Loading @@ -334,13 +379,13 @@ class HighBrightnessModeController { // or if brightness is already in the high range, if there is any time left at all. final boolean isAllowedWithoutRestrictions = remainingTime >= mHbmData.timeMinMillis; final boolean isOnlyAllowedToStayOn = !isAllowedWithoutRestrictions && remainingTime > 0 && mAutoBrightness > mHbmData.transitionPoint; && remainingTime > 0 && mBrightness > mHbmData.transitionPoint; mIsTimeAvailable = isAllowedWithoutRestrictions || isOnlyAllowedToStayOn; // Calculate the time at which we want to recalculate mIsTimeAvailable in case a lux or // brightness change doesn't happen before then. long nextTimeout = -1; if (mAutoBrightness > mHbmData.transitionPoint) { if (mBrightness > mHbmData.transitionPoint) { // if we're in high-lux now, timeout when we run out of allowed time. nextTimeout = currentTime + remainingTime; } else if (!mIsTimeAvailable && mEvents.size() > 0) { Loading Loading @@ -370,7 +415,7 @@ class HighBrightnessModeController { + ", mIsInAllowedAmbientRange: " + mIsInAllowedAmbientRange + ", mIsThermalStatusWithinLimit: " + mIsThermalStatusWithinLimit + ", mIsBlockedByLowPowerMode: " + mIsBlockedByLowPowerMode + ", brightness: " + mAutoBrightness + ", mBrightness: " + mBrightness + ", RunningStartTimeMillis: " + mRunningStartTimeMillis + ", nextTimeout: " + (nextTimeout != -1 ? (nextTimeout - currentTime) : -1) + ", events: " + mEvents); Loading Loading @@ -447,11 +492,12 @@ class HighBrightnessModeController { public void onHdrInfoChanged(IBinder displayToken, int numberOfHdrLayers, int maxW, int maxH, int flags) { mHandler.post(() -> { mIsHdrLayerPresent = numberOfHdrLayers > 0; // Calling the auto-brightness update so that we can recalculate // auto-brightness with HDR in mind. When HDR layers are present, // we don't limit auto-brightness' HBM time limits. onAutoBrightnessChanged(mAutoBrightness); mIsHdrLayerPresent = numberOfHdrLayers > 0 && (float) (maxW * maxH) >= ((float) (mWidth * mHeight) * HDR_PERCENT_OF_SCREEN_REQUIRED); // Calling the brightness update so that we can recalculate // brightness with HDR in mind. onBrightnessChanged(mBrightness); }); } } Loading services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java +22 −14 Original line number Diff line number Diff line Loading @@ -74,6 +74,9 @@ public class HighBrightnessModeControllerTest { private static final float DEFAULT_MIN = 0.01f; private static final float DEFAULT_MAX = 0.80f; private static final int DISPLAY_WIDTH = 900; private static final int DISPLAY_HEIGHT = 1600; private static final float EPSILON = 0.000001f; private OffsettableClock mClock; Loading @@ -90,6 +93,8 @@ public class HighBrightnessModeControllerTest { @Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor; @Mock private BrightnessSetting mBrightnessSetting; private static final HighBrightnessModeData DEFAULT_HBM_DATA = new HighBrightnessModeData(MINIMUM_LUX, TRANSITION_POINT, TIME_WINDOW_MILLIS, TIME_ALLOWED_IN_WINDOW_MILLIS, TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS, Loading @@ -98,6 +103,8 @@ public class HighBrightnessModeControllerTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); mClock = new OffsettableClock.Stopped(); mTestLooper = new TestLooper(mClock::now); mDisplayToken = null; mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext())); final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContextSpy); Loading @@ -114,8 +121,8 @@ public class HighBrightnessModeControllerTest { public void testNoHbmData() { initHandler(null); final HighBrightnessModeController hbmc = new HighBrightnessModeController( mInjectorMock, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {}, mContextSpy); mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {}, mContextSpy, mBrightnessSetting); assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF); } Loading @@ -123,8 +130,8 @@ public class HighBrightnessModeControllerTest { public void testNoHbmData_Enabled() { initHandler(null); final HighBrightnessModeController hbmc = new HighBrightnessModeController( mInjectorMock, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {}, mContextSpy); mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {}, mContextSpy, mBrightnessSetting); hbmc.setAutoBrightnessEnabled(true); hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF); Loading Loading @@ -180,7 +187,7 @@ public class HighBrightnessModeControllerTest { hbmc.setAutoBrightnessEnabled(true); hbmc.onAmbientLuxChange(MINIMUM_LUX + 1); hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f); hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f); // Verify we are in HBM assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); Loading Loading @@ -212,7 +219,7 @@ public class HighBrightnessModeControllerTest { hbmc.setAutoBrightnessEnabled(true); hbmc.onAmbientLuxChange(MINIMUM_LUX + 1); hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f); hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f); // Verify we are in HBM assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); Loading @@ -237,18 +244,18 @@ public class HighBrightnessModeControllerTest { hbmc.setAutoBrightnessEnabled(true); hbmc.onAmbientLuxChange(MINIMUM_LUX + 1); hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f); hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f); advanceTime(TIME_ALLOWED_IN_WINDOW_MILLIS / 2); // Verify we are in HBM assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); hbmc.onAutoBrightnessChanged(TRANSITION_POINT - 0.01f); hbmc.onBrightnessChanged(TRANSITION_POINT - 0.01f); advanceTime(1); assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f); hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f); advanceTime(TIME_ALLOWED_IN_WINDOW_MILLIS / 2); assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); Loading @@ -267,13 +274,13 @@ public class HighBrightnessModeControllerTest { hbmc.onAmbientLuxChange(MINIMUM_LUX + 1); // Go into HBM for half the allowed window hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f); hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f); advanceTime(TIME_ALLOWED_IN_WINDOW_MILLIS / 2); assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); // Move lux below threshold (ending first event); hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); hbmc.onAutoBrightnessChanged(TRANSITION_POINT); hbmc.onBrightnessChanged(TRANSITION_POINT); assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF); // Move up some amount of time so that there's still time in the window even after a Loading @@ -283,7 +290,7 @@ public class HighBrightnessModeControllerTest { // Go into HBM for just under the second half of allowed window hbmc.onAmbientLuxChange(MINIMUM_LUX + 1); hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 1); hbmc.onBrightnessChanged(TRANSITION_POINT + 1); advanceTime((TIME_ALLOWED_IN_WINDOW_MILLIS / 2) - 1); assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); Loading Loading @@ -355,8 +362,9 @@ public class HighBrightnessModeControllerTest { // Creates instance with standard initialization values. private HighBrightnessModeController createDefaultHbm(OffsettableClock clock) { initHandler(clock); return new HighBrightnessModeController(mInjectorMock, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, DEFAULT_HBM_DATA, () -> {}, mContextSpy); return new HighBrightnessModeController(mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, DEFAULT_HBM_DATA, () -> {}, mContextSpy, mBrightnessSetting); } private void initHandler(OffsettableClock clock) { Loading Loading
services/core/java/com/android/server/display/AutomaticBrightnessController.java +0 −1 Original line number Diff line number Diff line Loading @@ -778,7 +778,6 @@ class AutomaticBrightnessController { mScreenBrightnessThresholds.getBrighteningThreshold(newScreenAutoBrightness)); mScreenDarkeningThreshold = clampScreenBrightness( mScreenBrightnessThresholds.getDarkeningThreshold(newScreenAutoBrightness)); mHbmController.onAutoBrightnessChanged(mScreenAutoBrightness); if (sendUpdate) { mCallbacks.updateBrightness(); Loading
services/core/java/com/android/server/display/DisplayManagerService.java +5 −5 Original line number Diff line number Diff line Loading @@ -1281,6 +1281,11 @@ public final class DisplayManagerService extends SystemService { sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); scheduleTraversalLocked(false); mPersistentDataStore.saveIfNeeded(); DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); if (dpc != null) { dpc.onDisplayChanged(); } } private void handleLogicalDisplayFrameRateOverridesChangedLocked( Loading Loading @@ -1312,11 +1317,6 @@ public final class DisplayManagerService extends SystemService { if (work != null) { mHandler.post(work); } final int displayId = display.getDisplayIdLocked(); DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); if (dpc != null) { dpc.onDisplayChanged(); } handleLogicalDisplayChangedLocked(display); } Loading
services/core/java/com/android/server/display/DisplayPowerController.java +14 −10 Original line number Diff line number Diff line Loading @@ -511,7 +511,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mSkipScreenOnBrightnessRamp = resources.getBoolean( com.android.internal.R.bool.config_skipScreenOnBrightnessRamp); mHbmController = createHbmController(); mHbmController = createHbmControllerLocked(); // Seed the cached brightness saveBrightnessInfo(getScreenBrightnessSetting()); Loading Loading @@ -717,6 +717,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call final String uniqueId = device.getUniqueId(); final DisplayDeviceConfig config = device.getDisplayDeviceConfig(); final IBinder token = device.getDisplayTokenLocked(); final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); mHandler.post(() -> { if (mDisplayDevice == device) { return; Loading @@ -724,7 +725,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mDisplayDevice = device; mUniqueDisplayId = uniqueId; mDisplayDeviceConfig = config; loadFromDisplayDeviceConfig(token); loadFromDisplayDeviceConfig(token, info); }); } Loading Loading @@ -765,7 +766,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } private void loadFromDisplayDeviceConfig(IBinder token) { private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info) { // All properties that depend on the associated DisplayDevice and the DDC must be // updated here. loadAmbientLightSensor(); Loading @@ -774,7 +775,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call loadNitsRange(mContext.getResources()); setUpAutoBrightness(mContext.getResources(), mHandler); reloadReduceBrightColours(); mHbmController.resetHbmData(token, mDisplayDeviceConfig.getHighBrightnessModeData()); mHbmController.resetHbmData(info.width, info.height, token, mDisplayDeviceConfig.getHighBrightnessModeData(), mBrightnessSetting); } private void sendUpdatePowerState() { Loading Loading @@ -1343,6 +1345,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR && ((mBrightnessReason.modifier & BrightnessReason.MODIFIER_DIMMED) == 0 || (mBrightnessReason.modifier & BrightnessReason.MODIFIER_LOW_POWER) == 0)) { // We want to scale HDR brightness level with the SDR level animateValue = mHbmController.getHdrBrightnessValue(); } Loading Loading @@ -1514,21 +1517,22 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } private HighBrightnessModeController createHbmController() { final DisplayDeviceConfig ddConfig = mLogicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig(); private HighBrightnessModeController createHbmControllerLocked() { final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked(); final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig(); final IBinder displayToken = mLogicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayTokenLocked(); final DisplayDeviceConfig.HighBrightnessModeData hbmData = ddConfig != null ? ddConfig.getHighBrightnessModeData() : null; return new HighBrightnessModeController(mHandler, displayToken, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, hbmData, final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); return new HighBrightnessModeController(mHandler, info.width, info.height, displayToken, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, hbmData, () -> { sendUpdatePowerStateLocked(); mHandler.post(mOnBrightnessChangeRunnable); // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern. mAutomaticBrightnessController.update(); }, mContext); }, mContext, mBrightnessSetting); } private void blockScreenOn() { Loading
services/core/java/com/android/server/display/HighBrightnessModeController.java +80 −34 Original line number Diff line number Diff line Loading @@ -31,11 +31,13 @@ import android.os.SystemClock; import android.os.Temperature; import android.os.UserHandle; import android.provider.Settings; import android.util.MathUtils; import android.util.Slog; import android.util.TimeUtils; import android.view.SurfaceControlHdrLayerInfoListener; import com.android.internal.annotations.VisibleForTesting; import com.android.server.display.BrightnessSetting.BrightnessSettingListener; import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData; import com.android.server.display.DisplayManagerService.Clock; Loading @@ -56,6 +58,8 @@ class HighBrightnessModeController { private static final boolean DEBUG = false; private static final float HDR_PERCENT_OF_SCREEN_REQUIRED = 0.50f; private final float mBrightnessMin; private final float mBrightnessMax; private final Handler mHandler; Loading @@ -66,6 +70,7 @@ class HighBrightnessModeController { private final Context mContext; private final SettingsObserver mSettingsObserver; private final Injector mInjector; private final BrightnessSettingListener mBrightnessSettingListener = this::onBrightnessChanged; private SurfaceControlHdrLayerInfoListener mHdrListener; private HighBrightnessModeData mHbmData; Loading @@ -74,11 +79,15 @@ class HighBrightnessModeController { private boolean mIsInAllowedAmbientRange = false; private boolean mIsTimeAvailable = false; private boolean mIsAutoBrightnessEnabled = false; private float mAutoBrightness; private float mBrightness; private int mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF; private boolean mIsHdrLayerPresent = false; private boolean mIsThermalStatusWithinLimit = true; private boolean mIsBlockedByLowPowerMode = false; private int mWidth; private int mHeight; private BrightnessSetting mBrightnessSetting; private float mAmbientLux; /** * If HBM is currently running, this is the start time for the current HBM session. Loading @@ -92,30 +101,32 @@ class HighBrightnessModeController { */ private LinkedList<HbmEvent> mEvents = new LinkedList<>(); HighBrightnessModeController(Handler handler, IBinder displayToken, float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback, Context context) { this(new Injector(), handler, displayToken, brightnessMin, brightnessMax, hbmData, hbmChangeCallback, context); HighBrightnessModeController(Handler handler, int width, int height, IBinder displayToken, float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback, Context context, BrightnessSetting brightnessSetting) { this(new Injector(), handler, width, height, displayToken, brightnessMin, brightnessMax, hbmData, hbmChangeCallback, context, brightnessSetting); } @VisibleForTesting HighBrightnessModeController(Injector injector, Handler handler, IBinder displayToken, float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback, Context context) { HighBrightnessModeController(Injector injector, Handler handler, int width, int height, IBinder displayToken, float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback, Context context, BrightnessSetting brightnessSetting) { mInjector = injector; mContext = context; mClock = injector.getClock(); mHandler = handler; mBrightnessMin = brightnessMin; mBrightnessMax = brightnessMax; mBrightness = brightnessSetting.getBrightness(); mHbmChangeCallback = hbmChangeCallback; mContext = context; mAutoBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT; mRecalcRunnable = this::recalculateTimeAllowance; mHdrListener = new HdrListener(); mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler); mSettingsObserver = new SettingsObserver(mHandler); resetHbmData(displayToken, hbmData); mRecalcRunnable = this::recalculateTimeAllowance; mHdrListener = new HdrListener(); resetHbmData(width, height, displayToken, hbmData, brightnessSetting); } void setAutoBrightnessEnabled(boolean isEnabled) { Loading @@ -123,7 +134,7 @@ class HighBrightnessModeController { return; } if (DEBUG) { Slog.d(TAG, "setAutoBrightness( " + isEnabled + " )"); Slog.d(TAG, "setAutoBrightnessEnabled( " + isEnabled + " )"); } mIsAutoBrightnessEnabled = isEnabled; mIsInAllowedAmbientRange = false; // reset when auto-brightness switches Loading @@ -147,11 +158,22 @@ class HighBrightnessModeController { } } float getNormalBrightnessMax() { return deviceSupportsHbm() ? mHbmData.transitionPoint : mBrightnessMax; } float getHdrBrightnessValue() { return mBrightnessMax; // For HDR brightness, we take the current brightness and scale it to the max. The reason // we do this is because we want brightness to go to HBM max when it would normally go // to normal max, meaning it should not wait to go to 10000 lux (or whatever the transition // point happens to be) in order to go full HDR. Likewise, HDR on manual brightness should // automatically scale the brightness without forcing the user to adjust to higher values. return MathUtils.map(getCurrentBrightnessMin(), getCurrentBrightnessMax(), mBrightnessMin, mBrightnessMax, mBrightness); } void onAmbientLuxChange(float ambientLux) { mAmbientLux = ambientLux; if (!deviceSupportsHbm() || !mIsAutoBrightnessEnabled) { return; } Loading @@ -163,17 +185,17 @@ class HighBrightnessModeController { } } void onAutoBrightnessChanged(float autoBrightness) { @VisibleForTesting void onBrightnessChanged(float brightness) { if (!deviceSupportsHbm()) { return; } final float oldAutoBrightness = mAutoBrightness; mAutoBrightness = autoBrightness; mBrightness = brightness; // If we are starting or ending a high brightness mode session, store the current // session in mRunningStartTimeMillis, or the old one in mEvents. final boolean wasHbmDrainingAvailableTime = mRunningStartTimeMillis != -1; final boolean shouldHbmDrainAvailableTime = mAutoBrightness > mHbmData.transitionPoint final boolean shouldHbmDrainAvailableTime = mBrightness > mHbmData.transitionPoint && !mIsHdrLayerPresent; if (wasHbmDrainingAvailableTime != shouldHbmDrainAvailableTime) { final long currentTime = mClock.uptimeMillis(); Loading Loading @@ -202,8 +224,12 @@ class HighBrightnessModeController { mSettingsObserver.stopObserving(); } void resetHbmData(IBinder displayToken, HighBrightnessModeData hbmData) { void resetHbmData(int width, int height, IBinder displayToken, HighBrightnessModeData hbmData, BrightnessSetting brightnessSetting) { mWidth = width; mHeight = height; mHbmData = hbmData; resetBrightnessSetting(brightnessSetting); unregisterHdrListener(); mSkinThermalStatusObserver.stopObserving(); mSettingsObserver.stopObserving(); Loading @@ -227,21 +253,23 @@ class HighBrightnessModeController { private void dumpLocal(PrintWriter pw) { pw.println("HighBrightnessModeController:"); pw.println(" mBrightness=" + mBrightness); pw.println(" mCurrentMin=" + getCurrentBrightnessMin()); pw.println(" mCurrentMax=" + getCurrentBrightnessMax()); pw.println(" mHbmMode=" + BrightnessInfo.hbmToString(mHbmMode)); pw.println(" remainingTime=" + calculateRemainingTime(mClock.uptimeMillis())); pw.println(" mHbmData=" + mHbmData); pw.println(" mAmbientLux=" + mAmbientLux); pw.println(" mIsInAllowedAmbientRange=" + mIsInAllowedAmbientRange); pw.println(" mIsTimeAvailable= " + mIsTimeAvailable); pw.println(" mIsAutoBrightnessEnabled=" + mIsAutoBrightnessEnabled); pw.println(" mAutoBrightness=" + mAutoBrightness); pw.println(" mIsHdrLayerPresent=" + mIsHdrLayerPresent); pw.println(" mBrightnessMin=" + mBrightnessMin); pw.println(" mBrightnessMax=" + mBrightnessMax); pw.println(" remainingTime=" + calculateRemainingTime(mClock.uptimeMillis())); pw.println(" mIsTimeAvailable= " + mIsTimeAvailable); pw.println(" mRunningStartTimeMillis=" + TimeUtils.formatUptime(mRunningStartTimeMillis)); pw.println(" mIsThermalStatusWithinLimit=" + mIsThermalStatusWithinLimit); pw.println(" mIsBlockedByLowPowerMode=" + mIsBlockedByLowPowerMode); pw.println(" width*height=" + mWidth + "*" + mHeight); pw.println(" mEvents="); final long currentTime = mClock.uptimeMillis(); long lastStartTime = currentTime; Loading @@ -268,9 +296,26 @@ class HighBrightnessModeController { return event.startTimeMillis; } private void resetBrightnessSetting(BrightnessSetting brightnessSetting) { if (mBrightnessSetting != null) { mBrightnessSetting.unregisterListener(mBrightnessSettingListener); } mBrightnessSetting = brightnessSetting; if (mBrightnessSetting != null) { mBrightnessSetting.registerListener(mBrightnessSettingListener); } } private boolean isCurrentlyAllowed() { return mIsHdrLayerPresent || (mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange // Returns true if HBM is allowed (above the ambient lux threshold) and there's still // time within the current window for additional HBM usage. We return false if there is an // HDR layer because we don't want the brightness MAX to change for HDR, which has its // brightness scaled in a different way than sunlight HBM that doesn't require changing // the MAX. HDR also needs to work under manual brightness which never adjusts the // brightness maximum; so we implement HDR-HBM in a way that doesn't adjust the max. // See {@link #getHdrBrightnessValue}. return !mIsHdrLayerPresent && (mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange && mIsThermalStatusWithinLimit && !mIsBlockedByLowPowerMode); } Loading Loading @@ -334,13 +379,13 @@ class HighBrightnessModeController { // or if brightness is already in the high range, if there is any time left at all. final boolean isAllowedWithoutRestrictions = remainingTime >= mHbmData.timeMinMillis; final boolean isOnlyAllowedToStayOn = !isAllowedWithoutRestrictions && remainingTime > 0 && mAutoBrightness > mHbmData.transitionPoint; && remainingTime > 0 && mBrightness > mHbmData.transitionPoint; mIsTimeAvailable = isAllowedWithoutRestrictions || isOnlyAllowedToStayOn; // Calculate the time at which we want to recalculate mIsTimeAvailable in case a lux or // brightness change doesn't happen before then. long nextTimeout = -1; if (mAutoBrightness > mHbmData.transitionPoint) { if (mBrightness > mHbmData.transitionPoint) { // if we're in high-lux now, timeout when we run out of allowed time. nextTimeout = currentTime + remainingTime; } else if (!mIsTimeAvailable && mEvents.size() > 0) { Loading Loading @@ -370,7 +415,7 @@ class HighBrightnessModeController { + ", mIsInAllowedAmbientRange: " + mIsInAllowedAmbientRange + ", mIsThermalStatusWithinLimit: " + mIsThermalStatusWithinLimit + ", mIsBlockedByLowPowerMode: " + mIsBlockedByLowPowerMode + ", brightness: " + mAutoBrightness + ", mBrightness: " + mBrightness + ", RunningStartTimeMillis: " + mRunningStartTimeMillis + ", nextTimeout: " + (nextTimeout != -1 ? (nextTimeout - currentTime) : -1) + ", events: " + mEvents); Loading Loading @@ -447,11 +492,12 @@ class HighBrightnessModeController { public void onHdrInfoChanged(IBinder displayToken, int numberOfHdrLayers, int maxW, int maxH, int flags) { mHandler.post(() -> { mIsHdrLayerPresent = numberOfHdrLayers > 0; // Calling the auto-brightness update so that we can recalculate // auto-brightness with HDR in mind. When HDR layers are present, // we don't limit auto-brightness' HBM time limits. onAutoBrightnessChanged(mAutoBrightness); mIsHdrLayerPresent = numberOfHdrLayers > 0 && (float) (maxW * maxH) >= ((float) (mWidth * mHeight) * HDR_PERCENT_OF_SCREEN_REQUIRED); // Calling the brightness update so that we can recalculate // brightness with HDR in mind. onBrightnessChanged(mBrightness); }); } } Loading
services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java +22 −14 Original line number Diff line number Diff line Loading @@ -74,6 +74,9 @@ public class HighBrightnessModeControllerTest { private static final float DEFAULT_MIN = 0.01f; private static final float DEFAULT_MAX = 0.80f; private static final int DISPLAY_WIDTH = 900; private static final int DISPLAY_HEIGHT = 1600; private static final float EPSILON = 0.000001f; private OffsettableClock mClock; Loading @@ -90,6 +93,8 @@ public class HighBrightnessModeControllerTest { @Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor; @Mock private BrightnessSetting mBrightnessSetting; private static final HighBrightnessModeData DEFAULT_HBM_DATA = new HighBrightnessModeData(MINIMUM_LUX, TRANSITION_POINT, TIME_WINDOW_MILLIS, TIME_ALLOWED_IN_WINDOW_MILLIS, TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS, Loading @@ -98,6 +103,8 @@ public class HighBrightnessModeControllerTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); mClock = new OffsettableClock.Stopped(); mTestLooper = new TestLooper(mClock::now); mDisplayToken = null; mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext())); final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContextSpy); Loading @@ -114,8 +121,8 @@ public class HighBrightnessModeControllerTest { public void testNoHbmData() { initHandler(null); final HighBrightnessModeController hbmc = new HighBrightnessModeController( mInjectorMock, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {}, mContextSpy); mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {}, mContextSpy, mBrightnessSetting); assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF); } Loading @@ -123,8 +130,8 @@ public class HighBrightnessModeControllerTest { public void testNoHbmData_Enabled() { initHandler(null); final HighBrightnessModeController hbmc = new HighBrightnessModeController( mInjectorMock, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {}, mContextSpy); mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {}, mContextSpy, mBrightnessSetting); hbmc.setAutoBrightnessEnabled(true); hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF); Loading Loading @@ -180,7 +187,7 @@ public class HighBrightnessModeControllerTest { hbmc.setAutoBrightnessEnabled(true); hbmc.onAmbientLuxChange(MINIMUM_LUX + 1); hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f); hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f); // Verify we are in HBM assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); Loading Loading @@ -212,7 +219,7 @@ public class HighBrightnessModeControllerTest { hbmc.setAutoBrightnessEnabled(true); hbmc.onAmbientLuxChange(MINIMUM_LUX + 1); hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f); hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f); // Verify we are in HBM assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); Loading @@ -237,18 +244,18 @@ public class HighBrightnessModeControllerTest { hbmc.setAutoBrightnessEnabled(true); hbmc.onAmbientLuxChange(MINIMUM_LUX + 1); hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f); hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f); advanceTime(TIME_ALLOWED_IN_WINDOW_MILLIS / 2); // Verify we are in HBM assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); hbmc.onAutoBrightnessChanged(TRANSITION_POINT - 0.01f); hbmc.onBrightnessChanged(TRANSITION_POINT - 0.01f); advanceTime(1); assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f); hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f); advanceTime(TIME_ALLOWED_IN_WINDOW_MILLIS / 2); assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); Loading @@ -267,13 +274,13 @@ public class HighBrightnessModeControllerTest { hbmc.onAmbientLuxChange(MINIMUM_LUX + 1); // Go into HBM for half the allowed window hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f); hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f); advanceTime(TIME_ALLOWED_IN_WINDOW_MILLIS / 2); assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); // Move lux below threshold (ending first event); hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); hbmc.onAutoBrightnessChanged(TRANSITION_POINT); hbmc.onBrightnessChanged(TRANSITION_POINT); assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF); // Move up some amount of time so that there's still time in the window even after a Loading @@ -283,7 +290,7 @@ public class HighBrightnessModeControllerTest { // Go into HBM for just under the second half of allowed window hbmc.onAmbientLuxChange(MINIMUM_LUX + 1); hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 1); hbmc.onBrightnessChanged(TRANSITION_POINT + 1); advanceTime((TIME_ALLOWED_IN_WINDOW_MILLIS / 2) - 1); assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT); Loading Loading @@ -355,8 +362,9 @@ public class HighBrightnessModeControllerTest { // Creates instance with standard initialization values. private HighBrightnessModeController createDefaultHbm(OffsettableClock clock) { initHandler(clock); return new HighBrightnessModeController(mInjectorMock, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, DEFAULT_HBM_DATA, () -> {}, mContextSpy); return new HighBrightnessModeController(mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, DEFAULT_HBM_DATA, () -> {}, mContextSpy, mBrightnessSetting); } private void initHandler(OffsettableClock clock) { Loading