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