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