• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.power;
18 
19 import com.android.server.LightsService;
20 import com.android.server.TwilightService;
21 import com.android.server.TwilightService.TwilightState;
22 import com.android.server.display.DisplayManagerService;
23 
24 import android.animation.Animator;
25 import android.animation.ObjectAnimator;
26 import android.content.Context;
27 import android.content.res.Resources;
28 import android.hardware.Sensor;
29 import android.hardware.SensorEvent;
30 import android.hardware.SensorEventListener;
31 import android.hardware.SensorManager;
32 import android.hardware.SystemSensorManager;
33 import android.os.Handler;
34 import android.os.Looper;
35 import android.os.Message;
36 import android.os.PowerManager;
37 import android.os.SystemClock;
38 import android.text.format.DateUtils;
39 import android.util.FloatMath;
40 import android.util.Slog;
41 import android.util.Spline;
42 import android.util.TimeUtils;
43 
44 import java.io.PrintWriter;
45 
46 /**
47  * Controls the power state of the display.
48  *
49  * Handles the proximity sensor, light sensor, and animations between states
50  * including the screen off animation.
51  *
52  * This component acts independently of the rest of the power manager service.
53  * In particular, it does not share any state and it only communicates
54  * via asynchronous callbacks to inform the power manager that something has
55  * changed.
56  *
57  * Everything this class does internally is serialized on its handler although
58  * it may be accessed by other threads from the outside.
59  *
60  * Note that the power manager service guarantees that it will hold a suspend
61  * blocker as long as the display is not ready.  So most of the work done here
62  * does not need to worry about holding a suspend blocker unless it happens
63  * independently of the display ready signal.
64  *
65  * For debugging, you can make the electron beam and brightness animations run
66  * slower by changing the "animator duration scale" option in Development Settings.
67  */
68 final class DisplayPowerController {
69     private static final String TAG = "DisplayPowerController";
70 
71     private static boolean DEBUG = false;
72     private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
73     private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false;
74 
75     // If true, uses the electron beam on animation.
76     // We might want to turn this off if we cannot get a guarantee that the screen
77     // actually turns on and starts showing new content after the call to set the
78     // screen state returns.  Playing the animation can also be somewhat slow.
79     private static final boolean USE_ELECTRON_BEAM_ON_ANIMATION = false;
80 
81     // If true, enables the use of the screen auto-brightness adjustment setting.
82     private static final boolean USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT =
83             PowerManager.useScreenAutoBrightnessAdjustmentFeature();
84 
85     // The maximum range of gamma adjustment possible using the screen
86     // auto-brightness adjustment setting.
87     private static final float SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA = 3.0f;
88 
89     // The minimum reduction in brightness when dimmed.
90     private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10;
91 
92     // If true, enables the use of the current time as an auto-brightness adjustment.
93     // The basic idea here is to expand the dynamic range of auto-brightness
94     // when it is especially dark outside.  The light sensor tends to perform
95     // poorly at low light levels so we compensate for it by making an
96     // assumption about the environment.
97     private static final boolean USE_TWILIGHT_ADJUSTMENT =
98             PowerManager.useTwilightAdjustmentFeature();
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 
109     private static final int ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS = 250;
110     private static final int ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS = 400;
111 
112     private static final int MSG_UPDATE_POWER_STATE = 1;
113     private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
114     private static final int MSG_LIGHT_SENSOR_DEBOUNCED = 3;
115 
116     private static final int PROXIMITY_UNKNOWN = -1;
117     private static final int PROXIMITY_NEGATIVE = 0;
118     private static final int PROXIMITY_POSITIVE = 1;
119 
120     // Proximity sensor debounce delay in milliseconds for positive or negative transitions.
121     private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0;
122     private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 500;
123 
124     // Trigger proximity if distance is less than 5 cm.
125     private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
126 
127     // Light sensor event rate in milliseconds.
128     private static final int LIGHT_SENSOR_RATE_MILLIS = 1000;
129 
130     // A rate for generating synthetic light sensor events in the case where the light
131     // sensor hasn't reported any new data in a while and we need it to update the
132     // debounce filter.  We only synthesize light sensor measurements when needed.
133     private static final int SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS =
134             LIGHT_SENSOR_RATE_MILLIS * 2;
135 
136     // Brightness animation ramp rate in brightness units per second.
137     private static final int BRIGHTNESS_RAMP_RATE_FAST = 200;
138     private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
139 
140     // IIR filter time constants in milliseconds for computing two moving averages of
141     // the light samples.  One is a long-term average and the other is a short-term average.
142     // We can use these filters to assess trends in ambient brightness.
143     // The short term average gives us a filtered but relatively low latency measurement.
144     // The long term average informs us about the overall trend.
145     private static final long SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 1000;
146     private static final long LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 5000;
147 
148     // Stability requirements in milliseconds for accepting a new brightness
149     // level.  This is used for debouncing the light sensor.  Different constants
150     // are used to debounce the light sensor when adapting to brighter or darker environments.
151     // This parameter controls how quickly brightness changes occur in response to
152     // an observed change in light level that exceeds the hysteresis threshold.
153     private static final long BRIGHTENING_LIGHT_DEBOUNCE = 4000;
154     private static final long DARKENING_LIGHT_DEBOUNCE = 8000;
155 
156     // Hysteresis constraints for brightening or darkening.
157     // The recent lux must have changed by at least this fraction relative to the
158     // current ambient lux before a change will be considered.
159     private static final float BRIGHTENING_LIGHT_HYSTERESIS = 0.10f;
160     private static final float DARKENING_LIGHT_HYSTERESIS = 0.20f;
161 
162     private final Object mLock = new Object();
163 
164     // Notifier for sending asynchronous notifications.
165     private final Notifier mNotifier;
166 
167     // The display blanker.
168     private final DisplayBlanker mDisplayBlanker;
169 
170     // Our handler.
171     private final DisplayControllerHandler mHandler;
172 
173     // Asynchronous callbacks into the power manager service.
174     // Only invoked from the handler thread while no locks are held.
175     private final Callbacks mCallbacks;
176     private Handler mCallbackHandler;
177 
178     // The lights service.
179     private final LightsService mLights;
180 
181     // The twilight service.
182     private final TwilightService mTwilight;
183 
184     // The display manager.
185     private final DisplayManagerService mDisplayManager;
186 
187     // The sensor manager.
188     private final SensorManager mSensorManager;
189 
190     // The proximity sensor, or null if not available or needed.
191     private Sensor mProximitySensor;
192 
193     // The light sensor, or null if not available or needed.
194     private Sensor mLightSensor;
195 
196     // The dim screen brightness.
197     private final int mScreenBrightnessDimConfig;
198 
199     // The minimum allowed brightness.
200     private final int mScreenBrightnessRangeMinimum;
201 
202     // The maximum allowed brightness.
203     private final int mScreenBrightnessRangeMaximum;
204 
205     // True if auto-brightness should be used.
206     private boolean mUseSoftwareAutoBrightnessConfig;
207 
208     // The auto-brightness spline adjustment.
209     // The brightness values have been scaled to a range of 0..1.
210     private Spline mScreenAutoBrightnessSpline;
211 
212     // Amount of time to delay auto-brightness after screen on while waiting for
213     // the light sensor to warm-up in milliseconds.
214     // May be 0 if no warm-up is required.
215     private int mLightSensorWarmUpTimeConfig;
216 
217     // True if we should fade the screen while turning it off, false if we should play
218     // a stylish electron beam animation instead.
219     private boolean mElectronBeamFadesConfig;
220 
221     // The pending power request.
222     // Initially null until the first call to requestPowerState.
223     // Guarded by mLock.
224     private DisplayPowerRequest mPendingRequestLocked;
225 
226     // True if a request has been made to wait for the proximity sensor to go negative.
227     // Guarded by mLock.
228     private boolean mPendingWaitForNegativeProximityLocked;
229 
230     // True if the pending power request or wait for negative proximity flag
231     // has been changed since the last update occurred.
232     // Guarded by mLock.
233     private boolean mPendingRequestChangedLocked;
234 
235     // Set to true when the important parts of the pending power request have been applied.
236     // The important parts are mainly the screen state.  Brightness changes may occur
237     // concurrently.
238     // Guarded by mLock.
239     private boolean mDisplayReadyLocked;
240 
241     // Set to true if a power state update is required.
242     // Guarded by mLock.
243     private boolean mPendingUpdatePowerStateLocked;
244 
245     /* The following state must only be accessed by the handler thread. */
246 
247     // The currently requested power state.
248     // The power controller will progressively update its internal state to match
249     // the requested power state.  Initially null until the first update.
250     private DisplayPowerRequest mPowerRequest;
251 
252     // The current power state.
253     // Must only be accessed on the handler thread.
254     private DisplayPowerState mPowerState;
255 
256     // True if the device should wait for negative proximity sensor before
257     // waking up the screen.  This is set to false as soon as a negative
258     // proximity sensor measurement is observed or when the device is forced to
259     // go to sleep by the user.  While true, the screen remains off.
260     private boolean mWaitingForNegativeProximity;
261 
262     // The actual proximity sensor threshold value.
263     private float mProximityThreshold;
264 
265     // Set to true if the proximity sensor listener has been registered
266     // with the sensor manager.
267     private boolean mProximitySensorEnabled;
268 
269     // The debounced proximity sensor state.
270     private int mProximity = PROXIMITY_UNKNOWN;
271 
272     // The raw non-debounced proximity sensor state.
273     private int mPendingProximity = PROXIMITY_UNKNOWN;
274     private long mPendingProximityDebounceTime;
275 
276     // True if the screen was turned off because of the proximity sensor.
277     // When the screen turns on again, we report user activity to the power manager.
278     private boolean mScreenOffBecauseOfProximity;
279 
280     // True if the screen on is being blocked.
281     private boolean mScreenOnWasBlocked;
282 
283     // The elapsed real time when the screen on was blocked.
284     private long mScreenOnBlockStartRealTime;
285 
286     // Set to true if the light sensor is enabled.
287     private boolean mLightSensorEnabled;
288 
289     // The time when the light sensor was enabled.
290     private long mLightSensorEnableTime;
291 
292     // The currently accepted nominal ambient light level.
293     private float mAmbientLux;
294 
295     // True if mAmbientLux holds a valid value.
296     private boolean mAmbientLuxValid;
297 
298     // The most recent light sample.
299     private float mLastObservedLux;
300 
301     // The time of the most light recent sample.
302     private long mLastObservedLuxTime;
303 
304     // The number of light samples collected since the light sensor was enabled.
305     private int mRecentLightSamples;
306 
307     // The long-term and short-term filtered light measurements.
308     private float mRecentShortTermAverageLux;
309     private float mRecentLongTermAverageLux;
310 
311     // The direction in which the average lux is moving relative to the current ambient lux.
312     //    0 if not changing or within hysteresis threshold.
313     //    1 if brightening beyond hysteresis threshold.
314     //   -1 if darkening beyond hysteresis threshold.
315     private int mDebounceLuxDirection;
316 
317     // The time when the average lux last changed direction.
318     private long mDebounceLuxTime;
319 
320     // The screen brightness level that has been chosen by the auto-brightness
321     // algorithm.  The actual brightness should ramp towards this value.
322     // We preserve this value even when we stop using the light sensor so
323     // that we can quickly revert to the previous auto-brightness level
324     // while the light sensor warms up.
325     // Use -1 if there is no current auto-brightness value available.
326     private int mScreenAutoBrightness = -1;
327 
328     // The last screen auto-brightness gamma.  (For printing in dump() only.)
329     private float mLastScreenAutoBrightnessGamma = 1.0f;
330 
331     // True if the screen auto-brightness value is actually being used to
332     // set the display brightness.
333     private boolean mUsingScreenAutoBrightness;
334 
335     // Animators.
336     private ObjectAnimator mElectronBeamOnAnimator;
337     private ObjectAnimator mElectronBeamOffAnimator;
338     private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
339 
340     // Twilight changed.  We might recalculate auto-brightness values.
341     private boolean mTwilightChanged;
342 
343     /**
344      * Creates the display power controller.
345      */
DisplayPowerController(Looper looper, Context context, Notifier notifier, LightsService lights, TwilightService twilight, SensorManager sensorManager, DisplayManagerService displayManager, DisplayBlanker displayBlanker, Callbacks callbacks, Handler callbackHandler)346     public DisplayPowerController(Looper looper, Context context, Notifier notifier,
347             LightsService lights, TwilightService twilight, SensorManager sensorManager,
348             DisplayManagerService displayManager,
349             DisplayBlanker displayBlanker,
350             Callbacks callbacks, Handler callbackHandler) {
351         mHandler = new DisplayControllerHandler(looper);
352         mNotifier = notifier;
353         mDisplayBlanker = displayBlanker;
354         mCallbacks = callbacks;
355         mCallbackHandler = callbackHandler;
356 
357         mLights = lights;
358         mTwilight = twilight;
359         mSensorManager = sensorManager;
360         mDisplayManager = displayManager;
361 
362         final Resources resources = context.getResources();
363 
364         mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger(
365                 com.android.internal.R.integer.config_screenBrightnessDim));
366 
367         int screenBrightnessMinimum = Math.min(resources.getInteger(
368                 com.android.internal.R.integer.config_screenBrightnessSettingMinimum),
369                 mScreenBrightnessDimConfig);
370 
371         mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
372                 com.android.internal.R.bool.config_automatic_brightness_available);
373         if (mUseSoftwareAutoBrightnessConfig) {
374             int[] lux = resources.getIntArray(
375                     com.android.internal.R.array.config_autoBrightnessLevels);
376             int[] screenBrightness = resources.getIntArray(
377                     com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
378 
379             mScreenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
380             if (mScreenAutoBrightnessSpline == null) {
381                 Slog.e(TAG, "Error in config.xml.  config_autoBrightnessLcdBacklightValues "
382                         + "(size " + screenBrightness.length + ") "
383                         + "must be monotic and have exactly one more entry than "
384                         + "config_autoBrightnessLevels (size " + lux.length + ") "
385                         + "which must be strictly increasing.  "
386                         + "Auto-brightness will be disabled.");
387                 mUseSoftwareAutoBrightnessConfig = false;
388             } else {
389                 if (screenBrightness[0] < screenBrightnessMinimum) {
390                     screenBrightnessMinimum = screenBrightness[0];
391                 }
392             }
393 
394             mLightSensorWarmUpTimeConfig = resources.getInteger(
395                     com.android.internal.R.integer.config_lightSensorWarmupTime);
396         }
397 
398         mScreenBrightnessRangeMinimum = clampAbsoluteBrightness(screenBrightnessMinimum);
399         mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON;
400 
401         mElectronBeamFadesConfig = resources.getBoolean(
402                 com.android.internal.R.bool.config_animateScreenLights);
403 
404         if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
405             mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
406             if (mProximitySensor != null) {
407                 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
408                         TYPICAL_PROXIMITY_THRESHOLD);
409             }
410         }
411 
412         if (mUseSoftwareAutoBrightnessConfig
413                 && !DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
414             mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
415         }
416 
417         if (mUseSoftwareAutoBrightnessConfig && USE_TWILIGHT_ADJUSTMENT) {
418             mTwilight.registerListener(mTwilightListener, mHandler);
419         }
420     }
421 
createAutoBrightnessSpline(int[] lux, int[] brightness)422     private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) {
423         try {
424             final int n = brightness.length;
425             float[] x = new float[n];
426             float[] y = new float[n];
427             y[0] = normalizeAbsoluteBrightness(brightness[0]);
428             for (int i = 1; i < n; i++) {
429                 x[i] = lux[i - 1];
430                 y[i] = normalizeAbsoluteBrightness(brightness[i]);
431             }
432 
433             Spline spline = Spline.createMonotoneCubicSpline(x, y);
434             if (DEBUG) {
435                 Slog.d(TAG, "Auto-brightness spline: " + spline);
436                 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
437                     Slog.d(TAG, String.format("  %7.1f: %7.1f", v, spline.interpolate(v)));
438                 }
439             }
440             return spline;
441         } catch (IllegalArgumentException ex) {
442             Slog.e(TAG, "Could not create auto-brightness spline.", ex);
443             return null;
444         }
445     }
446 
447     /**
448      * Returns true if the proximity sensor screen-off function is available.
449      */
isProximitySensorAvailable()450     public boolean isProximitySensorAvailable() {
451         return mProximitySensor != null;
452     }
453 
454     /**
455      * Requests a new power state.
456      * The controller makes a copy of the provided object and then
457      * begins adjusting the power state to match what was requested.
458      *
459      * @param request The requested power state.
460      * @param waitForNegativeProximity If true, issues a request to wait for
461      * negative proximity before turning the screen back on, assuming the screen
462      * was turned off by the proximity sensor.
463      * @return True if display is ready, false if there are important changes that must
464      * be made asynchronously (such as turning the screen on), in which case the caller
465      * should grab a wake lock, watch for {@link Callbacks#onStateChanged()} then try
466      * the request again later until the state converges.
467      */
requestPowerState(DisplayPowerRequest request, boolean waitForNegativeProximity)468     public boolean requestPowerState(DisplayPowerRequest request,
469             boolean waitForNegativeProximity) {
470         if (DEBUG) {
471             Slog.d(TAG, "requestPowerState: "
472                     + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
473         }
474 
475         synchronized (mLock) {
476             boolean changed = false;
477 
478             if (waitForNegativeProximity
479                     && !mPendingWaitForNegativeProximityLocked) {
480                 mPendingWaitForNegativeProximityLocked = true;
481                 changed = true;
482             }
483 
484             if (mPendingRequestLocked == null) {
485                 mPendingRequestLocked = new DisplayPowerRequest(request);
486                 changed = true;
487             } else if (!mPendingRequestLocked.equals(request)) {
488                 mPendingRequestLocked.copyFrom(request);
489                 changed = true;
490             }
491 
492             if (changed) {
493                 mDisplayReadyLocked = false;
494             }
495 
496             if (changed && !mPendingRequestChangedLocked) {
497                 mPendingRequestChangedLocked = true;
498                 sendUpdatePowerStateLocked();
499             }
500 
501             return mDisplayReadyLocked;
502         }
503     }
504 
sendUpdatePowerState()505     private void sendUpdatePowerState() {
506         synchronized (mLock) {
507             sendUpdatePowerStateLocked();
508         }
509     }
510 
sendUpdatePowerStateLocked()511     private void sendUpdatePowerStateLocked() {
512         if (!mPendingUpdatePowerStateLocked) {
513             mPendingUpdatePowerStateLocked = true;
514             Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
515             msg.setAsynchronous(true);
516             mHandler.sendMessage(msg);
517         }
518     }
519 
initialize()520     private void initialize() {
521         mPowerState = new DisplayPowerState(
522                 new ElectronBeam(mDisplayManager), mDisplayBlanker,
523                 mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT));
524 
525         mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
526                 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f);
527         mElectronBeamOnAnimator.setDuration(ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS);
528         mElectronBeamOnAnimator.addListener(mAnimatorListener);
529 
530         mElectronBeamOffAnimator = ObjectAnimator.ofFloat(
531                 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 1.0f, 0.0f);
532         mElectronBeamOffAnimator.setDuration(ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS);
533         mElectronBeamOffAnimator.addListener(mAnimatorListener);
534 
535         mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
536                 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
537     }
538 
539     private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
540         @Override
541         public void onAnimationStart(Animator animation) {
542         }
543         @Override
544         public void onAnimationEnd(Animator animation) {
545             sendUpdatePowerState();
546         }
547         @Override
548         public void onAnimationRepeat(Animator animation) {
549         }
550         @Override
551         public void onAnimationCancel(Animator animation) {
552         }
553     };
554 
updatePowerState()555     private void updatePowerState() {
556         // Update the power state request.
557         final boolean mustNotify;
558         boolean mustInitialize = false;
559         boolean updateAutoBrightness = mTwilightChanged;
560         boolean wasDim = false;
561         mTwilightChanged = false;
562 
563         synchronized (mLock) {
564             mPendingUpdatePowerStateLocked = false;
565             if (mPendingRequestLocked == null) {
566                 return; // wait until first actual power request
567             }
568 
569             if (mPowerRequest == null) {
570                 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
571                 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
572                 mPendingWaitForNegativeProximityLocked = false;
573                 mPendingRequestChangedLocked = false;
574                 mustInitialize = true;
575             } else if (mPendingRequestChangedLocked) {
576                 if (mPowerRequest.screenAutoBrightnessAdjustment
577                         != mPendingRequestLocked.screenAutoBrightnessAdjustment) {
578                     updateAutoBrightness = true;
579                 }
580                 wasDim = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM);
581                 mPowerRequest.copyFrom(mPendingRequestLocked);
582                 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
583                 mPendingWaitForNegativeProximityLocked = false;
584                 mPendingRequestChangedLocked = false;
585                 mDisplayReadyLocked = false;
586             }
587 
588             mustNotify = !mDisplayReadyLocked;
589         }
590 
591         // Initialize things the first time the power state is changed.
592         if (mustInitialize) {
593             initialize();
594         }
595 
596         // Apply the proximity sensor.
597         if (mProximitySensor != null) {
598             if (mPowerRequest.useProximitySensor
599                     && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
600                 setProximitySensorEnabled(true);
601                 if (!mScreenOffBecauseOfProximity
602                         && mProximity == PROXIMITY_POSITIVE) {
603                     mScreenOffBecauseOfProximity = true;
604                     sendOnProximityPositive();
605                     setScreenOn(false);
606                 }
607             } else if (mWaitingForNegativeProximity
608                     && mScreenOffBecauseOfProximity
609                     && mProximity == PROXIMITY_POSITIVE
610                     && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
611                 setProximitySensorEnabled(true);
612             } else {
613                 setProximitySensorEnabled(false);
614                 mWaitingForNegativeProximity = false;
615             }
616             if (mScreenOffBecauseOfProximity
617                     && mProximity != PROXIMITY_POSITIVE) {
618                 mScreenOffBecauseOfProximity = false;
619                 sendOnProximityNegative();
620             }
621         } else {
622             mWaitingForNegativeProximity = false;
623         }
624 
625         // Turn on the light sensor if needed.
626         if (mLightSensor != null) {
627             setLightSensorEnabled(mPowerRequest.useAutoBrightness
628                     && wantScreenOn(mPowerRequest.screenState), updateAutoBrightness);
629         }
630 
631         // Set the screen brightness.
632         if (wantScreenOn(mPowerRequest.screenState)) {
633             int target;
634             boolean slow;
635             if (mScreenAutoBrightness >= 0 && mLightSensorEnabled) {
636                 // Use current auto-brightness value.
637                 target = mScreenAutoBrightness;
638                 slow = mUsingScreenAutoBrightness;
639                 mUsingScreenAutoBrightness = true;
640             } else {
641                 // Light sensor is disabled or not ready yet.
642                 // Use the current brightness setting from the request, which is expected
643                 // provide a nominal default value for the case where auto-brightness
644                 // is not ready yet.
645                 target = mPowerRequest.screenBrightness;
646                 slow = false;
647                 mUsingScreenAutoBrightness = false;
648             }
649             if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) {
650                 // Dim quickly by at least some minimum amount.
651                 target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION,
652                         mScreenBrightnessDimConfig);
653                 slow = false;
654             } else if (wasDim) {
655                 // Brighten quickly.
656                 slow = false;
657             }
658             animateScreenBrightness(clampScreenBrightness(target),
659                     slow ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
660         } else {
661             // Screen is off.  Don't bother changing the brightness.
662             mUsingScreenAutoBrightness = false;
663         }
664 
665         // Animate the screen on or off.
666         if (!mScreenOffBecauseOfProximity) {
667             if (wantScreenOn(mPowerRequest.screenState)) {
668                 // Want screen on.
669                 // Wait for previous off animation to complete beforehand.
670                 // It is relatively short but if we cancel it and switch to the
671                 // on animation immediately then the results are pretty ugly.
672                 if (!mElectronBeamOffAnimator.isStarted()) {
673                     // Turn the screen on.  The contents of the screen may not yet
674                     // be visible if the electron beam has not been dismissed because
675                     // its last frame of animation is solid black.
676                     setScreenOn(true);
677 
678                     if (mPowerRequest.blockScreenOn
679                             && mPowerState.getElectronBeamLevel() == 0.0f) {
680                         blockScreenOn();
681                     } else {
682                         unblockScreenOn();
683                         if (USE_ELECTRON_BEAM_ON_ANIMATION) {
684                             if (!mElectronBeamOnAnimator.isStarted()) {
685                                 if (mPowerState.getElectronBeamLevel() == 1.0f) {
686                                     mPowerState.dismissElectronBeam();
687                                 } else if (mPowerState.prepareElectronBeam(
688                                         mElectronBeamFadesConfig ?
689                                                 ElectronBeam.MODE_FADE :
690                                                         ElectronBeam.MODE_WARM_UP)) {
691                                     mElectronBeamOnAnimator.start();
692                                 } else {
693                                     mElectronBeamOnAnimator.end();
694                                 }
695                             }
696                         } else {
697                             mPowerState.setElectronBeamLevel(1.0f);
698                             mPowerState.dismissElectronBeam();
699                         }
700                     }
701                 }
702             } else {
703                 // Want screen off.
704                 // Wait for previous on animation to complete beforehand.
705                 if (!mElectronBeamOnAnimator.isStarted()) {
706                     if (!mElectronBeamOffAnimator.isStarted()) {
707                         if (mPowerState.getElectronBeamLevel() == 0.0f) {
708                             setScreenOn(false);
709                         } else if (mPowerState.prepareElectronBeam(
710                                 mElectronBeamFadesConfig ?
711                                         ElectronBeam.MODE_FADE :
712                                                 ElectronBeam.MODE_COOL_DOWN)
713                                 && mPowerState.isScreenOn()) {
714                             mElectronBeamOffAnimator.start();
715                         } else {
716                             mElectronBeamOffAnimator.end();
717                         }
718                     }
719                 }
720             }
721         }
722 
723         // Report whether the display is ready for use.
724         // We mostly care about the screen state here, ignoring brightness changes
725         // which will be handled asynchronously.
726         if (mustNotify
727                 && !mScreenOnWasBlocked
728                 && !mElectronBeamOnAnimator.isStarted()
729                 && !mElectronBeamOffAnimator.isStarted()
730                 && mPowerState.waitUntilClean(mCleanListener)) {
731             synchronized (mLock) {
732                 if (!mPendingRequestChangedLocked) {
733                     mDisplayReadyLocked = true;
734 
735                     if (DEBUG) {
736                         Slog.d(TAG, "Display ready!");
737                     }
738                 }
739             }
740             sendOnStateChanged();
741         }
742     }
743 
blockScreenOn()744     private void blockScreenOn() {
745         if (!mScreenOnWasBlocked) {
746             mScreenOnWasBlocked = true;
747             if (DEBUG) {
748                 Slog.d(TAG, "Blocked screen on.");
749                 mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
750             }
751         }
752     }
753 
unblockScreenOn()754     private void unblockScreenOn() {
755         if (mScreenOnWasBlocked) {
756             mScreenOnWasBlocked = false;
757             if (DEBUG) {
758                 Slog.d(TAG, "Unblocked screen on after " +
759                         (SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime) + " ms");
760             }
761         }
762     }
763 
setScreenOn(boolean on)764     private void setScreenOn(boolean on) {
765         if (!mPowerState.isScreenOn() == on) {
766             mPowerState.setScreenOn(on);
767             if (on) {
768                 mNotifier.onScreenOn();
769             } else {
770                 mNotifier.onScreenOff();
771             }
772         }
773     }
774 
clampScreenBrightness(int value)775     private int clampScreenBrightness(int value) {
776         return clamp(value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
777     }
778 
clampAbsoluteBrightness(int value)779     private static int clampAbsoluteBrightness(int value) {
780         return clamp(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
781     }
782 
clamp(int value, int min, int max)783     private static int clamp(int value, int min, int max) {
784         if (value <= min) {
785             return min;
786         }
787         if (value >= max) {
788             return max;
789         }
790         return value;
791     }
792 
normalizeAbsoluteBrightness(int value)793     private static float normalizeAbsoluteBrightness(int value) {
794         return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON;
795     }
796 
animateScreenBrightness(int target, int rate)797     private void animateScreenBrightness(int target, int rate) {
798         if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
799             mNotifier.onScreenBrightness(target);
800         }
801     }
802 
803     private final Runnable mCleanListener = new Runnable() {
804         @Override
805         public void run() {
806             sendUpdatePowerState();
807         }
808     };
809 
setProximitySensorEnabled(boolean enable)810     private void setProximitySensorEnabled(boolean enable) {
811         if (enable) {
812             if (!mProximitySensorEnabled) {
813                 mProximitySensorEnabled = true;
814                 mPendingProximity = PROXIMITY_UNKNOWN;
815                 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
816                         SensorManager.SENSOR_DELAY_NORMAL, mHandler);
817             }
818         } else {
819             if (mProximitySensorEnabled) {
820                 mProximitySensorEnabled = false;
821                 mProximity = PROXIMITY_UNKNOWN;
822                 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
823                 mSensorManager.unregisterListener(mProximitySensorListener);
824             }
825         }
826     }
827 
handleProximitySensorEvent(long time, boolean positive)828     private void handleProximitySensorEvent(long time, boolean positive) {
829         if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
830             return; // no change
831         }
832         if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
833             return; // no change
834         }
835 
836         // Only accept a proximity sensor reading if it remains
837         // stable for the entire debounce delay.
838         mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
839         if (positive) {
840             mPendingProximity = PROXIMITY_POSITIVE;
841             mPendingProximityDebounceTime = time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY;
842         } else {
843             mPendingProximity = PROXIMITY_NEGATIVE;
844             mPendingProximityDebounceTime = time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY;
845         }
846         debounceProximitySensor();
847     }
848 
debounceProximitySensor()849     private void debounceProximitySensor() {
850         if (mPendingProximity != PROXIMITY_UNKNOWN) {
851             final long now = SystemClock.uptimeMillis();
852             if (mPendingProximityDebounceTime <= now) {
853                 mProximity = mPendingProximity;
854                 sendUpdatePowerState();
855             } else {
856                 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
857                 msg.setAsynchronous(true);
858                 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
859             }
860         }
861     }
862 
setLightSensorEnabled(boolean enable, boolean updateAutoBrightness)863     private void setLightSensorEnabled(boolean enable, boolean updateAutoBrightness) {
864         if (enable) {
865             if (!mLightSensorEnabled) {
866                 updateAutoBrightness = true;
867                 mLightSensorEnabled = true;
868                 mLightSensorEnableTime = SystemClock.uptimeMillis();
869                 mSensorManager.registerListener(mLightSensorListener, mLightSensor,
870                         LIGHT_SENSOR_RATE_MILLIS * 1000, mHandler);
871             }
872         } else {
873             if (mLightSensorEnabled) {
874                 mLightSensorEnabled = false;
875                 mAmbientLuxValid = false;
876                 mRecentLightSamples = 0;
877                 mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
878                 mSensorManager.unregisterListener(mLightSensorListener);
879             }
880         }
881         if (updateAutoBrightness) {
882             updateAutoBrightness(false);
883         }
884     }
885 
handleLightSensorEvent(long time, float lux)886     private void handleLightSensorEvent(long time, float lux) {
887         mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
888 
889         applyLightSensorMeasurement(time, lux);
890         updateAmbientLux(time);
891     }
892 
applyLightSensorMeasurement(long time, float lux)893     private void applyLightSensorMeasurement(long time, float lux) {
894         // Update our filters.
895         mRecentLightSamples += 1;
896         if (mRecentLightSamples == 1) {
897             mRecentShortTermAverageLux = lux;
898             mRecentLongTermAverageLux = lux;
899         } else {
900             final long timeDelta = time - mLastObservedLuxTime;
901             mRecentShortTermAverageLux += (lux - mRecentShortTermAverageLux)
902                     * timeDelta / (SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta);
903             mRecentLongTermAverageLux += (lux - mRecentLongTermAverageLux)
904                     * timeDelta / (LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta);
905         }
906 
907         // Remember this sample value.
908         mLastObservedLux = lux;
909         mLastObservedLuxTime = time;
910     }
911 
updateAmbientLux(long time)912     private void updateAmbientLux(long time) {
913         // If the light sensor was just turned on then immediately update our initial
914         // estimate of the current ambient light level.
915         if (!mAmbientLuxValid
916                 || (time - mLightSensorEnableTime) < mLightSensorWarmUpTimeConfig) {
917             mAmbientLux = mRecentShortTermAverageLux;
918             mAmbientLuxValid = true;
919             mDebounceLuxDirection = 0;
920             mDebounceLuxTime = time;
921             if (DEBUG) {
922                 Slog.d(TAG, "updateAmbientLux: Initializing: "
923                         + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
924                         + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
925                         + ", mAmbientLux=" + mAmbientLux);
926             }
927             updateAutoBrightness(true);
928             return;
929         }
930 
931         // Determine whether the ambient environment appears to be brightening.
932         float brighteningLuxThreshold = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS);
933         if (mRecentShortTermAverageLux > brighteningLuxThreshold
934                 && mRecentLongTermAverageLux > brighteningLuxThreshold) {
935             if (mDebounceLuxDirection <= 0) {
936                 mDebounceLuxDirection = 1;
937                 mDebounceLuxTime = time;
938                 if (DEBUG) {
939                     Slog.d(TAG, "updateAmbientLux: Possibly brightened, waiting for "
940                             + BRIGHTENING_LIGHT_DEBOUNCE + " ms: "
941                             + "brighteningLuxThreshold=" + brighteningLuxThreshold
942                             + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
943                             + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
944                             + ", mAmbientLux=" + mAmbientLux);
945                 }
946             }
947             long debounceTime = mDebounceLuxTime + BRIGHTENING_LIGHT_DEBOUNCE;
948             if (time >= debounceTime) {
949                 mAmbientLux = mRecentShortTermAverageLux;
950                 if (DEBUG) {
951                     Slog.d(TAG, "updateAmbientLux: Brightened: "
952                             + "brighteningLuxThreshold=" + brighteningLuxThreshold
953                             + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
954                             + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
955                             + ", mAmbientLux=" + mAmbientLux);
956                 }
957                 updateAutoBrightness(true);
958             } else {
959                 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
960             }
961             return;
962         }
963 
964         // Determine whether the ambient environment appears to be darkening.
965         float darkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS);
966         if (mRecentShortTermAverageLux < darkeningLuxThreshold
967                 && mRecentLongTermAverageLux < darkeningLuxThreshold) {
968             if (mDebounceLuxDirection >= 0) {
969                 mDebounceLuxDirection = -1;
970                 mDebounceLuxTime = time;
971                 if (DEBUG) {
972                     Slog.d(TAG, "updateAmbientLux: Possibly darkened, waiting for "
973                             + DARKENING_LIGHT_DEBOUNCE + " ms: "
974                             + "darkeningLuxThreshold=" + darkeningLuxThreshold
975                             + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
976                             + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
977                             + ", mAmbientLux=" + mAmbientLux);
978                 }
979             }
980             long debounceTime = mDebounceLuxTime + DARKENING_LIGHT_DEBOUNCE;
981             if (time >= debounceTime) {
982                 // Be conservative about reducing the brightness, only reduce it a little bit
983                 // at a time to avoid having to bump it up again soon.
984                 mAmbientLux = Math.max(mRecentShortTermAverageLux, mRecentLongTermAverageLux);
985                 if (DEBUG) {
986                     Slog.d(TAG, "updateAmbientLux: Darkened: "
987                             + "darkeningLuxThreshold=" + darkeningLuxThreshold
988                             + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
989                             + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
990                             + ", mAmbientLux=" + mAmbientLux);
991                 }
992                 updateAutoBrightness(true);
993             } else {
994                 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
995             }
996             return;
997         }
998 
999         // No change or change is within the hysteresis thresholds.
1000         if (mDebounceLuxDirection != 0) {
1001             mDebounceLuxDirection = 0;
1002             mDebounceLuxTime = time;
1003             if (DEBUG) {
1004                 Slog.d(TAG, "updateAmbientLux: Canceled debounce: "
1005                         + "brighteningLuxThreshold=" + brighteningLuxThreshold
1006                         + ", darkeningLuxThreshold=" + darkeningLuxThreshold
1007                         + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1008                         + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1009                         + ", mAmbientLux=" + mAmbientLux);
1010             }
1011         }
1012 
1013         // If the light level does not change, then the sensor may not report
1014         // a new value.  This can cause problems for the auto-brightness algorithm
1015         // because the filters might not be updated.  To work around it, we want to
1016         // make sure to update the filters whenever the observed light level could
1017         // possibly exceed one of the hysteresis thresholds.
1018         if (mLastObservedLux > brighteningLuxThreshold
1019                 || mLastObservedLux < darkeningLuxThreshold) {
1020             mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED,
1021                     time + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS);
1022         }
1023     }
1024 
debounceLightSensor()1025     private void debounceLightSensor() {
1026         if (mLightSensorEnabled) {
1027             long time = SystemClock.uptimeMillis();
1028             if (time >= mLastObservedLuxTime + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS) {
1029                 if (DEBUG) {
1030                     Slog.d(TAG, "debounceLightSensor: Synthesizing light sensor measurement "
1031                             + "after " + (time - mLastObservedLuxTime) + " ms.");
1032                 }
1033                 applyLightSensorMeasurement(time, mLastObservedLux);
1034             }
1035             updateAmbientLux(time);
1036         }
1037     }
1038 
updateAutoBrightness(boolean sendUpdate)1039     private void updateAutoBrightness(boolean sendUpdate) {
1040         if (!mAmbientLuxValid) {
1041             return;
1042         }
1043 
1044         float value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux);
1045         float gamma = 1.0f;
1046 
1047         if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT
1048                 && mPowerRequest.screenAutoBrightnessAdjustment != 0.0f) {
1049             final float adjGamma = FloatMath.pow(SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA,
1050                     Math.min(1.0f, Math.max(-1.0f,
1051                             -mPowerRequest.screenAutoBrightnessAdjustment)));
1052             gamma *= adjGamma;
1053             if (DEBUG) {
1054                 Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma);
1055             }
1056         }
1057 
1058         if (USE_TWILIGHT_ADJUSTMENT) {
1059             TwilightState state = mTwilight.getCurrentState();
1060             if (state != null && state.isNight()) {
1061                 final long now = System.currentTimeMillis();
1062                 final float earlyGamma =
1063                         getTwilightGamma(now, state.getYesterdaySunset(), state.getTodaySunrise());
1064                 final float lateGamma =
1065                         getTwilightGamma(now, state.getTodaySunset(), state.getTomorrowSunrise());
1066                 gamma *= earlyGamma * lateGamma;
1067                 if (DEBUG) {
1068                     Slog.d(TAG, "updateAutoBrightness: earlyGamma=" + earlyGamma
1069                             + ", lateGamma=" + lateGamma);
1070                 }
1071             }
1072         }
1073 
1074         if (gamma != 1.0f) {
1075             final float in = value;
1076             value = FloatMath.pow(value, gamma);
1077             if (DEBUG) {
1078                 Slog.d(TAG, "updateAutoBrightness: gamma=" + gamma
1079                         + ", in=" + in + ", out=" + value);
1080             }
1081         }
1082 
1083         int newScreenAutoBrightness = clampScreenBrightness(
1084                 Math.round(value * PowerManager.BRIGHTNESS_ON));
1085         if (mScreenAutoBrightness != newScreenAutoBrightness) {
1086             if (DEBUG) {
1087                 Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness="
1088                         + mScreenAutoBrightness + ", newScreenAutoBrightness="
1089                         + newScreenAutoBrightness);
1090             }
1091 
1092             mScreenAutoBrightness = newScreenAutoBrightness;
1093             mLastScreenAutoBrightnessGamma = gamma;
1094             if (sendUpdate) {
1095                 sendUpdatePowerState();
1096             }
1097         }
1098     }
1099 
getTwilightGamma(long now, long lastSunset, long nextSunrise)1100     private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) {
1101         if (lastSunset < 0 || nextSunrise < 0
1102                 || now < lastSunset || now > nextSunrise) {
1103             return 1.0f;
1104         }
1105 
1106         if (now < lastSunset + TWILIGHT_ADJUSTMENT_TIME) {
1107             return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
1108                     (float)(now - lastSunset) / TWILIGHT_ADJUSTMENT_TIME);
1109         }
1110 
1111         if (now > nextSunrise - TWILIGHT_ADJUSTMENT_TIME) {
1112             return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
1113                     (float)(nextSunrise - now) / TWILIGHT_ADJUSTMENT_TIME);
1114         }
1115 
1116         return TWILIGHT_ADJUSTMENT_MAX_GAMMA;
1117     }
1118 
lerp(float x, float y, float alpha)1119     private static float lerp(float x, float y, float alpha) {
1120         return x + (y - x) * alpha;
1121     }
1122 
sendOnStateChanged()1123     private void sendOnStateChanged() {
1124         mCallbackHandler.post(mOnStateChangedRunnable);
1125     }
1126 
1127     private final Runnable mOnStateChangedRunnable = new Runnable() {
1128         @Override
1129         public void run() {
1130             mCallbacks.onStateChanged();
1131         }
1132     };
1133 
sendOnProximityPositive()1134     private void sendOnProximityPositive() {
1135         mCallbackHandler.post(mOnProximityPositiveRunnable);
1136     }
1137 
1138     private final Runnable mOnProximityPositiveRunnable = new Runnable() {
1139         @Override
1140         public void run() {
1141             mCallbacks.onProximityPositive();
1142         }
1143     };
1144 
sendOnProximityNegative()1145     private void sendOnProximityNegative() {
1146         mCallbackHandler.post(mOnProximityNegativeRunnable);
1147     }
1148 
1149     private final Runnable mOnProximityNegativeRunnable = new Runnable() {
1150         @Override
1151         public void run() {
1152             mCallbacks.onProximityNegative();
1153         }
1154     };
1155 
dump(final PrintWriter pw)1156     public void dump(final PrintWriter pw) {
1157         synchronized (mLock) {
1158             pw.println();
1159             pw.println("Display Controller Locked State:");
1160             pw.println("  mDisplayReadyLocked=" + mDisplayReadyLocked);
1161             pw.println("  mPendingRequestLocked=" + mPendingRequestLocked);
1162             pw.println("  mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
1163             pw.println("  mPendingWaitForNegativeProximityLocked="
1164                     + mPendingWaitForNegativeProximityLocked);
1165             pw.println("  mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
1166         }
1167 
1168         pw.println();
1169         pw.println("Display Controller Configuration:");
1170         pw.println("  mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
1171         pw.println("  mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
1172         pw.println("  mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
1173         pw.println("  mUseSoftwareAutoBrightnessConfig="
1174                 + mUseSoftwareAutoBrightnessConfig);
1175         pw.println("  mScreenAutoBrightnessSpline=" + mScreenAutoBrightnessSpline);
1176         pw.println("  mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig);
1177 
1178         mHandler.runWithScissors(new Runnable() {
1179             @Override
1180             public void run() {
1181                 dumpLocal(pw);
1182             }
1183         }, 1000);
1184     }
1185 
dumpLocal(PrintWriter pw)1186     private void dumpLocal(PrintWriter pw) {
1187         pw.println();
1188         pw.println("Display Controller Thread State:");
1189         pw.println("  mPowerRequest=" + mPowerRequest);
1190         pw.println("  mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
1191 
1192         pw.println("  mProximitySensor=" + mProximitySensor);
1193         pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
1194         pw.println("  mProximityThreshold=" + mProximityThreshold);
1195         pw.println("  mProximity=" + proximityToString(mProximity));
1196         pw.println("  mPendingProximity=" + proximityToString(mPendingProximity));
1197         pw.println("  mPendingProximityDebounceTime="
1198                 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
1199         pw.println("  mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
1200 
1201         pw.println("  mLightSensor=" + mLightSensor);
1202         pw.println("  mLightSensorEnabled=" + mLightSensorEnabled);
1203         pw.println("  mLightSensorEnableTime="
1204                 + TimeUtils.formatUptime(mLightSensorEnableTime));
1205         pw.println("  mAmbientLux=" + mAmbientLux);
1206         pw.println("  mAmbientLuxValid=" + mAmbientLuxValid);
1207         pw.println("  mLastObservedLux=" + mLastObservedLux);
1208         pw.println("  mLastObservedLuxTime="
1209                 + TimeUtils.formatUptime(mLastObservedLuxTime));
1210         pw.println("  mRecentLightSamples=" + mRecentLightSamples);
1211         pw.println("  mRecentShortTermAverageLux=" + mRecentShortTermAverageLux);
1212         pw.println("  mRecentLongTermAverageLux=" + mRecentLongTermAverageLux);
1213         pw.println("  mDebounceLuxDirection=" + mDebounceLuxDirection);
1214         pw.println("  mDebounceLuxTime=" + TimeUtils.formatUptime(mDebounceLuxTime));
1215         pw.println("  mScreenAutoBrightness=" + mScreenAutoBrightness);
1216         pw.println("  mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness);
1217         pw.println("  mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
1218         pw.println("  mTwilight.getCurrentState()=" + mTwilight.getCurrentState());
1219 
1220         if (mElectronBeamOnAnimator != null) {
1221             pw.println("  mElectronBeamOnAnimator.isStarted()=" +
1222                     mElectronBeamOnAnimator.isStarted());
1223         }
1224         if (mElectronBeamOffAnimator != null) {
1225             pw.println("  mElectronBeamOffAnimator.isStarted()=" +
1226                     mElectronBeamOffAnimator.isStarted());
1227         }
1228 
1229         if (mPowerState != null) {
1230             mPowerState.dump(pw);
1231         }
1232     }
1233 
proximityToString(int state)1234     private static String proximityToString(int state) {
1235         switch (state) {
1236             case PROXIMITY_UNKNOWN:
1237                 return "Unknown";
1238             case PROXIMITY_NEGATIVE:
1239                 return "Negative";
1240             case PROXIMITY_POSITIVE:
1241                 return "Positive";
1242             default:
1243                 return Integer.toString(state);
1244         }
1245     }
1246 
wantScreenOn(int state)1247     private static boolean wantScreenOn(int state) {
1248         switch (state) {
1249             case DisplayPowerRequest.SCREEN_STATE_BRIGHT:
1250             case DisplayPowerRequest.SCREEN_STATE_DIM:
1251                 return true;
1252         }
1253         return false;
1254     }
1255 
1256     /**
1257      * Asynchronous callbacks from the power controller to the power manager service.
1258      */
1259     public interface Callbacks {
onStateChanged()1260         void onStateChanged();
onProximityPositive()1261         void onProximityPositive();
onProximityNegative()1262         void onProximityNegative();
1263     }
1264 
1265     private final class DisplayControllerHandler extends Handler {
DisplayControllerHandler(Looper looper)1266         public DisplayControllerHandler(Looper looper) {
1267             super(looper, null, true /*async*/);
1268         }
1269 
1270         @Override
handleMessage(Message msg)1271         public void handleMessage(Message msg) {
1272             switch (msg.what) {
1273                 case MSG_UPDATE_POWER_STATE:
1274                     updatePowerState();
1275                     break;
1276 
1277                 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
1278                     debounceProximitySensor();
1279                     break;
1280 
1281                 case MSG_LIGHT_SENSOR_DEBOUNCED:
1282                     debounceLightSensor();
1283                     break;
1284             }
1285         }
1286     }
1287 
1288     private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
1289         @Override
1290         public void onSensorChanged(SensorEvent event) {
1291             if (mProximitySensorEnabled) {
1292                 final long time = SystemClock.uptimeMillis();
1293                 final float distance = event.values[0];
1294                 boolean positive = distance >= 0.0f && distance < mProximityThreshold;
1295                 handleProximitySensorEvent(time, positive);
1296             }
1297         }
1298 
1299         @Override
1300         public void onAccuracyChanged(Sensor sensor, int accuracy) {
1301             // Not used.
1302         }
1303     };
1304 
1305     private final SensorEventListener mLightSensorListener = new SensorEventListener() {
1306         @Override
1307         public void onSensorChanged(SensorEvent event) {
1308             if (mLightSensorEnabled) {
1309                 final long time = SystemClock.uptimeMillis();
1310                 final float lux = event.values[0];
1311                 handleLightSensorEvent(time, lux);
1312             }
1313         }
1314 
1315         @Override
1316         public void onAccuracyChanged(Sensor sensor, int accuracy) {
1317             // Not used.
1318         }
1319     };
1320 
1321     private final TwilightService.TwilightListener mTwilightListener =
1322             new TwilightService.TwilightListener() {
1323         @Override
1324         public void onTwilightStateChanged() {
1325             mTwilightChanged = true;
1326             updatePowerState();
1327         }
1328     };
1329 }
1330