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