Improve brightness handling during screen off timeout.

- Align doze brightness logic with DisplayPowerController, so that the
  'minimum dim amount' is taken into account by DozeScreenBrightness.
- Clamp brightness to the now-correct dim value during the entire screen
  off animation, rather than sometimes transitioning to the sensor value.
  Apply the sensor brightness value on changing to the DOZE Display state,
  which happens after the screen off animation.

This brings the changes from ag/15974454 (Improve brightness handling
during screen off timeout) and ag/16047064 (Fix DozeScreenBrightnessTest)
into sc-v2/master from sc/qpr1, along with externalizing the minimum dim
percent as a config value.

Bug: 194972547
Test: at 0%, 45%, and 100% brightness, allow the screen to time out in
bright and dark rooms, observe minimal brightness changes
Change-Id: I0a1ae320274661e58d6b398a8facdfad54e49a06
This commit is contained in:
Josh Tsuji
2021-10-04 15:23:59 -04:00
parent 635a90d46a
commit 19f3902f60
7 changed files with 80 additions and 20 deletions

View File

@@ -1388,6 +1388,12 @@
<integer name="config_screenBrightnessDim">10</integer>
<item name="config_screenBrightnessDimFloat" format="float" type="dimen">0.05</item>
<!-- If the screen brightness is already set at or below config_screenBrightnessDim, and the
user activity timeout expires, we still want to dim the screen slightly to indicate that
the device is about to go to sleep. The screen will dim by this amount in that case.
-->
<item name="config_screenBrightnessMinimumDimAmountFloat" format="float" type="dimen">0.04</item>
<!-- Minimum allowable screen brightness to use in a very dark room.
This value sets the floor for the darkest possible auto-brightness
adjustment. It is expected to be somewhat less than the first entry in

View File

@@ -2040,6 +2040,7 @@
<java-symbol type="dimen" name="config_screenBrightnessSettingDefaultFloat" />
<java-symbol type="dimen" name="config_screenBrightnessDozeFloat" />
<java-symbol type="dimen" name="config_screenBrightnessDimFloat" />
<java-symbol type="dimen" name="config_screenBrightnessMinimumDimAmountFloat" />
<java-symbol type="integer" name="config_screenBrightnessDark" />
<java-symbol type="integer" name="config_screenBrightnessDim" />
<java-symbol type="integer" name="config_screenBrightnessDoze" />

View File

@@ -31,11 +31,13 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.util.IndentingPrintWriter;
import com.android.internal.R;
import com.android.systemui.doze.dagger.BrightnessSensor;
import com.android.systemui.doze.dagger.DozeScope;
import com.android.systemui.doze.dagger.WrappedService;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.util.sensors.AsyncSensorManager;
@@ -57,6 +59,12 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
"com.android.systemui.doze.AOD_BRIGHTNESS";
protected static final String BRIGHTNESS_BUCKET = "brightness_bucket";
/**
* Just before the screen times out from user inactivity, DisplayPowerController dims the screen
* brightness to the lower of {@link #mScreenBrightnessDim}, or the current brightness minus
* this amount.
*/
private final float mScreenBrightnessMinimumDimAmountFloat;
private final Context mContext;
private final DozeMachine.Service mDozeService;
private final DozeHost mDozeHost;
@@ -87,6 +95,8 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
*/
private int mDebugBrightnessBucket = -1;
private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@Inject
public DozeScreenBrightness(
Context context,
@@ -98,8 +108,8 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
WakefulnessLifecycle wakefulnessLifecycle,
DozeParameters dozeParameters,
DevicePostureController devicePostureController,
DozeLog dozeLog
) {
DozeLog dozeLog,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
mContext = context;
mDozeService = service;
mSensorManager = sensorManager;
@@ -111,6 +121,10 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
mDozeHost = host;
mHandler = handler;
mDozeLog = dozeLog;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
mScreenBrightnessMinimumDimAmountFloat = context.getResources().getFloat(
R.dimen.config_screenBrightnessMinimumDimAmountFloat);
mDefaultDozeBrightness = alwaysOnDisplayPolicy.defaultDozeBrightness;
mScreenBrightnessDim = alwaysOnDisplayPolicy.dimBrightness;
@@ -163,14 +177,15 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
}
}
private void updateBrightnessAndReady(boolean force) {
public void updateBrightnessAndReady(boolean force) {
if (force || mRegistered || mDebugBrightnessBucket != -1) {
int sensorValue = mDebugBrightnessBucket == -1
? mLastSensorValue : mDebugBrightnessBucket;
int brightness = computeBrightness(sensorValue);
boolean brightnessReady = brightness > 0;
if (brightnessReady) {
mDozeService.setDozeScreenBrightness(clampToUserSetting(brightness));
mDozeService.setDozeScreenBrightness(
clampToDimBrightnessForScreenOff(clampToUserSetting(brightness)));
}
int scrimOpacity = -1;
@@ -243,13 +258,22 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
/**
* Clamp the brightness to the dim brightness value used by PowerManagerService just before the
* device times out and goes to sleep, if we are sleeping from a timeout. This ensures that we
* don't raise the brightness back to the user setting before playing the screen off animation.
* don't raise the brightness back to the user setting before or during the screen off
* animation.
*/
private int clampToDimBrightnessForScreenOff(int brightness) {
if (mDozeParameters.shouldControlUnlockedScreenOff()
if (mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()
&& mWakefulnessLifecycle.getLastSleepReason()
== PowerManager.GO_TO_SLEEP_REASON_TIMEOUT) {
return Math.min(mScreenBrightnessDim, brightness);
return Math.max(
PowerManager.BRIGHTNESS_OFF,
// Use the lower of either the dim brightness, or the current brightness reduced
// by the minimum dim amount. This is the same logic used in
// DisplayPowerController#updatePowerState to apply a minimum dim amount.
Math.min(
brightness - (int) Math.floor(
mScreenBrightnessMinimumDimAmountFloat * 255),
mScreenBrightnessDim));
} else {
return brightness;
}

View File

@@ -77,6 +77,7 @@ public class DozeScreenState implements DozeMachine.Part {
private final Provider<UdfpsController> mUdfpsControllerProvider;
@Nullable private UdfpsController mUdfpsController;
private final DozeLog mDozeLog;
private final DozeScreenBrightness mDozeScreenBrightness;
private int mPendingScreenState = Display.STATE_UNKNOWN;
private SettableWakeLock mWakeLock;
@@ -90,7 +91,8 @@ public class DozeScreenState implements DozeMachine.Part {
WakeLock wakeLock,
AuthController authController,
Provider<UdfpsController> udfpsControllerProvider,
DozeLog dozeLog) {
DozeLog dozeLog,
DozeScreenBrightness dozeScreenBrightness) {
mDozeService = service;
mHandler = handler;
mParameters = parameters;
@@ -99,6 +101,7 @@ public class DozeScreenState implements DozeMachine.Part {
mAuthController = authController;
mUdfpsControllerProvider = udfpsControllerProvider;
mDozeLog = dozeLog;
mDozeScreenBrightness = dozeScreenBrightness;
updateUdfpsController();
if (mUdfpsController == null) {
@@ -209,6 +212,12 @@ public class DozeScreenState implements DozeMachine.Part {
if (screenState != Display.STATE_UNKNOWN) {
if (DEBUG) Log.d(TAG, "setDozeScreenState(" + screenState + ")");
mDozeService.setDozeScreenState(screenState);
if (screenState == Display.STATE_DOZE) {
// If we're entering doze, update the doze screen brightness. We might have been
// clamping it to the dim brightness during the screen off animation, and we should
// now change it to the brightness we actually want according to the sensor.
mDozeScreenBrightness.updateBrightnessAndReady(false /* force */);
}
mPendingScreenState = Display.STATE_UNKNOWN;
mWakeLock.setAcquired(false);
}

View File

@@ -51,6 +51,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.concurrency.FakeThreadFactory;
@@ -93,6 +94,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
DevicePostureController mDevicePostureController;
@Mock
DozeLog mDozeLog;
@Mock
private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
private FakeThreadFactory mFakeThreadFactory = new FakeThreadFactory(mFakeExecutor);
@@ -130,7 +133,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
mDozeLog);
mDozeLog,
mUnlockedScreenOffAnimationController);
}
@Test
@@ -236,7 +240,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
mDozeLog);
mDozeLog,
mUnlockedScreenOffAnimationController);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
reset(mDozeHost);
@@ -273,7 +278,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
mDozeLog);
mDozeLog,
mUnlockedScreenOffAnimationController);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
@@ -304,7 +310,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
mDozeLog);
mDozeLog,
mUnlockedScreenOffAnimationController);
// GIVEN the device is in AOD
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
@@ -342,7 +349,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
mDozeLog);
mDozeLog,
mUnlockedScreenOffAnimationController);
// GIVEN device is in AOD
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
@@ -384,7 +392,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
mDozeLog);
mDozeLog,
mUnlockedScreenOffAnimationController);
verify(mDevicePostureController).addCallback(postureCallbackCaptor.capture());
// GIVEN device is in AOD
@@ -470,13 +479,14 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true);
when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(true);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
// If we're dozing after a timeout, and playing the unlocked screen animation, we should
// stay at dim brightness, because the screen dims just before timeout.
assertEquals(mServiceFake.screenBrightness, DIM_BRIGHTNESS);
// stay at or below dim brightness, because the screen dims just before timeout.
assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS);
}
@Test
@@ -484,6 +494,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true);
when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(true);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
@@ -498,6 +509,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false);
when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(false);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);

View File

@@ -82,6 +82,8 @@ public class DozeScreenStateTest extends SysuiTestCase {
private UdfpsController mUdfpsController;
@Mock
private DozeLog mDozeLog;
@Mock
private DozeScreenBrightness mDozeScreenBrightness;
@Before
public void setUp() throws Exception {
@@ -96,7 +98,8 @@ public class DozeScreenStateTest extends SysuiTestCase {
mHandlerFake = new FakeHandler(Looper.getMainLooper());
mWakeLock = new WakeLockFake();
mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeHost, mDozeParameters,
mWakeLock, mAuthController, mUdfpsControllerProvider, mDozeLog);
mWakeLock, mAuthController, mUdfpsControllerProvider, mDozeLog,
mDozeScreenBrightness);
}
@Test

View File

@@ -108,8 +108,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// screen state returns. Playing the animation can also be somewhat slow.
private static final boolean USE_COLOR_FADE_ON_ANIMATION = false;
// The minimum reduction in brightness when dimmed.
private static final float SCREEN_DIM_MINIMUM_REDUCTION_FLOAT = 0.04f;
private static final float SCREEN_ANIMATION_RATE_MINIMUM = 0.0f;
private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
@@ -200,6 +198,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// The dim screen brightness.
private final float mScreenBrightnessDimConfig;
// The minimum dim amount to use if the screen brightness is already below
// mScreenBrightnessDimConfig.
private final float mScreenBrightnessMinimumDimAmount;
private final float mScreenBrightnessDefault;
// The minimum allowed brightness while in VR.
@@ -485,6 +487,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DOZE));
mScreenBrightnessDimConfig = clampAbsoluteBrightness(
pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DIM));
mScreenBrightnessMinimumDimAmount = resources.getFloat(
com.android.internal.R.dimen.config_screenBrightnessMinimumDimAmountFloat);
// NORMAL SCREEN SETTINGS
mScreenBrightnessDefault = clampAbsoluteBrightness(
@@ -1284,7 +1289,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
brightnessState = Math.max(
Math.min(brightnessState - SCREEN_DIM_MINIMUM_REDUCTION_FLOAT,
Math.min(brightnessState - mScreenBrightnessMinimumDimAmount,
mScreenBrightnessDimConfig),
PowerManager.BRIGHTNESS_MIN);
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);