2 * Copyright (C) 2012 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server.display;
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;
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;
48 import java.io.PrintWriter;
51 * Controls the power state of the display.
53 * Handles the proximity sensor, light sensor, and animations between states
54 * including the screen off animation.
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
61 * Everything this class does internally is serialized on its handler although
62 * it may be accessed by other threads from the outside.
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.
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.
72 final class DisplayPowerController implements AutomaticBrightnessController.Callbacks {
73 private static final String TAG = "DisplayPowerController";
74 private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
76 private static boolean DEBUG = false;
77 private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
79 // If true, uses the color fade on animation.
80 // We might want to turn this off if we cannot get a guarantee that the screen
81 // actually turns on and starts showing new content after the call to set the
82 // screen state returns. Playing the animation can also be somewhat slow.
83 private static final boolean USE_COLOR_FADE_ON_ANIMATION = false;
85 // The minimum reduction in brightness when dimmed.
86 private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10;
88 private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
89 private static final int COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS = 400;
91 private static final int MSG_UPDATE_POWER_STATE = 1;
92 private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
93 private static final int MSG_SCREEN_ON_UNBLOCKED = 3;
95 private static final int PROXIMITY_UNKNOWN = -1;
96 private static final int PROXIMITY_NEGATIVE = 0;
97 private static final int PROXIMITY_POSITIVE = 1;
99 // Proximity sensor debounce delay in milliseconds for positive or negative transitions.
100 private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0;
101 private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 250;
103 // Trigger proximity if distance is less than 5 cm.
104 private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
106 // Brightness animation ramp rate in brightness units per second.
107 private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
109 private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
110 private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
111 private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
113 private final Object mLock = new Object();
115 private final Context mContext;
118 private final DisplayControllerHandler mHandler;
120 // Asynchronous callbacks into the power manager service.
121 // Only invoked from the handler thread while no locks are held.
122 private final DisplayPowerCallbacks mCallbacks;
125 private final IBatteryStats mBatteryStats;
127 // The lights service.
128 private final LightsManager mLights;
130 // The sensor manager.
131 private final SensorManager mSensorManager;
133 // The window manager policy.
134 private final WindowManagerPolicy mWindowManagerPolicy;
136 // The display blanker.
137 private final DisplayBlanker mBlanker;
139 // The proximity sensor, or null if not available or needed.
140 private Sensor mProximitySensor;
142 // The doze screen brightness.
143 private final int mScreenBrightnessDozeConfig;
145 // The dim screen brightness.
146 private final int mScreenBrightnessDimConfig;
148 // The minimum screen brightness to use in a very dark room.
149 private final int mScreenBrightnessDarkConfig;
151 // The minimum allowed brightness.
152 private final int mScreenBrightnessRangeMinimum;
154 // The maximum allowed brightness.
155 private final int mScreenBrightnessRangeMaximum;
157 // True if auto-brightness should be used.
158 private boolean mUseSoftwareAutoBrightnessConfig;
160 // True if should use light sensor to automatically determine doze screen brightness.
161 private final boolean mAllowAutoBrightnessWhileDozingConfig;
163 // True if we should fade the screen while turning it off, false if we should play
164 // a stylish color fade animation instead.
165 private boolean mColorFadeFadesConfig;
167 // The pending power request.
168 // Initially null until the first call to requestPowerState.
170 private DisplayPowerRequest mPendingRequestLocked;
172 // True if a request has been made to wait for the proximity sensor to go negative.
174 private boolean mPendingWaitForNegativeProximityLocked;
176 // True if the pending power request or wait for negative proximity flag
177 // has been changed since the last update occurred.
179 private boolean mPendingRequestChangedLocked;
181 // Set to true when the important parts of the pending power request have been applied.
182 // The important parts are mainly the screen state. Brightness changes may occur
185 private boolean mDisplayReadyLocked;
187 // Set to true if a power state update is required.
189 private boolean mPendingUpdatePowerStateLocked;
191 /* The following state must only be accessed by the handler thread. */
193 // The currently requested power state.
194 // The power controller will progressively update its internal state to match
195 // the requested power state. Initially null until the first update.
196 private DisplayPowerRequest mPowerRequest;
198 // The current power state.
199 // Must only be accessed on the handler thread.
200 private DisplayPowerState mPowerState;
202 // True if the device should wait for negative proximity sensor before
203 // waking up the screen. This is set to false as soon as a negative
204 // proximity sensor measurement is observed or when the device is forced to
205 // go to sleep by the user. While true, the screen remains off.
206 private boolean mWaitingForNegativeProximity;
208 // The actual proximity sensor threshold value.
209 private float mProximityThreshold;
211 // Set to true if the proximity sensor listener has been registered
212 // with the sensor manager.
213 private boolean mProximitySensorEnabled;
215 // The debounced proximity sensor state.
216 private int mProximity = PROXIMITY_UNKNOWN;
218 // The raw non-debounced proximity sensor state.
219 private int mPendingProximity = PROXIMITY_UNKNOWN;
220 private long mPendingProximityDebounceTime = -1; // -1 if fully debounced
222 // True if the screen was turned off because of the proximity sensor.
223 // When the screen turns on again, we report user activity to the power manager.
224 private boolean mScreenOffBecauseOfProximity;
226 // The currently active screen on unblocker. This field is non-null whenever
227 // we are waiting for a callback to release it and unblock the screen.
228 private ScreenOnUnblocker mPendingScreenOnUnblocker;
230 // True if we were in the process of turning off the screen.
231 // This allows us to recover more gracefully from situations where we abort
232 // turning off the screen.
233 private boolean mPendingScreenOff;
235 // True if we have unfinished business and are holding a suspend blocker.
236 private boolean mUnfinishedBusiness;
238 // The elapsed real time when the screen on was blocked.
239 private long mScreenOnBlockStartRealTime;
241 // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_SCREEN_* fields.
242 private int mReportedScreenStateToPolicy;
244 // Remembers whether certain kinds of brightness adjustments
245 // were recently applied so that we can decide how to transition.
246 private boolean mAppliedAutoBrightness;
247 private boolean mAppliedDimming;
248 private boolean mAppliedLowPower;
250 // Brightness ramp rate fast.
251 private final int mBrightnessRampRateFast;
253 // The controller for the automatic brightness level.
254 private AutomaticBrightnessController mAutomaticBrightnessController;
257 private ObjectAnimator mColorFadeOnAnimator;
258 private ObjectAnimator mColorFadeOffAnimator;
259 private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
262 * Creates the display power controller.
264 public DisplayPowerController(Context context,
265 DisplayPowerCallbacks callbacks, Handler handler,
266 SensorManager sensorManager, DisplayBlanker blanker) {
267 mHandler = new DisplayControllerHandler(handler.getLooper());
268 mCallbacks = callbacks;
270 mBatteryStats = BatteryStatsService.getService();
271 mLights = LocalServices.getService(LightsManager.class);
272 mSensorManager = sensorManager;
273 mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
277 final Resources resources = context.getResources();
278 final int screenBrightnessSettingMinimum = clampAbsoluteBrightness(resources.getInteger(
279 com.android.internal.R.integer.config_screenBrightnessSettingMinimum));
281 mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger(
282 com.android.internal.R.integer.config_screenBrightnessDoze));
284 mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger(
285 com.android.internal.R.integer.config_screenBrightnessDim));
287 mScreenBrightnessDarkConfig = clampAbsoluteBrightness(resources.getInteger(
288 com.android.internal.R.integer.config_screenBrightnessDark));
289 if (mScreenBrightnessDarkConfig > mScreenBrightnessDimConfig) {
290 Slog.w(TAG, "Expected config_screenBrightnessDark ("
291 + mScreenBrightnessDarkConfig + ") to be less than or equal to "
292 + "config_screenBrightnessDim (" + mScreenBrightnessDimConfig + ").");
294 if (mScreenBrightnessDarkConfig > mScreenBrightnessDimConfig) {
295 Slog.w(TAG, "Expected config_screenBrightnessDark ("
296 + mScreenBrightnessDarkConfig + ") to be less than or equal to "
297 + "config_screenBrightnessSettingMinimum ("
298 + screenBrightnessSettingMinimum + ").");
301 int screenBrightnessRangeMinimum = Math.min(Math.min(
302 screenBrightnessSettingMinimum, mScreenBrightnessDimConfig),
303 mScreenBrightnessDarkConfig);
305 mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON;
307 mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
308 com.android.internal.R.bool.config_automatic_brightness_available);
310 mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
311 com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
313 mBrightnessRampRateFast = resources.getInteger(
314 com.android.internal.R.integer.config_brightness_ramp_rate_fast);
316 int lightSensorRate = resources.getInteger(
317 com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
318 long brighteningLightDebounce = resources.getInteger(
319 com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);
320 long brighteningLightFastDebounce = resources.getInteger(
321 com.android.internal.R.integer.config_autoBrightnessBrighteningLightFastDebounce);
322 long darkeningLightDebounce = resources.getInteger(
323 com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce);
324 boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean(
325 com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
326 int ambientLightHorizon = resources.getInteger(
327 com.android.internal.R.integer.config_autoBrightnessAmbientLightHorizon);
328 float autoBrightnessAdjustmentMaxGamma = resources.getFraction(
329 com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
332 if (mUseSoftwareAutoBrightnessConfig) {
333 int[] lux = resources.getIntArray(
334 com.android.internal.R.array.config_autoBrightnessLevels);
335 int[] screenBrightness = resources.getIntArray(
336 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
337 int lightSensorWarmUpTimeConfig = resources.getInteger(
338 com.android.internal.R.integer.config_lightSensorWarmupTime);
339 final float dozeScaleFactor = resources.getFraction(
340 com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
343 Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
344 if (screenAutoBrightnessSpline == null) {
345 Slog.e(TAG, "Error in config.xml. config_autoBrightnessLcdBacklightValues "
346 + "(size " + screenBrightness.length + ") "
347 + "must be monotic and have exactly one more entry than "
348 + "config_autoBrightnessLevels (size " + lux.length + ") "
349 + "which must be strictly increasing. "
350 + "Auto-brightness will be disabled.");
351 mUseSoftwareAutoBrightnessConfig = false;
353 int bottom = clampAbsoluteBrightness(screenBrightness[0]);
354 if (mScreenBrightnessDarkConfig > bottom) {
355 Slog.w(TAG, "config_screenBrightnessDark (" + mScreenBrightnessDarkConfig
356 + ") should be less than or equal to the first value of "
357 + "config_autoBrightnessLcdBacklightValues ("
360 if (bottom < screenBrightnessRangeMinimum) {
361 screenBrightnessRangeMinimum = bottom;
363 mAutomaticBrightnessController = new AutomaticBrightnessController(this,
364 handler.getLooper(), sensorManager, screenAutoBrightnessSpline,
365 lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
366 mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
367 brighteningLightDebounce, brighteningLightFastDebounce,
368 darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp,
369 ambientLightHorizon, autoBrightnessAdjustmentMaxGamma);
373 mScreenBrightnessRangeMinimum = screenBrightnessRangeMinimum;
375 mColorFadeFadesConfig = resources.getBoolean(
376 com.android.internal.R.bool.config_animateScreenLights);
378 if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
379 mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
380 if (mProximitySensor != null) {
381 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
382 TYPICAL_PROXIMITY_THRESHOLD);
389 * Returns true if the proximity sensor screen-off function is available.
391 public boolean isProximitySensorAvailable() {
392 return mProximitySensor != null;
396 * Requests a new power state.
397 * The controller makes a copy of the provided object and then
398 * begins adjusting the power state to match what was requested.
400 * @param request The requested power state.
401 * @param waitForNegativeProximity If true, issues a request to wait for
402 * negative proximity before turning the screen back on, assuming the screen
403 * was turned off by the proximity sensor.
404 * @return True if display is ready, false if there are important changes that must
405 * be made asynchronously (such as turning the screen on), in which case the caller
406 * should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged()}
407 * then try the request again later until the state converges.
409 public boolean requestPowerState(DisplayPowerRequest request,
410 boolean waitForNegativeProximity) {
412 Slog.d(TAG, "requestPowerState: "
413 + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
416 synchronized (mLock) {
417 boolean changed = false;
419 if (waitForNegativeProximity
420 && !mPendingWaitForNegativeProximityLocked) {
421 mPendingWaitForNegativeProximityLocked = true;
425 if (mPendingRequestLocked == null) {
426 mPendingRequestLocked = new DisplayPowerRequest(request);
428 } else if (!mPendingRequestLocked.equals(request)) {
429 mPendingRequestLocked.copyFrom(request);
434 mDisplayReadyLocked = false;
437 if (changed && !mPendingRequestChangedLocked) {
438 mPendingRequestChangedLocked = true;
439 sendUpdatePowerStateLocked();
442 return mDisplayReadyLocked;
446 private void sendUpdatePowerState() {
447 synchronized (mLock) {
448 sendUpdatePowerStateLocked();
452 private void sendUpdatePowerStateLocked() {
453 if (!mPendingUpdatePowerStateLocked) {
454 mPendingUpdatePowerStateLocked = true;
455 Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
456 msg.setAsynchronous(true);
457 mHandler.sendMessage(msg);
461 private void initialize() {
462 // Initialize the power state object for the default display.
463 // In the future, we might manage multiple displays independently.
464 mPowerState = new DisplayPowerState(mBlanker,
465 new ColorFade(Display.DEFAULT_DISPLAY));
467 mColorFadeOnAnimator = ObjectAnimator.ofFloat(
468 mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 0.0f, 1.0f);
469 mColorFadeOnAnimator.setDuration(COLOR_FADE_ON_ANIMATION_DURATION_MILLIS);
470 mColorFadeOnAnimator.addListener(mAnimatorListener);
472 mColorFadeOffAnimator = ObjectAnimator.ofFloat(
473 mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 1.0f, 0.0f);
474 mColorFadeOffAnimator.setDuration(COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS);
475 mColorFadeOffAnimator.addListener(mAnimatorListener);
477 mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
478 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
479 mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
481 // Initialize screen state for battery stats.
483 mBatteryStats.noteScreenState(mPowerState.getScreenState());
484 mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness());
485 } catch (RemoteException ex) {
490 private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
492 public void onAnimationStart(Animator animation) {
495 public void onAnimationEnd(Animator animation) {
496 sendUpdatePowerState();
499 public void onAnimationRepeat(Animator animation) {
502 public void onAnimationCancel(Animator animation) {
506 private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
508 public void onAnimationEnd() {
509 sendUpdatePowerState();
513 private void updatePowerState() {
514 // Update the power state request.
515 final boolean mustNotify;
516 boolean mustInitialize = false;
517 boolean autoBrightnessAdjustmentChanged = false;
519 synchronized (mLock) {
520 mPendingUpdatePowerStateLocked = false;
521 if (mPendingRequestLocked == null) {
522 return; // wait until first actual power request
525 if (mPowerRequest == null) {
526 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
527 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
528 mPendingWaitForNegativeProximityLocked = false;
529 mPendingRequestChangedLocked = false;
530 mustInitialize = true;
531 } else if (mPendingRequestChangedLocked) {
532 autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
533 != mPendingRequestLocked.screenAutoBrightnessAdjustment);
534 mPowerRequest.copyFrom(mPendingRequestLocked);
535 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
536 mPendingWaitForNegativeProximityLocked = false;
537 mPendingRequestChangedLocked = false;
538 mDisplayReadyLocked = false;
541 mustNotify = !mDisplayReadyLocked;
544 // Initialize things the first time the power state is changed.
545 if (mustInitialize) {
549 // Compute the basic display state using the policy.
550 // We might override this below based on other factors.
552 int brightness = PowerManager.BRIGHTNESS_DEFAULT;
553 boolean performScreenOffTransition = false;
554 switch (mPowerRequest.policy) {
555 case DisplayPowerRequest.POLICY_OFF:
556 state = Display.STATE_OFF;
557 performScreenOffTransition = true;
559 case DisplayPowerRequest.POLICY_DOZE:
560 if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
561 state = mPowerRequest.dozeScreenState;
563 state = Display.STATE_DOZE;
565 if (!mAllowAutoBrightnessWhileDozingConfig) {
566 brightness = mPowerRequest.dozeScreenBrightness;
569 case DisplayPowerRequest.POLICY_DIM:
570 case DisplayPowerRequest.POLICY_BRIGHT:
572 state = Display.STATE_ON;
575 assert(state != Display.STATE_UNKNOWN);
577 // Apply the proximity sensor.
578 if (mProximitySensor != null) {
579 if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
580 setProximitySensorEnabled(true);
581 if (!mScreenOffBecauseOfProximity
582 && mProximity == PROXIMITY_POSITIVE) {
583 mScreenOffBecauseOfProximity = true;
584 sendOnProximityPositiveWithWakelock();
586 } else if (mWaitingForNegativeProximity
587 && mScreenOffBecauseOfProximity
588 && mProximity == PROXIMITY_POSITIVE
589 && state != Display.STATE_OFF) {
590 setProximitySensorEnabled(true);
592 setProximitySensorEnabled(false);
593 mWaitingForNegativeProximity = false;
595 if (mScreenOffBecauseOfProximity
596 && mProximity != PROXIMITY_POSITIVE) {
597 mScreenOffBecauseOfProximity = false;
598 sendOnProximityNegativeWithWakelock();
601 mWaitingForNegativeProximity = false;
603 if (mScreenOffBecauseOfProximity) {
604 state = Display.STATE_OFF;
607 // Animate the screen state change unless already animating.
608 // The transition may be deferred, so after this point we will use the
609 // actual state instead of the desired one.
610 animateScreenStateChange(state, performScreenOffTransition);
611 state = mPowerState.getScreenState();
613 // Use zero brightness when screen is off.
614 if (state == Display.STATE_OFF) {
615 brightness = PowerManager.BRIGHTNESS_OFF;
616 mLights.getLight(LightsManager.LIGHT_ID_BUTTONS).setBrightness(brightness);
617 mLights.getLight(LightsManager.LIGHT_ID_KEYBOARD).setBrightness(brightness);
620 // Disable button lights when dozing
621 if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND) {
622 mLights.getLight(LightsManager.LIGHT_ID_BUTTONS).setBrightness(PowerManager.BRIGHTNESS_OFF);
623 mLights.getLight(LightsManager.LIGHT_ID_KEYBOARD).setBrightness(PowerManager.BRIGHTNESS_OFF);
626 // Configure auto-brightness.
627 boolean autoBrightnessEnabled = false;
628 if (mAutomaticBrightnessController != null) {
629 final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig
630 && (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);
631 autoBrightnessEnabled = mPowerRequest.useAutoBrightness
632 && (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
634 final boolean userInitiatedChange = autoBrightnessAdjustmentChanged
635 && mPowerRequest.brightnessSetByUser;
636 mAutomaticBrightnessController.configure(autoBrightnessEnabled,
637 mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,
638 userInitiatedChange, mPowerRequest.useTwilight);
641 // Apply brightness boost.
642 // We do this here after configuring auto-brightness so that we don't
643 // disable the light sensor during this temporary state. That way when
644 // boost ends we will be able to resume normal auto-brightness behavior
645 // without any delay.
646 if (mPowerRequest.boostScreenBrightness
647 && brightness != PowerManager.BRIGHTNESS_OFF) {
648 brightness = PowerManager.BRIGHTNESS_ON;
651 // Apply auto-brightness.
652 boolean slowChange = false;
653 if (brightness < 0) {
654 if (autoBrightnessEnabled) {
655 brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();
657 if (brightness >= 0) {
658 // Use current auto-brightness value and slowly adjust to changes.
659 brightness = clampScreenBrightness(brightness);
660 if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
661 slowChange = true; // slowly adapt to auto-brightness
663 mAppliedAutoBrightness = true;
665 mAppliedAutoBrightness = false;
668 mAppliedAutoBrightness = false;
671 // Use default brightness when dozing unless overridden.
672 if (brightness < 0 && (state == Display.STATE_DOZE
673 || state == Display.STATE_DOZE_SUSPEND)) {
674 brightness = mScreenBrightnessDozeConfig;
677 // Apply manual brightness.
678 // Use the current brightness setting from the request, which is expected
679 // provide a nominal default value for the case where auto-brightness
681 if (brightness < 0) {
682 brightness = clampScreenBrightness(mPowerRequest.screenBrightness);
685 // Apply dimming by at least some minimum amount when user activity
686 // timeout is about to expire.
687 if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
688 if (brightness > mScreenBrightnessRangeMinimum) {
689 brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,
690 mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
692 if (!mAppliedDimming) {
695 mAppliedDimming = true;
696 } else if (mAppliedDimming) {
698 mAppliedDimming = false;
701 // If low power mode is enabled, cut the brightness level by half
702 // as long as it is above the minimum threshold.
703 if (mPowerRequest.lowPowerMode) {
704 if (brightness > mScreenBrightnessRangeMinimum) {
705 brightness = Math.max(brightness / 2, mScreenBrightnessRangeMinimum);
707 if (!mAppliedLowPower) {
710 mAppliedLowPower = true;
711 } else if (mAppliedLowPower) {
713 mAppliedLowPower = false;
716 // Animate the screen brightness when the screen is on or dozing.
717 // Skip the animation when the screen is off or suspended.
718 if (!mPendingScreenOff) {
719 if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
720 animateScreenBrightness(brightness,
721 slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast);
723 animateScreenBrightness(brightness, 0);
727 // Determine whether the display is ready for use in the newly requested state.
728 // Note that we do not wait for the brightness ramp animation to complete before
729 // reporting the display is ready because we only need to ensure the screen is in the
730 // right power state even as it continues to converge on the desired brightness.
731 final boolean ready = mPendingScreenOnUnblocker == null
732 && !mColorFadeOnAnimator.isStarted()
733 && !mColorFadeOffAnimator.isStarted()
734 && mPowerState.waitUntilClean(mCleanListener);
735 final boolean finished = ready
736 && !mScreenBrightnessRampAnimator.isAnimating();
738 // Notify policy about screen turned on.
739 if (ready && state != Display.STATE_OFF
740 && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
741 mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_ON;
742 mWindowManagerPolicy.screenTurnedOn();
745 // Grab a wake lock if we have unfinished business.
746 if (!finished && !mUnfinishedBusiness) {
748 Slog.d(TAG, "Unfinished business...");
750 mCallbacks.acquireSuspendBlocker();
751 mUnfinishedBusiness = true;
754 // Notify the power manager when ready.
755 if (ready && mustNotify) {
756 // Send state change.
757 synchronized (mLock) {
758 if (!mPendingRequestChangedLocked) {
759 mDisplayReadyLocked = true;
762 Slog.d(TAG, "Display ready!");
766 sendOnStateChangedWithWakelock();
769 // Release the wake lock when we have no unfinished business.
770 if (finished && mUnfinishedBusiness) {
772 Slog.d(TAG, "Finished business...");
774 mUnfinishedBusiness = false;
775 mCallbacks.releaseSuspendBlocker();
780 public void updateBrightness() {
781 sendUpdatePowerState();
784 private void blockScreenOn() {
785 if (mPendingScreenOnUnblocker == null) {
786 Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
787 mPendingScreenOnUnblocker = new ScreenOnUnblocker();
788 mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
789 Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
793 private void unblockScreenOn() {
794 if (mPendingScreenOnUnblocker != null) {
795 mPendingScreenOnUnblocker = null;
796 long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
797 Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
798 Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
802 private boolean setScreenState(int state) {
803 if (mPowerState.getScreenState() != state) {
804 final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
805 mPowerState.setScreenState(state);
807 // Tell battery stats about the transition.
809 mBatteryStats.noteScreenState(state);
810 } catch (RemoteException ex) {
815 // Tell the window manager policy when the screen is turned off or on unless it's due
816 // to the proximity sensor. We temporarily block turning the screen on until the
817 // window manager is ready by leaving a black surface covering the screen.
818 // This surface is essentially the final state of the color fade animation and
819 // it is only removed once the window manager tells us that the activity has
820 // finished drawing underneath.
821 final boolean isOff = (state == Display.STATE_OFF);
822 if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
823 && !mScreenOffBecauseOfProximity) {
824 mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_OFF;
826 mWindowManagerPolicy.screenTurnedOff();
827 } else if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
828 mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_ON;
829 if (mPowerState.getColorFadeLevel() == 0.0f) {
834 mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
837 // Return true if the screen isn't blocked.
838 return mPendingScreenOnUnblocker == null;
841 private int clampScreenBrightness(int value) {
842 return MathUtils.constrain(
843 value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
846 private void animateScreenBrightness(int target, int rate) {
848 Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
850 if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
852 mBatteryStats.noteScreenBrightness(target);
853 } catch (RemoteException ex) {
859 private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
860 // If there is already an animation in progress, don't interfere with it.
861 if (mColorFadeOnAnimator.isStarted()
862 || mColorFadeOffAnimator.isStarted()) {
863 if (target != Display.STATE_ON) {
866 // If display state changed to on, proceed and stop the color fade and turn screen on.
867 mPendingScreenOff = false;
870 // If we were in the process of turning off the screen but didn't quite
871 // finish. Then finish up now to prevent a jarring transition back
872 // to screen on if we skipped blocking screen on as usual.
873 if (mPendingScreenOff && target != Display.STATE_OFF) {
874 setScreenState(Display.STATE_OFF);
875 mPendingScreenOff = false;
876 mPowerState.dismissColorFadeResources();
879 if (target == Display.STATE_ON) {
880 // Want screen on. The contents of the screen may not yet
881 // be visible if the color fade has not been dismissed because
882 // its last frame of animation is solid black.
883 if (!setScreenState(Display.STATE_ON)) {
884 return; // screen on blocked
886 if (USE_COLOR_FADE_ON_ANIMATION && mPowerRequest.isBrightOrDim()) {
887 // Perform screen on animation.
888 if (mPowerState.getColorFadeLevel() == 1.0f) {
889 mPowerState.dismissColorFade();
890 } else if (mPowerState.prepareColorFade(mContext,
891 mColorFadeFadesConfig ?
892 ColorFade.MODE_FADE :
893 ColorFade.MODE_WARM_UP)) {
894 mColorFadeOnAnimator.start();
896 mColorFadeOnAnimator.end();
899 // Skip screen on animation.
900 mPowerState.setColorFadeLevel(1.0f);
901 mPowerState.dismissColorFade();
903 } else if (target == Display.STATE_DOZE) {
904 // Want screen dozing.
905 // Wait for brightness animation to complete beforehand when entering doze
906 // from screen on to prevent a perceptible jump because brightness may operate
907 // differently when the display is configured for dozing.
908 if (mScreenBrightnessRampAnimator.isAnimating()
909 && mPowerState.getScreenState() == Display.STATE_ON) {
914 if (!setScreenState(Display.STATE_DOZE)) {
915 return; // screen on blocked
918 // Dismiss the black surface without fanfare.
919 mPowerState.setColorFadeLevel(1.0f);
920 mPowerState.dismissColorFade();
921 } else if (target == Display.STATE_DOZE_SUSPEND) {
922 // Want screen dozing and suspended.
923 // Wait for brightness animation to complete beforehand unless already
924 // suspended because we may not be able to change it after suspension.
925 if (mScreenBrightnessRampAnimator.isAnimating()
926 && mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
930 // If not already suspending, temporarily set the state to doze until the
931 // screen on is unblocked, then suspend.
932 if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
933 if (!setScreenState(Display.STATE_DOZE)) {
934 return; // screen on blocked
936 setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
939 // Dismiss the black surface without fanfare.
940 mPowerState.setColorFadeLevel(1.0f);
941 mPowerState.dismissColorFade();
944 mPendingScreenOff = true;
945 if (mPowerState.getColorFadeLevel() == 0.0f) {
946 // Turn the screen off.
947 // A black surface is already hiding the contents of the screen.
948 setScreenState(Display.STATE_OFF);
949 mPendingScreenOff = false;
950 mPowerState.dismissColorFadeResources();
951 } else if (performScreenOffTransition
952 && mPowerState.prepareColorFade(mContext,
953 mColorFadeFadesConfig ?
954 ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
955 && mPowerState.getScreenState() != Display.STATE_OFF) {
956 // Perform the screen off animation.
957 mColorFadeOffAnimator.start();
959 // Skip the screen off animation and add a black surface to hide the
960 // contents of the screen.
961 mColorFadeOffAnimator.end();
966 private final Runnable mCleanListener = new Runnable() {
969 sendUpdatePowerState();
973 private void setProximitySensorEnabled(boolean enable) {
975 if (!mProximitySensorEnabled) {
976 // Register the listener.
977 // Proximity sensor state already cleared initially.
978 mProximitySensorEnabled = true;
979 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
980 SensorManager.SENSOR_DELAY_NORMAL, mHandler);
983 if (mProximitySensorEnabled) {
984 // Unregister the listener.
985 // Clear the proximity sensor state for next time.
986 mProximitySensorEnabled = false;
987 mProximity = PROXIMITY_UNKNOWN;
988 mPendingProximity = PROXIMITY_UNKNOWN;
989 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
990 mSensorManager.unregisterListener(mProximitySensorListener);
991 clearPendingProximityDebounceTime(); // release wake lock (must be last)
996 private void handleProximitySensorEvent(long time, boolean positive) {
997 if (mProximitySensorEnabled) {
998 if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
1001 if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
1002 return; // no change
1005 // Only accept a proximity sensor reading if it remains
1006 // stable for the entire debounce delay. We hold a wake lock while
1007 // debouncing the sensor.
1008 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
1010 mPendingProximity = PROXIMITY_POSITIVE;
1011 setPendingProximityDebounceTime(
1012 time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
1014 mPendingProximity = PROXIMITY_NEGATIVE;
1015 setPendingProximityDebounceTime(
1016 time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
1019 // Debounce the new sensor reading.
1020 debounceProximitySensor();
1024 private void debounceProximitySensor() {
1025 if (mProximitySensorEnabled
1026 && mPendingProximity != PROXIMITY_UNKNOWN
1027 && mPendingProximityDebounceTime >= 0) {
1028 final long now = SystemClock.uptimeMillis();
1029 if (mPendingProximityDebounceTime <= now) {
1030 // Sensor reading accepted. Apply the change then release the wake lock.
1031 mProximity = mPendingProximity;
1033 clearPendingProximityDebounceTime(); // release wake lock (must be last)
1035 // Need to wait a little longer.
1036 // Debounce again later. We continue holding a wake lock while waiting.
1037 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
1038 msg.setAsynchronous(true);
1039 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
1044 private void clearPendingProximityDebounceTime() {
1045 if (mPendingProximityDebounceTime >= 0) {
1046 mPendingProximityDebounceTime = -1;
1047 mCallbacks.releaseSuspendBlocker(); // release wake lock
1051 private void setPendingProximityDebounceTime(long debounceTime) {
1052 if (mPendingProximityDebounceTime < 0) {
1053 mCallbacks.acquireSuspendBlocker(); // acquire wake lock
1055 mPendingProximityDebounceTime = debounceTime;
1058 private void sendOnStateChangedWithWakelock() {
1059 mCallbacks.acquireSuspendBlocker();
1060 mHandler.post(mOnStateChangedRunnable);
1063 private final Runnable mOnStateChangedRunnable = new Runnable() {
1066 mCallbacks.onStateChanged();
1067 mCallbacks.releaseSuspendBlocker();
1071 private void sendOnProximityPositiveWithWakelock() {
1072 mCallbacks.acquireSuspendBlocker();
1073 mHandler.post(mOnProximityPositiveRunnable);
1076 private final Runnable mOnProximityPositiveRunnable = new Runnable() {
1079 mCallbacks.onProximityPositive();
1080 mCallbacks.releaseSuspendBlocker();
1084 private void sendOnProximityNegativeWithWakelock() {
1085 mCallbacks.acquireSuspendBlocker();
1086 mHandler.post(mOnProximityNegativeRunnable);
1089 private final Runnable mOnProximityNegativeRunnable = new Runnable() {
1092 mCallbacks.onProximityNegative();
1093 mCallbacks.releaseSuspendBlocker();
1097 public void dump(final PrintWriter pw) {
1098 synchronized (mLock) {
1100 pw.println("Display Power Controller Locked State:");
1101 pw.println(" mDisplayReadyLocked=" + mDisplayReadyLocked);
1102 pw.println(" mPendingRequestLocked=" + mPendingRequestLocked);
1103 pw.println(" mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
1104 pw.println(" mPendingWaitForNegativeProximityLocked="
1105 + mPendingWaitForNegativeProximityLocked);
1106 pw.println(" mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
1110 pw.println("Display Power Controller Configuration:");
1111 pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
1112 pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
1113 pw.println(" mScreenBrightnessDarkConfig=" + mScreenBrightnessDarkConfig);
1114 pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
1115 pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
1116 pw.println(" mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
1117 pw.println(" mAllowAutoBrightnessWhileDozingConfig=" +
1118 mAllowAutoBrightnessWhileDozingConfig);
1119 pw.println(" mColorFadeFadesConfig=" + mColorFadeFadesConfig);
1121 mHandler.runWithScissors(new Runnable() {
1129 private void dumpLocal(PrintWriter pw) {
1131 pw.println("Display Power Controller Thread State:");
1132 pw.println(" mPowerRequest=" + mPowerRequest);
1133 pw.println(" mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
1135 pw.println(" mProximitySensor=" + mProximitySensor);
1136 pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled);
1137 pw.println(" mProximityThreshold=" + mProximityThreshold);
1138 pw.println(" mProximity=" + proximityToString(mProximity));
1139 pw.println(" mPendingProximity=" + proximityToString(mPendingProximity));
1140 pw.println(" mPendingProximityDebounceTime="
1141 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
1142 pw.println(" mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
1143 pw.println(" mAppliedAutoBrightness=" + mAppliedAutoBrightness);
1144 pw.println(" mAppliedDimming=" + mAppliedDimming);
1145 pw.println(" mAppliedLowPower=" + mAppliedLowPower);
1146 pw.println(" mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
1147 pw.println(" mPendingScreenOff=" + mPendingScreenOff);
1148 pw.println(" mReportedToPolicy=" + reportedToPolicyToString(mReportedScreenStateToPolicy));
1150 pw.println(" mScreenBrightnessRampAnimator.isAnimating()=" +
1151 mScreenBrightnessRampAnimator.isAnimating());
1153 if (mColorFadeOnAnimator != null) {
1154 pw.println(" mColorFadeOnAnimator.isStarted()=" +
1155 mColorFadeOnAnimator.isStarted());
1157 if (mColorFadeOffAnimator != null) {
1158 pw.println(" mColorFadeOffAnimator.isStarted()=" +
1159 mColorFadeOffAnimator.isStarted());
1162 if (mPowerState != null) {
1163 mPowerState.dump(pw);
1166 if (mAutomaticBrightnessController != null) {
1167 mAutomaticBrightnessController.dump(pw);
1172 private static String proximityToString(int state) {
1174 case PROXIMITY_UNKNOWN:
1176 case PROXIMITY_NEGATIVE:
1178 case PROXIMITY_POSITIVE:
1181 return Integer.toString(state);
1185 private static String reportedToPolicyToString(int state) {
1187 case REPORTED_TO_POLICY_SCREEN_OFF:
1188 return "REPORTED_TO_POLICY_SCREEN_OFF";
1189 case REPORTED_TO_POLICY_SCREEN_TURNING_ON:
1190 return "REPORTED_TO_POLICY_SCREEN_TURNING_ON";
1191 case REPORTED_TO_POLICY_SCREEN_ON:
1192 return "REPORTED_TO_POLICY_SCREEN_ON";
1194 return Integer.toString(state);
1198 private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) {
1200 final int n = brightness.length;
1201 float[] x = new float[n];
1202 float[] y = new float[n];
1203 y[0] = normalizeAbsoluteBrightness(brightness[0]);
1204 for (int i = 1; i < n; i++) {
1206 y[i] = normalizeAbsoluteBrightness(brightness[i]);
1209 Spline spline = Spline.createSpline(x, y);
1211 Slog.d(TAG, "Auto-brightness spline: " + spline);
1212 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
1213 Slog.d(TAG, String.format(" %7.1f: %7.1f", v, spline.interpolate(v)));
1217 } catch (IllegalArgumentException ex) {
1218 Slog.e(TAG, "Could not create auto-brightness spline.", ex);
1223 private static float normalizeAbsoluteBrightness(int value) {
1224 return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON;
1227 private static int clampAbsoluteBrightness(int value) {
1228 return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
1231 private final class DisplayControllerHandler extends Handler {
1232 public DisplayControllerHandler(Looper looper) {
1233 super(looper, null, true /*async*/);
1237 public void handleMessage(Message msg) {
1239 case MSG_UPDATE_POWER_STATE:
1243 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
1244 debounceProximitySensor();
1247 case MSG_SCREEN_ON_UNBLOCKED:
1248 if (mPendingScreenOnUnblocker == msg.obj) {
1257 private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
1259 public void onSensorChanged(SensorEvent event) {
1260 if (mProximitySensorEnabled) {
1261 final long time = SystemClock.uptimeMillis();
1262 final float distance = event.values[0];
1263 boolean positive = distance >= 0.0f && distance < mProximityThreshold;
1264 handleProximitySensorEvent(time, positive);
1269 public void onAccuracyChanged(Sensor sensor, int accuracy) {
1274 private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
1276 public void onScreenOn() {
1277 Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
1278 msg.setAsynchronous(true);
1279 mHandler.sendMessage(msg);