DisplayPowerController.java revision 3edf5272fb2185403dfe64b9722b9fc9b9de80f8
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.os.Trace; 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 private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked"; 78 79 // If true, uses the electron beam on animation. 80 // We might want to turn this off if we cannot get a guarantee that the screen 81 // actually turns on and starts showing new content after the call to set the 82 // screen state returns. Playing the animation can also be somewhat slow. 83 private static final boolean USE_COLOR_FADE_ON_ANIMATION = false; 84 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 = 600; 91 92 private static final int MSG_UPDATE_POWER_STATE = 1; 93 private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2; 94 95 private static final int PROXIMITY_UNKNOWN = -1; 96 private static final int PROXIMITY_NEGATIVE = 0; 97 private static final int PROXIMITY_POSITIVE = 1; 98 99 // Proximity sensor debounce delay in milliseconds for positive or negative transitions. 100 private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0; 101 private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 250; 102 103 // Trigger proximity if distance is less than 5 cm. 104 private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f; 105 106 // Brightness animation ramp rate in brightness units per second. 107 private static final int BRIGHTNESS_RAMP_RATE_FAST = 200; 108 private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40; 109 110 private final Object mLock = new Object(); 111 112 private final Context mContext; 113 114 // Our handler. 115 private final DisplayControllerHandler mHandler; 116 117 // Asynchronous callbacks into the power manager service. 118 // Only invoked from the handler thread while no locks are held. 119 private final DisplayPowerCallbacks mCallbacks; 120 121 // Battery stats. 122 private final IBatteryStats mBatteryStats; 123 124 // The lights service. 125 private final LightsManager mLights; 126 127 // The sensor manager. 128 private final SensorManager mSensorManager; 129 130 // The display blanker. 131 private final DisplayBlanker mBlanker; 132 133 // The proximity sensor, or null if not available or needed. 134 private Sensor mProximitySensor; 135 136 // The doze screen brightness. 137 private final int mScreenBrightnessDozeConfig; 138 139 // The dim screen brightness. 140 private final int mScreenBrightnessDimConfig; 141 142 // The minimum allowed brightness. 143 private final int mScreenBrightnessRangeMinimum; 144 145 // The maximum allowed brightness. 146 private final int mScreenBrightnessRangeMaximum; 147 148 // True if auto-brightness should be used. 149 private boolean mUseSoftwareAutoBrightnessConfig; 150 151 // True if we should fade the screen while turning it off, false if we should play 152 // a stylish electron beam animation instead. 153 private boolean mColorFadeFadesConfig; 154 155 // The pending power request. 156 // Initially null until the first call to requestPowerState. 157 // Guarded by mLock. 158 private DisplayPowerRequest mPendingRequestLocked; 159 160 // True if a request has been made to wait for the proximity sensor to go negative. 161 // Guarded by mLock. 162 private boolean mPendingWaitForNegativeProximityLocked; 163 164 // True if the pending power request or wait for negative proximity flag 165 // has been changed since the last update occurred. 166 // Guarded by mLock. 167 private boolean mPendingRequestChangedLocked; 168 169 // Set to true when the important parts of the pending power request have been applied. 170 // The important parts are mainly the screen state. Brightness changes may occur 171 // concurrently. 172 // Guarded by mLock. 173 private boolean mDisplayReadyLocked; 174 175 // Set to true if a power state update is required. 176 // Guarded by mLock. 177 private boolean mPendingUpdatePowerStateLocked; 178 179 /* The following state must only be accessed by the handler thread. */ 180 181 // The currently requested power state. 182 // The power controller will progressively update its internal state to match 183 // the requested power state. Initially null until the first update. 184 private DisplayPowerRequest mPowerRequest; 185 186 // The current power state. 187 // Must only be accessed on the handler thread. 188 private DisplayPowerState mPowerState; 189 190 // True if the device should wait for negative proximity sensor before 191 // waking up the screen. This is set to false as soon as a negative 192 // proximity sensor measurement is observed or when the device is forced to 193 // go to sleep by the user. While true, the screen remains off. 194 private boolean mWaitingForNegativeProximity; 195 196 // The actual proximity sensor threshold value. 197 private float mProximityThreshold; 198 199 // Set to true if the proximity sensor listener has been registered 200 // with the sensor manager. 201 private boolean mProximitySensorEnabled; 202 203 // The debounced proximity sensor state. 204 private int mProximity = PROXIMITY_UNKNOWN; 205 206 // The raw non-debounced proximity sensor state. 207 private int mPendingProximity = PROXIMITY_UNKNOWN; 208 private long mPendingProximityDebounceTime = -1; // -1 if fully debounced 209 210 // True if the screen was turned off because of the proximity sensor. 211 // When the screen turns on again, we report user activity to the power manager. 212 private boolean mScreenOffBecauseOfProximity; 213 214 // True if the screen on is being blocked. 215 private boolean mScreenOnWasBlocked; 216 217 // The elapsed real time when the screen on was blocked. 218 private long mScreenOnBlockStartRealTime; 219 220 // Remembers whether certain kinds of brightness adjustments 221 // were recently applied so that we can decide how to transition. 222 private boolean mAppliedAutoBrightness; 223 private boolean mAppliedDimming; 224 private boolean mAppliedLowPower; 225 226 // The controller for the automatic brightness level. 227 private AutomaticBrightnessController mAutomaticBrightnessController; 228 229 // Animators. 230 private ObjectAnimator mColorFadeOnAnimator; 231 private ObjectAnimator mColorFadeOffAnimator; 232 private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator; 233 234 /** 235 * Creates the display power controller. 236 */ 237 public DisplayPowerController(Context context, 238 DisplayPowerCallbacks callbacks, Handler handler, 239 SensorManager sensorManager, DisplayBlanker blanker) { 240 mHandler = new DisplayControllerHandler(handler.getLooper()); 241 mCallbacks = callbacks; 242 243 mBatteryStats = BatteryStatsService.getService(); 244 mLights = LocalServices.getService(LightsManager.class); 245 mSensorManager = sensorManager; 246 mBlanker = blanker; 247 mContext = context; 248 249 final Resources resources = context.getResources(); 250 251 mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger( 252 com.android.internal.R.integer.config_screenBrightnessDoze)); 253 254 mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger( 255 com.android.internal.R.integer.config_screenBrightnessDim)); 256 257 int screenBrightnessRangeMinimum = clampAbsoluteBrightness(Math.min(resources.getInteger( 258 com.android.internal.R.integer.config_screenBrightnessSettingMinimum), 259 mScreenBrightnessDimConfig)); 260 261 mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON; 262 263 mUseSoftwareAutoBrightnessConfig = resources.getBoolean( 264 com.android.internal.R.bool.config_automatic_brightness_available); 265 if (mUseSoftwareAutoBrightnessConfig) { 266 int[] lux = resources.getIntArray( 267 com.android.internal.R.array.config_autoBrightnessLevels); 268 int[] screenBrightness = resources.getIntArray( 269 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues); 270 int lightSensorWarmUpTimeConfig = resources.getInteger( 271 com.android.internal.R.integer.config_lightSensorWarmupTime); 272 273 Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness); 274 if (screenAutoBrightnessSpline == null) { 275 Slog.e(TAG, "Error in config.xml. config_autoBrightnessLcdBacklightValues " 276 + "(size " + screenBrightness.length + ") " 277 + "must be monotic and have exactly one more entry than " 278 + "config_autoBrightnessLevels (size " + lux.length + ") " 279 + "which must be strictly increasing. " 280 + "Auto-brightness will be disabled."); 281 mUseSoftwareAutoBrightnessConfig = false; 282 } else { 283 if (screenBrightness[0] < screenBrightnessRangeMinimum) { 284 screenBrightnessRangeMinimum = clampAbsoluteBrightness(screenBrightness[0]); 285 } 286 mAutomaticBrightnessController = new AutomaticBrightnessController(this, 287 handler.getLooper(), sensorManager, screenAutoBrightnessSpline, 288 lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum, 289 mScreenBrightnessRangeMaximum); 290 } 291 } 292 293 mScreenBrightnessRangeMinimum = screenBrightnessRangeMinimum; 294 295 mColorFadeFadesConfig = resources.getBoolean( 296 com.android.internal.R.bool.config_animateScreenLights); 297 298 if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) { 299 mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); 300 if (mProximitySensor != null) { 301 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(), 302 TYPICAL_PROXIMITY_THRESHOLD); 303 } 304 } 305 306 } 307 308 /** 309 * Returns true if the proximity sensor screen-off function is available. 310 */ 311 public boolean isProximitySensorAvailable() { 312 return mProximitySensor != null; 313 } 314 315 /** 316 * Requests a new power state. 317 * The controller makes a copy of the provided object and then 318 * begins adjusting the power state to match what was requested. 319 * 320 * @param request The requested power state. 321 * @param waitForNegativeProximity If true, issues a request to wait for 322 * negative proximity before turning the screen back on, assuming the screen 323 * was turned off by the proximity sensor. 324 * @return True if display is ready, false if there are important changes that must 325 * be made asynchronously (such as turning the screen on), in which case the caller 326 * should grab a wake lock, watch for {@link Callbacks#onStateChanged()} then try 327 * the request again later until the state converges. 328 */ 329 public boolean requestPowerState(DisplayPowerRequest request, 330 boolean waitForNegativeProximity) { 331 if (DEBUG) { 332 Slog.d(TAG, "requestPowerState: " 333 + request + ", waitForNegativeProximity=" + waitForNegativeProximity); 334 } 335 336 synchronized (mLock) { 337 boolean changed = false; 338 339 if (waitForNegativeProximity 340 && !mPendingWaitForNegativeProximityLocked) { 341 mPendingWaitForNegativeProximityLocked = true; 342 changed = true; 343 } 344 345 if (mPendingRequestLocked == null) { 346 mPendingRequestLocked = new DisplayPowerRequest(request); 347 changed = true; 348 } else if (!mPendingRequestLocked.equals(request)) { 349 mPendingRequestLocked.copyFrom(request); 350 changed = true; 351 } 352 353 if (changed) { 354 mDisplayReadyLocked = false; 355 } 356 357 if (changed && !mPendingRequestChangedLocked) { 358 mPendingRequestChangedLocked = true; 359 sendUpdatePowerStateLocked(); 360 } 361 362 return mDisplayReadyLocked; 363 } 364 } 365 366 private void sendUpdatePowerState() { 367 synchronized (mLock) { 368 sendUpdatePowerStateLocked(); 369 } 370 } 371 372 private void sendUpdatePowerStateLocked() { 373 if (!mPendingUpdatePowerStateLocked) { 374 mPendingUpdatePowerStateLocked = true; 375 Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE); 376 msg.setAsynchronous(true); 377 mHandler.sendMessage(msg); 378 } 379 } 380 381 private void initialize() { 382 // Initialize the power state object for the default display. 383 // In the future, we might manage multiple displays independently. 384 mPowerState = new DisplayPowerState(mBlanker, 385 mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT), 386 new ColorFade(Display.DEFAULT_DISPLAY)); 387 388 mColorFadeOnAnimator = ObjectAnimator.ofFloat( 389 mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 0.0f, 1.0f); 390 mColorFadeOnAnimator.setDuration(COLOR_FADE_ON_ANIMATION_DURATION_MILLIS); 391 mColorFadeOnAnimator.addListener(mAnimatorListener); 392 393 mColorFadeOffAnimator = ObjectAnimator.ofFloat( 394 mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 1.0f, 0.0f); 395 mColorFadeOffAnimator.setDuration(COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS); 396 mColorFadeOffAnimator.addListener(mAnimatorListener); 397 398 mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>( 399 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS); 400 mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener); 401 402 // Initialize screen state for battery stats. 403 try { 404 mBatteryStats.noteScreenState(mPowerState.getScreenState()); 405 mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness()); 406 } catch (RemoteException ex) { 407 // same process 408 } 409 } 410 411 private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() { 412 @Override 413 public void onAnimationStart(Animator animation) { 414 } 415 @Override 416 public void onAnimationEnd(Animator animation) { 417 sendUpdatePowerState(); 418 } 419 @Override 420 public void onAnimationRepeat(Animator animation) { 421 } 422 @Override 423 public void onAnimationCancel(Animator animation) { 424 } 425 }; 426 427 private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() { 428 @Override 429 public void onAnimationEnd() { 430 sendUpdatePowerState(); 431 } 432 }; 433 434 private void updatePowerState() { 435 // Update the power state request. 436 final boolean mustNotify; 437 boolean mustInitialize = false; 438 boolean autoBrightnessAdjustmentChanged = false; 439 440 synchronized (mLock) { 441 mPendingUpdatePowerStateLocked = false; 442 if (mPendingRequestLocked == null) { 443 return; // wait until first actual power request 444 } 445 446 if (mPowerRequest == null) { 447 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked); 448 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked; 449 mPendingWaitForNegativeProximityLocked = false; 450 mPendingRequestChangedLocked = false; 451 mustInitialize = true; 452 } else if (mPendingRequestChangedLocked) { 453 autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment 454 != mPendingRequestLocked.screenAutoBrightnessAdjustment); 455 mPowerRequest.copyFrom(mPendingRequestLocked); 456 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked; 457 mPendingWaitForNegativeProximityLocked = false; 458 mPendingRequestChangedLocked = false; 459 mDisplayReadyLocked = false; 460 } 461 462 mustNotify = !mDisplayReadyLocked; 463 } 464 465 // Initialize things the first time the power state is changed. 466 if (mustInitialize) { 467 initialize(); 468 } 469 470 // Compute the basic display state using the policy. 471 // We might override this below based on other factors. 472 int state; 473 int brightness = PowerManager.BRIGHTNESS_DEFAULT; 474 switch (mPowerRequest.policy) { 475 case DisplayPowerRequest.POLICY_OFF: 476 state = Display.STATE_OFF; 477 break; 478 case DisplayPowerRequest.POLICY_DOZE: 479 if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) { 480 state = mPowerRequest.dozeScreenState; 481 } else { 482 state = Display.STATE_DOZE; 483 } 484 brightness = mPowerRequest.dozeScreenBrightness; 485 break; 486 case DisplayPowerRequest.POLICY_DIM: 487 case DisplayPowerRequest.POLICY_BRIGHT: 488 default: 489 state = Display.STATE_ON; 490 break; 491 } 492 493 // Apply the proximity sensor. 494 if (mProximitySensor != null) { 495 if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) { 496 setProximitySensorEnabled(true); 497 if (!mScreenOffBecauseOfProximity 498 && mProximity == PROXIMITY_POSITIVE) { 499 mScreenOffBecauseOfProximity = true; 500 sendOnProximityPositiveWithWakelock(); 501 } 502 } else if (mWaitingForNegativeProximity 503 && mScreenOffBecauseOfProximity 504 && mProximity == PROXIMITY_POSITIVE 505 && state != Display.STATE_OFF) { 506 setProximitySensorEnabled(true); 507 } else { 508 setProximitySensorEnabled(false); 509 mWaitingForNegativeProximity = false; 510 } 511 if (mScreenOffBecauseOfProximity 512 && mProximity != PROXIMITY_POSITIVE) { 513 mScreenOffBecauseOfProximity = false; 514 sendOnProximityNegativeWithWakelock(); 515 } 516 } else { 517 mWaitingForNegativeProximity = false; 518 } 519 if (mScreenOffBecauseOfProximity) { 520 state = Display.STATE_OFF; 521 } 522 523 // Use zero brightness when screen is off. 524 if (state == Display.STATE_OFF) { 525 brightness = PowerManager.BRIGHTNESS_OFF; 526 } 527 528 // Use default brightness when dozing unless overridden. 529 if (brightness < 0 && (state == Display.STATE_DOZE 530 || state == Display.STATE_DOZE_SUSPEND)) { 531 brightness = mScreenBrightnessDozeConfig; 532 } 533 534 // Configure auto-brightness. 535 boolean autoBrightnessEnabled = false; 536 if (mAutomaticBrightnessController != null) { 537 autoBrightnessEnabled = mPowerRequest.useAutoBrightness 538 && state == Display.STATE_ON && brightness < 0; 539 mAutomaticBrightnessController.configure(autoBrightnessEnabled, 540 mPowerRequest.screenAutoBrightnessAdjustment); 541 } 542 543 // Apply auto-brightness. 544 boolean slowChange = false; 545 if (brightness < 0) { 546 if (autoBrightnessEnabled) { 547 brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness(); 548 } 549 if (brightness >= 0) { 550 // Use current auto-brightness value and slowly adjust to changes. 551 brightness = clampScreenBrightness(brightness); 552 if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) { 553 slowChange = true; // slowly adapt to auto-brightness 554 } 555 mAppliedAutoBrightness = true; 556 } else { 557 mAppliedAutoBrightness = false; 558 } 559 } else { 560 mAppliedAutoBrightness = false; 561 } 562 563 // Apply manual brightness. 564 // Use the current brightness setting from the request, which is expected 565 // provide a nominal default value for the case where auto-brightness 566 // is not ready yet. 567 if (brightness < 0) { 568 brightness = clampScreenBrightness(mPowerRequest.screenBrightness); 569 } 570 571 // Apply dimming by at least some minimum amount when user activity 572 // timeout is about to expire. 573 if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) { 574 if (brightness > mScreenBrightnessRangeMinimum) { 575 brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION, 576 mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum); 577 } 578 if (!mAppliedDimming) { 579 slowChange = false; 580 } 581 mAppliedDimming = true; 582 } 583 584 // If low power mode is enabled, cut the brightness level by half 585 // as long as it is above the minimum threshold. 586 if (mPowerRequest.lowPowerMode) { 587 if (brightness > mScreenBrightnessRangeMinimum) { 588 brightness = Math.max(brightness / 2, mScreenBrightnessRangeMinimum); 589 } 590 if (!mAppliedLowPower) { 591 slowChange = false; 592 } 593 mAppliedLowPower = true; 594 } 595 596 // Animate the screen brightness when the screen is on. 597 if (state != Display.STATE_OFF) { 598 animateScreenBrightness(brightness, slowChange 599 ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST); 600 } 601 602 // Animate the screen on or off unless blocked. 603 if (state == Display.STATE_ON) { 604 // Want screen on. 605 // Wait for previous off animation to complete beforehand. 606 // It is relatively short but if we cancel it and switch to the 607 // on animation immediately then the results are pretty ugly. 608 if (!mColorFadeOffAnimator.isStarted()) { 609 // Turn the screen on. The contents of the screen may not yet 610 // be visible if the electron beam has not been dismissed because 611 // its last frame of animation is solid black. 612 setScreenState(Display.STATE_ON); 613 if (mPowerRequest.blockScreenOn 614 && mPowerState.getColorFadeLevel() == 0.0f) { 615 blockScreenOn(); 616 } else { 617 unblockScreenOn(); 618 if (USE_COLOR_FADE_ON_ANIMATION && mPowerRequest.isBrightOrDim()) { 619 // Perform screen on animation. 620 if (!mColorFadeOnAnimator.isStarted()) { 621 if (mPowerState.getColorFadeLevel() == 1.0f) { 622 mPowerState.dismissColorFade(); 623 } else if (mPowerState.prepareColorFade(mContext, 624 mColorFadeFadesConfig ? 625 ColorFade.MODE_FADE : 626 ColorFade.MODE_WARM_UP)) { 627 mColorFadeOnAnimator.start(); 628 } else { 629 mColorFadeOnAnimator.end(); 630 } 631 } 632 } else { 633 // Skip screen on animation. 634 mPowerState.setColorFadeLevel(1.0f); 635 mPowerState.dismissColorFade(); 636 } 637 } 638 } 639 } else if (state == Display.STATE_DOZE) { 640 // Want screen dozing. 641 // Wait for brightness animation to complete beforehand when entering doze 642 // from screen on. 643 unblockScreenOn(); 644 if (!mScreenBrightnessRampAnimator.isAnimating() 645 || mPowerState.getScreenState() != Display.STATE_ON) { 646 // Set screen state and dismiss the black surface without fanfare. 647 setScreenState(state); 648 mPowerState.setColorFadeLevel(1.0f); 649 mPowerState.dismissColorFade(); 650 } 651 } else if (state == Display.STATE_DOZE_SUSPEND) { 652 // Want screen dozing and suspended. 653 // Wait for brightness animation to complete beforehand unless already 654 // suspended because we may not be able to change it after suspension. 655 unblockScreenOn(); 656 if (!mScreenBrightnessRampAnimator.isAnimating() 657 || mPowerState.getScreenState() == Display.STATE_DOZE_SUSPEND) { 658 // Set screen state and dismiss the black surface without fanfare. 659 setScreenState(state); 660 mPowerState.setColorFadeLevel(1.0f); 661 mPowerState.dismissColorFade(); 662 } 663 } else { 664 // Want screen off. 665 // Wait for previous on animation to complete beforehand. 666 unblockScreenOn(); 667 if (!mColorFadeOnAnimator.isStarted()) { 668 if (mPowerRequest.policy == DisplayPowerRequest.POLICY_OFF) { 669 // Perform screen off animation. 670 if (!mColorFadeOffAnimator.isStarted()) { 671 if (mPowerState.getColorFadeLevel() == 0.0f) { 672 setScreenState(Display.STATE_OFF); 673 } else if (mPowerState.prepareColorFade(mContext, 674 mColorFadeFadesConfig ? 675 ColorFade.MODE_FADE : 676 ColorFade.MODE_COOL_DOWN) 677 && mPowerState.getScreenState() != Display.STATE_OFF) { 678 mColorFadeOffAnimator.start(); 679 } else { 680 mColorFadeOffAnimator.end(); 681 } 682 } 683 } else { 684 // Skip screen off animation. 685 setScreenState(Display.STATE_OFF); 686 } 687 } 688 } 689 690 // Report whether the display is ready for use. 691 // We mostly care about the screen state here, ignoring brightness changes 692 // which will be handled asynchronously. 693 if (mustNotify 694 && !mScreenOnWasBlocked 695 && !mColorFadeOnAnimator.isStarted() 696 && !mColorFadeOffAnimator.isStarted() 697 && !mScreenBrightnessRampAnimator.isAnimating() 698 && mPowerState.waitUntilClean(mCleanListener)) { 699 synchronized (mLock) { 700 if (!mPendingRequestChangedLocked) { 701 mDisplayReadyLocked = true; 702 703 if (DEBUG) { 704 Slog.d(TAG, "Display ready!"); 705 } 706 } 707 } 708 sendOnStateChangedWithWakelock(); 709 } 710 } 711 712 @Override 713 public void updateBrightness() { 714 sendUpdatePowerState(); 715 } 716 717 private void blockScreenOn() { 718 if (!mScreenOnWasBlocked) { 719 Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0); 720 mScreenOnWasBlocked = true; 721 mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime(); 722 Slog.i(TAG, "Blocking screen on until initial contents have been drawn."); 723 } 724 } 725 726 private void unblockScreenOn() { 727 if (mScreenOnWasBlocked) { 728 mScreenOnWasBlocked = false; 729 long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime; 730 Slog.i(TAG, "Unblocked screen on after " + delay + " ms"); 731 Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0); 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