@@ -128,28 +128,33 @@ final class DisplayPowerController {
128128 private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f ;
129129
130130 // Light sensor event rate in microseconds.
131- private static final int LIGHT_SENSOR_RATE = 1000000 ;
131+ private static final int LIGHT_SENSOR_RATE = 500 * 1000 ;
132132
133133 // Brightness animation ramp rate in brightness units per second.
134134 private static final int BRIGHTNESS_RAMP_RATE_FAST = 200 ;
135- private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40 ;
135+ private static final int BRIGHTNESS_RAMP_RATE_SLOW = 30 ;
136136
137- // Filter time constant in milliseconds for computing a moving
138- // average of light samples. Different constants are used
139- // to calculate the average light level when adapting to brighter or
140- // dimmer environments .
141- // This parameter only controls the filtering of light samples .
142- private static final long BRIGHTENING_LIGHT_TIME_CONSTANT = 600 ;
143- private static final long DIMMING_LIGHT_TIME_CONSTANT = 4000 ;
137+ // IIR filter time constants in milliseconds for computing two moving averages of
138+ // the light samples. One is a long-term average and the other is a short-term average.
139+ // We can use these filters to assess trends in ambient brightness.
140+ // The short term average gives us a filtered but relatively low latency measurement .
141+ // The long term average informs us about the overall trend .
142+ private static final long SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 1000 ;
143+ private static final long LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 8000 ;
144144
145145 // Stability requirements in milliseconds for accepting a new brightness
146146 // level. This is used for debouncing the light sensor. Different constants
147- // are used to debounce the light sensor when adapting to brighter or dimmer
148- // environments.
147+ // are used to debounce the light sensor when adapting to brighter or darker environments.
149148 // This parameter controls how quickly brightness changes occur in response to
150- // an observed change in light level.
151- private static final long BRIGHTENING_LIGHT_DEBOUNCE = 2500 ;
152- private static final long DIMMING_LIGHT_DEBOUNCE = 10000 ;
149+ // an observed change in light level following a previous change in the opposite direction.
150+ private static final long BRIGHTENING_LIGHT_DEBOUNCE = 5000 ;
151+ private static final long DARKENING_LIGHT_DEBOUNCE = 15000 ;
152+
153+ // Hysteresis constraints for brightening or darkening.
154+ // The recent lux must have changed by at least this fraction relative to the
155+ // current ambient lux before a change will be considered.
156+ private static final float BRIGHTENING_LIGHT_HYSTERESIS = 0.10f ;
157+ private static final float DARKENING_LIGHT_HYSTERESIS = 0.20f ;
153158
154159 private final Object mLock = new Object ();
155160
@@ -284,39 +289,28 @@ final class DisplayPowerController {
284289 // The time when the light sensor was enabled.
285290 private long mLightSensorEnableTime ;
286291
287- // The currently accepted average light sensor value.
288- private float mLightMeasurement ;
289-
290- // True if the light sensor measurement is valid.
291- private boolean mLightMeasurementValid ;
292-
293- // The number of light sensor samples that have been collected since the
294- // last time a light sensor reading was accepted.
295- private int mRecentLightSamples ;
296-
297- // The moving average of recent light sensor values.
298- private float mRecentLightAverage ;
292+ // The currently accepted nominal ambient light level.
293+ private float mAmbientLux ;
299294
300- // True if recent light samples are getting brighter than the previous
301- // stable light measurement.
302- private boolean mRecentLightBrightening ;
295+ // True if mAmbientLux holds a valid value.
296+ private boolean mAmbientLuxValid ;
303297
304- // The time constant to use for filtering based on whether the
305- // light appears to be brightening or dimming.
306- private long mRecentLightTimeConstant ;
298+ // The time when the ambient lux was last brightened or darkened.
299+ private long mLastAmbientBrightenTime ;
300+ private long mLastAmbientDarkenTime ;
307301
308302 // The most recent light sample.
309- private float mLastLightSample ;
303+ private float mLastObservedLux ;
310304
311305 // The time of the most light recent sample.
312- private long mLastLightSampleTime ;
306+ private long mLastObservedLuxTime ;
313307
314- // The time when we accumulated the first recent light sample into mRecentLightSamples .
315- private long mFirstRecentLightSampleTime ;
308+ // The number of light samples collected since the light sensor was enabled .
309+ private int mRecentLightSamples ;
316310
317- // The upcoming debounce light sensor time .
318- // This is only valid when mLightMeasurementValue && mRecentLightSamples >= 1.
319- private long mPendingLightSensorDebounceTime ;
311+ // The long-term and short-term filtered light measurements .
312+ private float mRecentShortTermAverageLux ;
313+ private float mRecentLongTermAverageLux ;
320314
321315 // The screen brightness level that has been chosen by the auto-brightness
322316 // algorithm. The actual brightness should ramp towards this value.
@@ -873,7 +867,8 @@ private void setLightSensorEnabled(boolean enable, boolean updateAutoBrightness)
873867 } else {
874868 if (mLightSensorEnabled ) {
875869 mLightSensorEnabled = false ;
876- mLightMeasurementValid = false ;
870+ mAmbientLuxValid = false ;
871+ mRecentLightSamples = 0 ;
877872 mHandler .removeMessages (MSG_LIGHT_SENSOR_DEBOUNCED );
878873 mSensorManager .unregisterListener (mLightSensorListener );
879874 }
@@ -884,114 +879,99 @@ private void setLightSensorEnabled(boolean enable, boolean updateAutoBrightness)
884879 }
885880
886881 private void handleLightSensorEvent (long time , float lux ) {
887- // Take the first few readings during the warm-up period and apply them
888- // immediately without debouncing.
889- if (!mLightMeasurementValid
890- || (time - mLightSensorEnableTime ) < mLightSensorWarmUpTimeConfig ) {
891- mLightMeasurement = lux ;
892- mLightMeasurementValid = true ;
893- mRecentLightSamples = 0 ;
894- updateAutoBrightness (true );
882+ // Update our filters.
883+ mRecentLightSamples += 1 ;
884+ if (mRecentLightSamples == 1 ) {
885+ mRecentShortTermAverageLux = lux ;
886+ mRecentLongTermAverageLux = lux ;
887+ } else {
888+ final long timeDelta = time - mLastObservedLuxTime ;
889+ mRecentShortTermAverageLux += (lux - mRecentShortTermAverageLux )
890+ * timeDelta / (SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta );
891+ mRecentLongTermAverageLux += (lux - mRecentLongTermAverageLux )
892+ * timeDelta / (LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta );
895893 }
896894
897- // Update our moving average.
898- if (lux != mLightMeasurement && (mRecentLightSamples == 0
899- || (lux < mLightMeasurement && mRecentLightBrightening )
900- || (lux > mLightMeasurement && !mRecentLightBrightening ))) {
901- // If the newest light sample doesn't seem to be going in the
902- // same general direction as recent samples, then start over.
903- setRecentLight (time , lux , lux > mLightMeasurement );
904- } else if (mRecentLightSamples >= 1 ) {
905- // Add the newest light sample to the moving average.
906- accumulateRecentLight (time , lux );
907- }
908- if (DEBUG ) {
909- Slog .d (TAG , "handleLightSensorEvent: lux=" + lux
910- + ", mLightMeasurementValid=" + mLightMeasurementValid
911- + ", mLightMeasurement=" + mLightMeasurement
912- + ", mRecentLightSamples=" + mRecentLightSamples
913- + ", mRecentLightAverage=" + mRecentLightAverage
914- + ", mRecentLightBrightening=" + mRecentLightBrightening
915- + ", mRecentLightTimeConstant=" + mRecentLightTimeConstant
916- + ", mFirstRecentLightSampleTime="
917- + TimeUtils .formatUptime (mFirstRecentLightSampleTime )
918- + ", mPendingLightSensorDebounceTime="
919- + TimeUtils .formatUptime (mPendingLightSensorDebounceTime ));
920- }
895+ // Remember this sample value.
896+ mLastObservedLux = lux ;
897+ mLastObservedLuxTime = time ;
921898
922- // Debounce .
899+ // Update the ambient lux level .
923900 mHandler .removeMessages (MSG_LIGHT_SENSOR_DEBOUNCED );
924- debounceLightSensor ();
925- }
926-
927- private void setRecentLight (long time , float lux , boolean brightening ) {
928- mRecentLightBrightening = brightening ;
929- mRecentLightTimeConstant = brightening ?
930- BRIGHTENING_LIGHT_TIME_CONSTANT : DIMMING_LIGHT_TIME_CONSTANT ;
931- mRecentLightSamples = 1 ;
932- mRecentLightAverage = lux ;
933- mLastLightSample = lux ;
934- mLastLightSampleTime = time ;
935- mFirstRecentLightSampleTime = time ;
936- mPendingLightSensorDebounceTime = time + (brightening ?
937- BRIGHTENING_LIGHT_DEBOUNCE : DIMMING_LIGHT_DEBOUNCE );
901+ updateAmbientLux (time );
938902 }
939903
940- private void accumulateRecentLight (long time , float lux ) {
941- final long timeDelta = time - mLastLightSampleTime ;
942- mRecentLightSamples += 1 ;
943- mRecentLightAverage += (lux - mRecentLightAverage ) *
944- timeDelta / (mRecentLightTimeConstant + timeDelta );
945- mLastLightSample = lux ;
946- mLastLightSampleTime = time ;
947- }
948-
949- private void debounceLightSensor () {
950- if (mLightMeasurementValid && mRecentLightSamples >= 1 ) {
951- final long now = SystemClock .uptimeMillis ();
952- if (mPendingLightSensorDebounceTime <= now ) {
953- accumulateRecentLight (now , mLastLightSample );
954- mLightMeasurement = mRecentLightAverage ;
904+ private void updateAmbientLux (long time ) {
905+ // If the light sensor was just turned on then immediately update our initial
906+ // estimate of the current ambient light level.
907+ if (!mAmbientLuxValid
908+ || (time - mLightSensorEnableTime ) < mLightSensorWarmUpTimeConfig ) {
909+ if (DEBUG ) {
910+ Slog .d (TAG , "updateAmbientLux: Initializing, "
911+ + "mAmbientLux=" + (mAmbientLuxValid ? mAmbientLux : -1 )
912+ + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
913+ + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux );
914+ }
915+ mAmbientLux = mRecentShortTermAverageLux ;
916+ mAmbientLuxValid = true ;
917+ mLastAmbientBrightenTime = time ;
918+ mLastAmbientDarkenTime = time ;
919+ updateAutoBrightness (true );
920+ return ;
921+ }
955922
923+ // Determine whether the ambient environment appears to be brightening.
924+ float minAmbientLux = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS );
925+ if (mRecentShortTermAverageLux > minAmbientLux
926+ && mRecentLongTermAverageLux > minAmbientLux ) {
927+ long debounceTime = mLastAmbientDarkenTime + BRIGHTENING_LIGHT_DEBOUNCE ;
928+ if (time >= debounceTime ) {
956929 if (DEBUG ) {
957- Slog .d (TAG , "debounceLightSensor: Accepted new measurement "
958- + mLightMeasurement + " after "
959- + ( now - mFirstRecentLightSampleTime ) + " ms based on "
960- + mRecentLightSamples + " recent samples." );
930+ Slog .d (TAG , "updateAmbientLux: Brightened: "
931+ + "mAmbientLux=" + mAmbientLux
932+ + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
933+ + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux );
961934 }
962-
935+ mLastAmbientBrightenTime = time ;
936+ mAmbientLux = mRecentShortTermAverageLux ;
963937 updateAutoBrightness (true );
938+ } else {
939+ mHandler .sendEmptyMessageAtTime (MSG_LIGHT_SENSOR_DEBOUNCED , debounceTime );
940+ }
941+ return ;
942+ }
964943
965- // Now that we have debounced the light sensor data, we have the
966- // option of either leaving the sensor in a debounced state or
967- // restarting the debounce cycle by setting mRecentLightSamples to 0.
968- //
969- // If we leave the sensor debounced, then new average light measurements
970- // may be accepted immediately as long as they are trending in the same
971- // direction as they were before. If the measurements start
972- // jittering or trending in the opposite direction then the debounce
973- // cycle will automatically be restarted. The benefit is that the
974- // auto-brightness control can be more responsive to changes over a
975- // broad range.
976- //
977- // For now, we choose to be more responsive and leave the following line
978- // commented out.
979- //
980- // mRecentLightSamples = 0;
944+ // Determine whether the ambient environment appears to be darkening.
945+ float maxAmbientLux = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS );
946+ if (mRecentShortTermAverageLux < maxAmbientLux
947+ && mRecentLongTermAverageLux < maxAmbientLux ) {
948+ long debounceTime = mLastAmbientBrightenTime + DARKENING_LIGHT_DEBOUNCE ;
949+ if (time >= debounceTime ) {
950+ if (DEBUG ) {
951+ Slog .d (TAG , "updateAmbientLux: Darkened: "
952+ + "mAmbientLux=" + mAmbientLux
953+ + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
954+ + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux );
955+ }
956+ mLastAmbientDarkenTime = time ;
957+ mAmbientLux = mRecentShortTermAverageLux ;
958+ updateAutoBrightness (true );
981959 } else {
982- Message msg = mHandler .obtainMessage (MSG_LIGHT_SENSOR_DEBOUNCED );
983- msg .setAsynchronous (true );
984- mHandler .sendMessageAtTime (msg , mPendingLightSensorDebounceTime );
960+ mHandler .sendEmptyMessageAtTime (MSG_LIGHT_SENSOR_DEBOUNCED , debounceTime );
985961 }
986962 }
987963 }
988964
965+ private void debounceLightSensor () {
966+ updateAmbientLux (SystemClock .uptimeMillis ());
967+ }
968+
989969 private void updateAutoBrightness (boolean sendUpdate ) {
990- if (!mLightMeasurementValid ) {
970+ if (!mAmbientLuxValid ) {
991971 return ;
992972 }
993973
994- float value = mScreenAutoBrightnessSpline .interpolate (mLightMeasurement );
974+ float value = mScreenAutoBrightnessSpline .interpolate (mAmbientLux );
995975 float gamma = 1.0f ;
996976
997977 if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT
@@ -1031,7 +1011,7 @@ private void updateAutoBrightness(boolean sendUpdate) {
10311011 }
10321012
10331013 int newScreenAutoBrightness = clampScreenBrightness (
1034- ( int ) Math .round (value * PowerManager .BRIGHTNESS_ON ));
1014+ Math .round (value * PowerManager .BRIGHTNESS_ON ));
10351015 if (mScreenAutoBrightness != newScreenAutoBrightness ) {
10361016 if (DEBUG ) {
10371017 Slog .d (TAG , "updateAutoBrightness: mScreenAutoBrightness="
@@ -1152,19 +1132,18 @@ private void dumpLocal(PrintWriter pw) {
11521132 pw .println (" mLightSensorEnabled=" + mLightSensorEnabled );
11531133 pw .println (" mLightSensorEnableTime="
11541134 + TimeUtils .formatUptime (mLightSensorEnableTime ));
1155- pw .println (" mLightMeasurement=" + mLightMeasurement );
1156- pw .println (" mLightMeasurementValid=" + mLightMeasurementValid );
1157- pw .println (" mLastLightSample=" + mLastLightSample );
1158- pw .println (" mLastLightSampleTime="
1159- + TimeUtils .formatUptime (mLastLightSampleTime ));
1135+ pw .println (" mAmbientLux=" + mAmbientLux );
1136+ pw .println (" mAmbientLuxValid=" + mAmbientLuxValid );
1137+ pw .println (" mLastAmbientBrightenTime="
1138+ + TimeUtils .formatUptime (mLastAmbientBrightenTime ));
1139+ pw .println (" mLastAmbientDimTime="
1140+ + TimeUtils .formatUptime (mLastAmbientDarkenTime ));
1141+ pw .println (" mLastObservedLux=" + mLastObservedLux );
1142+ pw .println (" mLastObservedLuxTime="
1143+ + TimeUtils .formatUptime (mLastObservedLuxTime ));
11601144 pw .println (" mRecentLightSamples=" + mRecentLightSamples );
1161- pw .println (" mRecentLightAverage=" + mRecentLightAverage );
1162- pw .println (" mRecentLightBrightening=" + mRecentLightBrightening );
1163- pw .println (" mRecentLightTimeConstant=" + mRecentLightTimeConstant );
1164- pw .println (" mFirstRecentLightSampleTime="
1165- + TimeUtils .formatUptime (mFirstRecentLightSampleTime ));
1166- pw .println (" mPendingLightSensorDebounceTime="
1167- + TimeUtils .formatUptime (mPendingLightSensorDebounceTime ));
1145+ pw .println (" mRecentShortTermAverageLux=" + mRecentShortTermAverageLux );
1146+ pw .println (" mRecentLongTermAverageLux=" + mRecentLongTermAverageLux );
11681147 pw .println (" mScreenAutoBrightness=" + mScreenAutoBrightness );
11691148 pw .println (" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness );
11701149 pw .println (" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma );
0 commit comments