OSDN Git Service

Increase brightness faster if ambient light is brightening quickly.
[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 brighteningLightFastDebounce = resources.getInteger(
321                 com.android.internal.R.integer.config_autoBrightnessBrighteningLightFastDebounce);
322         long darkeningLightDebounce = resources.getInteger(
323                 com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce);
324         boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean(
325                 com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
326         int ambientLightHorizon = resources.getInteger(
327                 com.android.internal.R.integer.config_autoBrightnessAmbientLightHorizon);
328         float autoBrightnessAdjustmentMaxGamma = resources.getFraction(
329                 com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
330                 1, 1);
331
332         if (mUseSoftwareAutoBrightnessConfig) {
333             int[] lux = resources.getIntArray(
334                     com.android.internal.R.array.config_autoBrightnessLevels);
335             int[] screenBrightness = resources.getIntArray(
336                     com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
337             int lightSensorWarmUpTimeConfig = resources.getInteger(
338                     com.android.internal.R.integer.config_lightSensorWarmupTime);
339             final float dozeScaleFactor = resources.getFraction(
340                     com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
341                     1, 1);
342
343             Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
344             if (screenAutoBrightnessSpline == null) {
345                 Slog.e(TAG, "Error in config.xml.  config_autoBrightnessLcdBacklightValues "
346                         + "(size " + screenBrightness.length + ") "
347                         + "must be monotic and have exactly one more entry than "
348                         + "config_autoBrightnessLevels (size " + lux.length + ") "
349                         + "which must be strictly increasing.  "
350                         + "Auto-brightness will be disabled.");
351                 mUseSoftwareAutoBrightnessConfig = false;
352             } else {
353                 int bottom = clampAbsoluteBrightness(screenBrightness[0]);
354                 if (mScreenBrightnessDarkConfig > bottom) {
355                     Slog.w(TAG, "config_screenBrightnessDark (" + mScreenBrightnessDarkConfig
356                             + ") should be less than or equal to the first value of "
357                             + "config_autoBrightnessLcdBacklightValues ("
358                             + bottom + ").");
359                 }
360                 if (bottom < screenBrightnessRangeMinimum) {
361                     screenBrightnessRangeMinimum = bottom;
362                 }
363                 mAutomaticBrightnessController = new AutomaticBrightnessController(this,
364                         handler.getLooper(), sensorManager, screenAutoBrightnessSpline,
365                         lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
366                         mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
367                         brighteningLightDebounce, brighteningLightFastDebounce,
368                         darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp,
369                         ambientLightHorizon, autoBrightnessAdjustmentMaxGamma);
370             }
371         }
372
373         mScreenBrightnessRangeMinimum = screenBrightnessRangeMinimum;
374
375         mColorFadeFadesConfig = resources.getBoolean(
376                 com.android.internal.R.bool.config_animateScreenLights);
377
378         if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
379             mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
380             if (mProximitySensor != null) {
381                 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
382                         TYPICAL_PROXIMITY_THRESHOLD);
383             }
384         }
385
386     }
387
388     /**
389      * Returns true if the proximity sensor screen-off function is available.
390      */
391     public boolean isProximitySensorAvailable() {
392         return mProximitySensor != null;
393     }
394
395     /**
396      * Requests a new power state.
397      * The controller makes a copy of the provided object and then
398      * begins adjusting the power state to match what was requested.
399      *
400      * @param request The requested power state.
401      * @param waitForNegativeProximity If true, issues a request to wait for
402      * negative proximity before turning the screen back on, assuming the screen
403      * was turned off by the proximity sensor.
404      * @return True if display is ready, false if there are important changes that must
405      * be made asynchronously (such as turning the screen on), in which case the caller
406      * should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged()}
407      * then try the request again later until the state converges.
408      */
409     public boolean requestPowerState(DisplayPowerRequest request,
410             boolean waitForNegativeProximity) {
411         if (DEBUG) {
412             Slog.d(TAG, "requestPowerState: "
413                     + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
414         }
415
416         synchronized (mLock) {
417             boolean changed = false;
418
419             if (waitForNegativeProximity
420                     && !mPendingWaitForNegativeProximityLocked) {
421                 mPendingWaitForNegativeProximityLocked = true;
422                 changed = true;
423             }
424
425             if (mPendingRequestLocked == null) {
426                 mPendingRequestLocked = new DisplayPowerRequest(request);
427                 changed = true;
428             } else if (!mPendingRequestLocked.equals(request)) {
429                 mPendingRequestLocked.copyFrom(request);
430                 changed = true;
431             }
432
433             if (changed) {
434                 mDisplayReadyLocked = false;
435             }
436
437             if (changed && !mPendingRequestChangedLocked) {
438                 mPendingRequestChangedLocked = true;
439                 sendUpdatePowerStateLocked();
440             }
441
442             return mDisplayReadyLocked;
443         }
444     }
445
446     private void sendUpdatePowerState() {
447         synchronized (mLock) {
448             sendUpdatePowerStateLocked();
449         }
450     }
451
452     private void sendUpdatePowerStateLocked() {
453         if (!mPendingUpdatePowerStateLocked) {
454             mPendingUpdatePowerStateLocked = true;
455             Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
456             msg.setAsynchronous(true);
457             mHandler.sendMessage(msg);
458         }
459     }
460
461     private void initialize() {
462         // Initialize the power state object for the default display.
463         // In the future, we might manage multiple displays independently.
464         mPowerState = new DisplayPowerState(mBlanker,
465                 new ColorFade(Display.DEFAULT_DISPLAY));
466
467         mColorFadeOnAnimator = ObjectAnimator.ofFloat(
468                 mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 0.0f, 1.0f);
469         mColorFadeOnAnimator.setDuration(COLOR_FADE_ON_ANIMATION_DURATION_MILLIS);
470         mColorFadeOnAnimator.addListener(mAnimatorListener);
471
472         mColorFadeOffAnimator = ObjectAnimator.ofFloat(
473                 mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 1.0f, 0.0f);
474         mColorFadeOffAnimator.setDuration(COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS);
475         mColorFadeOffAnimator.addListener(mAnimatorListener);
476
477         mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
478                 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
479         mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
480
481         // Initialize screen state for battery stats.
482         try {
483             mBatteryStats.noteScreenState(mPowerState.getScreenState());
484             mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness());
485         } catch (RemoteException ex) {
486             // same process
487         }
488     }
489
490     private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
491         @Override
492         public void onAnimationStart(Animator animation) {
493         }
494         @Override
495         public void onAnimationEnd(Animator animation) {
496             sendUpdatePowerState();
497         }
498         @Override
499         public void onAnimationRepeat(Animator animation) {
500         }
501         @Override
502         public void onAnimationCancel(Animator animation) {
503         }
504     };
505
506     private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
507         @Override
508         public void onAnimationEnd() {
509             sendUpdatePowerState();
510         }
511     };
512
513     private void updatePowerState() {
514         // Update the power state request.
515         final boolean mustNotify;
516         boolean mustInitialize = false;
517         boolean autoBrightnessAdjustmentChanged = false;
518
519         synchronized (mLock) {
520             mPendingUpdatePowerStateLocked = false;
521             if (mPendingRequestLocked == null) {
522                 return; // wait until first actual power request
523             }
524
525             if (mPowerRequest == null) {
526                 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
527                 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
528                 mPendingWaitForNegativeProximityLocked = false;
529                 mPendingRequestChangedLocked = false;
530                 mustInitialize = true;
531             } else if (mPendingRequestChangedLocked) {
532                 autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
533                         != mPendingRequestLocked.screenAutoBrightnessAdjustment);
534                 mPowerRequest.copyFrom(mPendingRequestLocked);
535                 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
536                 mPendingWaitForNegativeProximityLocked = false;
537                 mPendingRequestChangedLocked = false;
538                 mDisplayReadyLocked = false;
539             }
540
541             mustNotify = !mDisplayReadyLocked;
542         }
543
544         // Initialize things the first time the power state is changed.
545         if (mustInitialize) {
546             initialize();
547         }
548
549         // Compute the basic display state using the policy.
550         // We might override this below based on other factors.
551         int state;
552         int brightness = PowerManager.BRIGHTNESS_DEFAULT;
553         boolean performScreenOffTransition = false;
554         switch (mPowerRequest.policy) {
555             case DisplayPowerRequest.POLICY_OFF:
556                 state = Display.STATE_OFF;
557                 performScreenOffTransition = true;
558                 break;
559             case DisplayPowerRequest.POLICY_DOZE:
560                 if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
561                     state = mPowerRequest.dozeScreenState;
562                 } else {
563                     state = Display.STATE_DOZE;
564                 }
565                 if (!mAllowAutoBrightnessWhileDozingConfig) {
566                     brightness = mPowerRequest.dozeScreenBrightness;
567                 }
568                 break;
569             case DisplayPowerRequest.POLICY_DIM:
570             case DisplayPowerRequest.POLICY_BRIGHT:
571             default:
572                 state = Display.STATE_ON;
573                 break;
574         }
575         assert(state != Display.STATE_UNKNOWN);
576
577         // Apply the proximity sensor.
578         if (mProximitySensor != null) {
579             if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
580                 setProximitySensorEnabled(true);
581                 if (!mScreenOffBecauseOfProximity
582                         && mProximity == PROXIMITY_POSITIVE) {
583                     mScreenOffBecauseOfProximity = true;
584                     sendOnProximityPositiveWithWakelock();
585                 }
586             } else if (mWaitingForNegativeProximity
587                     && mScreenOffBecauseOfProximity
588                     && mProximity == PROXIMITY_POSITIVE
589                     && state != Display.STATE_OFF) {
590                 setProximitySensorEnabled(true);
591             } else {
592                 setProximitySensorEnabled(false);
593                 mWaitingForNegativeProximity = false;
594             }
595             if (mScreenOffBecauseOfProximity
596                     && mProximity != PROXIMITY_POSITIVE) {
597                 mScreenOffBecauseOfProximity = false;
598                 sendOnProximityNegativeWithWakelock();
599             }
600         } else {
601             mWaitingForNegativeProximity = false;
602         }
603         if (mScreenOffBecauseOfProximity) {
604             state = Display.STATE_OFF;
605         }
606
607         // Animate the screen state change unless already animating.
608         // The transition may be deferred, so after this point we will use the
609         // actual state instead of the desired one.
610         animateScreenStateChange(state, performScreenOffTransition);
611         state = mPowerState.getScreenState();
612
613         // Use zero brightness when screen is off.
614         if (state == Display.STATE_OFF) {
615             brightness = PowerManager.BRIGHTNESS_OFF;
616             mLights.getLight(LightsManager.LIGHT_ID_BUTTONS).setBrightness(brightness);
617             mLights.getLight(LightsManager.LIGHT_ID_KEYBOARD).setBrightness(brightness);
618         }
619
620         // Disable button lights when dozing
621         if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND) {
622             mLights.getLight(LightsManager.LIGHT_ID_BUTTONS).setBrightness(PowerManager.BRIGHTNESS_OFF);
623             mLights.getLight(LightsManager.LIGHT_ID_KEYBOARD).setBrightness(PowerManager.BRIGHTNESS_OFF);
624         }
625
626         // Configure auto-brightness.
627         boolean autoBrightnessEnabled = false;
628         if (mAutomaticBrightnessController != null) {
629             final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig
630                     && (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);
631             autoBrightnessEnabled = mPowerRequest.useAutoBrightness
632                     && (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
633                     && brightness < 0;
634             final boolean userInitiatedChange = autoBrightnessAdjustmentChanged
635                     && mPowerRequest.brightnessSetByUser;
636             mAutomaticBrightnessController.configure(autoBrightnessEnabled,
637                     mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,
638                     userInitiatedChange, mPowerRequest.useTwilight);
639         }
640
641         // Apply brightness boost.
642         // We do this here after configuring auto-brightness so that we don't
643         // disable the light sensor during this temporary state.  That way when
644         // boost ends we will be able to resume normal auto-brightness behavior
645         // without any delay.
646         if (mPowerRequest.boostScreenBrightness
647                 && brightness != PowerManager.BRIGHTNESS_OFF) {
648             brightness = PowerManager.BRIGHTNESS_ON;
649         }
650
651         // Apply auto-brightness.
652         boolean slowChange = false;
653         if (brightness < 0) {
654             if (autoBrightnessEnabled) {
655                 brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();
656             }
657             if (brightness >= 0) {
658                 // Use current auto-brightness value and slowly adjust to changes.
659                 brightness = clampScreenBrightness(brightness);
660                 if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
661                     slowChange = true; // slowly adapt to auto-brightness
662                 }
663                 mAppliedAutoBrightness = true;
664             } else {
665                 mAppliedAutoBrightness = false;
666             }
667         } else {
668             mAppliedAutoBrightness = false;
669         }
670
671         // Use default brightness when dozing unless overridden.
672         if (brightness < 0 && (state == Display.STATE_DOZE
673                 || state == Display.STATE_DOZE_SUSPEND)) {
674             brightness = mScreenBrightnessDozeConfig;
675         }
676
677         // Apply manual brightness.
678         // Use the current brightness setting from the request, which is expected
679         // provide a nominal default value for the case where auto-brightness
680         // is not ready yet.
681         if (brightness < 0) {
682             brightness = clampScreenBrightness(mPowerRequest.screenBrightness);
683         }
684
685         // Apply dimming by at least some minimum amount when user activity
686         // timeout is about to expire.
687         if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
688             if (brightness > mScreenBrightnessRangeMinimum) {
689                 brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,
690                         mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
691             }
692             if (!mAppliedDimming) {
693                 slowChange = false;
694             }
695             mAppliedDimming = true;
696         } else if (mAppliedDimming) {
697             slowChange = false;
698             mAppliedDimming = false;
699         }
700
701         // If low power mode is enabled, cut the brightness level by half
702         // as long as it is above the minimum threshold.
703         if (mPowerRequest.lowPowerMode) {
704             if (brightness > mScreenBrightnessRangeMinimum) {
705                 brightness = Math.max(brightness / 2, mScreenBrightnessRangeMinimum);
706             }
707             if (!mAppliedLowPower) {
708                 slowChange = false;
709             }
710             mAppliedLowPower = true;
711         } else if (mAppliedLowPower) {
712             slowChange = false;
713             mAppliedLowPower = false;
714         }
715
716         // Animate the screen brightness when the screen is on or dozing.
717         // Skip the animation when the screen is off or suspended.
718         if (!mPendingScreenOff) {
719             if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
720                 animateScreenBrightness(brightness,
721                         slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast);
722             } else {
723                 animateScreenBrightness(brightness, 0);
724             }
725         }
726
727         // Determine whether the display is ready for use in the newly requested state.
728         // Note that we do not wait for the brightness ramp animation to complete before
729         // reporting the display is ready because we only need to ensure the screen is in the
730         // right power state even as it continues to converge on the desired brightness.
731         final boolean ready = mPendingScreenOnUnblocker == null
732                 && !mColorFadeOnAnimator.isStarted()
733                 && !mColorFadeOffAnimator.isStarted()
734                 && mPowerState.waitUntilClean(mCleanListener);
735         final boolean finished = ready
736                 && !mScreenBrightnessRampAnimator.isAnimating();
737
738         // Notify policy about screen turned on.
739         if (ready && state != Display.STATE_OFF
740                 && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
741             mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_ON;
742             mWindowManagerPolicy.screenTurnedOn();
743         }
744
745         // Grab a wake lock if we have unfinished business.
746         if (!finished && !mUnfinishedBusiness) {
747             if (DEBUG) {
748                 Slog.d(TAG, "Unfinished business...");
749             }
750             mCallbacks.acquireSuspendBlocker();
751             mUnfinishedBusiness = true;
752         }
753
754         // Notify the power manager when ready.
755         if (ready && mustNotify) {
756             // Send state change.
757             synchronized (mLock) {
758                 if (!mPendingRequestChangedLocked) {
759                     mDisplayReadyLocked = true;
760
761                     if (DEBUG) {
762                         Slog.d(TAG, "Display ready!");
763                     }
764                 }
765             }
766             sendOnStateChangedWithWakelock();
767         }
768
769         // Release the wake lock when we have no unfinished business.
770         if (finished && mUnfinishedBusiness) {
771             if (DEBUG) {
772                 Slog.d(TAG, "Finished business...");
773             }
774             mUnfinishedBusiness = false;
775             mCallbacks.releaseSuspendBlocker();
776         }
777     }
778
779     @Override
780     public void updateBrightness() {
781         sendUpdatePowerState();
782     }
783
784     private void blockScreenOn() {
785         if (mPendingScreenOnUnblocker == null) {
786             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
787             mPendingScreenOnUnblocker = new ScreenOnUnblocker();
788             mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
789             Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
790         }
791     }
792
793     private void unblockScreenOn() {
794         if (mPendingScreenOnUnblocker != null) {
795             mPendingScreenOnUnblocker = null;
796             long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
797             Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
798             Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
799         }
800     }
801
802     private boolean setScreenState(int state) {
803         if (mPowerState.getScreenState() != state) {
804             final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
805             mPowerState.setScreenState(state);
806
807             // Tell battery stats about the transition.
808             try {
809                 mBatteryStats.noteScreenState(state);
810             } catch (RemoteException ex) {
811                 // same process
812             }
813         }
814
815         // Tell the window manager policy when the screen is turned off or on unless it's due
816         // to the proximity sensor.  We temporarily block turning the screen on until the
817         // window manager is ready by leaving a black surface covering the screen.
818         // This surface is essentially the final state of the color fade animation and
819         // it is only removed once the window manager tells us that the activity has
820         // finished drawing underneath.
821         final boolean isOff = (state == Display.STATE_OFF);
822         if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
823                 && !mScreenOffBecauseOfProximity) {
824             mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_OFF;
825             unblockScreenOn();
826             mWindowManagerPolicy.screenTurnedOff();
827         } else if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
828             mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_ON;
829             if (mPowerState.getColorFadeLevel() == 0.0f) {
830                 blockScreenOn();
831             } else {
832                 unblockScreenOn();
833             }
834             mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
835         }
836
837         // Return true if the screen isn't blocked.
838         return mPendingScreenOnUnblocker == null;
839     }
840
841     private int clampScreenBrightness(int value) {
842         return MathUtils.constrain(
843                 value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
844     }
845
846     private void animateScreenBrightness(int target, int rate) {
847         if (DEBUG) {
848             Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
849         }
850         if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
851             try {
852                 mBatteryStats.noteScreenBrightness(target);
853             } catch (RemoteException ex) {
854                 // same process
855             }
856         }
857     }
858
859     private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
860         // If there is already an animation in progress, don't interfere with it.
861         if (mColorFadeOnAnimator.isStarted()
862                 || mColorFadeOffAnimator.isStarted()) {
863             if (target != Display.STATE_ON) {
864                 return;
865             }
866             // If display state changed to on, proceed and stop the color fade and turn screen on.
867             mPendingScreenOff = false;
868         }
869
870         // If we were in the process of turning off the screen but didn't quite
871         // finish.  Then finish up now to prevent a jarring transition back
872         // to screen on if we skipped blocking screen on as usual.
873         if (mPendingScreenOff && target != Display.STATE_OFF) {
874             setScreenState(Display.STATE_OFF);
875             mPendingScreenOff = false;
876             mPowerState.dismissColorFadeResources();
877         }
878
879         if (target == Display.STATE_ON) {
880             // Want screen on.  The contents of the screen may not yet
881             // be visible if the color fade has not been dismissed because
882             // its last frame of animation is solid black.
883             if (!setScreenState(Display.STATE_ON)) {
884                 return; // screen on blocked
885             }
886             if (USE_COLOR_FADE_ON_ANIMATION && mPowerRequest.isBrightOrDim()) {
887                 // Perform screen on animation.
888                 if (mPowerState.getColorFadeLevel() == 1.0f) {
889                     mPowerState.dismissColorFade();
890                 } else if (mPowerState.prepareColorFade(mContext,
891                         mColorFadeFadesConfig ?
892                                 ColorFade.MODE_FADE :
893                                         ColorFade.MODE_WARM_UP)) {
894                     mColorFadeOnAnimator.start();
895                 } else {
896                     mColorFadeOnAnimator.end();
897                 }
898             } else {
899                 // Skip screen on animation.
900                 mPowerState.setColorFadeLevel(1.0f);
901                 mPowerState.dismissColorFade();
902             }
903         } else if (target == Display.STATE_DOZE) {
904             // Want screen dozing.
905             // Wait for brightness animation to complete beforehand when entering doze
906             // from screen on to prevent a perceptible jump because brightness may operate
907             // differently when the display is configured for dozing.
908             if (mScreenBrightnessRampAnimator.isAnimating()
909                     && mPowerState.getScreenState() == Display.STATE_ON) {
910                 return;
911             }
912
913             // Set screen state.
914             if (!setScreenState(Display.STATE_DOZE)) {
915                 return; // screen on blocked
916             }
917
918             // Dismiss the black surface without fanfare.
919             mPowerState.setColorFadeLevel(1.0f);
920             mPowerState.dismissColorFade();
921         } else if (target == Display.STATE_DOZE_SUSPEND) {
922             // Want screen dozing and suspended.
923             // Wait for brightness animation to complete beforehand unless already
924             // suspended because we may not be able to change it after suspension.
925             if (mScreenBrightnessRampAnimator.isAnimating()
926                     && mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
927                 return;
928             }
929
930             // If not already suspending, temporarily set the state to doze until the
931             // screen on is unblocked, then suspend.
932             if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
933                 if (!setScreenState(Display.STATE_DOZE)) {
934                     return; // screen on blocked
935                 }
936                 setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
937             }
938
939             // Dismiss the black surface without fanfare.
940             mPowerState.setColorFadeLevel(1.0f);
941             mPowerState.dismissColorFade();
942         } else {
943             // Want screen off.
944             mPendingScreenOff = true;
945             if (mPowerState.getColorFadeLevel() == 0.0f) {
946                 // Turn the screen off.
947                 // A black surface is already hiding the contents of the screen.
948                 setScreenState(Display.STATE_OFF);
949                 mPendingScreenOff = false;
950                 mPowerState.dismissColorFadeResources();
951             } else if (performScreenOffTransition
952                     && mPowerState.prepareColorFade(mContext,
953                             mColorFadeFadesConfig ?
954                                     ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
955                     && mPowerState.getScreenState() != Display.STATE_OFF) {
956                 // Perform the screen off animation.
957                 mColorFadeOffAnimator.start();
958             } else {
959                 // Skip the screen off animation and add a black surface to hide the
960                 // contents of the screen.
961                 mColorFadeOffAnimator.end();
962             }
963         }
964     }
965
966     private final Runnable mCleanListener = new Runnable() {
967         @Override
968         public void run() {
969             sendUpdatePowerState();
970         }
971     };
972
973     private void setProximitySensorEnabled(boolean enable) {
974         if (enable) {
975             if (!mProximitySensorEnabled) {
976                 // Register the listener.
977                 // Proximity sensor state already cleared initially.
978                 mProximitySensorEnabled = true;
979                 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
980                         SensorManager.SENSOR_DELAY_NORMAL, mHandler);
981             }
982         } else {
983             if (mProximitySensorEnabled) {
984                 // Unregister the listener.
985                 // Clear the proximity sensor state for next time.
986                 mProximitySensorEnabled = false;
987                 mProximity = PROXIMITY_UNKNOWN;
988                 mPendingProximity = PROXIMITY_UNKNOWN;
989                 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
990                 mSensorManager.unregisterListener(mProximitySensorListener);
991                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
992             }
993         }
994     }
995
996     private void handleProximitySensorEvent(long time, boolean positive) {
997         if (mProximitySensorEnabled) {
998             if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
999                 return; // no change
1000             }
1001             if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
1002                 return; // no change
1003             }
1004
1005             // Only accept a proximity sensor reading if it remains
1006             // stable for the entire debounce delay.  We hold a wake lock while
1007             // debouncing the sensor.
1008             mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
1009             if (positive) {
1010                 mPendingProximity = PROXIMITY_POSITIVE;
1011                 setPendingProximityDebounceTime(
1012                         time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
1013             } else {
1014                 mPendingProximity = PROXIMITY_NEGATIVE;
1015                 setPendingProximityDebounceTime(
1016                         time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
1017             }
1018
1019             // Debounce the new sensor reading.
1020             debounceProximitySensor();
1021         }
1022     }
1023
1024     private void debounceProximitySensor() {
1025         if (mProximitySensorEnabled
1026                 && mPendingProximity != PROXIMITY_UNKNOWN
1027                 && mPendingProximityDebounceTime >= 0) {
1028             final long now = SystemClock.uptimeMillis();
1029             if (mPendingProximityDebounceTime <= now) {
1030                 // Sensor reading accepted.  Apply the change then release the wake lock.
1031                 mProximity = mPendingProximity;
1032                 updatePowerState();
1033                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
1034             } else {
1035                 // Need to wait a little longer.
1036                 // Debounce again later.  We continue holding a wake lock while waiting.
1037                 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
1038                 msg.setAsynchronous(true);
1039                 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
1040             }
1041         }
1042     }
1043
1044     private void clearPendingProximityDebounceTime() {
1045         if (mPendingProximityDebounceTime >= 0) {
1046             mPendingProximityDebounceTime = -1;
1047             mCallbacks.releaseSuspendBlocker(); // release wake lock
1048         }
1049     }
1050
1051     private void setPendingProximityDebounceTime(long debounceTime) {
1052         if (mPendingProximityDebounceTime < 0) {
1053             mCallbacks.acquireSuspendBlocker(); // acquire wake lock
1054         }
1055         mPendingProximityDebounceTime = debounceTime;
1056     }
1057
1058     private void sendOnStateChangedWithWakelock() {
1059         mCallbacks.acquireSuspendBlocker();
1060         mHandler.post(mOnStateChangedRunnable);
1061     }
1062
1063     private final Runnable mOnStateChangedRunnable = new Runnable() {
1064         @Override
1065         public void run() {
1066             mCallbacks.onStateChanged();
1067             mCallbacks.releaseSuspendBlocker();
1068         }
1069     };
1070
1071     private void sendOnProximityPositiveWithWakelock() {
1072         mCallbacks.acquireSuspendBlocker();
1073         mHandler.post(mOnProximityPositiveRunnable);
1074     }
1075
1076     private final Runnable mOnProximityPositiveRunnable = new Runnable() {
1077         @Override
1078         public void run() {
1079             mCallbacks.onProximityPositive();
1080             mCallbacks.releaseSuspendBlocker();
1081         }
1082     };
1083
1084     private void sendOnProximityNegativeWithWakelock() {
1085         mCallbacks.acquireSuspendBlocker();
1086         mHandler.post(mOnProximityNegativeRunnable);
1087     }
1088
1089     private final Runnable mOnProximityNegativeRunnable = new Runnable() {
1090         @Override
1091         public void run() {
1092             mCallbacks.onProximityNegative();
1093             mCallbacks.releaseSuspendBlocker();
1094         }
1095     };
1096
1097     public void dump(final PrintWriter pw) {
1098         synchronized (mLock) {
1099             pw.println();
1100             pw.println("Display Power Controller Locked State:");
1101             pw.println("  mDisplayReadyLocked=" + mDisplayReadyLocked);
1102             pw.println("  mPendingRequestLocked=" + mPendingRequestLocked);
1103             pw.println("  mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
1104             pw.println("  mPendingWaitForNegativeProximityLocked="
1105                     + mPendingWaitForNegativeProximityLocked);
1106             pw.println("  mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
1107         }
1108
1109         pw.println();
1110         pw.println("Display Power Controller Configuration:");
1111         pw.println("  mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
1112         pw.println("  mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
1113         pw.println("  mScreenBrightnessDarkConfig=" + mScreenBrightnessDarkConfig);
1114         pw.println("  mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
1115         pw.println("  mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
1116         pw.println("  mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
1117         pw.println("  mAllowAutoBrightnessWhileDozingConfig=" +
1118                 mAllowAutoBrightnessWhileDozingConfig);
1119         pw.println("  mColorFadeFadesConfig=" + mColorFadeFadesConfig);
1120
1121         mHandler.runWithScissors(new Runnable() {
1122             @Override
1123             public void run() {
1124                 dumpLocal(pw);
1125             }
1126         }, 1000);
1127     }
1128
1129     private void dumpLocal(PrintWriter pw) {
1130         pw.println();
1131         pw.println("Display Power Controller Thread State:");
1132         pw.println("  mPowerRequest=" + mPowerRequest);
1133         pw.println("  mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
1134
1135         pw.println("  mProximitySensor=" + mProximitySensor);
1136         pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
1137         pw.println("  mProximityThreshold=" + mProximityThreshold);
1138         pw.println("  mProximity=" + proximityToString(mProximity));
1139         pw.println("  mPendingProximity=" + proximityToString(mPendingProximity));
1140         pw.println("  mPendingProximityDebounceTime="
1141                 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
1142         pw.println("  mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
1143         pw.println("  mAppliedAutoBrightness=" + mAppliedAutoBrightness);
1144         pw.println("  mAppliedDimming=" + mAppliedDimming);
1145         pw.println("  mAppliedLowPower=" + mAppliedLowPower);
1146         pw.println("  mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
1147         pw.println("  mPendingScreenOff=" + mPendingScreenOff);
1148         pw.println("  mReportedToPolicy=" + reportedToPolicyToString(mReportedScreenStateToPolicy));
1149
1150         pw.println("  mScreenBrightnessRampAnimator.isAnimating()=" +
1151                 mScreenBrightnessRampAnimator.isAnimating());
1152
1153         if (mColorFadeOnAnimator != null) {
1154             pw.println("  mColorFadeOnAnimator.isStarted()=" +
1155                     mColorFadeOnAnimator.isStarted());
1156         }
1157         if (mColorFadeOffAnimator != null) {
1158             pw.println("  mColorFadeOffAnimator.isStarted()=" +
1159                     mColorFadeOffAnimator.isStarted());
1160         }
1161
1162         if (mPowerState != null) {
1163             mPowerState.dump(pw);
1164         }
1165
1166         if (mAutomaticBrightnessController != null) {
1167             mAutomaticBrightnessController.dump(pw);
1168         }
1169
1170     }
1171
1172     private static String proximityToString(int state) {
1173         switch (state) {
1174             case PROXIMITY_UNKNOWN:
1175                 return "Unknown";
1176             case PROXIMITY_NEGATIVE:
1177                 return "Negative";
1178             case PROXIMITY_POSITIVE:
1179                 return "Positive";
1180             default:
1181                 return Integer.toString(state);
1182         }
1183     }
1184
1185     private static String reportedToPolicyToString(int state) {
1186         switch (state) {
1187             case REPORTED_TO_POLICY_SCREEN_OFF:
1188                 return "REPORTED_TO_POLICY_SCREEN_OFF";
1189             case REPORTED_TO_POLICY_SCREEN_TURNING_ON:
1190                 return "REPORTED_TO_POLICY_SCREEN_TURNING_ON";
1191             case REPORTED_TO_POLICY_SCREEN_ON:
1192                 return "REPORTED_TO_POLICY_SCREEN_ON";
1193             default:
1194                 return Integer.toString(state);
1195         }
1196     }
1197
1198     private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) {
1199         try {
1200             final int n = brightness.length;
1201             float[] x = new float[n];
1202             float[] y = new float[n];
1203             y[0] = normalizeAbsoluteBrightness(brightness[0]);
1204             for (int i = 1; i < n; i++) {
1205                 x[i] = lux[i - 1];
1206                 y[i] = normalizeAbsoluteBrightness(brightness[i]);
1207             }
1208
1209             Spline spline = Spline.createSpline(x, y);
1210             if (DEBUG) {
1211                 Slog.d(TAG, "Auto-brightness spline: " + spline);
1212                 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
1213                     Slog.d(TAG, String.format("  %7.1f: %7.1f", v, spline.interpolate(v)));
1214                 }
1215             }
1216             return spline;
1217         } catch (IllegalArgumentException ex) {
1218             Slog.e(TAG, "Could not create auto-brightness spline.", ex);
1219             return null;
1220         }
1221     }
1222
1223     private static float normalizeAbsoluteBrightness(int value) {
1224         return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON;
1225     }
1226
1227     private static int clampAbsoluteBrightness(int value) {
1228         return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
1229     }
1230
1231     private final class DisplayControllerHandler extends Handler {
1232         public DisplayControllerHandler(Looper looper) {
1233             super(looper, null, true /*async*/);
1234         }
1235
1236         @Override
1237         public void handleMessage(Message msg) {
1238             switch (msg.what) {
1239                 case MSG_UPDATE_POWER_STATE:
1240                     updatePowerState();
1241                     break;
1242
1243                 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
1244                     debounceProximitySensor();
1245                     break;
1246
1247                 case MSG_SCREEN_ON_UNBLOCKED:
1248                     if (mPendingScreenOnUnblocker == msg.obj) {
1249                         unblockScreenOn();
1250                         updatePowerState();
1251                     }
1252                     break;
1253             }
1254         }
1255     }
1256
1257     private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
1258         @Override
1259         public void onSensorChanged(SensorEvent event) {
1260             if (mProximitySensorEnabled) {
1261                 final long time = SystemClock.uptimeMillis();
1262                 final float distance = event.values[0];
1263                 boolean positive = distance >= 0.0f && distance < mProximityThreshold;
1264                 handleProximitySensorEvent(time, positive);
1265             }
1266         }
1267
1268         @Override
1269         public void onAccuracyChanged(Sensor sensor, int accuracy) {
1270             // Not used.
1271         }
1272     };
1273
1274     private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
1275         @Override
1276         public void onScreenOn() {
1277             Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
1278             msg.setAsynchronous(true);
1279             mHandler.sendMessage(msg);
1280         }
1281     }
1282 }