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