DisplayPowerController.java revision e95c3cd89591ba586aa8a0f7a17660c6fb8770bc
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_ELECTRON_BEAM_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 ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS = 250; 88 private static final int ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS = 400; 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 // Our handler. 111 private final DisplayControllerHandler mHandler; 112 113 // Asynchronous callbacks into the power manager service. 114 // Only invoked from the handler thread while no locks are held. 115 private final DisplayPowerCallbacks mCallbacks; 116 117 // Battery stats. 118 private final IBatteryStats mBatteryStats; 119 120 // The lights service. 121 private final LightsManager mLights; 122 123 // The sensor manager. 124 private final SensorManager mSensorManager; 125 126 // The display blanker. 127 private final DisplayBlanker mBlanker; 128 129 // The proximity sensor, or null if not available or needed. 130 private Sensor mProximitySensor; 131 132 // The doze screen brightness. 133 private final int mScreenBrightnessDozeConfig; 134 135 // The dim screen brightness. 136 private final int mScreenBrightnessDimConfig; 137 138 // The minimum allowed brightness. 139 private final int mScreenBrightnessRangeMinimum; 140 141 // The maximum allowed brightness. 142 private final int mScreenBrightnessRangeMaximum; 143 144 // True if auto-brightness should be used. 145 private boolean mUseSoftwareAutoBrightnessConfig; 146 147 // True if we should fade the screen while turning it off, false if we should play 148 // a stylish electron beam animation instead. 149 private boolean mElectronBeamFadesConfig; 150 151 // The pending power request. 152 // Initially null until the first call to requestPowerState. 153 // Guarded by mLock. 154 private DisplayPowerRequest mPendingRequestLocked; 155 156 // True if a request has been made to wait for the proximity sensor to go negative. 157 // Guarded by mLock. 158 private boolean mPendingWaitForNegativeProximityLocked; 159 160 // True if the pending power request or wait for negative proximity flag 161 // has been changed since the last update occurred. 162 // Guarded by mLock. 163 private boolean mPendingRequestChangedLocked; 164 165 // Set to true when the important parts of the pending power request have been applied. 166 // The important parts are mainly the screen state. Brightness changes may occur 167 // concurrently. 168 // Guarded by mLock. 169 private boolean mDisplayReadyLocked; 170 171 // Set to true if a power state update is required. 172 // Guarded by mLock. 173 private boolean mPendingUpdatePowerStateLocked; 174 175 /* The following state must only be accessed by the handler thread. */ 176 177 // The currently requested power state. 178 // The power controller will progressively update its internal state to match 179 // the requested power state. Initially null until the first update. 180 private DisplayPowerRequest mPowerRequest; 181 182 // The current power state. 183 // Must only be accessed on the handler thread. 184 private DisplayPowerState mPowerState; 185 186 // True if the device should wait for negative proximity sensor before 187 // waking up the screen. This is set to false as soon as a negative 188 // proximity sensor measurement is observed or when the device is forced to 189 // go to sleep by the user. While true, the screen remains off. 190 private boolean mWaitingForNegativeProximity; 191 192 // The actual proximity sensor threshold value. 193 private float mProximityThreshold; 194 195 // Set to true if the proximity sensor listener has been registered 196 // with the sensor manager. 197 private boolean mProximitySensorEnabled; 198 199 // The debounced proximity sensor state. 200 private int mProximity = PROXIMITY_UNKNOWN; 201 202 // The raw non-debounced proximity sensor state. 203 private int mPendingProximity = PROXIMITY_UNKNOWN; 204 private long mPendingProximityDebounceTime = -1; // -1 if fully debounced 205 206 // True if the screen was turned off because of the proximity sensor. 207 // When the screen turns on again, we report user activity to the power manager. 208 private boolean mScreenOffBecauseOfProximity; 209 210 // True if the screen on is being blocked. 211 private boolean mScreenOnWasBlocked; 212 213 // The elapsed real time when the screen on was blocked. 214 private long mScreenOnBlockStartRealTime; 215 216 // True if the screen auto-brightness value is actually being used to 217 // set the display brightness. 218 private boolean mUsingScreenAutoBrightness; 219 220 // The controller for the automatic brightness level. 221 private AutomaticBrightnessController mAutomaticBrightnessController; 222 223 // Animators. 224 private ObjectAnimator mElectronBeamOnAnimator; 225 private ObjectAnimator mElectronBeamOffAnimator; 226 private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator; 227 228 /** 229 * Creates the display power controller. 230 */ 231 public DisplayPowerController(Context context, 232 DisplayPowerCallbacks callbacks, Handler handler, 233 SensorManager sensorManager, DisplayBlanker blanker) { 234 mHandler = new DisplayControllerHandler(handler.getLooper()); 235 mCallbacks = callbacks; 236 237 mBatteryStats = BatteryStatsService.getService(); 238 mLights = LocalServices.getService(LightsManager.class); 239 mSensorManager = sensorManager; 240 mBlanker = blanker; 241 242 final Resources resources = context.getResources(); 243 244 mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger( 245 com.android.internal.R.integer.config_screenBrightnessDoze)); 246 247 mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger( 248 com.android.internal.R.integer.config_screenBrightnessDim)); 249 250 int screenBrightnessRangeMinimum = clampAbsoluteBrightness(Math.min(resources.getInteger( 251 com.android.internal.R.integer.config_screenBrightnessSettingMinimum), 252 mScreenBrightnessDimConfig)); 253 254 mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON; 255 256 mUseSoftwareAutoBrightnessConfig = resources.getBoolean( 257 com.android.internal.R.bool.config_automatic_brightness_available); 258 if (mUseSoftwareAutoBrightnessConfig) { 259 int[] lux = resources.getIntArray( 260 com.android.internal.R.array.config_autoBrightnessLevels); 261 int[] screenBrightness = resources.getIntArray( 262 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues); 263 int lightSensorWarmUpTimeConfig = resources.getInteger( 264 com.android.internal.R.integer.config_lightSensorWarmupTime); 265 266 Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness); 267 if (screenAutoBrightnessSpline == null) { 268 Slog.e(TAG, "Error in config.xml. config_autoBrightnessLcdBacklightValues " 269 + "(size " + screenBrightness.length + ") " 270 + "must be monotic and have exactly one more entry than " 271 + "config_autoBrightnessLevels (size " + lux.length + ") " 272 + "which must be strictly increasing. " 273 + "Auto-brightness will be disabled."); 274 mUseSoftwareAutoBrightnessConfig = false; 275 } else { 276 if (screenBrightness[0] < screenBrightnessRangeMinimum) { 277 screenBrightnessRangeMinimum = clampAbsoluteBrightness(screenBrightness[0]); 278 } 279 mAutomaticBrightnessController = new AutomaticBrightnessController(this, 280 handler.getLooper(), sensorManager, screenAutoBrightnessSpline, 281 lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum, 282 mScreenBrightnessRangeMaximum); 283 } 284 } 285 286 mScreenBrightnessRangeMinimum = screenBrightnessRangeMinimum; 287 288 mElectronBeamFadesConfig = resources.getBoolean( 289 com.android.internal.R.bool.config_animateScreenLights); 290 291 if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) { 292 mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); 293 if (mProximitySensor != null) { 294 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(), 295 TYPICAL_PROXIMITY_THRESHOLD); 296 } 297 } 298 299 } 300 301 /** 302 * Returns true if the proximity sensor screen-off function is available. 303 */ 304 public boolean isProximitySensorAvailable() { 305 return mProximitySensor != null; 306 } 307 308 /** 309 * Requests a new power state. 310 * The controller makes a copy of the provided object and then 311 * begins adjusting the power state to match what was requested. 312 * 313 * @param request The requested power state. 314 * @param waitForNegativeProximity If true, issues a request to wait for 315 * negative proximity before turning the screen back on, assuming the screen 316 * was turned off by the proximity sensor. 317 * @return True if display is ready, false if there are important changes that must 318 * be made asynchronously (such as turning the screen on), in which case the caller 319 * should grab a wake lock, watch for {@link Callbacks#onStateChanged()} then try 320 * the request again later until the state converges. 321 */ 322 public boolean requestPowerState(DisplayPowerRequest request, 323 boolean waitForNegativeProximity) { 324 if (DEBUG) { 325 Slog.d(TAG, "requestPowerState: " 326 + request + ", waitForNegativeProximity=" + waitForNegativeProximity); 327 } 328 329 synchronized (mLock) { 330 boolean changed = false; 331 332 if (waitForNegativeProximity 333 && !mPendingWaitForNegativeProximityLocked) { 334 mPendingWaitForNegativeProximityLocked = true; 335 changed = true; 336 } 337 338 if (mPendingRequestLocked == null) { 339 mPendingRequestLocked = new DisplayPowerRequest(request); 340 changed = true; 341 } else if (!mPendingRequestLocked.equals(request)) { 342 mPendingRequestLocked.copyFrom(request); 343 changed = true; 344 } 345 346 if (changed) { 347 mDisplayReadyLocked = false; 348 } 349 350 if (changed && !mPendingRequestChangedLocked) { 351 mPendingRequestChangedLocked = true; 352 sendUpdatePowerStateLocked(); 353 } 354 355 return mDisplayReadyLocked; 356 } 357 } 358 359 private void sendUpdatePowerState() { 360 synchronized (mLock) { 361 sendUpdatePowerStateLocked(); 362 } 363 } 364 365 private void sendUpdatePowerStateLocked() { 366 if (!mPendingUpdatePowerStateLocked) { 367 mPendingUpdatePowerStateLocked = true; 368 Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE); 369 msg.setAsynchronous(true); 370 mHandler.sendMessage(msg); 371 } 372 } 373 374 private void initialize() { 375 // Initialize the power state object for the default display. 376 // In the future, we might manage multiple displays independently. 377 mPowerState = new DisplayPowerState(mBlanker, 378 mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT), 379 new ElectronBeam(Display.DEFAULT_DISPLAY)); 380 381 mElectronBeamOnAnimator = ObjectAnimator.ofFloat( 382 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f); 383 mElectronBeamOnAnimator.setDuration(ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS); 384 mElectronBeamOnAnimator.addListener(mAnimatorListener); 385 386 mElectronBeamOffAnimator = ObjectAnimator.ofFloat( 387 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 1.0f, 0.0f); 388 mElectronBeamOffAnimator.setDuration(ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS); 389 mElectronBeamOffAnimator.addListener(mAnimatorListener); 390 391 mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>( 392 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS); 393 394 // Initialize screen state for battery stats. 395 try { 396 mBatteryStats.noteScreenState(mPowerState.getScreenState()); 397 mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness()); 398 } catch (RemoteException ex) { 399 // same process 400 } 401 } 402 403 private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() { 404 @Override 405 public void onAnimationStart(Animator animation) { 406 } 407 @Override 408 public void onAnimationEnd(Animator animation) { 409 sendUpdatePowerState(); 410 } 411 @Override 412 public void onAnimationRepeat(Animator animation) { 413 } 414 @Override 415 public void onAnimationCancel(Animator animation) { 416 } 417 }; 418 419 private void updatePowerState() { 420 // Update the power state request. 421 final boolean mustNotify; 422 boolean mustInitialize = false; 423 boolean wasDimOrDoze = false; 424 425 synchronized (mLock) { 426 mPendingUpdatePowerStateLocked = false; 427 if (mPendingRequestLocked == null) { 428 return; // wait until first actual power request 429 } 430 431 if (mPowerRequest == null) { 432 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked); 433 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked; 434 mPendingWaitForNegativeProximityLocked = false; 435 mPendingRequestChangedLocked = false; 436 mustInitialize = true; 437 } else if (mPendingRequestChangedLocked) { 438 wasDimOrDoze = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM 439 || mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE); 440 mPowerRequest.copyFrom(mPendingRequestLocked); 441 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked; 442 mPendingWaitForNegativeProximityLocked = false; 443 mPendingRequestChangedLocked = false; 444 mDisplayReadyLocked = false; 445 } 446 447 mustNotify = !mDisplayReadyLocked; 448 } 449 450 // Initialize things the first time the power state is changed. 451 if (mustInitialize) { 452 initialize(); 453 } 454 455 // Apply the proximity sensor. 456 if (mProximitySensor != null) { 457 if (mPowerRequest.useProximitySensor 458 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { 459 setProximitySensorEnabled(true); 460 if (!mScreenOffBecauseOfProximity 461 && mProximity == PROXIMITY_POSITIVE) { 462 mScreenOffBecauseOfProximity = true; 463 sendOnProximityPositiveWithWakelock(); 464 } 465 } else if (mWaitingForNegativeProximity 466 && mScreenOffBecauseOfProximity 467 && mProximity == PROXIMITY_POSITIVE 468 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { 469 setProximitySensorEnabled(true); 470 } else { 471 setProximitySensorEnabled(false); 472 mWaitingForNegativeProximity = false; 473 } 474 if (mScreenOffBecauseOfProximity 475 && mProximity != PROXIMITY_POSITIVE) { 476 mScreenOffBecauseOfProximity = false; 477 sendOnProximityNegativeWithWakelock(); 478 } 479 } else { 480 mWaitingForNegativeProximity = false; 481 } 482 483 // Turn on the light sensor if needed. 484 if (mAutomaticBrightnessController != null) { 485 mAutomaticBrightnessController.updatePowerState(mPowerRequest); 486 } 487 488 // Set the screen brightness. 489 if (mPowerRequest.wantScreenOnAny()) { 490 int target; 491 boolean slow; 492 int screenAutoBrightness = mAutomaticBrightnessController != null ? 493 mAutomaticBrightnessController.getAutomaticScreenBrightness() : -1; 494 if (screenAutoBrightness >= 0 && mPowerRequest.useAutoBrightness) { 495 // Use current auto-brightness value. 496 target = screenAutoBrightness; 497 slow = mUsingScreenAutoBrightness; 498 mUsingScreenAutoBrightness = true; 499 } else { 500 // Light sensor is disabled or not ready yet. 501 // Use the current brightness setting from the request, which is expected 502 // provide a nominal default value for the case where auto-brightness 503 // is not ready yet. 504 target = mPowerRequest.screenBrightness; 505 slow = false; 506 mUsingScreenAutoBrightness = false; 507 } 508 if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE) { 509 // Dim quickly to the doze state. 510 target = mScreenBrightnessDozeConfig; 511 slow = false; 512 } else if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) { 513 // Dim quickly by at least some minimum amount. 514 target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION, 515 mScreenBrightnessDimConfig); 516 slow = false; 517 } else if (wasDimOrDoze) { 518 // Brighten quickly. 519 slow = false; 520 } 521 animateScreenBrightness(clampScreenBrightness(target), 522 slow ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST); 523 } else { 524 // Screen is off. Don't bother changing the brightness. 525 mUsingScreenAutoBrightness = false; 526 } 527 528 // Animate the screen on or off unless blocked. 529 if (mScreenOffBecauseOfProximity) { 530 // Screen off due to proximity. 531 setScreenState(Display.STATE_OFF); 532 unblockScreenOn(); 533 } else if (mPowerRequest.wantScreenOnAny()) { 534 // Want screen on. 535 // Wait for previous off animation to complete beforehand. 536 // It is relatively short but if we cancel it and switch to the 537 // on animation immediately then the results are pretty ugly. 538 if (!mElectronBeamOffAnimator.isStarted()) { 539 // Turn the screen on. The contents of the screen may not yet 540 // be visible if the electron beam has not been dismissed because 541 // its last frame of animation is solid black. 542 setScreenState(mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE 543 ? Display.STATE_DOZING : Display.STATE_ON); 544 545 if (mPowerRequest.blockScreenOn 546 && mPowerState.getElectronBeamLevel() == 0.0f) { 547 blockScreenOn(); 548 } else { 549 unblockScreenOn(); 550 if (USE_ELECTRON_BEAM_ON_ANIMATION) { 551 if (!mElectronBeamOnAnimator.isStarted()) { 552 if (mPowerState.getElectronBeamLevel() == 1.0f) { 553 mPowerState.dismissElectronBeam(); 554 } else if (mPowerState.prepareElectronBeam( 555 mElectronBeamFadesConfig ? 556 ElectronBeam.MODE_FADE : 557 ElectronBeam.MODE_WARM_UP)) { 558 mElectronBeamOnAnimator.start(); 559 } else { 560 mElectronBeamOnAnimator.end(); 561 } 562 } 563 } else { 564 mPowerState.setElectronBeamLevel(1.0f); 565 mPowerState.dismissElectronBeam(); 566 } 567 } 568 } 569 } else { 570 // Want screen off. 571 // Wait for previous on animation to complete beforehand. 572 unblockScreenOn(); 573 if (!mElectronBeamOnAnimator.isStarted()) { 574 if (!mElectronBeamOffAnimator.isStarted()) { 575 if (mPowerState.getElectronBeamLevel() == 0.0f) { 576 setScreenState(Display.STATE_OFF); 577 } else if (mPowerState.prepareElectronBeam( 578 mElectronBeamFadesConfig ? 579 ElectronBeam.MODE_FADE : 580 ElectronBeam.MODE_COOL_DOWN) 581 && mPowerState.getScreenState() != Display.STATE_OFF) { 582 mElectronBeamOffAnimator.start(); 583 } else { 584 mElectronBeamOffAnimator.end(); 585 } 586 } 587 } 588 } 589 590 // Report whether the display is ready for use. 591 // We mostly care about the screen state here, ignoring brightness changes 592 // which will be handled asynchronously. 593 if (mustNotify 594 && !mScreenOnWasBlocked 595 && !mElectronBeamOnAnimator.isStarted() 596 && !mElectronBeamOffAnimator.isStarted() 597 && mPowerState.waitUntilClean(mCleanListener)) { 598 synchronized (mLock) { 599 if (!mPendingRequestChangedLocked) { 600 mDisplayReadyLocked = true; 601 602 if (DEBUG) { 603 Slog.d(TAG, "Display ready!"); 604 } 605 } 606 } 607 sendOnStateChangedWithWakelock(); 608 } 609 } 610 611 @Override 612 public void updateBrightness() { 613 sendUpdatePowerState(); 614 } 615 616 private void blockScreenOn() { 617 if (!mScreenOnWasBlocked) { 618 mScreenOnWasBlocked = true; 619 mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime(); 620 if (DEBUG) { 621 Slog.d(TAG, "Blocked screen on."); 622 } 623 } 624 } 625 626 private void unblockScreenOn() { 627 if (mScreenOnWasBlocked) { 628 mScreenOnWasBlocked = false; 629 long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime; 630 if (delay > 1000 || DEBUG) { 631 Slog.d(TAG, "Unblocked screen on after " + delay + " ms"); 632 } 633 } 634 } 635 636 private void setScreenState(int state) { 637 if (mPowerState.getScreenState() != state) { 638 mPowerState.setScreenState(state); 639 try { 640 mBatteryStats.noteScreenState(state); 641 } catch (RemoteException ex) { 642 // same process 643 } 644 } 645 } 646 647 private int clampScreenBrightness(int value) { 648 return MathUtils.constrain( 649 value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum); 650 } 651 652 private void animateScreenBrightness(int target, int rate) { 653 if (mScreenBrightnessRampAnimator.animateTo(target, rate)) { 654 try { 655 mBatteryStats.noteScreenBrightness(target); 656 } catch (RemoteException ex) { 657 // same process 658 } 659 } 660 } 661 662 private final Runnable mCleanListener = new Runnable() { 663 @Override 664 public void run() { 665 sendUpdatePowerState(); 666 } 667 }; 668 669 private void setProximitySensorEnabled(boolean enable) { 670 if (enable) { 671 if (!mProximitySensorEnabled) { 672 // Register the listener. 673 // Proximity sensor state already cleared initially. 674 mProximitySensorEnabled = true; 675 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor, 676 SensorManager.SENSOR_DELAY_NORMAL, mHandler); 677 } 678 } else { 679 if (mProximitySensorEnabled) { 680 // Unregister the listener. 681 // Clear the proximity sensor state for next time. 682 mProximitySensorEnabled = false; 683 mProximity = PROXIMITY_UNKNOWN; 684 mPendingProximity = PROXIMITY_UNKNOWN; 685 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED); 686 mSensorManager.unregisterListener(mProximitySensorListener); 687 clearPendingProximityDebounceTime(); // release wake lock (must be last) 688 } 689 } 690 } 691 692 private void handleProximitySensorEvent(long time, boolean positive) { 693 if (mProximitySensorEnabled) { 694 if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) { 695 return; // no change 696 } 697 if (mPendingProximity == PROXIMITY_POSITIVE && positive) { 698 return; // no change 699 } 700 701 // Only accept a proximity sensor reading if it remains 702 // stable for the entire debounce delay. We hold a wake lock while 703 // debouncing the sensor. 704 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED); 705 if (positive) { 706 mPendingProximity = PROXIMITY_POSITIVE; 707 setPendingProximityDebounceTime( 708 time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock 709 } else { 710 mPendingProximity = PROXIMITY_NEGATIVE; 711 setPendingProximityDebounceTime( 712 time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock 713 } 714 715 // Debounce the new sensor reading. 716 debounceProximitySensor(); 717 } 718 } 719 720 private void debounceProximitySensor() { 721 if (mProximitySensorEnabled 722 && mPendingProximity != PROXIMITY_UNKNOWN 723 && mPendingProximityDebounceTime >= 0) { 724 final long now = SystemClock.uptimeMillis(); 725 if (mPendingProximityDebounceTime <= now) { 726 // Sensor reading accepted. Apply the change then release the wake lock. 727 mProximity = mPendingProximity; 728 updatePowerState(); 729 clearPendingProximityDebounceTime(); // release wake lock (must be last) 730 } else { 731 // Need to wait a little longer. 732 // Debounce again later. We continue holding a wake lock while waiting. 733 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED); 734 msg.setAsynchronous(true); 735 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime); 736 } 737 } 738 } 739 740 private void clearPendingProximityDebounceTime() { 741 if (mPendingProximityDebounceTime >= 0) { 742 mPendingProximityDebounceTime = -1; 743 mCallbacks.releaseSuspendBlocker(); // release wake lock 744 } 745 } 746 747 private void setPendingProximityDebounceTime(long debounceTime) { 748 if (mPendingProximityDebounceTime < 0) { 749 mCallbacks.acquireSuspendBlocker(); // acquire wake lock 750 } 751 mPendingProximityDebounceTime = debounceTime; 752 } 753 754 private void sendOnStateChangedWithWakelock() { 755 mCallbacks.acquireSuspendBlocker(); 756 mHandler.post(mOnStateChangedRunnable); 757 } 758 759 private final Runnable mOnStateChangedRunnable = new Runnable() { 760 @Override 761 public void run() { 762 mCallbacks.onStateChanged(); 763 mCallbacks.releaseSuspendBlocker(); 764 } 765 }; 766 767 private void sendOnProximityPositiveWithWakelock() { 768 mCallbacks.acquireSuspendBlocker(); 769 mHandler.post(mOnProximityPositiveRunnable); 770 } 771 772 private final Runnable mOnProximityPositiveRunnable = new Runnable() { 773 @Override 774 public void run() { 775 mCallbacks.onProximityPositive(); 776 mCallbacks.releaseSuspendBlocker(); 777 } 778 }; 779 780 private void sendOnProximityNegativeWithWakelock() { 781 mCallbacks.acquireSuspendBlocker(); 782 mHandler.post(mOnProximityNegativeRunnable); 783 } 784 785 private final Runnable mOnProximityNegativeRunnable = new Runnable() { 786 @Override 787 public void run() { 788 mCallbacks.onProximityNegative(); 789 mCallbacks.releaseSuspendBlocker(); 790 } 791 }; 792 793 public void dump(final PrintWriter pw) { 794 synchronized (mLock) { 795 pw.println(); 796 pw.println("Display Power Controller Locked State:"); 797 pw.println(" mDisplayReadyLocked=" + mDisplayReadyLocked); 798 pw.println(" mPendingRequestLocked=" + mPendingRequestLocked); 799 pw.println(" mPendingRequestChangedLocked=" + mPendingRequestChangedLocked); 800 pw.println(" mPendingWaitForNegativeProximityLocked=" 801 + mPendingWaitForNegativeProximityLocked); 802 pw.println(" mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked); 803 } 804 805 pw.println(); 806 pw.println("Display Power Controller Configuration:"); 807 pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig); 808 pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig); 809 pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum); 810 pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum); 811 pw.println(" mUseSoftwareAutoBrightnessConfig=" 812 + mUseSoftwareAutoBrightnessConfig); 813 814 mHandler.runWithScissors(new Runnable() { 815 @Override 816 public void run() { 817 dumpLocal(pw); 818 } 819 }, 1000); 820 } 821 822 private void dumpLocal(PrintWriter pw) { 823 pw.println(); 824 pw.println("Display Power Controller Thread State:"); 825 pw.println(" mPowerRequest=" + mPowerRequest); 826 pw.println(" mWaitingForNegativeProximity=" + mWaitingForNegativeProximity); 827 828 pw.println(" mProximitySensor=" + mProximitySensor); 829 pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled); 830 pw.println(" mProximityThreshold=" + mProximityThreshold); 831 pw.println(" mProximity=" + proximityToString(mProximity)); 832 pw.println(" mPendingProximity=" + proximityToString(mPendingProximity)); 833 pw.println(" mPendingProximityDebounceTime=" 834 + TimeUtils.formatUptime(mPendingProximityDebounceTime)); 835 pw.println(" mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity); 836 pw.println(" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness); 837 838 if (mElectronBeamOnAnimator != null) { 839 pw.println(" mElectronBeamOnAnimator.isStarted()=" + 840 mElectronBeamOnAnimator.isStarted()); 841 } 842 if (mElectronBeamOffAnimator != null) { 843 pw.println(" mElectronBeamOffAnimator.isStarted()=" + 844 mElectronBeamOffAnimator.isStarted()); 845 } 846 847 if (mPowerState != null) { 848 mPowerState.dump(pw); 849 } 850 851 if (mAutomaticBrightnessController != null) { 852 mAutomaticBrightnessController.dump(pw); 853 } 854 855 } 856 857 private static String proximityToString(int state) { 858 switch (state) { 859 case PROXIMITY_UNKNOWN: 860 return "Unknown"; 861 case PROXIMITY_NEGATIVE: 862 return "Negative"; 863 case PROXIMITY_POSITIVE: 864 return "Positive"; 865 default: 866 return Integer.toString(state); 867 } 868 } 869 870 private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) { 871 try { 872 final int n = brightness.length; 873 float[] x = new float[n]; 874 float[] y = new float[n]; 875 y[0] = normalizeAbsoluteBrightness(brightness[0]); 876 for (int i = 1; i < n; i++) { 877 x[i] = lux[i - 1]; 878 y[i] = normalizeAbsoluteBrightness(brightness[i]); 879 } 880 881 Spline spline = Spline.createMonotoneCubicSpline(x, y); 882 if (DEBUG) { 883 Slog.d(TAG, "Auto-brightness spline: " + spline); 884 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) { 885 Slog.d(TAG, String.format(" %7.1f: %7.1f", v, spline.interpolate(v))); 886 } 887 } 888 return spline; 889 } catch (IllegalArgumentException ex) { 890 Slog.e(TAG, "Could not create auto-brightness spline.", ex); 891 return null; 892 } 893 } 894 895 private static float normalizeAbsoluteBrightness(int value) { 896 return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON; 897 } 898 899 private static int clampAbsoluteBrightness(int value) { 900 return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON); 901 } 902 903 private final class DisplayControllerHandler extends Handler { 904 public DisplayControllerHandler(Looper looper) { 905 super(looper, null, true /*async*/); 906 } 907 908 @Override 909 public void handleMessage(Message msg) { 910 switch (msg.what) { 911 case MSG_UPDATE_POWER_STATE: 912 updatePowerState(); 913 break; 914 915 case MSG_PROXIMITY_SENSOR_DEBOUNCED: 916 debounceProximitySensor(); 917 break; 918 } 919 } 920 } 921 922 private final SensorEventListener mProximitySensorListener = new SensorEventListener() { 923 @Override 924 public void onSensorChanged(SensorEvent event) { 925 if (mProximitySensorEnabled) { 926 final long time = SystemClock.uptimeMillis(); 927 final float distance = event.values[0]; 928 boolean positive = distance >= 0.0f && distance < mProximityThreshold; 929 handleProximitySensorEvent(time, positive); 930 } 931 } 932 933 @Override 934 public void onAccuracyChanged(Sensor sensor, int accuracy) { 935 // Not used. 936 } 937 }; 938} 939