Merge "Reflect BrightnessThrottler effects in Settings, UI and ABC"

This commit is contained in:
Daniel Solomon
2022-02-02 00:59:55 +00:00
committed by Android (Google) Code Review
3 changed files with 99 additions and 24 deletions

View File

@@ -201,6 +201,10 @@ class AutomaticBrightnessController {
// Controls High Brightness Mode.
private HighBrightnessModeController mHbmController;
// Throttles (caps) maximum allowed brightness
private BrightnessThrottler mBrightnessThrottler;
private boolean mIsBrightnessThrottled;
// Context-sensitive brightness configurations require keeping track of the foreground app's
// package name and category, which is done by registering a TaskStackListener to call back to
// us onTaskStackChanged, and then using the ActivityTaskManager to get the foreground app's
@@ -226,7 +230,7 @@ class AutomaticBrightnessController {
long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
HysteresisLevels screenBrightnessThresholds, Context context,
HighBrightnessModeController hbmController,
HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler,
BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort,
int ambientLightHorizonLong) {
this(new Injector(), callbacks, looper, sensorManager, lightSensor,
@@ -235,8 +239,8 @@ class AutomaticBrightnessController {
lightSensorRate, initialLightSensorRate, brighteningLightDebounceConfig,
darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig,
ambientBrightnessThresholds, screenBrightnessThresholds, context,
hbmController, idleModeBrightnessMapper, ambientLightHorizonShort,
ambientLightHorizonLong
hbmController, brightnessThrottler, idleModeBrightnessMapper,
ambientLightHorizonShort, ambientLightHorizonLong
);
}
@@ -249,7 +253,7 @@ class AutomaticBrightnessController {
long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
HysteresisLevels screenBrightnessThresholds, Context context,
HighBrightnessModeController hbmController,
HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler,
BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort,
int ambientLightHorizonLong) {
mInjector = injector;
@@ -291,6 +295,7 @@ class AutomaticBrightnessController {
mForegroundAppCategory = ApplicationInfo.CATEGORY_UNDEFINED;
mPendingForegroundAppCategory = ApplicationInfo.CATEGORY_UNDEFINED;
mHbmController = hbmController;
mBrightnessThrottler = brightnessThrottler;
mInteractiveModeBrightnessMapper = interactiveModeBrightnessMapper;
mIdleModeBrightnessMapper = idleModeBrightnessMapper;
// Initialize to active (normal) screen brightness mode
@@ -365,6 +370,13 @@ class AutomaticBrightnessController {
prepareBrightnessAdjustmentSample();
}
changed |= setLightSensorEnabled(enable && !dozing);
if (mIsBrightnessThrottled != mBrightnessThrottler.isThrottled()) {
// Maximum brightness has changed, so recalculate display brightness.
mIsBrightnessThrottled = mBrightnessThrottler.isThrottled();
changed = true;
}
if (changed) {
updateAutoBrightness(false /*sendUpdate*/, userInitiatedChange);
}
@@ -855,8 +867,11 @@ class AutomaticBrightnessController {
// Clamps values with float range [0.0-1.0]
private float clampScreenBrightness(float value) {
return MathUtils.constrain(value,
mHbmController.getCurrentBrightnessMin(), mHbmController.getCurrentBrightnessMax());
final float minBrightness = Math.min(mHbmController.getCurrentBrightnessMin(),
mBrightnessThrottler.getBrightnessCap());
final float maxBrightness = Math.min(mHbmController.getCurrentBrightnessMax(),
mBrightnessThrottler.getBrightnessCap());
return MathUtils.constrain(value, minBrightness, maxBrightness);
}
private void prepareBrightnessAdjustmentSample() {

View File

@@ -974,7 +974,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
lightSensorRate, initialLightSensorRate, brighteningLightDebounce,
darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp,
ambientBrightnessThresholds, screenBrightnessThresholds, mContext,
mHbmController, mIdleModeBrightnessMapper,
mHbmController, mBrightnessThrottler, mIdleModeBrightnessMapper,
mDisplayDeviceConfig.getAmbientHorizonShort(),
mDisplayDeviceConfig.getAmbientHorizonLong());
} else {
@@ -1347,6 +1347,29 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
}
// Now that a desired brightness has been calculated, apply brightness throttling. The
// dimming and low power transformations that follow can only dim brightness further.
//
// We didn't do this earlier through brightness clamping because we need to know both
// unthrottled (unclamped/ideal) and throttled brightness levels for subsequent operations.
// Note throttling effectively changes the allowed brightness range, so, similarly to HBM,
// we broadcast this change through setting.
final float unthrottledBrightnessState = brightnessState;
if (mBrightnessThrottler.isThrottled()) {
brightnessState = Math.min(brightnessState, mBrightnessThrottler.getBrightnessCap());
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_THROTTLED);
if (!mAppliedThrottling) {
// Brightness throttling is needed, so do so quickly.
// Later, when throttling is removed, we let other mechanisms decide on speed.
slowChange = false;
updateScreenBrightnessSetting = true;
}
mAppliedThrottling = true;
} else if (mAppliedThrottling) {
mAppliedThrottling = false;
updateScreenBrightnessSetting = true;
}
if (updateScreenBrightnessSetting) {
// Tell the rest of the system about the new brightness in case we had to change it
// for things like auto-brightness or high-brightness-mode. Note that we do this
@@ -1393,20 +1416,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mAppliedLowPower = false;
}
// Apply brightness throttling after applying all other transforms
final float unthrottledBrightnessState = brightnessState;
if (mBrightnessThrottler.isThrottled()) {
brightnessState = Math.min(brightnessState, mBrightnessThrottler.getBrightnessCap());
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_THROTTLED);
if (!mAppliedThrottling) {
slowChange = false;
}
mAppliedThrottling = true;
} else if (mAppliedThrottling) {
slowChange = false;
mAppliedThrottling = false;
}
// The current brightness to use has been calculated at this point, and HbmController should
// be notified so that it can accurately calculate HDR or HBM levels. We specifically do it
// here instead of having HbmController listen to the brightness setting because certain
@@ -1656,6 +1665,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private boolean saveBrightnessInfo(float brightness, float adjustedBrightness) {
synchronized (mCachedBrightnessInfo) {
final float minBrightness = Math.min(mHbmController.getCurrentBrightnessMin(),
mBrightnessThrottler.getBrightnessCap());
final float maxBrightness = Math.min(mHbmController.getCurrentBrightnessMax(),
mBrightnessThrottler.getBrightnessCap());
boolean changed = false;
changed |=
@@ -1666,10 +1679,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
adjustedBrightness);
changed |=
mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMin,
mHbmController.getCurrentBrightnessMin());
minBrightness);
changed |=
mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMax,
mHbmController.getCurrentBrightnessMax());
maxBrightness);
changed |=
mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.hbmMode,
mHbmController.getHighBrightnessMode());

View File

@@ -81,6 +81,7 @@ public class AutomaticBrightnessControllerTest {
@Mock HysteresisLevels mScreenBrightnessThresholds;
@Mock Handler mNoOpHandler;
@Mock HighBrightnessModeController mHbmController;
@Mock BrightnessThrottler mBrightnessThrottler;
@Before
public void setUp() {
@@ -128,12 +129,15 @@ public class AutomaticBrightnessControllerTest {
INITIAL_LIGHT_SENSOR_RATE, BRIGHTENING_LIGHT_DEBOUNCE_CONFIG,
DARKENING_LIGHT_DEBOUNCE_CONFIG, RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG,
mAmbientBrightnessThresholds, mScreenBrightnessThresholds,
mContext, mHbmController, mIdleBrightnessMappingStrategy,
mContext, mHbmController, mBrightnessThrottler, mIdleBrightnessMappingStrategy,
AMBIENT_LIGHT_HORIZON_SHORT, AMBIENT_LIGHT_HORIZON_LONG
);
when(mHbmController.getCurrentBrightnessMax()).thenReturn(BRIGHTNESS_MAX_FLOAT);
when(mHbmController.getCurrentBrightnessMin()).thenReturn(BRIGHTNESS_MIN_FLOAT);
// Disable brightness throttling by default. Individual tests can enable it as needed.
when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT);
when(mBrightnessThrottler.isThrottled()).thenReturn(false);
// Configure the brightness controller and grab an instance of the sensor listener,
// through which we can deliver fake (for test) sensor values.
@@ -420,4 +424,47 @@ public class AutomaticBrightnessControllerTest {
assertEquals(600f, hysteresisLevels.getBrighteningThreshold(500f), EPSILON);
assertEquals(250f, hysteresisLevels.getDarkeningThreshold(500f), EPSILON);
}
@Test
public void testBrightnessGetsThrottled() throws Exception {
Sensor lightSensor = TestUtils.createSensor(Sensor.TYPE_LIGHT, "Light Sensor");
mController = setupController(lightSensor);
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(lightSensor),
eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
SensorEventListener listener = listenerCaptor.getValue();
// Set up system to return max brightness at 100 lux
final float normalizedBrightness = BRIGHTNESS_MAX_FLOAT;
final float lux = 100.0f;
when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux))
.thenReturn(lux);
when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux))
.thenReturn(lux);
when(mBrightnessMappingStrategy.getBrightness(eq(lux), eq(null), anyInt()))
.thenReturn(normalizedBrightness);
// Sensor reads 100 lux. We should get max brightness.
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, (int) lux));
assertEquals(BRIGHTNESS_MAX_FLOAT, mController.getAutomaticScreenBrightness(), 0.0f);
// Apply throttling and notify ABC (simulates DisplayPowerController#updatePowerState())
final float throttledBrightness = 0.123f;
when(mBrightnessThrottler.getBrightnessCap()).thenReturn(throttledBrightness);
when(mBrightnessThrottler.isThrottled()).thenReturn(true);
mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration */,
BRIGHTNESS_MAX_FLOAT /* brightness */, false /* userChangedBrightness */,
0 /* adjustment */, false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
assertEquals(throttledBrightness, mController.getAutomaticScreenBrightness(), 0.0f);
// Remove throttling and notify ABC again
when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT);
when(mBrightnessThrottler.isThrottled()).thenReturn(false);
mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration */,
BRIGHTNESS_MAX_FLOAT /* brightness */, false /* userChangedBrightness */,
0 /* adjustment */, false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
assertEquals(BRIGHTNESS_MAX_FLOAT, mController.getAutomaticScreenBrightness(), 0.0f);
}
}