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