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