1717package com .android .server .power ;
1818
1919import com .android .server .LightsService ;
20+ import com .android .server .TwilightService ;
21+ import com .android .server .TwilightService .TwilightState ;
2022
2123import android .animation .Animator ;
2224import android .animation .ObjectAnimator ;
@@ -88,6 +90,22 @@ final class DisplayPowerController {
8890 // auto-brightness adjustment setting.
8991 private static final float SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA = 3.0f ;
9092
93+ // If true, enables the use of the current time as an auto-brightness adjustment.
94+ // The basic idea here is to expand the dynamic range of auto-brightness
95+ // when it is especially dark outside. The light sensor tends to perform
96+ // poorly at low light levels so we compensate for it by making an
97+ // assumption about the environment.
98+ private static final boolean USE_TWILIGHT_ADJUSTMENT = true ;
99+
100+ // Specifies the maximum magnitude of the time of day adjustment.
101+ private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1.5f ;
102+
103+ // The amount of time after or before sunrise over which to start adjusting
104+ // the gamma. We want the change to happen gradually so that it is below the
105+ // threshold of perceptibility and so that the adjustment has maximum effect
106+ // well after dusk.
107+ private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils .HOUR_IN_MILLIS * 2 ;
108+
91109 private static final int ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS = 300 ;
92110 private static final int ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS = 600 ;
93111
@@ -148,6 +166,9 @@ final class DisplayPowerController {
148166 // The lights service.
149167 private final LightsService mLights ;
150168
169+ // The twilight service.
170+ private final TwilightService mTwilight ;
171+
151172 // The sensor manager.
152173 private final SensorManager mSensorManager ;
153174
@@ -291,11 +312,14 @@ final class DisplayPowerController {
291312 private ObjectAnimator mElectronBeamOffAnimator ;
292313 private RampAnimator <DisplayPowerState > mScreenBrightnessRampAnimator ;
293314
315+ // Twilight changed. We might recalculate auto-brightness values.
316+ private boolean mTwilightChanged ;
317+
294318 /**
295319 * Creates the display power controller.
296320 */
297321 public DisplayPowerController (Looper looper , Context context , Notifier notifier ,
298- LightsService lights , SuspendBlocker suspendBlocker ,
322+ LightsService lights , TwilightService twilight , SuspendBlocker suspendBlocker ,
299323 Callbacks callbacks , Handler callbackHandler ) {
300324 mHandler = new DisplayControllerHandler (looper );
301325 mNotifier = notifier ;
@@ -304,6 +328,7 @@ public DisplayPowerController(Looper looper, Context context, Notifier notifier,
304328 mCallbackHandler = callbackHandler ;
305329
306330 mLights = lights ;
331+ mTwilight = twilight ;
307332 mSensorManager = new SystemSensorManager (mHandler .getLooper ());
308333
309334 final Resources resources = context .getResources ();
@@ -344,6 +369,10 @@ public DisplayPowerController(Looper looper, Context context, Notifier notifier,
344369 && !DEBUG_PRETEND_LIGHT_SENSOR_ABSENT ) {
345370 mLightSensor = mSensorManager .getDefaultSensor (Sensor .TYPE_LIGHT );
346371 }
372+
373+ if (mUseSoftwareAutoBrightnessConfig && USE_TWILIGHT_ADJUSTMENT ) {
374+ mTwilight .registerListener (mTwilightListener , mHandler );
375+ }
347376 }
348377
349378 private static Spline createAutoBrightnessSpline (int [] lux , int [] brightness ) {
@@ -486,7 +515,8 @@ private void updatePowerState() {
486515 // Update the power state request.
487516 final boolean mustNotify ;
488517 boolean mustInitialize = false ;
489- boolean updateAutoBrightness = false ;
518+ boolean updateAutoBrightness = mTwilightChanged ;
519+ mTwilightChanged = false ;
490520
491521 synchronized (mLock ) {
492522 mPendingUpdatePowerStateLocked = false ;
@@ -863,6 +893,22 @@ private void updateAutoBrightness(boolean sendUpdate) {
863893 }
864894 }
865895
896+ if (USE_TWILIGHT_ADJUSTMENT ) {
897+ TwilightState state = mTwilight .getCurrentState ();
898+ if (state != null && state .isNight ()) {
899+ final long now = System .currentTimeMillis ();
900+ final float earlyGamma =
901+ getTwilightGamma (now , state .getYesterdaySunset (), state .getTodaySunrise ());
902+ final float lateGamma =
903+ getTwilightGamma (now , state .getTodaySunset (), state .getTomorrowSunrise ());
904+ gamma *= earlyGamma * lateGamma ;
905+ if (DEBUG ) {
906+ Slog .d (TAG , "updateAutoBrightness: earlyGamma=" + earlyGamma
907+ + ", lateGamma=" + lateGamma );
908+ }
909+ }
910+ }
911+
866912 if (gamma != 1.0f ) {
867913 final float in = value ;
868914 value = FloatMath .pow (value , gamma );
@@ -889,6 +935,29 @@ private void updateAutoBrightness(boolean sendUpdate) {
889935 }
890936 }
891937
938+ private static float getTwilightGamma (long now , long lastSunset , long nextSunrise ) {
939+ if (lastSunset < 0 || nextSunrise < 0
940+ || now < lastSunset || now > nextSunrise ) {
941+ return 1.0f ;
942+ }
943+
944+ if (now < lastSunset + TWILIGHT_ADJUSTMENT_TIME ) {
945+ return lerp (1.0f , TWILIGHT_ADJUSTMENT_MAX_GAMMA ,
946+ (float )(now - lastSunset ) / TWILIGHT_ADJUSTMENT_TIME );
947+ }
948+
949+ if (now > nextSunrise - TWILIGHT_ADJUSTMENT_TIME ) {
950+ return lerp (1.0f , TWILIGHT_ADJUSTMENT_MAX_GAMMA ,
951+ (float )(nextSunrise - now ) / TWILIGHT_ADJUSTMENT_TIME );
952+ }
953+
954+ return TWILIGHT_ADJUSTMENT_MAX_GAMMA ;
955+ }
956+
957+ private static float lerp (float x , float y , float alpha ) {
958+ return x + (y - x ) * alpha ;
959+ }
960+
892961 private void sendOnStateChanged () {
893962 mCallbackHandler .post (mOnStateChangedRunnable );
894963 }
@@ -995,6 +1064,7 @@ private void dumpLocal(PrintWriter pw) {
9951064 pw .println (" mScreenAutoBrightness=" + mScreenAutoBrightness );
9961065 pw .println (" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness );
9971066 pw .println (" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma );
1067+ pw .println (" mTwilight.getCurrentState()=" + mTwilight .getCurrentState ());
9981068
9991069 if (mElectronBeamOnAnimator != null ) {
10001070 pw .println (" mElectronBeamOnAnimator.isStarted()=" +
@@ -1095,4 +1165,13 @@ public void onAccuracyChanged(Sensor sensor, int accuracy) {
10951165 // Not used.
10961166 }
10971167 };
1168+
1169+ private final TwilightService .TwilightListener mTwilightListener =
1170+ new TwilightService .TwilightListener () {
1171+ @ Override
1172+ public void onTwilightStateChanged () {
1173+ mTwilightChanged = true ;
1174+ updatePowerState ();
1175+ }
1176+ };
10981177}
0 commit comments