DisplayPowerController.java revision 448a4e59adf736e7d76daf715ff191e8a0a7eff5
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
710                if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE) {
711                    if (!mScreenBrightnessRampAnimator.isAnimating()) {
712                        setScreenState(Display.STATE_DOZING);
713                    }
714                } else {
715                    setScreenState(Display.STATE_ON);
716                }
717
718                if (mPowerRequest.blockScreenOn
719                        && mPowerState.getElectronBeamLevel() == 0.0f) {
720                    blockScreenOn();
721                } else {
722                    unblockScreenOn();
723                    if (USE_ELECTRON_BEAM_ON_ANIMATION) {
724                        if (!mElectronBeamOnAnimator.isStarted()) {
725                            if (mPowerState.getElectronBeamLevel() == 1.0f) {
726                                mPowerState.dismissElectronBeam();
727                            } else if (mPowerState.prepareElectronBeam(
728                                    mElectronBeamFadesConfig ?
729                                            ElectronBeam.MODE_FADE :
730                                                    ElectronBeam.MODE_WARM_UP)) {
731                                mElectronBeamOnAnimator.start();
732                            } else {
733                                mElectronBeamOnAnimator.end();
734                            }
735                        }
736                    } else {
737                        mPowerState.setElectronBeamLevel(1.0f);
738                        mPowerState.dismissElectronBeam();
739                    }
740                }
741            }
742        } else {
743            // Want screen off.
744            // Wait for previous on animation to complete beforehand.
745            unblockScreenOn();
746            if (!mElectronBeamOnAnimator.isStarted()) {
747                if (!mElectronBeamOffAnimator.isStarted()) {
748                    if (mPowerState.getElectronBeamLevel() == 0.0f) {
749                        setScreenState(Display.STATE_OFF);
750                    } else if (mPowerState.prepareElectronBeam(
751                            mElectronBeamFadesConfig ?
752                                    ElectronBeam.MODE_FADE :
753                                            ElectronBeam.MODE_COOL_DOWN)
754                            && mPowerState.getScreenState() != Display.STATE_OFF) {
755                        mElectronBeamOffAnimator.start();
756                    } else {
757                        mElectronBeamOffAnimator.end();
758                    }
759                }
760            }
761        }
762
763        // Report whether the display is ready for use.
764        // We mostly care about the screen state here, ignoring brightness changes
765        // which will be handled asynchronously.
766        if (mustNotify
767                && !mScreenOnWasBlocked
768                && !mElectronBeamOnAnimator.isStarted()
769                && !mElectronBeamOffAnimator.isStarted()
770                && !mScreenBrightnessRampAnimator.isAnimating()
771                && mPowerState.waitUntilClean(mCleanListener)) {
772            synchronized (mLock) {
773                if (!mPendingRequestChangedLocked) {
774                    mDisplayReadyLocked = true;
775
776                    if (DEBUG) {
777                        Slog.d(TAG, "Display ready!");
778                    }
779                }
780            }
781            sendOnStateChangedWithWakelock();
782        }
783    }
784
785    private void blockScreenOn() {
786        if (!mScreenOnWasBlocked) {
787            mScreenOnWasBlocked = true;
788            mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
789            if (DEBUG) {
790                Slog.d(TAG, "Blocked screen on.");
791            }
792        }
793    }
794
795    private void unblockScreenOn() {
796        if (mScreenOnWasBlocked) {
797            mScreenOnWasBlocked = false;
798            long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
799            if (delay > 1000 || DEBUG) {
800                Slog.d(TAG, "Unblocked screen on after " + delay + " ms");
801            }
802        }
803    }
804
805    private void setScreenState(int state) {
806        if (mPowerState.getScreenState() != state) {
807            mPowerState.setScreenState(state);
808            try {
809                mBatteryStats.noteScreenState(state);
810            } catch (RemoteException ex) {
811                // same process
812            }
813        }
814    }
815
816    private int clampScreenBrightness(int value) {
817        return clamp(value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
818    }
819
820    private static int clampAbsoluteBrightness(int value) {
821        return clamp(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
822    }
823
824    private static int clamp(int value, int min, int max) {
825        if (value <= min) {
826            return min;
827        }
828        if (value >= max) {
829            return max;
830        }
831        return value;
832    }
833
834    private static float normalizeAbsoluteBrightness(int value) {
835        return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON;
836    }
837
838    private void animateScreenBrightness(int target, int rate) {
839        if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
840            try {
841                mBatteryStats.noteScreenBrightness(target);
842            } catch (RemoteException ex) {
843                // same process
844            }
845        }
846    }
847
848    private final Runnable mCleanListener = new Runnable() {
849        @Override
850        public void run() {
851            sendUpdatePowerState();
852        }
853    };
854
855    private void setProximitySensorEnabled(boolean enable) {
856        if (enable) {
857            if (!mProximitySensorEnabled) {
858                // Register the listener.
859                // Proximity sensor state already cleared initially.
860                mProximitySensorEnabled = true;
861                mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
862                        SensorManager.SENSOR_DELAY_NORMAL, mHandler);
863            }
864        } else {
865            if (mProximitySensorEnabled) {
866                // Unregister the listener.
867                // Clear the proximity sensor state for next time.
868                mProximitySensorEnabled = false;
869                mProximity = PROXIMITY_UNKNOWN;
870                mPendingProximity = PROXIMITY_UNKNOWN;
871                mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
872                mSensorManager.unregisterListener(mProximitySensorListener);
873                clearPendingProximityDebounceTime(); // release wake lock (must be last)
874            }
875        }
876    }
877
878    private void handleProximitySensorEvent(long time, boolean positive) {
879        if (mProximitySensorEnabled) {
880            if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
881                return; // no change
882            }
883            if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
884                return; // no change
885            }
886
887            // Only accept a proximity sensor reading if it remains
888            // stable for the entire debounce delay.  We hold a wake lock while
889            // debouncing the sensor.
890            mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
891            if (positive) {
892                mPendingProximity = PROXIMITY_POSITIVE;
893                setPendingProximityDebounceTime(
894                        time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
895            } else {
896                mPendingProximity = PROXIMITY_NEGATIVE;
897                setPendingProximityDebounceTime(
898                        time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
899            }
900
901            // Debounce the new sensor reading.
902            debounceProximitySensor();
903        }
904    }
905
906    private void debounceProximitySensor() {
907        if (mProximitySensorEnabled
908                && mPendingProximity != PROXIMITY_UNKNOWN
909                && mPendingProximityDebounceTime >= 0) {
910            final long now = SystemClock.uptimeMillis();
911            if (mPendingProximityDebounceTime <= now) {
912                // Sensor reading accepted.  Apply the change then release the wake lock.
913                mProximity = mPendingProximity;
914                updatePowerState();
915                clearPendingProximityDebounceTime(); // release wake lock (must be last)
916            } else {
917                // Need to wait a little longer.
918                // Debounce again later.  We continue holding a wake lock while waiting.
919                Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
920                msg.setAsynchronous(true);
921                mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
922            }
923        }
924    }
925
926    private void clearPendingProximityDebounceTime() {
927        if (mPendingProximityDebounceTime >= 0) {
928            mPendingProximityDebounceTime = -1;
929            mCallbacks.releaseSuspendBlocker(); // release wake lock
930        }
931    }
932
933    private void setPendingProximityDebounceTime(long debounceTime) {
934        if (mPendingProximityDebounceTime < 0) {
935            mCallbacks.acquireSuspendBlocker(); // acquire wake lock
936        }
937        mPendingProximityDebounceTime = debounceTime;
938    }
939
940    private void setLightSensorEnabled(boolean enable, boolean updateAutoBrightness) {
941        if (enable) {
942            if (!mLightSensorEnabled) {
943                updateAutoBrightness = true;
944                mLightSensorEnabled = true;
945                mLightSensorEnableTime = SystemClock.uptimeMillis();
946                mSensorManager.registerListener(mLightSensorListener, mLightSensor,
947                        LIGHT_SENSOR_RATE_MILLIS * 1000, mHandler);
948            }
949        } else {
950            if (mLightSensorEnabled) {
951                mLightSensorEnabled = false;
952                mAmbientLuxValid = false;
953                mRecentLightSamples = 0;
954                mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
955                mSensorManager.unregisterListener(mLightSensorListener);
956            }
957        }
958        if (updateAutoBrightness) {
959            updateAutoBrightness(false);
960        }
961    }
962
963    private void handleLightSensorEvent(long time, float lux) {
964        mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
965
966        applyLightSensorMeasurement(time, lux);
967        updateAmbientLux(time);
968    }
969
970    private void applyLightSensorMeasurement(long time, float lux) {
971        // Update our filters.
972        mRecentLightSamples += 1;
973        if (mRecentLightSamples == 1) {
974            mRecentShortTermAverageLux = lux;
975            mRecentLongTermAverageLux = lux;
976        } else {
977            final long timeDelta = time - mLastObservedLuxTime;
978            mRecentShortTermAverageLux += (lux - mRecentShortTermAverageLux)
979                    * timeDelta / (SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta);
980            mRecentLongTermAverageLux += (lux - mRecentLongTermAverageLux)
981                    * timeDelta / (LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta);
982        }
983
984        // Remember this sample value.
985        mLastObservedLux = lux;
986        mLastObservedLuxTime = time;
987    }
988
989    private void setAmbientLux(float lux) {
990        mAmbientLux = lux;
991        mBrighteningLuxThreshold = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS);
992        mDarkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS);
993    }
994
995    private void updateAmbientLux(long time) {
996        // If the light sensor was just turned on then immediately update our initial
997        // estimate of the current ambient light level.
998        if (!mAmbientLuxValid) {
999            final long timeWhenSensorWarmedUp =
1000                mLightSensorWarmUpTimeConfig + mLightSensorEnableTime;
1001            if (time < timeWhenSensorWarmedUp) {
1002                mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED,
1003                        timeWhenSensorWarmedUp);
1004                return;
1005            }
1006            setAmbientLux(mRecentShortTermAverageLux);
1007            mAmbientLuxValid = true;
1008            mDebounceLuxDirection = 0;
1009            mDebounceLuxTime = time;
1010            if (DEBUG) {
1011                Slog.d(TAG, "updateAmbientLux: Initializing: "
1012                        + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1013                        + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1014                        + ", mAmbientLux=" + mAmbientLux);
1015            }
1016            updateAutoBrightness(true);
1017        } else if (mRecentShortTermAverageLux > mBrighteningLuxThreshold
1018                && mRecentLongTermAverageLux > mBrighteningLuxThreshold) {
1019            // The ambient environment appears to be brightening.
1020            if (mDebounceLuxDirection <= 0) {
1021                mDebounceLuxDirection = 1;
1022                mDebounceLuxTime = time;
1023                if (DEBUG) {
1024                    Slog.d(TAG, "updateAmbientLux: Possibly brightened, waiting for "
1025                            + BRIGHTENING_LIGHT_DEBOUNCE + " ms: "
1026                            + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold
1027                            + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1028                            + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1029                            + ", mAmbientLux=" + mAmbientLux);
1030                }
1031            }
1032            long debounceTime = mDebounceLuxTime + BRIGHTENING_LIGHT_DEBOUNCE;
1033            if (time < debounceTime) {
1034                mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
1035                return;
1036            }
1037            setAmbientLux(mRecentShortTermAverageLux);
1038            if (DEBUG) {
1039                Slog.d(TAG, "updateAmbientLux: Brightened: "
1040                        + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold
1041                        + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1042                        + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1043                        + ", mAmbientLux=" + mAmbientLux);
1044            }
1045            updateAutoBrightness(true);
1046        } else if (mRecentShortTermAverageLux < mDarkeningLuxThreshold
1047                && mRecentLongTermAverageLux < mDarkeningLuxThreshold) {
1048            // The ambient environment appears to be darkening.
1049            if (mDebounceLuxDirection >= 0) {
1050                mDebounceLuxDirection = -1;
1051                mDebounceLuxTime = time;
1052                if (DEBUG) {
1053                    Slog.d(TAG, "updateAmbientLux: Possibly darkened, waiting for "
1054                            + DARKENING_LIGHT_DEBOUNCE + " ms: "
1055                            + "mDarkeningLuxThreshold=" + mDarkeningLuxThreshold
1056                            + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1057                            + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1058                            + ", mAmbientLux=" + mAmbientLux);
1059                }
1060            }
1061            long debounceTime = mDebounceLuxTime + DARKENING_LIGHT_DEBOUNCE;
1062            if (time < debounceTime) {
1063                mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
1064                return;
1065            }
1066            // Be conservative about reducing the brightness, only reduce it a little bit
1067            // at a time to avoid having to bump it up again soon.
1068            setAmbientLux(Math.max(mRecentShortTermAverageLux, mRecentLongTermAverageLux));
1069            if (DEBUG) {
1070                Slog.d(TAG, "updateAmbientLux: Darkened: "
1071                        + "mDarkeningLuxThreshold=" + mDarkeningLuxThreshold
1072                        + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1073                        + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1074                        + ", mAmbientLux=" + mAmbientLux);
1075            }
1076            updateAutoBrightness(true);
1077        } else if (mDebounceLuxDirection != 0) {
1078            // No change or change is within the hysteresis thresholds.
1079            mDebounceLuxDirection = 0;
1080            mDebounceLuxTime = time;
1081            if (DEBUG) {
1082                Slog.d(TAG, "updateAmbientLux: Canceled debounce: "
1083                        + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold
1084                        + ", mDarkeningLuxThreshold=" + mDarkeningLuxThreshold
1085                        + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1086                        + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1087                        + ", mAmbientLux=" + mAmbientLux);
1088            }
1089        }
1090
1091        // Now that we've done all of that, we haven't yet posted a debounce
1092        // message. So consider the case where current lux is beyond the
1093        // threshold. It's possible that the light sensor may not report values
1094        // if the light level does not change, so we need to occasionally
1095        // synthesize sensor readings in order to make sure the brightness is
1096        // adjusted accordingly. Note these thresholds may have changed since
1097        // we entered the function because we called setAmbientLux and
1098        // updateAutoBrightness along the way.
1099        if (mLastObservedLux > mBrighteningLuxThreshold
1100                || mLastObservedLux < mDarkeningLuxThreshold) {
1101            mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED,
1102                    time + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS);
1103        }
1104    }
1105
1106    private void debounceLightSensor() {
1107        if (mLightSensorEnabled) {
1108            long time = SystemClock.uptimeMillis();
1109            if (time >= mLastObservedLuxTime + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS) {
1110                if (DEBUG) {
1111                    Slog.d(TAG, "debounceLightSensor: Synthesizing light sensor measurement "
1112                            + "after " + (time - mLastObservedLuxTime) + " ms.");
1113                }
1114                applyLightSensorMeasurement(time, mLastObservedLux);
1115            }
1116            updateAmbientLux(time);
1117        }
1118    }
1119
1120    private void updateAutoBrightness(boolean sendUpdate) {
1121        if (!mAmbientLuxValid) {
1122            return;
1123        }
1124
1125        float value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux);
1126        float gamma = 1.0f;
1127
1128        if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT
1129                && mPowerRequest.screenAutoBrightnessAdjustment != 0.0f) {
1130            final float adjGamma = FloatMath.pow(SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA,
1131                    Math.min(1.0f, Math.max(-1.0f,
1132                            -mPowerRequest.screenAutoBrightnessAdjustment)));
1133            gamma *= adjGamma;
1134            if (DEBUG) {
1135                Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma);
1136            }
1137        }
1138
1139        if (USE_TWILIGHT_ADJUSTMENT) {
1140            TwilightState state = mTwilight.getCurrentState();
1141            if (state != null && state.isNight()) {
1142                final long now = System.currentTimeMillis();
1143                final float earlyGamma =
1144                        getTwilightGamma(now, state.getYesterdaySunset(), state.getTodaySunrise());
1145                final float lateGamma =
1146                        getTwilightGamma(now, state.getTodaySunset(), state.getTomorrowSunrise());
1147                gamma *= earlyGamma * lateGamma;
1148                if (DEBUG) {
1149                    Slog.d(TAG, "updateAutoBrightness: earlyGamma=" + earlyGamma
1150                            + ", lateGamma=" + lateGamma);
1151                }
1152            }
1153        }
1154
1155        if (gamma != 1.0f) {
1156            final float in = value;
1157            value = FloatMath.pow(value, gamma);
1158            if (DEBUG) {
1159                Slog.d(TAG, "updateAutoBrightness: gamma=" + gamma
1160                        + ", in=" + in + ", out=" + value);
1161            }
1162        }
1163
1164        int newScreenAutoBrightness = clampScreenBrightness(
1165                Math.round(value * PowerManager.BRIGHTNESS_ON));
1166        if (mScreenAutoBrightness != newScreenAutoBrightness) {
1167            if (DEBUG) {
1168                Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness="
1169                        + mScreenAutoBrightness + ", newScreenAutoBrightness="
1170                        + newScreenAutoBrightness);
1171            }
1172
1173            mScreenAutoBrightness = newScreenAutoBrightness;
1174            mLastScreenAutoBrightnessGamma = gamma;
1175            if (sendUpdate) {
1176                sendUpdatePowerState();
1177            }
1178        }
1179    }
1180
1181    private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) {
1182        if (lastSunset < 0 || nextSunrise < 0
1183                || now < lastSunset || now > nextSunrise) {
1184            return 1.0f;
1185        }
1186
1187        if (now < lastSunset + TWILIGHT_ADJUSTMENT_TIME) {
1188            return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
1189                    (float)(now - lastSunset) / TWILIGHT_ADJUSTMENT_TIME);
1190        }
1191
1192        if (now > nextSunrise - TWILIGHT_ADJUSTMENT_TIME) {
1193            return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
1194                    (float)(nextSunrise - now) / TWILIGHT_ADJUSTMENT_TIME);
1195        }
1196
1197        return TWILIGHT_ADJUSTMENT_MAX_GAMMA;
1198    }
1199
1200    private static float lerp(float x, float y, float alpha) {
1201        return x + (y - x) * alpha;
1202    }
1203
1204    private void sendOnStateChangedWithWakelock() {
1205        mCallbacks.acquireSuspendBlocker();
1206        mHandler.post(mOnStateChangedRunnable);
1207    }
1208
1209    private final Runnable mOnStateChangedRunnable = new Runnable() {
1210        @Override
1211        public void run() {
1212            mCallbacks.onStateChanged();
1213            mCallbacks.releaseSuspendBlocker();
1214        }
1215    };
1216
1217    private void sendOnProximityPositiveWithWakelock() {
1218        mCallbacks.acquireSuspendBlocker();
1219        mHandler.post(mOnProximityPositiveRunnable);
1220    }
1221
1222    private final Runnable mOnProximityPositiveRunnable = new Runnable() {
1223        @Override
1224        public void run() {
1225            mCallbacks.onProximityPositive();
1226            mCallbacks.releaseSuspendBlocker();
1227        }
1228    };
1229
1230    private void sendOnProximityNegativeWithWakelock() {
1231        mCallbacks.acquireSuspendBlocker();
1232        mHandler.post(mOnProximityNegativeRunnable);
1233    }
1234
1235    private final Runnable mOnProximityNegativeRunnable = new Runnable() {
1236        @Override
1237        public void run() {
1238            mCallbacks.onProximityNegative();
1239            mCallbacks.releaseSuspendBlocker();
1240        }
1241    };
1242
1243    public void dump(final PrintWriter pw) {
1244        synchronized (mLock) {
1245            pw.println();
1246            pw.println("Display Power Controller Locked State:");
1247            pw.println("  mDisplayReadyLocked=" + mDisplayReadyLocked);
1248            pw.println("  mPendingRequestLocked=" + mPendingRequestLocked);
1249            pw.println("  mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
1250            pw.println("  mPendingWaitForNegativeProximityLocked="
1251                    + mPendingWaitForNegativeProximityLocked);
1252            pw.println("  mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
1253        }
1254
1255        pw.println();
1256        pw.println("Display Power Controller Configuration:");
1257        pw.println("  mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
1258        pw.println("  mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
1259        pw.println("  mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
1260        pw.println("  mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
1261        pw.println("  mUseSoftwareAutoBrightnessConfig="
1262                + mUseSoftwareAutoBrightnessConfig);
1263        pw.println("  mScreenAutoBrightnessSpline=" + mScreenAutoBrightnessSpline);
1264        pw.println("  mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig);
1265
1266        mHandler.runWithScissors(new Runnable() {
1267            @Override
1268            public void run() {
1269                dumpLocal(pw);
1270            }
1271        }, 1000);
1272    }
1273
1274    private void dumpLocal(PrintWriter pw) {
1275        pw.println();
1276        pw.println("Display Power Controller Thread State:");
1277        pw.println("  mPowerRequest=" + mPowerRequest);
1278        pw.println("  mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
1279
1280        pw.println("  mProximitySensor=" + mProximitySensor);
1281        pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
1282        pw.println("  mProximityThreshold=" + mProximityThreshold);
1283        pw.println("  mProximity=" + proximityToString(mProximity));
1284        pw.println("  mPendingProximity=" + proximityToString(mPendingProximity));
1285        pw.println("  mPendingProximityDebounceTime="
1286                + TimeUtils.formatUptime(mPendingProximityDebounceTime));
1287        pw.println("  mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
1288
1289        pw.println("  mLightSensor=" + mLightSensor);
1290        pw.println("  mLightSensorEnabled=" + mLightSensorEnabled);
1291        pw.println("  mLightSensorEnableTime="
1292                + TimeUtils.formatUptime(mLightSensorEnableTime));
1293        pw.println("  mAmbientLux=" + mAmbientLux);
1294        pw.println("  mAmbientLuxValid=" + mAmbientLuxValid);
1295        pw.println("  mLastObservedLux=" + mLastObservedLux);
1296        pw.println("  mLastObservedLuxTime="
1297                + TimeUtils.formatUptime(mLastObservedLuxTime));
1298        pw.println("  mRecentLightSamples=" + mRecentLightSamples);
1299        pw.println("  mRecentShortTermAverageLux=" + mRecentShortTermAverageLux);
1300        pw.println("  mRecentLongTermAverageLux=" + mRecentLongTermAverageLux);
1301        pw.println("  mDebounceLuxDirection=" + mDebounceLuxDirection);
1302        pw.println("  mDebounceLuxTime=" + TimeUtils.formatUptime(mDebounceLuxTime));
1303        pw.println("  mScreenAutoBrightness=" + mScreenAutoBrightness);
1304        pw.println("  mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness);
1305        pw.println("  mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
1306        pw.println("  mTwilight.getCurrentState()=" + mTwilight.getCurrentState());
1307
1308        pw.println("  mScreenBrightnessRampAnimator.isAnimating()=" +
1309                mScreenBrightnessRampAnimator.isAnimating());
1310
1311        if (mElectronBeamOnAnimator != null) {
1312            pw.println("  mElectronBeamOnAnimator.isStarted()=" +
1313                    mElectronBeamOnAnimator.isStarted());
1314        }
1315        if (mElectronBeamOffAnimator != null) {
1316            pw.println("  mElectronBeamOffAnimator.isStarted()=" +
1317                    mElectronBeamOffAnimator.isStarted());
1318        }
1319
1320        if (mPowerState != null) {
1321            mPowerState.dump(pw);
1322        }
1323    }
1324
1325    private static String proximityToString(int state) {
1326        switch (state) {
1327            case PROXIMITY_UNKNOWN:
1328                return "Unknown";
1329            case PROXIMITY_NEGATIVE:
1330                return "Negative";
1331            case PROXIMITY_POSITIVE:
1332                return "Positive";
1333            default:
1334                return Integer.toString(state);
1335        }
1336    }
1337
1338    private final class DisplayControllerHandler extends Handler {
1339        public DisplayControllerHandler(Looper looper) {
1340            super(looper, null, true /*async*/);
1341        }
1342
1343        @Override
1344        public void handleMessage(Message msg) {
1345            switch (msg.what) {
1346                case MSG_UPDATE_POWER_STATE:
1347                    updatePowerState();
1348                    break;
1349
1350                case MSG_PROXIMITY_SENSOR_DEBOUNCED:
1351                    debounceProximitySensor();
1352                    break;
1353
1354                case MSG_LIGHT_SENSOR_DEBOUNCED:
1355                    debounceLightSensor();
1356                    break;
1357            }
1358        }
1359    }
1360
1361    private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
1362        @Override
1363        public void onSensorChanged(SensorEvent event) {
1364            if (mProximitySensorEnabled) {
1365                final long time = SystemClock.uptimeMillis();
1366                final float distance = event.values[0];
1367                boolean positive = distance >= 0.0f && distance < mProximityThreshold;
1368                handleProximitySensorEvent(time, positive);
1369            }
1370        }
1371
1372        @Override
1373        public void onAccuracyChanged(Sensor sensor, int accuracy) {
1374            // Not used.
1375        }
1376    };
1377
1378    private final SensorEventListener mLightSensorListener = new SensorEventListener() {
1379        @Override
1380        public void onSensorChanged(SensorEvent event) {
1381            if (mLightSensorEnabled) {
1382                final long time = SystemClock.uptimeMillis();
1383                final float lux = event.values[0];
1384                handleLightSensorEvent(time, lux);
1385            }
1386        }
1387
1388        @Override
1389        public void onAccuracyChanged(Sensor sensor, int accuracy) {
1390            // Not used.
1391        }
1392    };
1393
1394    private final TwilightListener mTwilightListener = new TwilightListener() {
1395        @Override
1396        public void onTwilightStateChanged() {
1397            mTwilightChanged = true;
1398            updatePowerState();
1399        }
1400    };
1401}
1402