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