OSDN Git Service

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