OSDN Git Service

7922dfbdddfcb9785173a059bf68c21c022f2bad
[android-x86/frameworks-base.git] / services / core / java / com / android / server / display / DisplayPowerController.java
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.display;
18
19 import com.android.internal.app.IBatteryStats;
20 import com.android.server.LocalServices;
21 import com.android.server.am.BatteryStatsService;
22 import com.android.server.lights.LightsManager;
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.display.DisplayManagerInternal.DisplayPowerCallbacks;
33 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
34 import android.os.Handler;
35 import android.os.Looper;
36 import android.os.Message;
37 import android.os.PowerManager;
38 import android.os.RemoteException;
39 import android.os.SystemClock;
40 import android.os.Trace;
41 import android.util.MathUtils;
42 import android.util.Slog;
43 import android.util.Spline;
44 import android.util.TimeUtils;
45 import android.view.Display;
46 import android.view.WindowManagerPolicy;
47
48 import java.io.PrintWriter;
49
50 /**
51  * Controls the power state of the display.
52  *
53  * Handles the proximity sensor, light sensor, and animations between states
54  * including the screen off animation.
55  *
56  * This component acts independently of the rest of the power manager service.
57  * In particular, it does not share any state and it only communicates
58  * via asynchronous callbacks to inform the power manager that something has
59  * changed.
60  *
61  * Everything this class does internally is serialized on its handler although
62  * it may be accessed by other threads from the outside.
63  *
64  * Note that the power manager service guarantees that it will hold a suspend
65  * blocker as long as the display is not ready.  So most of the work done here
66  * does not need to worry about holding a suspend blocker unless it happens
67  * independently of the display ready signal.
68    *
69  * For debugging, you can make the color fade and brightness animations run
70  * slower by changing the "animator duration scale" option in Development Settings.
71  */
72 final class DisplayPowerController implements AutomaticBrightnessController.Callbacks {
73     private static final String TAG = "DisplayPowerController";
74     private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
75
76     private static boolean DEBUG = false;
77     private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
78
79     // If true, uses the color fade on animation.
80     // We might want to turn this off if we cannot get a guarantee that the screen
81     // actually turns on and starts showing new content after the call to set the
82     // screen state returns.  Playing the animation can also be somewhat slow.
83     private static final boolean USE_COLOR_FADE_ON_ANIMATION = false;
84
85     // The minimum reduction in brightness when dimmed.
86     private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10;
87
88     private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
89     private static final int COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS = 400;
90
91     private static final int MSG_UPDATE_POWER_STATE = 1;
92     private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
93     private static final int MSG_SCREEN_ON_UNBLOCKED = 3;
94
95     private static final int PROXIMITY_UNKNOWN = -1;
96     private static final int PROXIMITY_NEGATIVE = 0;
97     private static final int PROXIMITY_POSITIVE = 1;
98
99     // Proximity sensor debounce delay in milliseconds for positive or negative transitions.
100     private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0;
101     private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 250;
102
103     // Trigger proximity if distance is less than 5 cm.
104     private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
105
106     // Brightness animation ramp rate in brightness units per second.
107     private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
108
109     private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
110     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
111     private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
112
113     private final Object mLock = new Object();
114
115     private final Context mContext;
116
117     // Our handler.
118     private final DisplayControllerHandler mHandler;
119
120     // Asynchronous callbacks into the power manager service.
121     // Only invoked from the handler thread while no locks are held.
122     private final DisplayPowerCallbacks mCallbacks;
123
124     // Battery stats.
125     private final IBatteryStats mBatteryStats;
126
127     // The lights service.
128     private final LightsManager mLights;
129
130     // The sensor manager.
131     private final SensorManager mSensorManager;
132
133     // The window manager policy.
134     private final WindowManagerPolicy mWindowManagerPolicy;
135
136     // The display blanker.
137     private final DisplayBlanker mBlanker;
138
139     // The proximity sensor, or null if not available or needed.
140     private Sensor mProximitySensor;
141
142     // The doze screen brightness.
143     private final int mScreenBrightnessDozeConfig;
144
145     // The dim screen brightness.
146     private final int mScreenBrightnessDimConfig;
147
148     // The minimum screen brightness to use in a very dark room.
149     private final int mScreenBrightnessDarkConfig;
150
151     // The minimum allowed brightness.
152     private final int mScreenBrightnessRangeMinimum;
153
154     // The maximum allowed brightness.
155     private final int mScreenBrightnessRangeMaximum;
156
157     // True if auto-brightness should be used.
158     private boolean mUseSoftwareAutoBrightnessConfig;
159
160     // True if should use light sensor to automatically determine doze screen brightness.
161     private final boolean mAllowAutoBrightnessWhileDozingConfig;
162
163     // True if we should fade the screen while turning it off, false if we should play
164     // a stylish color fade animation instead.
165     private boolean mColorFadeFadesConfig;
166
167     // The pending power request.
168     // Initially null until the first call to requestPowerState.
169     // Guarded by mLock.
170     private DisplayPowerRequest mPendingRequestLocked;
171
172     // True if a request has been made to wait for the proximity sensor to go negative.
173     // Guarded by mLock.
174     private boolean mPendingWaitForNegativeProximityLocked;
175
176     // True if the pending power request or wait for negative proximity flag
177     // has been changed since the last update occurred.
178     // Guarded by mLock.
179     private boolean mPendingRequestChangedLocked;
180
181     // Set to true when the important parts of the pending power request have been applied.
182     // The important parts are mainly the screen state.  Brightness changes may occur
183     // concurrently.
184     // Guarded by mLock.
185     private boolean mDisplayReadyLocked;
186
187     // Set to true if a power state update is required.
188     // Guarded by mLock.
189     private boolean mPendingUpdatePowerStateLocked;
190
191     /* The following state must only be accessed by the handler thread. */
192
193     // The currently requested power state.
194     // The power controller will progressively update its internal state to match
195     // the requested power state.  Initially null until the first update.
196     private DisplayPowerRequest mPowerRequest;
197
198     // The current power state.
199     // Must only be accessed on the handler thread.
200     private DisplayPowerState mPowerState;
201
202     // True if the device should wait for negative proximity sensor before
203     // waking up the screen.  This is set to false as soon as a negative
204     // proximity sensor measurement is observed or when the device is forced to
205     // go to sleep by the user.  While true, the screen remains off.
206     private boolean mWaitingForNegativeProximity;
207
208     // The actual proximity sensor threshold value.
209     private float mProximityThreshold;
210
211     // Set to true if the proximity sensor listener has been registered
212     // with the sensor manager.
213     private boolean mProximitySensorEnabled;
214
215     // The debounced proximity sensor state.
216     private int mProximity = PROXIMITY_UNKNOWN;
217
218     // The raw non-debounced proximity sensor state.
219     private int mPendingProximity = PROXIMITY_UNKNOWN;
220     private long mPendingProximityDebounceTime = -1; // -1 if fully debounced
221
222     // True if the screen was turned off because of the proximity sensor.
223     // When the screen turns on again, we report user activity to the power manager.
224     private boolean mScreenOffBecauseOfProximity;
225
226     // The currently active screen on unblocker.  This field is non-null whenever
227     // we are waiting for a callback to release it and unblock the screen.
228     private ScreenOnUnblocker mPendingScreenOnUnblocker;
229
230     // True if we were in the process of turning off the screen.
231     // This allows us to recover more gracefully from situations where we abort
232     // turning off the screen.
233     private boolean mPendingScreenOff;
234
235     // True if we have unfinished business and are holding a suspend blocker.
236     private boolean mUnfinishedBusiness;
237
238     // The elapsed real time when the screen on was blocked.
239     private long mScreenOnBlockStartRealTime;
240
241     // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_SCREEN_* fields.
242     private int mReportedScreenStateToPolicy;
243
244     // Remembers whether certain kinds of brightness adjustments
245     // were recently applied so that we can decide how to transition.
246     private boolean mAppliedAutoBrightness;
247     private boolean mAppliedDimming;
248     private boolean mAppliedLowPower;
249
250     // Brightness ramp rate fast.
251     private final int mBrightnessRampRateFast;
252
253     // The controller for the automatic brightness level.
254     private AutomaticBrightnessController mAutomaticBrightnessController;
255
256     // Animators.
257     private ObjectAnimator mColorFadeOnAnimator;
258     private ObjectAnimator mColorFadeOffAnimator;
259     private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
260
261     /**
262      * Creates the display power controller.
263      */
264     public DisplayPowerController(Context context,
265             DisplayPowerCallbacks callbacks, Handler handler,
266             SensorManager sensorManager, DisplayBlanker blanker) {
267         mHandler = new DisplayControllerHandler(handler.getLooper());
268         mCallbacks = callbacks;
269
270         mBatteryStats = BatteryStatsService.getService();
271         mLights = LocalServices.getService(LightsManager.class);
272         mSensorManager = sensorManager;
273         mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
274         mBlanker = blanker;
275         mContext = context;
276
277         final Resources resources = context.getResources();
278         final int screenBrightnessSettingMinimum = clampAbsoluteBrightness(resources.getInteger(
279                 com.android.internal.R.integer.config_screenBrightnessSettingMinimum));
280
281         mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger(
282                 com.android.internal.R.integer.config_screenBrightnessDoze));
283
284         mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger(
285                 com.android.internal.R.integer.config_screenBrightnessDim));
286
287         mScreenBrightnessDarkConfig = clampAbsoluteBrightness(resources.getInteger(
288                 com.android.internal.R.integer.config_screenBrightnessDark));
289         if (mScreenBrightnessDarkConfig > mScreenBrightnessDimConfig) {
290             Slog.w(TAG, "Expected config_screenBrightnessDark ("
291                     + mScreenBrightnessDarkConfig + ") to be less than or equal to "
292                     + "config_screenBrightnessDim (" + mScreenBrightnessDimConfig + ").");
293         }
294         if (mScreenBrightnessDarkConfig > mScreenBrightnessDimConfig) {
295             Slog.w(TAG, "Expected config_screenBrightnessDark ("
296                     + mScreenBrightnessDarkConfig + ") to be less than or equal to "
297                     + "config_screenBrightnessSettingMinimum ("
298                     + screenBrightnessSettingMinimum + ").");
299         }
300
301         int screenBrightnessRangeMinimum = Math.min(Math.min(
302                 screenBrightnessSettingMinimum, mScreenBrightnessDimConfig),
303                 mScreenBrightnessDarkConfig);
304
305         mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON;
306
307         mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
308                 com.android.internal.R.bool.config_automatic_brightness_available);
309
310         mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
311                 com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
312
313         mBrightnessRampRateFast = resources.getInteger(
314                 com.android.internal.R.integer.config_brightness_ramp_rate_fast);
315
316         int lightSensorRate = resources.getInteger(
317                 com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
318         long brighteningLightDebounce = resources.getInteger(
319                 com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);
320         long darkeningLightDebounce = resources.getInteger(
321                 com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce);
322         boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean(
323                 com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
324         int ambientLightHorizon = resources.getInteger(
325                 com.android.internal.R.integer.config_autoBrightnessAmbientLightHorizon);
326         float autoBrightnessAdjustmentMaxGamma = resources.getFraction(
327                 com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
328                 1, 1);
329
330         if (mUseSoftwareAutoBrightnessConfig) {
331             int[] lux = resources.getIntArray(
332                     com.android.internal.R.array.config_autoBrightnessLevels);
333             int[] screenBrightness = resources.getIntArray(
334                     com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
335             int lightSensorWarmUpTimeConfig = resources.getInteger(
336                     com.android.internal.R.integer.config_lightSensorWarmupTime);
337             final float dozeScaleFactor = resources.getFraction(
338                     com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
339                     1, 1);
340
341             Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
342             if (screenAutoBrightnessSpline == null) {
343                 Slog.e(TAG, "Error in config.xml.  config_autoBrightnessLcdBacklightValues "
344                         + "(size " + screenBrightness.length + ") "
345                         + "must be monotic and have exactly one more entry than "
346                         + "config_autoBrightnessLevels (size " + lux.length + ") "
347                         + "which must be strictly increasing.  "
348                         + "Auto-brightness will be disabled.");
349                 mUseSoftwareAutoBrightnessConfig = false;
350             } else {
351                 int bottom = clampAbsoluteBrightness(screenBrightness[0]);
352                 if (mScreenBrightnessDarkConfig > bottom) {
353                     Slog.w(TAG, "config_screenBrightnessDark (" + mScreenBrightnessDarkConfig
354                             + ") should be less than or equal to the first value of "
355                             + "config_autoBrightnessLcdBacklightValues ("
356                             + bottom + ").");
357                 }
358                 if (bottom < screenBrightnessRangeMinimum) {
359                     screenBrightnessRangeMinimum = bottom;
360                 }
361                 mAutomaticBrightnessController = new AutomaticBrightnessController(this,
362                         handler.getLooper(), sensorManager, screenAutoBrightnessSpline,
363                         lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
364                         mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
365                         brighteningLightDebounce, darkeningLightDebounce,
366                         autoBrightnessResetAmbientLuxAfterWarmUp,
367                         ambientLightHorizon, autoBrightnessAdjustmentMaxGamma);
368             }
369         }
370
371         mScreenBrightnessRangeMinimum = screenBrightnessRangeMinimum;
372
373         mColorFadeFadesConfig = resources.getBoolean(
374                 com.android.internal.R.bool.config_animateScreenLights);
375
376         if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
377             mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
378             if (mProximitySensor != null) {
379                 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
380                         TYPICAL_PROXIMITY_THRESHOLD);
381             }
382         }
383
384     }
385
386     /**
387      * Returns true if the proximity sensor screen-off function is available.
388      */
389     public boolean isProximitySensorAvailable() {
390         return mProximitySensor != null;
391     }
392
393     /**
394      * Requests a new power state.
395      * The controller makes a copy of the provided object and then
396      * begins adjusting the power state to match what was requested.
397      *
398      * @param request The requested power state.
399      * @param waitForNegativeProximity If true, issues a request to wait for
400      * negative proximity before turning the screen back on, assuming the screen
401      * was turned off by the proximity sensor.
402      * @return True if display is ready, false if there are important changes that must
403      * be made asynchronously (such as turning the screen on), in which case the caller
404      * should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged()}
405      * then try the request again later until the state converges.
406      */
407     public boolean requestPowerState(DisplayPowerRequest request,
408             boolean waitForNegativeProximity) {
409         if (DEBUG) {
410             Slog.d(TAG, "requestPowerState: "
411                     + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
412         }
413
414         synchronized (mLock) {
415             boolean changed = false;
416
417             if (waitForNegativeProximity
418                     && !mPendingWaitForNegativeProximityLocked) {
419                 mPendingWaitForNegativeProximityLocked = true;
420                 changed = true;
421             }
422
423             if (mPendingRequestLocked == null) {
424                 mPendingRequestLocked = new DisplayPowerRequest(request);
425                 changed = true;
426             } else if (!mPendingRequestLocked.equals(request)) {
427                 mPendingRequestLocked.copyFrom(request);
428                 changed = true;
429             }
430
431             if (changed) {
432                 mDisplayReadyLocked = false;
433             }
434
435             if (changed && !mPendingRequestChangedLocked) {
436                 mPendingRequestChangedLocked = true;
437                 sendUpdatePowerStateLocked();
438             }
439
440             return mDisplayReadyLocked;
441         }
442     }
443
444     private void sendUpdatePowerState() {
445         synchronized (mLock) {
446             sendUpdatePowerStateLocked();
447         }
448     }
449
450     private void sendUpdatePowerStateLocked() {
451         if (!mPendingUpdatePowerStateLocked) {
452             mPendingUpdatePowerStateLocked = true;
453             Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
454             msg.setAsynchronous(true);
455             mHandler.sendMessage(msg);
456         }
457     }
458
459     private void initialize() {
460         // Initialize the power state object for the default display.
461         // In the future, we might manage multiple displays independently.
462         mPowerState = new DisplayPowerState(mBlanker,
463                 new ColorFade(Display.DEFAULT_DISPLAY));
464
465         mColorFadeOnAnimator = ObjectAnimator.ofFloat(
466                 mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 0.0f, 1.0f);
467         mColorFadeOnAnimator.setDuration(COLOR_FADE_ON_ANIMATION_DURATION_MILLIS);
468         mColorFadeOnAnimator.addListener(mAnimatorListener);
469
470         mColorFadeOffAnimator = ObjectAnimator.ofFloat(
471                 mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 1.0f, 0.0f);
472         mColorFadeOffAnimator.setDuration(COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS);
473         mColorFadeOffAnimator.addListener(mAnimatorListener);
474
475         mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
476                 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
477         mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
478
479         // Initialize screen state for battery stats.
480         try {
481             mBatteryStats.noteScreenState(mPowerState.getScreenState());
482             mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness());
483         } catch (RemoteException ex) {
484             // same process
485         }
486     }
487
488     private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
489         @Override
490         public void onAnimationStart(Animator animation) {
491         }
492         @Override
493         public void onAnimationEnd(Animator animation) {
494             sendUpdatePowerState();
495         }
496         @Override
497         public void onAnimationRepeat(Animator animation) {
498         }
499         @Override
500         public void onAnimationCancel(Animator animation) {
501         }
502     };
503
504     private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
505         @Override
506         public void onAnimationEnd() {
507             sendUpdatePowerState();
508         }
509     };
510
511     private void updatePowerState() {
512         // Update the power state request.
513         final boolean mustNotify;
514         boolean mustInitialize = false;
515         boolean autoBrightnessAdjustmentChanged = false;
516
517         synchronized (mLock) {
518             mPendingUpdatePowerStateLocked = false;
519             if (mPendingRequestLocked == null) {
520                 return; // wait until first actual power request
521             }
522
523             if (mPowerRequest == null) {
524                 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
525                 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
526                 mPendingWaitForNegativeProximityLocked = false;
527                 mPendingRequestChangedLocked = false;
528                 mustInitialize = true;
529             } else if (mPendingRequestChangedLocked) {
530                 autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
531                         != mPendingRequestLocked.screenAutoBrightnessAdjustment);
532                 mPowerRequest.copyFrom(mPendingRequestLocked);
533                 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
534                 mPendingWaitForNegativeProximityLocked = false;
535                 mPendingRequestChangedLocked = false;
536                 mDisplayReadyLocked = false;
537             }
538
539             mustNotify = !mDisplayReadyLocked;
540         }
541
542         // Initialize things the first time the power state is changed.
543         if (mustInitialize) {
544             initialize();
545         }
546
547         // Compute the basic display state using the policy.
548         // We might override this below based on other factors.
549         int state;
550         int brightness = PowerManager.BRIGHTNESS_DEFAULT;
551         boolean performScreenOffTransition = false;
552         switch (mPowerRequest.policy) {
553             case DisplayPowerRequest.POLICY_OFF:
554                 state = Display.STATE_OFF;
555                 performScreenOffTransition = true;
556                 break;
557             case DisplayPowerRequest.POLICY_DOZE:
558                 if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
559                     state = mPowerRequest.dozeScreenState;
560                 } else {
561                     state = Display.STATE_DOZE;
562                 }
563                 if (!mAllowAutoBrightnessWhileDozingConfig) {
564                     brightness = mPowerRequest.dozeScreenBrightness;
565                 }
566                 break;
567             case DisplayPowerRequest.POLICY_DIM:
568             case DisplayPowerRequest.POLICY_BRIGHT:
569             default:
570                 state = Display.STATE_ON;
571                 break;
572         }
573         assert(state != Display.STATE_UNKNOWN);
574
575         // Apply the proximity sensor.
576         if (mProximitySensor != null) {
577             if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
578                 setProximitySensorEnabled(true);
579                 if (!mScreenOffBecauseOfProximity
580                         && mProximity == PROXIMITY_POSITIVE) {
581                     mScreenOffBecauseOfProximity = true;
582                     sendOnProximityPositiveWithWakelock();
583                 }
584             } else if (mWaitingForNegativeProximity
585                     && mScreenOffBecauseOfProximity
586                     && mProximity == PROXIMITY_POSITIVE
587                     && state != Display.STATE_OFF) {
588                 setProximitySensorEnabled(true);
589             } else {
590                 setProximitySensorEnabled(false);
591                 mWaitingForNegativeProximity = false;
592             }
593             if (mScreenOffBecauseOfProximity
594                     && mProximity != PROXIMITY_POSITIVE) {
595                 mScreenOffBecauseOfProximity = false;
596                 sendOnProximityNegativeWithWakelock();
597             }
598         } else {
599             mWaitingForNegativeProximity = false;
600         }
601         if (mScreenOffBecauseOfProximity) {
602             state = Display.STATE_OFF;
603         }
604
605         // Animate the screen state change unless already animating.
606         // The transition may be deferred, so after this point we will use the
607         // actual state instead of the desired one.
608         animateScreenStateChange(state, performScreenOffTransition);
609         state = mPowerState.getScreenState();
610
611         // Use zero brightness when screen is off.
612         if (state == Display.STATE_OFF) {
613             brightness = PowerManager.BRIGHTNESS_OFF;
614             mLights.getLight(LightsManager.LIGHT_ID_BUTTONS).setBrightness(brightness);
615             mLights.getLight(LightsManager.LIGHT_ID_KEYBOARD).setBrightness(brightness);
616         }
617
618         // Disable button lights when dozing
619         if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND) {
620             mLights.getLight(LightsManager.LIGHT_ID_BUTTONS).setBrightness(PowerManager.BRIGHTNESS_OFF);
621             mLights.getLight(LightsManager.LIGHT_ID_KEYBOARD).setBrightness(PowerManager.BRIGHTNESS_OFF);
622         }
623
624         // Configure auto-brightness.
625         boolean autoBrightnessEnabled = false;
626         if (mAutomaticBrightnessController != null) {
627             final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig
628                     && (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);
629             autoBrightnessEnabled = mPowerRequest.useAutoBrightness
630                     && (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
631                     && brightness < 0;
632             final boolean userInitiatedChange = autoBrightnessAdjustmentChanged
633                     && mPowerRequest.brightnessSetByUser;
634             mAutomaticBrightnessController.configure(autoBrightnessEnabled,
635                     mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,
636                     userInitiatedChange, mPowerRequest.useTwilight);
637         }
638
639         // Apply brightness boost.
640         // We do this here after configuring auto-brightness so that we don't
641         // disable the light sensor during this temporary state.  That way when
642         // boost ends we will be able to resume normal auto-brightness behavior
643         // without any delay.
644         if (mPowerRequest.boostScreenBrightness
645                 && brightness != PowerManager.BRIGHTNESS_OFF) {
646             brightness = PowerManager.BRIGHTNESS_ON;
647         }
648
649         // Apply auto-brightness.
650         boolean slowChange = false;
651         if (brightness < 0) {
652             if (autoBrightnessEnabled) {
653                 brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();
654             }
655             if (brightness >= 0) {
656                 // Use current auto-brightness value and slowly adjust to changes.
657                 brightness = clampScreenBrightness(brightness);
658                 if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
659                     slowChange = true; // slowly adapt to auto-brightness
660                 }
661                 mAppliedAutoBrightness = true;
662             } else {
663                 mAppliedAutoBrightness = false;
664             }
665         } else {
666             mAppliedAutoBrightness = false;
667         }
668
669         // Use default brightness when dozing unless overridden.
670         if (brightness < 0 && (state == Display.STATE_DOZE
671                 || state == Display.STATE_DOZE_SUSPEND)) {
672             brightness = mScreenBrightnessDozeConfig;
673         }
674
675         // Apply manual brightness.
676         // Use the current brightness setting from the request, which is expected
677         // provide a nominal default value for the case where auto-brightness
678         // is not ready yet.
679         if (brightness < 0) {
680             brightness = clampScreenBrightness(mPowerRequest.screenBrightness);
681         }
682
683         // Apply dimming by at least some minimum amount when user activity
684         // timeout is about to expire.
685         if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
686             if (brightness > mScreenBrightnessRangeMinimum) {
687                 brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,
688                         mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
689             }
690             if (!mAppliedDimming) {
691                 slowChange = false;
692             }
693             mAppliedDimming = true;
694         } else if (mAppliedDimming) {
695             slowChange = false;
696             mAppliedDimming = false;
697         }
698
699         // If low power mode is enabled, cut the brightness level by half
700         // as long as it is above the minimum threshold.
701         if (mPowerRequest.lowPowerMode) {
702             if (brightness > mScreenBrightnessRangeMinimum) {
703                 brightness = Math.max(brightness / 2, mScreenBrightnessRangeMinimum);
704             }
705             if (!mAppliedLowPower) {
706                 slowChange = false;
707             }
708             mAppliedLowPower = true;
709         } else if (mAppliedLowPower) {
710             slowChange = false;
711             mAppliedLowPower = false;
712         }
713
714         // Animate the screen brightness when the screen is on or dozing.
715         // Skip the animation when the screen is off or suspended.
716         if (!mPendingScreenOff) {
717             if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
718                 animateScreenBrightness(brightness,
719                         slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast);
720             } else {
721                 animateScreenBrightness(brightness, 0);
722             }
723         }
724
725         // Determine whether the display is ready for use in the newly requested state.
726         // Note that we do not wait for the brightness ramp animation to complete before
727         // reporting the display is ready because we only need to ensure the screen is in the
728         // right power state even as it continues to converge on the desired brightness.
729         final boolean ready = mPendingScreenOnUnblocker == null
730                 && !mColorFadeOnAnimator.isStarted()
731                 && !mColorFadeOffAnimator.isStarted()
732                 && mPowerState.waitUntilClean(mCleanListener);
733         final boolean finished = ready
734                 && !mScreenBrightnessRampAnimator.isAnimating();
735
736         // Notify policy about screen turned on.
737         if (ready && state != Display.STATE_OFF
738                 && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
739             mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_ON;
740             mWindowManagerPolicy.screenTurnedOn();
741         }
742
743         // Grab a wake lock if we have unfinished business.
744         if (!finished && !mUnfinishedBusiness) {
745             if (DEBUG) {
746                 Slog.d(TAG, "Unfinished business...");
747             }
748             mCallbacks.acquireSuspendBlocker();
749             mUnfinishedBusiness = true;
750         }
751
752         // Notify the power manager when ready.
753         if (ready && mustNotify) {
754             // Send state change.
755             synchronized (mLock) {
756                 if (!mPendingRequestChangedLocked) {
757                     mDisplayReadyLocked = true;
758
759                     if (DEBUG) {
760                         Slog.d(TAG, "Display ready!");
761                     }
762                 }
763             }
764             sendOnStateChangedWithWakelock();
765         }
766
767         // Release the wake lock when we have no unfinished business.
768         if (finished && mUnfinishedBusiness) {
769             if (DEBUG) {
770                 Slog.d(TAG, "Finished business...");
771             }
772             mUnfinishedBusiness = false;
773             mCallbacks.releaseSuspendBlocker();
774         }
775     }
776
777     @Override
778     public void updateBrightness() {
779         sendUpdatePowerState();
780     }
781
782     private void blockScreenOn() {
783         if (mPendingScreenOnUnblocker == null) {
784             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
785             mPendingScreenOnUnblocker = new ScreenOnUnblocker();
786             mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
787             Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
788         }
789     }
790
791     private void unblockScreenOn() {
792         if (mPendingScreenOnUnblocker != null) {
793             mPendingScreenOnUnblocker = null;
794             long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
795             Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
796             Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
797         }
798     }
799
800     private boolean setScreenState(int state) {
801         if (mPowerState.getScreenState() != state) {
802             final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
803             mPowerState.setScreenState(state);
804
805             // Tell battery stats about the transition.
806             try {
807                 mBatteryStats.noteScreenState(state);
808             } catch (RemoteException ex) {
809                 // same process
810             }
811         }
812
813         // Tell the window manager policy when the screen is turned off or on unless it's due
814         // to the proximity sensor.  We temporarily block turning the screen on until the
815         // window manager is ready by leaving a black surface covering the screen.
816         // This surface is essentially the final state of the color fade animation and
817         // it is only removed once the window manager tells us that the activity has
818         // finished drawing underneath.
819         final boolean isOff = (state == Display.STATE_OFF);
820         if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
821                 && !mScreenOffBecauseOfProximity) {
822             mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_OFF;
823             unblockScreenOn();
824             mWindowManagerPolicy.screenTurnedOff();
825         } else if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
826             mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_ON;
827             if (mPowerState.getColorFadeLevel() == 0.0f) {
828                 blockScreenOn();
829             } else {
830                 unblockScreenOn();
831             }
832             mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
833         }
834
835         // Return true if the screen isn't blocked.
836         return mPendingScreenOnUnblocker == null;
837     }
838
839     private int clampScreenBrightness(int value) {
840         return MathUtils.constrain(
841                 value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
842     }
843
844     private void animateScreenBrightness(int target, int rate) {
845         if (DEBUG) {
846             Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
847         }
848         if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
849             try {
850                 mBatteryStats.noteScreenBrightness(target);
851             } catch (RemoteException ex) {
852                 // same process
853             }
854         }
855     }
856
857     private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
858         // If there is already an animation in progress, don't interfere with it.
859         if (mColorFadeOnAnimator.isStarted()
860                 || mColorFadeOffAnimator.isStarted()) {
861             if (target != Display.STATE_ON) {
862                 return;
863             }
864             // If display state changed to on, proceed and stop the color fade and turn screen on.
865             mPendingScreenOff = false;
866         }
867
868         // If we were in the process of turning off the screen but didn't quite
869         // finish.  Then finish up now to prevent a jarring transition back
870         // to screen on if we skipped blocking screen on as usual.
871         if (mPendingScreenOff && target != Display.STATE_OFF) {
872             setScreenState(Display.STATE_OFF);
873             mPendingScreenOff = false;
874             mPowerState.dismissColorFadeResources();
875         }
876
877         if (target == Display.STATE_ON) {
878             // Want screen on.  The contents of the screen may not yet
879             // be visible if the color fade has not been dismissed because
880             // its last frame of animation is solid black.
881             if (!setScreenState(Display.STATE_ON)) {
882                 return; // screen on blocked
883             }
884             if (USE_COLOR_FADE_ON_ANIMATION && mPowerRequest.isBrightOrDim()) {
885                 // Perform screen on animation.
886                 if (mPowerState.getColorFadeLevel() == 1.0f) {
887                     mPowerState.dismissColorFade();
888                 } else if (mPowerState.prepareColorFade(mContext,
889                         mColorFadeFadesConfig ?
890                                 ColorFade.MODE_FADE :
891                                         ColorFade.MODE_WARM_UP)) {
892                     mColorFadeOnAnimator.start();
893                 } else {
894                     mColorFadeOnAnimator.end();
895                 }
896             } else {
897                 // Skip screen on animation.
898                 mPowerState.setColorFadeLevel(1.0f);
899                 mPowerState.dismissColorFade();
900             }
901         } else if (target == Display.STATE_DOZE) {
902             // Want screen dozing.
903             // Wait for brightness animation to complete beforehand when entering doze
904             // from screen on to prevent a perceptible jump because brightness may operate
905             // differently when the display is configured for dozing.
906             if (mScreenBrightnessRampAnimator.isAnimating()
907                     && mPowerState.getScreenState() == Display.STATE_ON) {
908                 return;
909             }
910
911             // Set screen state.
912             if (!setScreenState(Display.STATE_DOZE)) {
913                 return; // screen on blocked
914             }
915
916             // Dismiss the black surface without fanfare.
917             mPowerState.setColorFadeLevel(1.0f);
918             mPowerState.dismissColorFade();
919         } else if (target == Display.STATE_DOZE_SUSPEND) {
920             // Want screen dozing and suspended.
921             // Wait for brightness animation to complete beforehand unless already
922             // suspended because we may not be able to change it after suspension.
923             if (mScreenBrightnessRampAnimator.isAnimating()
924                     && mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
925                 return;
926             }
927
928             // If not already suspending, temporarily set the state to doze until the
929             // screen on is unblocked, then suspend.
930             if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
931                 if (!setScreenState(Display.STATE_DOZE)) {
932                     return; // screen on blocked
933                 }
934                 setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
935             }
936
937             // Dismiss the black surface without fanfare.
938             mPowerState.setColorFadeLevel(1.0f);
939             mPowerState.dismissColorFade();
940         } else {
941             // Want screen off.
942             mPendingScreenOff = true;
943             if (mPowerState.getColorFadeLevel() == 0.0f) {
944                 // Turn the screen off.
945                 // A black surface is already hiding the contents of the screen.
946                 setScreenState(Display.STATE_OFF);
947                 mPendingScreenOff = false;
948                 mPowerState.dismissColorFadeResources();
949             } else if (performScreenOffTransition
950                     && mPowerState.prepareColorFade(mContext,
951                             mColorFadeFadesConfig ?
952                                     ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
953                     && mPowerState.getScreenState() != Display.STATE_OFF) {
954                 // Perform the screen off animation.
955                 mColorFadeOffAnimator.start();
956             } else {
957                 // Skip the screen off animation and add a black surface to hide the
958                 // contents of the screen.
959                 mColorFadeOffAnimator.end();
960             }
961         }
962     }
963
964     private final Runnable mCleanListener = new Runnable() {
965         @Override
966         public void run() {
967             sendUpdatePowerState();
968         }
969     };
970
971     private void setProximitySensorEnabled(boolean enable) {
972         if (enable) {
973             if (!mProximitySensorEnabled) {
974                 // Register the listener.
975                 // Proximity sensor state already cleared initially.
976                 mProximitySensorEnabled = true;
977                 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
978                         SensorManager.SENSOR_DELAY_NORMAL, mHandler);
979             }
980         } else {
981             if (mProximitySensorEnabled) {
982                 // Unregister the listener.
983                 // Clear the proximity sensor state for next time.
984                 mProximitySensorEnabled = false;
985                 mProximity = PROXIMITY_UNKNOWN;
986                 mPendingProximity = PROXIMITY_UNKNOWN;
987                 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
988                 mSensorManager.unregisterListener(mProximitySensorListener);
989                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
990             }
991         }
992     }
993
994     private void handleProximitySensorEvent(long time, boolean positive) {
995         if (mProximitySensorEnabled) {
996             if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
997                 return; // no change
998             }
999             if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
1000                 return; // no change
1001             }
1002
1003             // Only accept a proximity sensor reading if it remains
1004             // stable for the entire debounce delay.  We hold a wake lock while
1005             // debouncing the sensor.
1006             mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
1007             if (positive) {
1008                 mPendingProximity = PROXIMITY_POSITIVE;
1009                 setPendingProximityDebounceTime(
1010                         time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
1011             } else {
1012                 mPendingProximity = PROXIMITY_NEGATIVE;
1013                 setPendingProximityDebounceTime(
1014                         time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
1015             }
1016
1017             // Debounce the new sensor reading.
1018             debounceProximitySensor();
1019         }
1020     }
1021
1022     private void debounceProximitySensor() {
1023         if (mProximitySensorEnabled
1024                 && mPendingProximity != PROXIMITY_UNKNOWN
1025                 && mPendingProximityDebounceTime >= 0) {
1026             final long now = SystemClock.uptimeMillis();
1027             if (mPendingProximityDebounceTime <= now) {
1028                 // Sensor reading accepted.  Apply the change then release the wake lock.
1029                 mProximity = mPendingProximity;
1030                 updatePowerState();
1031                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
1032             } else {
1033                 // Need to wait a little longer.
1034                 // Debounce again later.  We continue holding a wake lock while waiting.
1035                 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
1036                 msg.setAsynchronous(true);
1037                 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
1038             }
1039         }
1040     }
1041
1042     private void clearPendingProximityDebounceTime() {
1043         if (mPendingProximityDebounceTime >= 0) {
1044             mPendingProximityDebounceTime = -1;
1045             mCallbacks.releaseSuspendBlocker(); // release wake lock
1046         }
1047     }
1048
1049     private void setPendingProximityDebounceTime(long debounceTime) {
1050         if (mPendingProximityDebounceTime < 0) {
1051             mCallbacks.acquireSuspendBlocker(); // acquire wake lock
1052         }
1053         mPendingProximityDebounceTime = debounceTime;
1054     }
1055
1056     private void sendOnStateChangedWithWakelock() {
1057         mCallbacks.acquireSuspendBlocker();
1058         mHandler.post(mOnStateChangedRunnable);
1059     }
1060
1061     private final Runnable mOnStateChangedRunnable = new Runnable() {
1062         @Override
1063         public void run() {
1064             mCallbacks.onStateChanged();
1065             mCallbacks.releaseSuspendBlocker();
1066         }
1067     };
1068
1069     private void sendOnProximityPositiveWithWakelock() {
1070         mCallbacks.acquireSuspendBlocker();
1071         mHandler.post(mOnProximityPositiveRunnable);
1072     }
1073
1074     private final Runnable mOnProximityPositiveRunnable = new Runnable() {
1075         @Override
1076         public void run() {
1077             mCallbacks.onProximityPositive();
1078             mCallbacks.releaseSuspendBlocker();
1079         }
1080     };
1081
1082     private void sendOnProximityNegativeWithWakelock() {
1083         mCallbacks.acquireSuspendBlocker();
1084         mHandler.post(mOnProximityNegativeRunnable);
1085     }
1086
1087     private final Runnable mOnProximityNegativeRunnable = new Runnable() {
1088         @Override
1089         public void run() {
1090             mCallbacks.onProximityNegative();
1091             mCallbacks.releaseSuspendBlocker();
1092         }
1093     };
1094
1095     public void dump(final PrintWriter pw) {
1096         synchronized (mLock) {
1097             pw.println();
1098             pw.println("Display Power Controller Locked State:");
1099             pw.println("  mDisplayReadyLocked=" + mDisplayReadyLocked);
1100             pw.println("  mPendingRequestLocked=" + mPendingRequestLocked);
1101             pw.println("  mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
1102             pw.println("  mPendingWaitForNegativeProximityLocked="
1103                     + mPendingWaitForNegativeProximityLocked);
1104             pw.println("  mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
1105         }
1106
1107         pw.println();
1108         pw.println("Display Power Controller Configuration:");
1109         pw.println("  mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
1110         pw.println("  mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
1111         pw.println("  mScreenBrightnessDarkConfig=" + mScreenBrightnessDarkConfig);
1112         pw.println("  mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
1113         pw.println("  mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
1114         pw.println("  mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
1115         pw.println("  mAllowAutoBrightnessWhileDozingConfig=" +
1116                 mAllowAutoBrightnessWhileDozingConfig);
1117         pw.println("  mColorFadeFadesConfig=" + mColorFadeFadesConfig);
1118
1119         mHandler.runWithScissors(new Runnable() {
1120             @Override
1121             public void run() {
1122                 dumpLocal(pw);
1123             }
1124         }, 1000);
1125     }
1126
1127     private void dumpLocal(PrintWriter pw) {
1128         pw.println();
1129         pw.println("Display Power Controller Thread State:");
1130         pw.println("  mPowerRequest=" + mPowerRequest);
1131         pw.println("  mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
1132
1133         pw.println("  mProximitySensor=" + mProximitySensor);
1134         pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
1135         pw.println("  mProximityThreshold=" + mProximityThreshold);
1136         pw.println("  mProximity=" + proximityToString(mProximity));
1137         pw.println("  mPendingProximity=" + proximityToString(mPendingProximity));
1138         pw.println("  mPendingProximityDebounceTime="
1139                 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
1140         pw.println("  mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
1141         pw.println("  mAppliedAutoBrightness=" + mAppliedAutoBrightness);
1142         pw.println("  mAppliedDimming=" + mAppliedDimming);
1143         pw.println("  mAppliedLowPower=" + mAppliedLowPower);
1144         pw.println("  mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
1145         pw.println("  mPendingScreenOff=" + mPendingScreenOff);
1146         pw.println("  mReportedToPolicy=" + reportedToPolicyToString(mReportedScreenStateToPolicy));
1147
1148         pw.println("  mScreenBrightnessRampAnimator.isAnimating()=" +
1149                 mScreenBrightnessRampAnimator.isAnimating());
1150
1151         if (mColorFadeOnAnimator != null) {
1152             pw.println("  mColorFadeOnAnimator.isStarted()=" +
1153                     mColorFadeOnAnimator.isStarted());
1154         }
1155         if (mColorFadeOffAnimator != null) {
1156             pw.println("  mColorFadeOffAnimator.isStarted()=" +
1157                     mColorFadeOffAnimator.isStarted());
1158         }
1159
1160         if (mPowerState != null) {
1161             mPowerState.dump(pw);
1162         }
1163
1164         if (mAutomaticBrightnessController != null) {
1165             mAutomaticBrightnessController.dump(pw);
1166         }
1167
1168     }
1169
1170     private static String proximityToString(int state) {
1171         switch (state) {
1172             case PROXIMITY_UNKNOWN:
1173                 return "Unknown";
1174             case PROXIMITY_NEGATIVE:
1175                 return "Negative";
1176             case PROXIMITY_POSITIVE:
1177                 return "Positive";
1178             default:
1179                 return Integer.toString(state);
1180         }
1181     }
1182
1183     private static String reportedToPolicyToString(int state) {
1184         switch (state) {
1185             case REPORTED_TO_POLICY_SCREEN_OFF:
1186                 return "REPORTED_TO_POLICY_SCREEN_OFF";
1187             case REPORTED_TO_POLICY_SCREEN_TURNING_ON:
1188                 return "REPORTED_TO_POLICY_SCREEN_TURNING_ON";
1189             case REPORTED_TO_POLICY_SCREEN_ON:
1190                 return "REPORTED_TO_POLICY_SCREEN_ON";
1191             default:
1192                 return Integer.toString(state);
1193         }
1194     }
1195
1196     private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) {
1197         try {
1198             final int n = brightness.length;
1199             float[] x = new float[n];
1200             float[] y = new float[n];
1201             y[0] = normalizeAbsoluteBrightness(brightness[0]);
1202             for (int i = 1; i < n; i++) {
1203                 x[i] = lux[i - 1];
1204                 y[i] = normalizeAbsoluteBrightness(brightness[i]);
1205             }
1206
1207             Spline spline = Spline.createSpline(x, y);
1208             if (DEBUG) {
1209                 Slog.d(TAG, "Auto-brightness spline: " + spline);
1210                 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
1211                     Slog.d(TAG, String.format("  %7.1f: %7.1f", v, spline.interpolate(v)));
1212                 }
1213             }
1214             return spline;
1215         } catch (IllegalArgumentException ex) {
1216             Slog.e(TAG, "Could not create auto-brightness spline.", ex);
1217             return null;
1218         }
1219     }
1220
1221     private static float normalizeAbsoluteBrightness(int value) {
1222         return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON;
1223     }
1224
1225     private static int clampAbsoluteBrightness(int value) {
1226         return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
1227     }
1228
1229     private final class DisplayControllerHandler extends Handler {
1230         public DisplayControllerHandler(Looper looper) {
1231             super(looper, null, true /*async*/);
1232         }
1233
1234         @Override
1235         public void handleMessage(Message msg) {
1236             switch (msg.what) {
1237                 case MSG_UPDATE_POWER_STATE:
1238                     updatePowerState();
1239                     break;
1240
1241                 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
1242                     debounceProximitySensor();
1243                     break;
1244
1245                 case MSG_SCREEN_ON_UNBLOCKED:
1246                     if (mPendingScreenOnUnblocker == msg.obj) {
1247                         unblockScreenOn();
1248                         updatePowerState();
1249                     }
1250                     break;
1251             }
1252         }
1253     }
1254
1255     private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
1256         @Override
1257         public void onSensorChanged(SensorEvent event) {
1258             if (mProximitySensorEnabled) {
1259                 final long time = SystemClock.uptimeMillis();
1260                 final float distance = event.values[0];
1261                 boolean positive = distance >= 0.0f && distance < mProximityThreshold;
1262                 handleProximitySensorEvent(time, positive);
1263             }
1264         }
1265
1266         @Override
1267         public void onAccuracyChanged(Sensor sensor, int accuracy) {
1268             // Not used.
1269         }
1270     };
1271
1272     private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
1273         @Override
1274         public void onScreenOn() {
1275             Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
1276             msg.setAsynchronous(true);
1277             mHandler.sendMessage(msg);
1278         }
1279     }
1280 }