Home | History | Annotate | Download | only in display
      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.display;
     18 
     19 import android.app.ActivityManager;
     20 import com.android.internal.app.IBatteryStats;
     21 import com.android.server.LocalServices;
     22 import com.android.server.am.BatteryStatsService;
     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.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
     33 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
     34 import android.os.Handler;
     35 import android.os.Looper;
     36 import android.os.Message;
     37 import android.os.PowerManager;
     38 import android.os.RemoteException;
     39 import android.os.SystemClock;
     40 import android.os.Trace;
     41 import android.util.MathUtils;
     42 import android.util.Slog;
     43 import android.util.Spline;
     44 import android.util.TimeUtils;
     45 import android.view.Display;
     46 import android.view.WindowManagerPolicy;
     47 
     48 import java.io.PrintWriter;
     49 
     50 /**
     51  * Controls the power state of the display.
     52  *
     53  * Handles the proximity sensor, light sensor, and animations between states
     54  * including the screen off animation.
     55  *
     56  * This component acts independently of the rest of the power manager service.
     57  * In particular, it does not share any state and it only communicates
     58  * via asynchronous callbacks to inform the power manager that something has
     59  * changed.
     60  *
     61  * Everything this class does internally is serialized on its handler although
     62  * it may be accessed by other threads from the outside.
     63  *
     64  * Note that the power manager service guarantees that it will hold a suspend
     65  * blocker as long as the display is not ready.  So most of the work done here
     66  * does not need to worry about holding a suspend blocker unless it happens
     67  * independently of the display ready signal.
     68    *
     69  * For debugging, you can make the color fade and brightness animations run
     70  * slower by changing the "animator duration scale" option in Development Settings.
     71  */
     72 final class DisplayPowerController implements AutomaticBrightnessController.Callbacks {
     73     private static final String TAG = "DisplayPowerController";
     74     private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
     75     private static final String SCREEN_OFF_BLOCKED_TRACE_NAME = "Screen off blocked";
     76 
     77     private static final boolean DEBUG = false;
     78     private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
     79 
     80     // If true, uses the color fade on animation.
     81     // We might want to turn this off if we cannot get a guarantee that the screen
     82     // actually turns on and starts showing new content after the call to set the
     83     // screen state returns.  Playing the animation can also be somewhat slow.
     84     private static final boolean USE_COLOR_FADE_ON_ANIMATION = false;
     85 
     86     // The minimum reduction in brightness when dimmed.
     87     private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10;
     88 
     89     private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
     90     private static final int COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS = 400;
     91 
     92     private static final int MSG_UPDATE_POWER_STATE = 1;
     93     private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
     94     private static final int MSG_SCREEN_ON_UNBLOCKED = 3;
     95     private static final int MSG_SCREEN_OFF_UNBLOCKED = 4;
     96 
     97     private static final int PROXIMITY_UNKNOWN = -1;
     98     private static final int PROXIMITY_NEGATIVE = 0;
     99     private static final int PROXIMITY_POSITIVE = 1;
    100 
    101     // Proximity sensor debounce delay in milliseconds for positive or negative transitions.
    102     private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0;
    103     private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 250;
    104 
    105     // Trigger proximity if distance is less than 5 cm.
    106     private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
    107 
    108     // State machine constants for tracking initial brightness ramp skipping when enabled.
    109     private static final int RAMP_STATE_SKIP_NONE = 0;
    110     private static final int RAMP_STATE_SKIP_INITIAL = 1;
    111     private static final int RAMP_STATE_SKIP_AUTOBRIGHT = 2;
    112 
    113     private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
    114     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
    115     private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
    116     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_OFF = 3;
    117 
    118     private final Object mLock = new Object();
    119 
    120     private final Context mContext;
    121 
    122     // Our handler.
    123     private final DisplayControllerHandler mHandler;
    124 
    125     // Asynchronous callbacks into the power manager service.
    126     // Only invoked from the handler thread while no locks are held.
    127     private final DisplayPowerCallbacks mCallbacks;
    128 
    129     // Battery stats.
    130     private final IBatteryStats mBatteryStats;
    131 
    132     // The sensor manager.
    133     private final SensorManager mSensorManager;
    134 
    135     // The window manager policy.
    136     private final WindowManagerPolicy mWindowManagerPolicy;
    137 
    138     // The display blanker.
    139     private final DisplayBlanker mBlanker;
    140 
    141     // The proximity sensor, or null if not available or needed.
    142     private Sensor mProximitySensor;
    143 
    144     // The doze screen brightness.
    145     private final int mScreenBrightnessDozeConfig;
    146 
    147     // The dim screen brightness.
    148     private final int mScreenBrightnessDimConfig;
    149 
    150     // The minimum screen brightness to use in a very dark room.
    151     private final int mScreenBrightnessDarkConfig;
    152 
    153     // The minimum allowed brightness.
    154     private final int mScreenBrightnessRangeMinimum;
    155 
    156     // The maximum allowed brightness.
    157     private final int mScreenBrightnessRangeMaximum;
    158 
    159     // True if auto-brightness should be used.
    160     private boolean mUseSoftwareAutoBrightnessConfig;
    161 
    162     // True if should use light sensor to automatically determine doze screen brightness.
    163     private final boolean mAllowAutoBrightnessWhileDozingConfig;
    164 
    165     // Whether or not the color fade on screen on / off is enabled.
    166     private final boolean mColorFadeEnabled;
    167 
    168     // True if we should fade the screen while turning it off, false if we should play
    169     // a stylish color fade animation instead.
    170     private boolean mColorFadeFadesConfig;
    171 
    172     // True if we need to fake a transition to off when coming out of a doze state.
    173     // Some display hardware will blank itself when coming out of doze in order to hide
    174     // artifacts. For these displays we fake a transition into OFF so that policy can appropriately
    175     // blank itself and begin an appropriate power on animation.
    176     private boolean mDisplayBlanksAfterDozeConfig;
    177 
    178     // True if there are only buckets of brightness values when the display is in the doze state,
    179     // rather than a full range of values. If this is true, then we'll avoid animating the screen
    180     // brightness since it'd likely be multiple jarring brightness transitions instead of just one
    181     // to reach the final state.
    182     private boolean mBrightnessBucketsInDozeConfig;
    183 
    184     // The pending power request.
    185     // Initially null until the first call to requestPowerState.
    186     // Guarded by mLock.
    187     private DisplayPowerRequest mPendingRequestLocked;
    188 
    189     // True if a request has been made to wait for the proximity sensor to go negative.
    190     // Guarded by mLock.
    191     private boolean mPendingWaitForNegativeProximityLocked;
    192 
    193     // True if the pending power request or wait for negative proximity flag
    194     // has been changed since the last update occurred.
    195     // Guarded by mLock.
    196     private boolean mPendingRequestChangedLocked;
    197 
    198     // Set to true when the important parts of the pending power request have been applied.
    199     // The important parts are mainly the screen state.  Brightness changes may occur
    200     // concurrently.
    201     // Guarded by mLock.
    202     private boolean mDisplayReadyLocked;
    203 
    204     // Set to true if a power state update is required.
    205     // Guarded by mLock.
    206     private boolean mPendingUpdatePowerStateLocked;
    207 
    208     /* The following state must only be accessed by the handler thread. */
    209 
    210     // The currently requested power state.
    211     // The power controller will progressively update its internal state to match
    212     // the requested power state.  Initially null until the first update.
    213     private DisplayPowerRequest mPowerRequest;
    214 
    215     // The current power state.
    216     // Must only be accessed on the handler thread.
    217     private DisplayPowerState mPowerState;
    218 
    219     // True if the device should wait for negative proximity sensor before
    220     // waking up the screen.  This is set to false as soon as a negative
    221     // proximity sensor measurement is observed or when the device is forced to
    222     // go to sleep by the user.  While true, the screen remains off.
    223     private boolean mWaitingForNegativeProximity;
    224 
    225     // The actual proximity sensor threshold value.
    226     private float mProximityThreshold;
    227 
    228     // Set to true if the proximity sensor listener has been registered
    229     // with the sensor manager.
    230     private boolean mProximitySensorEnabled;
    231 
    232     // The debounced proximity sensor state.
    233     private int mProximity = PROXIMITY_UNKNOWN;
    234 
    235     // The raw non-debounced proximity sensor state.
    236     private int mPendingProximity = PROXIMITY_UNKNOWN;
    237     private long mPendingProximityDebounceTime = -1; // -1 if fully debounced
    238 
    239     // True if the screen was turned off because of the proximity sensor.
    240     // When the screen turns on again, we report user activity to the power manager.
    241     private boolean mScreenOffBecauseOfProximity;
    242 
    243     // The currently active screen on unblocker.  This field is non-null whenever
    244     // we are waiting for a callback to release it and unblock the screen.
    245     private ScreenOnUnblocker mPendingScreenOnUnblocker;
    246     private ScreenOffUnblocker mPendingScreenOffUnblocker;
    247 
    248     // True if we were in the process of turning off the screen.
    249     // This allows us to recover more gracefully from situations where we abort
    250     // turning off the screen.
    251     private boolean mPendingScreenOff;
    252 
    253     // True if we have unfinished business and are holding a suspend blocker.
    254     private boolean mUnfinishedBusiness;
    255 
    256     // The elapsed real time when the screen on was blocked.
    257     private long mScreenOnBlockStartRealTime;
    258     private long mScreenOffBlockStartRealTime;
    259 
    260     // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_SCREEN_* fields.
    261     private int mReportedScreenStateToPolicy;
    262 
    263     // If the last recorded screen state was dozing or not.
    264     private boolean mDozing;
    265 
    266     // Remembers whether certain kinds of brightness adjustments
    267     // were recently applied so that we can decide how to transition.
    268     private boolean mAppliedAutoBrightness;
    269     private boolean mAppliedDimming;
    270     private boolean mAppliedLowPower;
    271 
    272     // Brightness animation ramp rates in brightness units per second
    273     private final int mBrightnessRampRateFast;
    274     private final int mBrightnessRampRateSlow;
    275 
    276     // Whether or not to skip the initial brightness ramps into STATE_ON.
    277     private final boolean mSkipScreenOnBrightnessRamp;
    278 
    279     // A record of state for skipping brightness ramps.
    280     private int mSkipRampState = RAMP_STATE_SKIP_NONE;
    281 
    282     // The first autobrightness value set when entering RAMP_STATE_SKIP_INITIAL.
    283     private int mInitialAutoBrightness;
    284 
    285     // The controller for the automatic brightness level.
    286     private AutomaticBrightnessController mAutomaticBrightnessController;
    287 
    288     // Animators.
    289     private ObjectAnimator mColorFadeOnAnimator;
    290     private ObjectAnimator mColorFadeOffAnimator;
    291     private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
    292 
    293     /**
    294      * Creates the display power controller.
    295      */
    296     public DisplayPowerController(Context context,
    297             DisplayPowerCallbacks callbacks, Handler handler,
    298             SensorManager sensorManager, DisplayBlanker blanker) {
    299         mHandler = new DisplayControllerHandler(handler.getLooper());
    300         mCallbacks = callbacks;
    301 
    302         mBatteryStats = BatteryStatsService.getService();
    303         mSensorManager = sensorManager;
    304         mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
    305         mBlanker = blanker;
    306         mContext = context;
    307 
    308         final Resources resources = context.getResources();
    309         final int screenBrightnessSettingMinimum = clampAbsoluteBrightness(resources.getInteger(
    310                 com.android.internal.R.integer.config_screenBrightnessSettingMinimum));
    311 
    312         mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger(
    313                 com.android.internal.R.integer.config_screenBrightnessDoze));
    314 
    315         mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger(
    316                 com.android.internal.R.integer.config_screenBrightnessDim));
    317 
    318         mScreenBrightnessDarkConfig = clampAbsoluteBrightness(resources.getInteger(
    319                 com.android.internal.R.integer.config_screenBrightnessDark));
    320         if (mScreenBrightnessDarkConfig > mScreenBrightnessDimConfig) {
    321             Slog.w(TAG, "Expected config_screenBrightnessDark ("
    322                     + mScreenBrightnessDarkConfig + ") to be less than or equal to "
    323                     + "config_screenBrightnessDim (" + mScreenBrightnessDimConfig + ").");
    324         }
    325         if (mScreenBrightnessDarkConfig > screenBrightnessSettingMinimum) {
    326             Slog.w(TAG, "Expected config_screenBrightnessDark ("
    327                     + mScreenBrightnessDarkConfig + ") to be less than or equal to "
    328                     + "config_screenBrightnessSettingMinimum ("
    329                     + screenBrightnessSettingMinimum + ").");
    330         }
    331 
    332         int screenBrightnessRangeMinimum = Math.min(Math.min(
    333                 screenBrightnessSettingMinimum, mScreenBrightnessDimConfig),
    334                 mScreenBrightnessDarkConfig);
    335 
    336         mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON;
    337 
    338         mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
    339                 com.android.internal.R.bool.config_automatic_brightness_available);
    340 
    341         mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
    342                 com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
    343 
    344         mBrightnessRampRateFast = resources.getInteger(
    345                 com.android.internal.R.integer.config_brightness_ramp_rate_fast);
    346         mBrightnessRampRateSlow = resources.getInteger(
    347                 com.android.internal.R.integer.config_brightness_ramp_rate_slow);
    348         mSkipScreenOnBrightnessRamp = resources.getBoolean(
    349                 com.android.internal.R.bool.config_skipScreenOnBrightnessRamp);
    350 
    351         int lightSensorRate = resources.getInteger(
    352                 com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
    353         int initialLightSensorRate = resources.getInteger(
    354                 com.android.internal.R.integer.config_autoBrightnessInitialLightSensorRate);
    355         if (initialLightSensorRate == -1) {
    356           initialLightSensorRate = lightSensorRate;
    357         } else if (initialLightSensorRate > lightSensorRate) {
    358           Slog.w(TAG, "Expected config_autoBrightnessInitialLightSensorRate ("
    359                   + initialLightSensorRate + ") to be less than or equal to "
    360                   + "config_autoBrightnessLightSensorRate (" + lightSensorRate + ").");
    361         }
    362         long brighteningLightDebounce = resources.getInteger(
    363                 com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);
    364         long darkeningLightDebounce = resources.getInteger(
    365                 com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce);
    366         boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean(
    367                 com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
    368         int ambientLightHorizon = resources.getInteger(
    369                 com.android.internal.R.integer.config_autoBrightnessAmbientLightHorizon);
    370         float autoBrightnessAdjustmentMaxGamma = resources.getFraction(
    371                 com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
    372                 1, 1);
    373 
    374         int[] brightLevels = resources.getIntArray(
    375                 com.android.internal.R.array.config_dynamicHysteresisBrightLevels);
    376         int[] darkLevels = resources.getIntArray(
    377                 com.android.internal.R.array.config_dynamicHysteresisDarkLevels);
    378         int[] luxLevels = resources.getIntArray(
    379                 com.android.internal.R.array.config_dynamicHysteresisLuxLevels);
    380         HysteresisLevels dynamicHysteresis = new HysteresisLevels(
    381                 brightLevels, darkLevels, luxLevels);
    382 
    383         if (mUseSoftwareAutoBrightnessConfig) {
    384             int[] lux = resources.getIntArray(
    385                     com.android.internal.R.array.config_autoBrightnessLevels);
    386             int[] screenBrightness = resources.getIntArray(
    387                     com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
    388             int lightSensorWarmUpTimeConfig = resources.getInteger(
    389                     com.android.internal.R.integer.config_lightSensorWarmupTime);
    390             final float dozeScaleFactor = resources.getFraction(
    391                     com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
    392                     1, 1);
    393 
    394             Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
    395             if (screenAutoBrightnessSpline == null) {
    396                 Slog.e(TAG, "Error in config.xml.  config_autoBrightnessLcdBacklightValues "
    397                         + "(size " + screenBrightness.length + ") "
    398                         + "must be monotic and have exactly one more entry than "
    399                         + "config_autoBrightnessLevels (size " + lux.length + ") "
    400                         + "which must be strictly increasing.  "
    401                         + "Auto-brightness will be disabled.");
    402                 mUseSoftwareAutoBrightnessConfig = false;
    403             } else {
    404                 int bottom = clampAbsoluteBrightness(screenBrightness[0]);
    405                 if (mScreenBrightnessDarkConfig > bottom) {
    406                     Slog.w(TAG, "config_screenBrightnessDark (" + mScreenBrightnessDarkConfig
    407                             + ") should be less than or equal to the first value of "
    408                             + "config_autoBrightnessLcdBacklightValues ("
    409                             + bottom + ").");
    410                 }
    411                 if (bottom < screenBrightnessRangeMinimum) {
    412                     screenBrightnessRangeMinimum = bottom;
    413                 }
    414                 mAutomaticBrightnessController = new AutomaticBrightnessController(this,
    415                         handler.getLooper(), sensorManager, screenAutoBrightnessSpline,
    416                         lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
    417                         mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
    418                         initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
    419                         autoBrightnessResetAmbientLuxAfterWarmUp, ambientLightHorizon,
    420                         autoBrightnessAdjustmentMaxGamma, dynamicHysteresis);
    421             }
    422         }
    423 
    424         mScreenBrightnessRangeMinimum = screenBrightnessRangeMinimum;
    425 
    426 
    427         mColorFadeEnabled = !ActivityManager.isLowRamDeviceStatic();
    428         mColorFadeFadesConfig = resources.getBoolean(
    429                 com.android.internal.R.bool.config_animateScreenLights);
    430 
    431         mDisplayBlanksAfterDozeConfig = resources.getBoolean(
    432                 com.android.internal.R.bool.config_displayBlanksAfterDoze);
    433 
    434         mBrightnessBucketsInDozeConfig = resources.getBoolean(
    435                 com.android.internal.R.bool.config_displayBrightnessBucketsInDoze);
    436 
    437         if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
    438             mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
    439             if (mProximitySensor != null) {
    440                 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
    441                         TYPICAL_PROXIMITY_THRESHOLD);
    442             }
    443         }
    444 
    445     }
    446 
    447     /**
    448      * Returns true if the proximity sensor screen-off function is available.
    449      */
    450     public boolean isProximitySensorAvailable() {
    451         return mProximitySensor != null;
    452     }
    453 
    454     /**
    455      * Requests a new power state.
    456      * The controller makes a copy of the provided object and then
    457      * begins adjusting the power state to match what was requested.
    458      *
    459      * @param request The requested power state.
    460      * @param waitForNegativeProximity If true, issues a request to wait for
    461      * negative proximity before turning the screen back on, assuming the screen
    462      * was turned off by the proximity sensor.
    463      * @return True if display is ready, false if there are important changes that must
    464      * be made asynchronously (such as turning the screen on), in which case the caller
    465      * should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged()}
    466      * then try the request again later until the state converges.
    467      */
    468     public boolean requestPowerState(DisplayPowerRequest request,
    469             boolean waitForNegativeProximity) {
    470         if (DEBUG) {
    471             Slog.d(TAG, "requestPowerState: "
    472                     + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
    473         }
    474 
    475         synchronized (mLock) {
    476             boolean changed = false;
    477 
    478             if (waitForNegativeProximity
    479                     && !mPendingWaitForNegativeProximityLocked) {
    480                 mPendingWaitForNegativeProximityLocked = true;
    481                 changed = true;
    482             }
    483 
    484             if (mPendingRequestLocked == null) {
    485                 mPendingRequestLocked = new DisplayPowerRequest(request);
    486                 changed = true;
    487             } else if (!mPendingRequestLocked.equals(request)) {
    488                 mPendingRequestLocked.copyFrom(request);
    489                 changed = true;
    490             }
    491 
    492             if (changed) {
    493                 mDisplayReadyLocked = false;
    494             }
    495 
    496             if (changed && !mPendingRequestChangedLocked) {
    497                 mPendingRequestChangedLocked = true;
    498                 sendUpdatePowerStateLocked();
    499             }
    500 
    501             return mDisplayReadyLocked;
    502         }
    503     }
    504 
    505     private void sendUpdatePowerState() {
    506         synchronized (mLock) {
    507             sendUpdatePowerStateLocked();
    508         }
    509     }
    510 
    511     private void sendUpdatePowerStateLocked() {
    512         if (!mPendingUpdatePowerStateLocked) {
    513             mPendingUpdatePowerStateLocked = true;
    514             Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
    515             msg.setAsynchronous(true);
    516             mHandler.sendMessage(msg);
    517         }
    518     }
    519 
    520     private void initialize() {
    521         // Initialize the power state object for the default display.
    522         // In the future, we might manage multiple displays independently.
    523         mPowerState = new DisplayPowerState(mBlanker,
    524                 mColorFadeEnabled ? new ColorFade(Display.DEFAULT_DISPLAY) : null);
    525 
    526         if (mColorFadeEnabled) {
    527             mColorFadeOnAnimator = ObjectAnimator.ofFloat(
    528                     mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 0.0f, 1.0f);
    529             mColorFadeOnAnimator.setDuration(COLOR_FADE_ON_ANIMATION_DURATION_MILLIS);
    530             mColorFadeOnAnimator.addListener(mAnimatorListener);
    531 
    532             mColorFadeOffAnimator = ObjectAnimator.ofFloat(
    533                     mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 1.0f, 0.0f);
    534             mColorFadeOffAnimator.setDuration(COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS);
    535             mColorFadeOffAnimator.addListener(mAnimatorListener);
    536         }
    537 
    538         mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
    539                 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
    540         mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
    541 
    542         // Initialize screen state for battery stats.
    543         try {
    544             mBatteryStats.noteScreenState(mPowerState.getScreenState());
    545             mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness());
    546         } catch (RemoteException ex) {
    547             // same process
    548         }
    549     }
    550 
    551     private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
    552         @Override
    553         public void onAnimationStart(Animator animation) {
    554         }
    555         @Override
    556         public void onAnimationEnd(Animator animation) {
    557             sendUpdatePowerState();
    558         }
    559         @Override
    560         public void onAnimationRepeat(Animator animation) {
    561         }
    562         @Override
    563         public void onAnimationCancel(Animator animation) {
    564         }
    565     };
    566 
    567     private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
    568         @Override
    569         public void onAnimationEnd() {
    570             sendUpdatePowerState();
    571         }
    572     };
    573 
    574     private void updatePowerState() {
    575         // Update the power state request.
    576         final boolean mustNotify;
    577         boolean mustInitialize = false;
    578         boolean autoBrightnessAdjustmentChanged = false;
    579 
    580         synchronized (mLock) {
    581             mPendingUpdatePowerStateLocked = false;
    582             if (mPendingRequestLocked == null) {
    583                 return; // wait until first actual power request
    584             }
    585 
    586             if (mPowerRequest == null) {
    587                 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
    588                 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
    589                 mPendingWaitForNegativeProximityLocked = false;
    590                 mPendingRequestChangedLocked = false;
    591                 mustInitialize = true;
    592             } else if (mPendingRequestChangedLocked) {
    593                 autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
    594                         != mPendingRequestLocked.screenAutoBrightnessAdjustment);
    595                 mPowerRequest.copyFrom(mPendingRequestLocked);
    596                 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
    597                 mPendingWaitForNegativeProximityLocked = false;
    598                 mPendingRequestChangedLocked = false;
    599                 mDisplayReadyLocked = false;
    600             }
    601 
    602             mustNotify = !mDisplayReadyLocked;
    603         }
    604 
    605         // Initialize things the first time the power state is changed.
    606         if (mustInitialize) {
    607             initialize();
    608         }
    609 
    610         // Compute the basic display state using the policy.
    611         // We might override this below based on other factors.
    612         int state;
    613         int brightness = PowerManager.BRIGHTNESS_DEFAULT;
    614         boolean performScreenOffTransition = false;
    615         switch (mPowerRequest.policy) {
    616             case DisplayPowerRequest.POLICY_OFF:
    617                 state = Display.STATE_OFF;
    618                 performScreenOffTransition = true;
    619                 break;
    620             case DisplayPowerRequest.POLICY_DOZE:
    621                 if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
    622                     state = mPowerRequest.dozeScreenState;
    623                 } else {
    624                     state = Display.STATE_DOZE;
    625                 }
    626                 if (!mAllowAutoBrightnessWhileDozingConfig) {
    627                     brightness = mPowerRequest.dozeScreenBrightness;
    628                 }
    629                 break;
    630             case DisplayPowerRequest.POLICY_VR:
    631                 state = Display.STATE_VR;
    632                 break;
    633             case DisplayPowerRequest.POLICY_DIM:
    634             case DisplayPowerRequest.POLICY_BRIGHT:
    635             default:
    636                 state = Display.STATE_ON;
    637                 break;
    638         }
    639         assert(state != Display.STATE_UNKNOWN);
    640 
    641         // Apply the proximity sensor.
    642         if (mProximitySensor != null) {
    643             if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
    644                 setProximitySensorEnabled(true);
    645                 if (!mScreenOffBecauseOfProximity
    646                         && mProximity == PROXIMITY_POSITIVE) {
    647                     mScreenOffBecauseOfProximity = true;
    648                     sendOnProximityPositiveWithWakelock();
    649                 }
    650             } else if (mWaitingForNegativeProximity
    651                     && mScreenOffBecauseOfProximity
    652                     && mProximity == PROXIMITY_POSITIVE
    653                     && state != Display.STATE_OFF) {
    654                 setProximitySensorEnabled(true);
    655             } else {
    656                 setProximitySensorEnabled(false);
    657                 mWaitingForNegativeProximity = false;
    658             }
    659             if (mScreenOffBecauseOfProximity
    660                     && mProximity != PROXIMITY_POSITIVE) {
    661                 mScreenOffBecauseOfProximity = false;
    662                 sendOnProximityNegativeWithWakelock();
    663             }
    664         } else {
    665             mWaitingForNegativeProximity = false;
    666         }
    667         if (mScreenOffBecauseOfProximity) {
    668             state = Display.STATE_OFF;
    669         }
    670 
    671         // Animate the screen state change unless already animating.
    672         // The transition may be deferred, so after this point we will use the
    673         // actual state instead of the desired one.
    674         final int oldState = mPowerState.getScreenState();
    675         animateScreenStateChange(state, performScreenOffTransition);
    676         state = mPowerState.getScreenState();
    677 
    678         // Use zero brightness when screen is off.
    679         if (state == Display.STATE_OFF) {
    680             brightness = PowerManager.BRIGHTNESS_OFF;
    681         }
    682 
    683         // Configure auto-brightness.
    684         boolean autoBrightnessEnabled = false;
    685         if (mAutomaticBrightnessController != null) {
    686             final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig
    687                     && (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);
    688             autoBrightnessEnabled = mPowerRequest.useAutoBrightness
    689                     && (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
    690                     && brightness < 0;
    691             final boolean userInitiatedChange = autoBrightnessAdjustmentChanged
    692                     && mPowerRequest.brightnessSetByUser;
    693             mAutomaticBrightnessController.configure(autoBrightnessEnabled,
    694                     mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,
    695                     userInitiatedChange);
    696         }
    697 
    698         // Apply brightness boost.
    699         // We do this here after configuring auto-brightness so that we don't
    700         // disable the light sensor during this temporary state.  That way when
    701         // boost ends we will be able to resume normal auto-brightness behavior
    702         // without any delay.
    703         if (mPowerRequest.boostScreenBrightness
    704                 && brightness != PowerManager.BRIGHTNESS_OFF) {
    705             brightness = PowerManager.BRIGHTNESS_ON;
    706         }
    707 
    708         // Apply auto-brightness.
    709         boolean slowChange = false;
    710         if (brightness < 0) {
    711             if (autoBrightnessEnabled) {
    712                 brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();
    713             }
    714             if (brightness >= 0) {
    715                 // Use current auto-brightness value and slowly adjust to changes.
    716                 brightness = clampScreenBrightness(brightness);
    717                 if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
    718                     slowChange = true; // slowly adapt to auto-brightness
    719                 }
    720                 mAppliedAutoBrightness = true;
    721             } else {
    722                 mAppliedAutoBrightness = false;
    723             }
    724         } else {
    725             mAppliedAutoBrightness = false;
    726         }
    727 
    728         // Use default brightness when dozing unless overridden.
    729         if (brightness < 0 && (state == Display.STATE_DOZE
    730                 || state == Display.STATE_DOZE_SUSPEND)) {
    731             brightness = mScreenBrightnessDozeConfig;
    732         }
    733 
    734         // Apply manual brightness.
    735         // Use the current brightness setting from the request, which is expected
    736         // provide a nominal default value for the case where auto-brightness
    737         // is not ready yet.
    738         if (brightness < 0) {
    739             brightness = clampScreenBrightness(mPowerRequest.screenBrightness);
    740         }
    741 
    742         // Apply dimming by at least some minimum amount when user activity
    743         // timeout is about to expire.
    744         if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
    745             if (brightness > mScreenBrightnessRangeMinimum) {
    746                 brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,
    747                         mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
    748             }
    749             if (!mAppliedDimming) {
    750                 slowChange = false;
    751             }
    752             mAppliedDimming = true;
    753         } else if (mAppliedDimming) {
    754             slowChange = false;
    755             mAppliedDimming = false;
    756         }
    757 
    758         // If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
    759         // as long as it is above the minimum threshold.
    760         if (mPowerRequest.lowPowerMode) {
    761             if (brightness > mScreenBrightnessRangeMinimum) {
    762                 final float brightnessFactor =
    763                         Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
    764                 final int lowPowerBrightness = (int) (brightness * brightnessFactor);
    765                 brightness = Math.max(lowPowerBrightness, mScreenBrightnessRangeMinimum);
    766             }
    767             if (!mAppliedLowPower) {
    768                 slowChange = false;
    769             }
    770             mAppliedLowPower = true;
    771         } else if (mAppliedLowPower) {
    772             slowChange = false;
    773             mAppliedLowPower = false;
    774         }
    775 
    776         // Animate the screen brightness when the screen is on or dozing.
    777         // Skip the animation when the screen is off or suspended or transition to/from VR.
    778         if (!mPendingScreenOff) {
    779             if (mSkipScreenOnBrightnessRamp) {
    780 
    781                 if (state == Display.STATE_ON) {
    782                     if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
    783                         mInitialAutoBrightness = brightness;
    784                         mSkipRampState = RAMP_STATE_SKIP_INITIAL;
    785                     } else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL
    786                             && mUseSoftwareAutoBrightnessConfig
    787                             && brightness != mInitialAutoBrightness) {
    788                         mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;
    789                     } else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {
    790                         mSkipRampState = RAMP_STATE_SKIP_NONE;
    791                     }
    792                 } else {
    793                     mSkipRampState = RAMP_STATE_SKIP_NONE;
    794                 }
    795             }
    796 
    797             boolean wasOrWillBeInVr = (state == Display.STATE_VR || oldState == Display.STATE_VR);
    798             if ((state == Display.STATE_ON
    799                     && mSkipRampState == RAMP_STATE_SKIP_NONE
    800                     || state == Display.STATE_DOZE && !mBrightnessBucketsInDozeConfig)
    801                     && !wasOrWillBeInVr) {
    802                 animateScreenBrightness(brightness,
    803                         slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
    804             } else {
    805                 animateScreenBrightness(brightness, 0);
    806             }
    807         }
    808 
    809         // Determine whether the display is ready for use in the newly requested state.
    810         // Note that we do not wait for the brightness ramp animation to complete before
    811         // reporting the display is ready because we only need to ensure the screen is in the
    812         // right power state even as it continues to converge on the desired brightness.
    813         final boolean ready = mPendingScreenOnUnblocker == null &&
    814                 (!mColorFadeEnabled ||
    815                         (!mColorFadeOnAnimator.isStarted() && !mColorFadeOffAnimator.isStarted()))
    816                 && mPowerState.waitUntilClean(mCleanListener);
    817         final boolean finished = ready
    818                 && !mScreenBrightnessRampAnimator.isAnimating();
    819 
    820         // Notify policy about screen turned on.
    821         if (ready && state != Display.STATE_OFF
    822                 && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
    823             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_ON);
    824             mWindowManagerPolicy.screenTurnedOn();
    825         }
    826 
    827         // Grab a wake lock if we have unfinished business.
    828         if (!finished && !mUnfinishedBusiness) {
    829             if (DEBUG) {
    830                 Slog.d(TAG, "Unfinished business...");
    831             }
    832             mCallbacks.acquireSuspendBlocker();
    833             mUnfinishedBusiness = true;
    834         }
    835 
    836         // Notify the power manager when ready.
    837         if (ready && mustNotify) {
    838             // Send state change.
    839             synchronized (mLock) {
    840                 if (!mPendingRequestChangedLocked) {
    841                     mDisplayReadyLocked = true;
    842 
    843                     if (DEBUG) {
    844                         Slog.d(TAG, "Display ready!");
    845                     }
    846                 }
    847             }
    848             sendOnStateChangedWithWakelock();
    849         }
    850 
    851         // Release the wake lock when we have no unfinished business.
    852         if (finished && mUnfinishedBusiness) {
    853             if (DEBUG) {
    854                 Slog.d(TAG, "Finished business...");
    855             }
    856             mUnfinishedBusiness = false;
    857             mCallbacks.releaseSuspendBlocker();
    858         }
    859 
    860         // Record if dozing for future comparison.
    861         mDozing = state != Display.STATE_ON;
    862     }
    863 
    864     @Override
    865     public void updateBrightness() {
    866         sendUpdatePowerState();
    867     }
    868 
    869     private void blockScreenOn() {
    870         if (mPendingScreenOnUnblocker == null) {
    871             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
    872             mPendingScreenOnUnblocker = new ScreenOnUnblocker();
    873             mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
    874             Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
    875         }
    876     }
    877 
    878     private void unblockScreenOn() {
    879         if (mPendingScreenOnUnblocker != null) {
    880             mPendingScreenOnUnblocker = null;
    881             long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
    882             Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
    883             Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
    884         }
    885     }
    886 
    887     private void blockScreenOff() {
    888         if (mPendingScreenOffUnblocker == null) {
    889             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_OFF_BLOCKED_TRACE_NAME, 0);
    890             mPendingScreenOffUnblocker = new ScreenOffUnblocker();
    891             mScreenOffBlockStartRealTime = SystemClock.elapsedRealtime();
    892             Slog.i(TAG, "Blocking screen off");
    893         }
    894     }
    895 
    896     private void unblockScreenOff() {
    897         if (mPendingScreenOffUnblocker != null) {
    898             mPendingScreenOffUnblocker = null;
    899             long delay = SystemClock.elapsedRealtime() - mScreenOffBlockStartRealTime;
    900             Slog.i(TAG, "Unblocked screen off after " + delay + " ms");
    901             Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_OFF_BLOCKED_TRACE_NAME, 0);
    902         }
    903     }
    904 
    905     private boolean setScreenState(int state) {
    906         return setScreenState(state, false /*reportOnly*/);
    907     }
    908 
    909     private boolean setScreenState(int state, boolean reportOnly) {
    910         final boolean isOff = (state == Display.STATE_OFF);
    911         if (mPowerState.getScreenState() != state) {
    912 
    913             // If we are trying to turn screen off, give policy a chance to do something before we
    914             // actually turn the screen off.
    915             if (isOff && !mScreenOffBecauseOfProximity) {
    916                 if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON) {
    917                     setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);
    918                     blockScreenOff();
    919                     mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker);
    920                     unblockScreenOff();
    921                 } else if (mPendingScreenOffUnblocker != null) {
    922                     // Abort doing the state change until screen off is unblocked.
    923                     return false;
    924                 }
    925             }
    926 
    927             if (!reportOnly) {
    928                 mPowerState.setScreenState(state);
    929                 // Tell battery stats about the transition.
    930                 try {
    931                     mBatteryStats.noteScreenState(state);
    932                 } catch (RemoteException ex) {
    933                     // same process
    934                 }
    935             }
    936         }
    937 
    938         // Tell the window manager policy when the screen is turned off or on unless it's due
    939         // to the proximity sensor.  We temporarily block turning the screen on until the
    940         // window manager is ready by leaving a black surface covering the screen.
    941         // This surface is essentially the final state of the color fade animation and
    942         // it is only removed once the window manager tells us that the activity has
    943         // finished drawing underneath.
    944         if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
    945                 && !mScreenOffBecauseOfProximity) {
    946             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
    947             unblockScreenOn();
    948             mWindowManagerPolicy.screenTurnedOff();
    949         } else if (!isOff
    950                 && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_OFF) {
    951 
    952             // We told policy already that screen was turning off, but now we changed our minds.
    953             // Complete the full state transition on -> turningOff -> off.
    954             unblockScreenOff();
    955             mWindowManagerPolicy.screenTurnedOff();
    956             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
    957         }
    958         if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
    959             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
    960             if (mPowerState.getColorFadeLevel() == 0.0f) {
    961                 blockScreenOn();
    962             } else {
    963                 unblockScreenOn();
    964             }
    965             mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
    966         }
    967 
    968         // Return true if the screen isn't blocked.
    969         return mPendingScreenOnUnblocker == null;
    970     }
    971 
    972     private void setReportedScreenState(int state) {
    973         Trace.traceCounter(Trace.TRACE_TAG_POWER, "ReportedScreenStateToPolicy", state);
    974         mReportedScreenStateToPolicy = state;
    975     }
    976 
    977     private int clampScreenBrightness(int value) {
    978         return MathUtils.constrain(
    979                 value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
    980     }
    981 
    982     private void animateScreenBrightness(int target, int rate) {
    983         if (DEBUG) {
    984             Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
    985         }
    986         if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
    987             Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", target);
    988             try {
    989                 mBatteryStats.noteScreenBrightness(target);
    990             } catch (RemoteException ex) {
    991                 // same process
    992             }
    993         }
    994     }
    995 
    996     private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
    997         // If there is already an animation in progress, don't interfere with it.
    998         if (mColorFadeEnabled &&
    999                 (mColorFadeOnAnimator.isStarted() || mColorFadeOffAnimator.isStarted())) {
   1000             if (target != Display.STATE_ON) {
   1001                 return;
   1002             }
   1003             // If display state changed to on, proceed and stop the color fade and turn screen on.
   1004             mPendingScreenOff = false;
   1005         }
   1006 
   1007         if (mDisplayBlanksAfterDozeConfig
   1008                 && Display.isDozeState(mPowerState.getScreenState())
   1009                 && !Display.isDozeState(target)) {
   1010             // Skip the screen off animation and add a black surface to hide the
   1011             // contents of the screen.
   1012             mPowerState.prepareColorFade(mContext,
   1013                     mColorFadeFadesConfig ? ColorFade.MODE_FADE : ColorFade.MODE_WARM_UP);
   1014             if (mColorFadeOffAnimator != null) {
   1015                 mColorFadeOffAnimator.end();
   1016             }
   1017             // Some display hardware will blank itself on the transition between doze and non-doze
   1018             // but still on display states. In this case we want to report to policy that the
   1019             // display has turned off so it can prepare the appropriate power on animation, but we
   1020             // don't want to actually transition to the fully off state since that takes
   1021             // significantly longer to transition from.
   1022             setScreenState(Display.STATE_OFF, target != Display.STATE_OFF /*reportOnly*/);
   1023         }
   1024 
   1025         // If we were in the process of turning off the screen but didn't quite
   1026         // finish.  Then finish up now to prevent a jarring transition back
   1027         // to screen on if we skipped blocking screen on as usual.
   1028         if (mPendingScreenOff && target != Display.STATE_OFF) {
   1029             setScreenState(Display.STATE_OFF);
   1030             mPendingScreenOff = false;
   1031             mPowerState.dismissColorFadeResources();
   1032         }
   1033 
   1034         if (target == Display.STATE_ON) {
   1035             // Want screen on.  The contents of the screen may not yet
   1036             // be visible if the color fade has not been dismissed because
   1037             // its last frame of animation is solid black.
   1038             if (!setScreenState(Display.STATE_ON)) {
   1039                 return; // screen on blocked
   1040             }
   1041             if (USE_COLOR_FADE_ON_ANIMATION && mColorFadeEnabled && mPowerRequest.isBrightOrDim()) {
   1042                 // Perform screen on animation.
   1043                 if (mPowerState.getColorFadeLevel() == 1.0f) {
   1044                     mPowerState.dismissColorFade();
   1045                 } else if (mPowerState.prepareColorFade(mContext,
   1046                         mColorFadeFadesConfig ?
   1047                                 ColorFade.MODE_FADE :
   1048                                         ColorFade.MODE_WARM_UP)) {
   1049                     mColorFadeOnAnimator.start();
   1050                 } else {
   1051                     mColorFadeOnAnimator.end();
   1052                 }
   1053             } else {
   1054                 // Skip screen on animation.
   1055                 mPowerState.setColorFadeLevel(1.0f);
   1056                 mPowerState.dismissColorFade();
   1057             }
   1058         } else if (target == Display.STATE_VR) {
   1059             // Wait for brightness animation to complete beforehand when entering VR
   1060             // from screen on to prevent a perceptible jump because brightness may operate
   1061             // differently when the display is configured for dozing.
   1062             if (mScreenBrightnessRampAnimator.isAnimating()
   1063                     && mPowerState.getScreenState() == Display.STATE_ON) {
   1064                 return;
   1065             }
   1066 
   1067             // Set screen state.
   1068             if (!setScreenState(Display.STATE_VR)) {
   1069                 return; // screen on blocked
   1070             }
   1071 
   1072             // Dismiss the black surface without fanfare.
   1073             mPowerState.setColorFadeLevel(1.0f);
   1074             mPowerState.dismissColorFade();
   1075         } else if (target == Display.STATE_DOZE) {
   1076             // Want screen dozing.
   1077             // Wait for brightness animation to complete beforehand when entering doze
   1078             // from screen on to prevent a perceptible jump because brightness may operate
   1079             // differently when the display is configured for dozing.
   1080             if (mScreenBrightnessRampAnimator.isAnimating()
   1081                     && mPowerState.getScreenState() == Display.STATE_ON) {
   1082                 return;
   1083             }
   1084 
   1085             // Set screen state.
   1086             if (!setScreenState(Display.STATE_DOZE)) {
   1087                 return; // screen on blocked
   1088             }
   1089 
   1090             // Dismiss the black surface without fanfare.
   1091             mPowerState.setColorFadeLevel(1.0f);
   1092             mPowerState.dismissColorFade();
   1093         } else if (target == Display.STATE_DOZE_SUSPEND) {
   1094             // Want screen dozing and suspended.
   1095             // Wait for brightness animation to complete beforehand unless already
   1096             // suspended because we may not be able to change it after suspension.
   1097             if (mScreenBrightnessRampAnimator.isAnimating()
   1098                     && mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
   1099                 return;
   1100             }
   1101 
   1102             // If not already suspending, temporarily set the state to doze until the
   1103             // screen on is unblocked, then suspend.
   1104             if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
   1105                 if (!setScreenState(Display.STATE_DOZE)) {
   1106                     return; // screen on blocked
   1107                 }
   1108                 setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
   1109             }
   1110 
   1111             // Dismiss the black surface without fanfare.
   1112             mPowerState.setColorFadeLevel(1.0f);
   1113             mPowerState.dismissColorFade();
   1114         } else {
   1115             // Want screen off.
   1116             mPendingScreenOff = true;
   1117             if (!mColorFadeEnabled) {
   1118                 mPowerState.setColorFadeLevel(0.0f);
   1119             }
   1120 
   1121             if (mPowerState.getColorFadeLevel() == 0.0f) {
   1122                 // Turn the screen off.
   1123                 // A black surface is already hiding the contents of the screen.
   1124                 setScreenState(Display.STATE_OFF);
   1125                 mPendingScreenOff = false;
   1126                 mPowerState.dismissColorFadeResources();
   1127             } else if (performScreenOffTransition
   1128                     && mPowerState.prepareColorFade(mContext,
   1129                             mColorFadeFadesConfig ?
   1130                                     ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
   1131                     && mPowerState.getScreenState() != Display.STATE_OFF) {
   1132                 // Perform the screen off animation.
   1133                 mColorFadeOffAnimator.start();
   1134             } else {
   1135                 // Skip the screen off animation and add a black surface to hide the
   1136                 // contents of the screen.
   1137                 mColorFadeOffAnimator.end();
   1138             }
   1139         }
   1140     }
   1141 
   1142     private final Runnable mCleanListener = new Runnable() {
   1143         @Override
   1144         public void run() {
   1145             sendUpdatePowerState();
   1146         }
   1147     };
   1148 
   1149     private void setProximitySensorEnabled(boolean enable) {
   1150         if (enable) {
   1151             if (!mProximitySensorEnabled) {
   1152                 // Register the listener.
   1153                 // Proximity sensor state already cleared initially.
   1154                 mProximitySensorEnabled = true;
   1155                 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
   1156                         SensorManager.SENSOR_DELAY_NORMAL, mHandler);
   1157             }
   1158         } else {
   1159             if (mProximitySensorEnabled) {
   1160                 // Unregister the listener.
   1161                 // Clear the proximity sensor state for next time.
   1162                 mProximitySensorEnabled = false;
   1163                 mProximity = PROXIMITY_UNKNOWN;
   1164                 mPendingProximity = PROXIMITY_UNKNOWN;
   1165                 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
   1166                 mSensorManager.unregisterListener(mProximitySensorListener);
   1167                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
   1168             }
   1169         }
   1170     }
   1171 
   1172     private void handleProximitySensorEvent(long time, boolean positive) {
   1173         if (mProximitySensorEnabled) {
   1174             if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
   1175                 return; // no change
   1176             }
   1177             if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
   1178                 return; // no change
   1179             }
   1180 
   1181             // Only accept a proximity sensor reading if it remains
   1182             // stable for the entire debounce delay.  We hold a wake lock while
   1183             // debouncing the sensor.
   1184             mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
   1185             if (positive) {
   1186                 mPendingProximity = PROXIMITY_POSITIVE;
   1187                 setPendingProximityDebounceTime(
   1188                         time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
   1189             } else {
   1190                 mPendingProximity = PROXIMITY_NEGATIVE;
   1191                 setPendingProximityDebounceTime(
   1192                         time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
   1193             }
   1194 
   1195             // Debounce the new sensor reading.
   1196             debounceProximitySensor();
   1197         }
   1198     }
   1199 
   1200     private void debounceProximitySensor() {
   1201         if (mProximitySensorEnabled
   1202                 && mPendingProximity != PROXIMITY_UNKNOWN
   1203                 && mPendingProximityDebounceTime >= 0) {
   1204             final long now = SystemClock.uptimeMillis();
   1205             if (mPendingProximityDebounceTime <= now) {
   1206                 // Sensor reading accepted.  Apply the change then release the wake lock.
   1207                 mProximity = mPendingProximity;
   1208                 updatePowerState();
   1209                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
   1210             } else {
   1211                 // Need to wait a little longer.
   1212                 // Debounce again later.  We continue holding a wake lock while waiting.
   1213                 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
   1214                 msg.setAsynchronous(true);
   1215                 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
   1216             }
   1217         }
   1218     }
   1219 
   1220     private void clearPendingProximityDebounceTime() {
   1221         if (mPendingProximityDebounceTime >= 0) {
   1222             mPendingProximityDebounceTime = -1;
   1223             mCallbacks.releaseSuspendBlocker(); // release wake lock
   1224         }
   1225     }
   1226 
   1227     private void setPendingProximityDebounceTime(long debounceTime) {
   1228         if (mPendingProximityDebounceTime < 0) {
   1229             mCallbacks.acquireSuspendBlocker(); // acquire wake lock
   1230         }
   1231         mPendingProximityDebounceTime = debounceTime;
   1232     }
   1233 
   1234     private void sendOnStateChangedWithWakelock() {
   1235         mCallbacks.acquireSuspendBlocker();
   1236         mHandler.post(mOnStateChangedRunnable);
   1237     }
   1238 
   1239     private final Runnable mOnStateChangedRunnable = new Runnable() {
   1240         @Override
   1241         public void run() {
   1242             mCallbacks.onStateChanged();
   1243             mCallbacks.releaseSuspendBlocker();
   1244         }
   1245     };
   1246 
   1247     private void sendOnProximityPositiveWithWakelock() {
   1248         mCallbacks.acquireSuspendBlocker();
   1249         mHandler.post(mOnProximityPositiveRunnable);
   1250     }
   1251 
   1252     private final Runnable mOnProximityPositiveRunnable = new Runnable() {
   1253         @Override
   1254         public void run() {
   1255             mCallbacks.onProximityPositive();
   1256             mCallbacks.releaseSuspendBlocker();
   1257         }
   1258     };
   1259 
   1260     private void sendOnProximityNegativeWithWakelock() {
   1261         mCallbacks.acquireSuspendBlocker();
   1262         mHandler.post(mOnProximityNegativeRunnable);
   1263     }
   1264 
   1265     private final Runnable mOnProximityNegativeRunnable = new Runnable() {
   1266         @Override
   1267         public void run() {
   1268             mCallbacks.onProximityNegative();
   1269             mCallbacks.releaseSuspendBlocker();
   1270         }
   1271     };
   1272 
   1273     public void dump(final PrintWriter pw) {
   1274         synchronized (mLock) {
   1275             pw.println();
   1276             pw.println("Display Power Controller Locked State:");
   1277             pw.println("  mDisplayReadyLocked=" + mDisplayReadyLocked);
   1278             pw.println("  mPendingRequestLocked=" + mPendingRequestLocked);
   1279             pw.println("  mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
   1280             pw.println("  mPendingWaitForNegativeProximityLocked="
   1281                     + mPendingWaitForNegativeProximityLocked);
   1282             pw.println("  mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
   1283         }
   1284 
   1285         pw.println();
   1286         pw.println("Display Power Controller Configuration:");
   1287         pw.println("  mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
   1288         pw.println("  mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
   1289         pw.println("  mScreenBrightnessDarkConfig=" + mScreenBrightnessDarkConfig);
   1290         pw.println("  mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
   1291         pw.println("  mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
   1292         pw.println("  mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
   1293         pw.println("  mAllowAutoBrightnessWhileDozingConfig=" +
   1294                 mAllowAutoBrightnessWhileDozingConfig);
   1295         pw.println("  mColorFadeFadesConfig=" + mColorFadeFadesConfig);
   1296 
   1297         mHandler.runWithScissors(new Runnable() {
   1298             @Override
   1299             public void run() {
   1300                 dumpLocal(pw);
   1301             }
   1302         }, 1000);
   1303     }
   1304 
   1305     private void dumpLocal(PrintWriter pw) {
   1306         pw.println();
   1307         pw.println("Display Power Controller Thread State:");
   1308         pw.println("  mPowerRequest=" + mPowerRequest);
   1309         pw.println("  mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
   1310 
   1311         pw.println("  mProximitySensor=" + mProximitySensor);
   1312         pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
   1313         pw.println("  mProximityThreshold=" + mProximityThreshold);
   1314         pw.println("  mProximity=" + proximityToString(mProximity));
   1315         pw.println("  mPendingProximity=" + proximityToString(mPendingProximity));
   1316         pw.println("  mPendingProximityDebounceTime="
   1317                 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
   1318         pw.println("  mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
   1319         pw.println("  mAppliedAutoBrightness=" + mAppliedAutoBrightness);
   1320         pw.println("  mAppliedDimming=" + mAppliedDimming);
   1321         pw.println("  mAppliedLowPower=" + mAppliedLowPower);
   1322         pw.println("  mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
   1323         pw.println("  mPendingScreenOff=" + mPendingScreenOff);
   1324         pw.println("  mReportedToPolicy=" +
   1325                 reportedToPolicyToString(mReportedScreenStateToPolicy));
   1326 
   1327         pw.println("  mScreenBrightnessRampAnimator.isAnimating()=" +
   1328                 mScreenBrightnessRampAnimator.isAnimating());
   1329 
   1330         if (mColorFadeOnAnimator != null) {
   1331             pw.println("  mColorFadeOnAnimator.isStarted()=" +
   1332                     mColorFadeOnAnimator.isStarted());
   1333         }
   1334         if (mColorFadeOffAnimator != null) {
   1335             pw.println("  mColorFadeOffAnimator.isStarted()=" +
   1336                     mColorFadeOffAnimator.isStarted());
   1337         }
   1338 
   1339         if (mPowerState != null) {
   1340             mPowerState.dump(pw);
   1341         }
   1342 
   1343         if (mAutomaticBrightnessController != null) {
   1344             mAutomaticBrightnessController.dump(pw);
   1345         }
   1346 
   1347     }
   1348 
   1349     private static String proximityToString(int state) {
   1350         switch (state) {
   1351             case PROXIMITY_UNKNOWN:
   1352                 return "Unknown";
   1353             case PROXIMITY_NEGATIVE:
   1354                 return "Negative";
   1355             case PROXIMITY_POSITIVE:
   1356                 return "Positive";
   1357             default:
   1358                 return Integer.toString(state);
   1359         }
   1360     }
   1361 
   1362     private static String reportedToPolicyToString(int state) {
   1363         switch (state) {
   1364             case REPORTED_TO_POLICY_SCREEN_OFF:
   1365                 return "REPORTED_TO_POLICY_SCREEN_OFF";
   1366             case REPORTED_TO_POLICY_SCREEN_TURNING_ON:
   1367                 return "REPORTED_TO_POLICY_SCREEN_TURNING_ON";
   1368             case REPORTED_TO_POLICY_SCREEN_ON:
   1369                 return "REPORTED_TO_POLICY_SCREEN_ON";
   1370             default:
   1371                 return Integer.toString(state);
   1372         }
   1373     }
   1374 
   1375     private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) {
   1376         if (lux == null || lux.length == 0 || brightness == null || brightness.length == 0) {
   1377             Slog.e(TAG, "Could not create auto-brightness spline.");
   1378             return null;
   1379         }
   1380         try {
   1381             final int n = brightness.length;
   1382             float[] x = new float[n];
   1383             float[] y = new float[n];
   1384             y[0] = normalizeAbsoluteBrightness(brightness[0]);
   1385             for (int i = 1; i < n; i++) {
   1386                 x[i] = lux[i - 1];
   1387                 y[i] = normalizeAbsoluteBrightness(brightness[i]);
   1388             }
   1389 
   1390             Spline spline = Spline.createSpline(x, y);
   1391             if (DEBUG) {
   1392                 Slog.d(TAG, "Auto-brightness spline: " + spline);
   1393                 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
   1394                     Slog.d(TAG, String.format("  %7.1f: %7.1f", v, spline.interpolate(v)));
   1395                 }
   1396             }
   1397             return spline;
   1398         } catch (IllegalArgumentException ex) {
   1399             Slog.e(TAG, "Could not create auto-brightness spline.", ex);
   1400             return null;
   1401         }
   1402     }
   1403 
   1404     private static float normalizeAbsoluteBrightness(int value) {
   1405         return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON;
   1406     }
   1407 
   1408     private static int clampAbsoluteBrightness(int value) {
   1409         return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
   1410     }
   1411 
   1412     private final class DisplayControllerHandler extends Handler {
   1413         public DisplayControllerHandler(Looper looper) {
   1414             super(looper, null, true /*async*/);
   1415         }
   1416 
   1417         @Override
   1418         public void handleMessage(Message msg) {
   1419             switch (msg.what) {
   1420                 case MSG_UPDATE_POWER_STATE:
   1421                     updatePowerState();
   1422                     break;
   1423 
   1424                 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
   1425                     debounceProximitySensor();
   1426                     break;
   1427 
   1428                 case MSG_SCREEN_ON_UNBLOCKED:
   1429                     if (mPendingScreenOnUnblocker == msg.obj) {
   1430                         unblockScreenOn();
   1431                         updatePowerState();
   1432                     }
   1433                     break;
   1434                 case MSG_SCREEN_OFF_UNBLOCKED:
   1435                     if (mPendingScreenOffUnblocker == msg.obj) {
   1436                         unblockScreenOff();
   1437                         updatePowerState();
   1438                     }
   1439                     break;
   1440             }
   1441         }
   1442     }
   1443 
   1444     private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
   1445         @Override
   1446         public void onSensorChanged(SensorEvent event) {
   1447             if (mProximitySensorEnabled) {
   1448                 final long time = SystemClock.uptimeMillis();
   1449                 final float distance = event.values[0];
   1450                 boolean positive = distance >= 0.0f && distance < mProximityThreshold;
   1451                 handleProximitySensorEvent(time, positive);
   1452             }
   1453         }
   1454 
   1455         @Override
   1456         public void onAccuracyChanged(Sensor sensor, int accuracy) {
   1457             // Not used.
   1458         }
   1459     };
   1460 
   1461     private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
   1462         @Override
   1463         public void onScreenOn() {
   1464             Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
   1465             msg.setAsynchronous(true);
   1466             mHandler.sendMessage(msg);
   1467         }
   1468     }
   1469 
   1470     private final class ScreenOffUnblocker implements WindowManagerPolicy.ScreenOffListener {
   1471 
   1472         @Override
   1473         public void onScreenOff() {
   1474             Message msg = mHandler.obtainMessage(MSG_SCREEN_OFF_UNBLOCKED, this);
   1475             msg.setAsynchronous(true);
   1476             mHandler.sendMessage(msg);
   1477         }
   1478     }
   1479 }
   1480