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