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