diff --git a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java index 60ee806d0a9f7..735b3cd4b8242 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java @@ -59,6 +59,13 @@ public class AlwaysOnDisplayPolicy { */ public int defaultDozeBrightness; + /** + * Integer used to dim the screen just before the screen turns off. + * + * @see R.integer.config_screenBrightnessDim + */ + public int dimBrightness; + /** * Integer array to map ambient brightness type to real screen brightness. * @@ -175,6 +182,8 @@ public class AlwaysOnDisplayPolicy { DEFAULT_WALLPAPER_VISIBILITY_MS); defaultDozeBrightness = resources.getInteger( com.android.internal.R.integer.config_screenBrightnessDoze); + dimBrightness = resources.getInteger( + com.android.internal.R.integer.config_screenBrightnessDim); screenBrightnessArray = mParser.getIntArray(KEY_SCREEN_BRIGHTNESS_ARRAY, resources.getIntArray( R.array.config_doze_brightness_sensor_to_brightness)); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index 92494cf5b5469..470d2f364c1c6 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -24,6 +24,7 @@ import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Handler; +import android.os.PowerManager; import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; @@ -33,6 +34,8 @@ import android.view.Display; 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.util.sensors.AsyncSensorManager; import java.io.PrintWriter; @@ -58,8 +61,11 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi private final Handler mHandler; private final SensorManager mSensorManager; private final Optional mLightSensorOptional; + private final WakefulnessLifecycle mWakefulnessLifecycle; + private final DozeParameters mDozeParameters; private final int[] mSensorToBrightness; private final int[] mSensorToScrimOpacity; + private final int mScreenBrightnessDim; private boolean mRegistered; private int mDefaultDozeBrightness; @@ -79,15 +85,20 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi public DozeScreenBrightness(Context context, @WrappedService DozeMachine.Service service, AsyncSensorManager sensorManager, @BrightnessSensor Optional lightSensorOptional, DozeHost host, Handler handler, - AlwaysOnDisplayPolicy alwaysOnDisplayPolicy) { + AlwaysOnDisplayPolicy alwaysOnDisplayPolicy, + WakefulnessLifecycle wakefulnessLifecycle, + DozeParameters dozeParameters) { mContext = context; mDozeService = service; mSensorManager = sensorManager; mLightSensorOptional = lightSensorOptional; + mWakefulnessLifecycle = wakefulnessLifecycle; + mDozeParameters = dozeParameters; mDozeHost = host; mHandler = handler; mDefaultDozeBrightness = alwaysOnDisplayPolicy.defaultDozeBrightness; + mScreenBrightnessDim = alwaysOnDisplayPolicy.dimBrightness; mSensorToBrightness = alwaysOnDisplayPolicy.screenBrightnessArray; mSensorToScrimOpacity = alwaysOnDisplayPolicy.dimmingScrimArray; } @@ -178,7 +189,9 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi } private void resetBrightnessToDefault() { - mDozeService.setDozeScreenBrightness(clampToUserSetting(mDefaultDozeBrightness)); + mDozeService.setDozeScreenBrightness( + clampToDimBrightnessForScreenOff( + clampToUserSetting(mDefaultDozeBrightness))); mDozeHost.setAodDimmingScrim(0f); } //TODO: brightnessfloat change usages to float. @@ -189,6 +202,21 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi return Math.min(brightness, userSetting); } + /** + * 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. + */ + private int clampToDimBrightnessForScreenOff(int brightness) { + if (mDozeParameters.shouldControlUnlockedScreenOff() + && mWakefulnessLifecycle.getLastSleepReason() + == PowerManager.GO_TO_SLEEP_REASON_TIMEOUT) { + return Math.min(mScreenBrightnessDim, brightness); + } else { + return brightness; + } + } + private void setLightSensorEnabled(boolean enabled) { if (enabled && !mRegistered && mLightSensorOptional.isPresent()) { // Wait until we get an event from the sensor until indicating ready. diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java index be0865d1b3e97..4e8b59c956818 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java @@ -35,6 +35,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.content.Intent; import android.os.PowerManager; @@ -46,6 +47,8 @@ import android.view.Display; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.concurrency.FakeThreadFactory; import com.android.systemui.util.sensors.AsyncSensorManager; @@ -65,6 +68,7 @@ import java.util.Optional; public class DozeScreenBrightnessTest extends SysuiTestCase { private static final int DEFAULT_BRIGHTNESS = 10; + private static final int DIM_BRIGHTNESS = 1; private static final int[] SENSOR_TO_BRIGHTNESS = new int[]{-1, 1, 2, 3, 4}; private static final int[] SENSOR_TO_OPACITY = new int[]{-1, 10, 0, 0, 0}; @@ -74,6 +78,10 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { private AlwaysOnDisplayPolicy mAlwaysOnDisplayPolicy; @Mock DozeHost mDozeHost; + @Mock + WakefulnessLifecycle mWakefulnessLifecycle; + @Mock + DozeParameters mDozeParameters; private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); private FakeThreadFactory mFakeThreadFactory = new FakeThreadFactory(mFakeExecutor); @@ -96,11 +104,12 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mAlwaysOnDisplayPolicy = new AlwaysOnDisplayPolicy(mContext); mAlwaysOnDisplayPolicy.defaultDozeBrightness = DEFAULT_BRIGHTNESS; mAlwaysOnDisplayPolicy.screenBrightnessArray = SENSOR_TO_BRIGHTNESS; + mAlwaysOnDisplayPolicy.dimBrightness = DIM_BRIGHTNESS; mAlwaysOnDisplayPolicy.dimmingScrimArray = SENSOR_TO_OPACITY; mSensor = fakeSensorManager.getFakeLightSensor(); mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager, Optional.of(mSensor.getSensor()), mDozeHost, null /* handler */, - mAlwaysOnDisplayPolicy); + mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters); mScreen.onScreenState(Display.STATE_ON); } @@ -166,7 +175,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { public void testPulsing_withoutLightSensor_setsAoDDimmingScrimTransparent() throws Exception { mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager, Optional.empty() /* sensor */, mDozeHost, null /* handler */, - mAlwaysOnDisplayPolicy); + mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); reset(mDozeHost); @@ -207,7 +216,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { public void testNullSensor() throws Exception { mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager, Optional.empty() /* sensor */, mDozeHost, null /* handler */, - mAlwaysOnDisplayPolicy); + mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); @@ -282,6 +291,47 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { verify(mDozeHost).setAodDimmingScrim(eq(0f)); } + @Test + public void transitionToDoze_duringScreenOff_afterTimeout_clampsToDim() { + when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( + PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); + when(mDozeParameters.shouldControlUnlockedScreenOff()).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); + } + + @Test + public void transitionToDoze_duringScreenOff_notAfterTimeout_doesNotClampToDim() { + when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( + PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON); + when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true); + + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE); + + // If we're playing the unlocked screen off animation after a power button press, we should + // leave the brightness alone. + assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); + } + + @Test + public void transitionToDoze_duringScreenOff_afterTimeout_noScreenOff_doesNotClampToDim() { + when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( + PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); + when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false); + + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE); + + // If we aren't controlling the screen off animation, we should leave the brightness alone. + assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); + } + private void waitForSensorManager() { mFakeExecutor.runAllReady(); }