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