DisplayPowerController.java revision 6da87ab684f104baa836138ca5153eb2d6c1f929
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 boolean autoBrightnessAdjustmentChanged = false; 425 426 synchronized (mLock) { 427 mPendingUpdatePowerStateLocked = false; 428 if (mPendingRequestLocked == null) { 429 return; // wait until first actual power request 430 } 431 432 if (mPowerRequest == null) { 433 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked); 434 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked; 435 mPendingWaitForNegativeProximityLocked = false; 436 mPendingRequestChangedLocked = false; 437 mustInitialize = true; 438 } else if (mPendingRequestChangedLocked) { 439 wasDimOrDoze = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM 440 || mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE); 441 autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment 442 != mPendingRequestLocked.screenAutoBrightnessAdjustment); 443 mPowerRequest.copyFrom(mPendingRequestLocked); 444 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked; 445 mPendingWaitForNegativeProximityLocked = false; 446 mPendingRequestChangedLocked = false; 447 mDisplayReadyLocked = false; 448 } 449 450 mustNotify = !mDisplayReadyLocked; 451 } 452 453 // Initialize things the first time the power state is changed. 454 if (mustInitialize) { 455 initialize(); 456 } 457 458 // Apply the proximity sensor. 459 if (mProximitySensor != null) { 460 if (mPowerRequest.useProximitySensor 461 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { 462 setProximitySensorEnabled(true); 463 if (!mScreenOffBecauseOfProximity 464 && mProximity == PROXIMITY_POSITIVE) { 465 mScreenOffBecauseOfProximity = true; 466 sendOnProximityPositiveWithWakelock(); 467 } 468 } else if (mWaitingForNegativeProximity 469 && mScreenOffBecauseOfProximity 470 && mProximity == PROXIMITY_POSITIVE 471 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { 472 setProximitySensorEnabled(true); 473 } else { 474 setProximitySensorEnabled(false); 475 mWaitingForNegativeProximity = false; 476 } 477 if (mScreenOffBecauseOfProximity 478 && mProximity != PROXIMITY_POSITIVE) { 479 mScreenOffBecauseOfProximity = false; 480 sendOnProximityNegativeWithWakelock(); 481 } 482 } else { 483 mWaitingForNegativeProximity = false; 484 } 485 486 // Turn on the light sensor if needed. 487 if (mAutomaticBrightnessController != null) { 488 mAutomaticBrightnessController.updatePowerState(mPowerRequest); 489 } 490 491 // Set the screen brightness. 492 if (mPowerRequest.wantScreenOnAny()) { 493 int target; 494 boolean slow; 495 int screenAutoBrightness = mAutomaticBrightnessController != null ? 496 mAutomaticBrightnessController.getAutomaticScreenBrightness() : -1; 497 if (screenAutoBrightness >= 0 && mPowerRequest.useAutoBrightness) { 498 // Use current auto-brightness value. 499 target = screenAutoBrightness; 500 slow = mUsingScreenAutoBrightness && !autoBrightnessAdjustmentChanged; 501 mUsingScreenAutoBrightness = true; 502 } else { 503 // Light sensor is disabled or not ready yet. 504 // Use the current brightness setting from the request, which is expected 505 // provide a nominal default value for the case where auto-brightness 506 // is not ready yet. 507 target = mPowerRequest.screenBrightness; 508 slow = false; 509 mUsingScreenAutoBrightness = false; 510 } 511 if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE) { 512 // Dim quickly to the doze state. 513 target = mScreenBrightnessDozeConfig; 514 slow = false; 515 } else if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) { 516 // Dim quickly by at least some minimum amount. 517 target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION, 518 mScreenBrightnessDimConfig); 519 slow = false; 520 } else if (wasDimOrDoze) { 521 // Brighten quickly. 522 slow = false; 523 } 524 // If low power mode is enabled, brightness level 525 // would be scaled down to half 526 if (mPowerRequest.lowPowerMode) { 527 target = target/2; 528 } 529 animateScreenBrightness(clampScreenBrightness(target), 530 slow ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST); 531 } else { 532 // Screen is off. Don't bother changing the brightness. 533 mUsingScreenAutoBrightness = false; 534 } 535 536 // Animate the screen on or off unless blocked. 537 if (mScreenOffBecauseOfProximity) { 538 // Screen off due to proximity. 539 setScreenState(Display.STATE_OFF); 540 unblockScreenOn(); 541 } else if (mPowerRequest.wantScreenOnAny()) { 542 // Want screen on. 543 // Wait for previous off animation to complete beforehand. 544 // It is relatively short but if we cancel it and switch to the 545 // on animation immediately then the results are pretty ugly. 546 if (!mElectronBeamOffAnimator.isStarted()) { 547 // Turn the screen on. The contents of the screen may not yet 548 // be visible if the electron beam has not been dismissed because 549 // its last frame of animation is solid black. 550 setScreenState(mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE 551 ? Display.STATE_DOZING : Display.STATE_ON); 552 553 if (mPowerRequest.blockScreenOn 554 && mPowerState.getElectronBeamLevel() == 0.0f) { 555 blockScreenOn(); 556 } else { 557 unblockScreenOn(); 558 if (USE_ELECTRON_BEAM_ON_ANIMATION) { 559 if (!mElectronBeamOnAnimator.isStarted()) { 560 if (mPowerState.getElectronBeamLevel() == 1.0f) { 561 mPowerState.dismissElectronBeam(); 562 } else if (mPowerState.prepareElectronBeam( 563 mElectronBeamFadesConfig ? 564 ElectronBeam.MODE_FADE : 565 ElectronBeam.MODE_WARM_UP)) { 566 mElectronBeamOnAnimator.start(); 567 } else { 568 mElectronBeamOnAnimator.end(); 569 } 570 } 571 } else { 572 mPowerState.setElectronBeamLevel(1.0f); 573 mPowerState.dismissElectronBeam(); 574 } 575 } 576 } 577 } else { 578 // Want screen off. 579 // Wait for previous on animation to complete beforehand. 580 unblockScreenOn(); 581 if (!mElectronBeamOnAnimator.isStarted()) { 582 if (!mElectronBeamOffAnimator.isStarted()) { 583 if (mPowerState.getElectronBeamLevel() == 0.0f) { 584 setScreenState(Display.STATE_OFF); 585 } else if (mPowerState.prepareElectronBeam( 586 mElectronBeamFadesConfig ? 587 ElectronBeam.MODE_FADE : 588 ElectronBeam.MODE_COOL_DOWN) 589 && mPowerState.getScreenState() != Display.STATE_OFF) { 590 mElectronBeamOffAnimator.start(); 591 } else { 592 mElectronBeamOffAnimator.end(); 593 } 594 } 595 } 596 } 597 598 // Report whether the display is ready for use. 599 // We mostly care about the screen state here, ignoring brightness changes 600 // which will be handled asynchronously. 601 if (mustNotify 602 && !mScreenOnWasBlocked 603 && !mElectronBeamOnAnimator.isStarted() 604 && !mElectronBeamOffAnimator.isStarted() 605 && mPowerState.waitUntilClean(mCleanListener)) { 606 synchronized (mLock) { 607 if (!mPendingRequestChangedLocked) { 608 mDisplayReadyLocked = true; 609 610 if (DEBUG) { 611 Slog.d(TAG, "Display ready!"); 612 } 613 } 614 } 615 sendOnStateChangedWithWakelock(); 616 } 617 } 618 619 @Override 620 public void updateBrightness() { 621 sendUpdatePowerState(); 622 } 623 624 private void blockScreenOn() { 625 if (!mScreenOnWasBlocked) { 626 mScreenOnWasBlocked = true; 627 mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime(); 628 if (DEBUG) { 629 Slog.d(TAG, "Blocked screen on."); 630 } 631 } 632 } 633 634 private void unblockScreenOn() { 635 if (mScreenOnWasBlocked) { 636 mScreenOnWasBlocked = false; 637 long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime; 638 if (delay > 1000 || DEBUG) { 639 Slog.d(TAG, "Unblocked screen on after " + delay + " ms"); 640 } 641 } 642 } 643 644 private void setScreenState(int state) { 645 if (mPowerState.getScreenState() != state) { 646 mPowerState.setScreenState(state); 647 try { 648 mBatteryStats.noteScreenState(state); 649 } catch (RemoteException ex) { 650 // same process 651 } 652 } 653 } 654 655 private int clampScreenBrightness(int value) { 656 return MathUtils.constrain( 657 value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum); 658 } 659 660 private void animateScreenBrightness(int target, int rate) { 661 if (mScreenBrightnessRampAnimator.animateTo(target, rate)) { 662 try { 663 mBatteryStats.noteScreenBrightness(target); 664 } catch (RemoteException ex) { 665 // same process 666 } 667 } 668 } 669 670 private final Runnable mCleanListener = new Runnable() { 671 @Override 672 public void run() { 673 sendUpdatePowerState(); 674 } 675 }; 676 677 private void setProximitySensorEnabled(boolean enable) { 678 if (enable) { 679 if (!mProximitySensorEnabled) { 680 // Register the listener. 681 // Proximity sensor state already cleared initially. 682 mProximitySensorEnabled = true; 683 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor, 684 SensorManager.SENSOR_DELAY_NORMAL, mHandler); 685 } 686 } else { 687 if (mProximitySensorEnabled) { 688 // Unregister the listener. 689 // Clear the proximity sensor state for next time. 690 mProximitySensorEnabled = false; 691 mProximity = PROXIMITY_UNKNOWN; 692 mPendingProximity = PROXIMITY_UNKNOWN; 693 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED); 694 mSensorManager.unregisterListener(mProximitySensorListener); 695 clearPendingProximityDebounceTime(); // release wake lock (must be last) 696 } 697 } 698 } 699 700 private void handleProximitySensorEvent(long time, boolean positive) { 701 if (mProximitySensorEnabled) { 702 if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) { 703 return; // no change 704 } 705 if (mPendingProximity == PROXIMITY_POSITIVE && positive) { 706 return; // no change 707 } 708 709 // Only accept a proximity sensor reading if it remains 710 // stable for the entire debounce delay. We hold a wake lock while 711 // debouncing the sensor. 712 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED); 713 if (positive) { 714 mPendingProximity = PROXIMITY_POSITIVE; 715 setPendingProximityDebounceTime( 716 time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock 717 } else { 718 mPendingProximity = PROXIMITY_NEGATIVE; 719 setPendingProximityDebounceTime( 720 time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock 721 } 722 723 // Debounce the new sensor reading. 724 debounceProximitySensor(); 725 } 726 } 727 728 private void debounceProximitySensor() { 729 if (mProximitySensorEnabled 730 && mPendingProximity != PROXIMITY_UNKNOWN 731 && mPendingProximityDebounceTime >= 0) { 732 final long now = SystemClock.uptimeMillis(); 733 if (mPendingProximityDebounceTime <= now) { 734 // Sensor reading accepted. Apply the change then release the wake lock. 735 mProximity = mPendingProximity; 736 updatePowerState(); 737 clearPendingProximityDebounceTime(); // release wake lock (must be last) 738 } else { 739 // Need to wait a little longer. 740 // Debounce again later. We continue holding a wake lock while waiting. 741 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED); 742 msg.setAsynchronous(true); 743 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime); 744 } 745 } 746 } 747 748 private void clearPendingProximityDebounceTime() { 749 if (mPendingProximityDebounceTime >= 0) { 750 mPendingProximityDebounceTime = -1; 751 mCallbacks.releaseSuspendBlocker(); // release wake lock 752 } 753 } 754 755 private void setPendingProximityDebounceTime(long debounceTime) { 756 if (mPendingProximityDebounceTime < 0) { 757 mCallbacks.acquireSuspendBlocker(); // acquire wake lock 758 } 759 mPendingProximityDebounceTime = debounceTime; 760 } 761 762 private void sendOnStateChangedWithWakelock() { 763 mCallbacks.acquireSuspendBlocker(); 764 mHandler.post(mOnStateChangedRunnable); 765 } 766 767 private final Runnable mOnStateChangedRunnable = new Runnable() { 768 @Override 769 public void run() { 770 mCallbacks.onStateChanged(); 771 mCallbacks.releaseSuspendBlocker(); 772 } 773 }; 774 775 private void sendOnProximityPositiveWithWakelock() { 776 mCallbacks.acquireSuspendBlocker(); 777 mHandler.post(mOnProximityPositiveRunnable); 778 } 779 780 private final Runnable mOnProximityPositiveRunnable = new Runnable() { 781 @Override 782 public void run() { 783 mCallbacks.onProximityPositive(); 784 mCallbacks.releaseSuspendBlocker(); 785 } 786 }; 787 788 private void sendOnProximityNegativeWithWakelock() { 789 mCallbacks.acquireSuspendBlocker(); 790 mHandler.post(mOnProximityNegativeRunnable); 791 } 792 793 private final Runnable mOnProximityNegativeRunnable = new Runnable() { 794 @Override 795 public void run() { 796 mCallbacks.onProximityNegative(); 797 mCallbacks.releaseSuspendBlocker(); 798 } 799 }; 800 801 public void dump(final PrintWriter pw) { 802 synchronized (mLock) { 803 pw.println(); 804 pw.println("Display Power Controller Locked State:"); 805 pw.println(" mDisplayReadyLocked=" + mDisplayReadyLocked); 806 pw.println(" mPendingRequestLocked=" + mPendingRequestLocked); 807 pw.println(" mPendingRequestChangedLocked=" + mPendingRequestChangedLocked); 808 pw.println(" mPendingWaitForNegativeProximityLocked=" 809 + mPendingWaitForNegativeProximityLocked); 810 pw.println(" mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked); 811 } 812 813 pw.println(); 814 pw.println("Display Power Controller Configuration:"); 815 pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig); 816 pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig); 817 pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum); 818 pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum); 819 pw.println(" mUseSoftwareAutoBrightnessConfig=" 820 + mUseSoftwareAutoBrightnessConfig); 821 822 mHandler.runWithScissors(new Runnable() { 823 @Override 824 public void run() { 825 dumpLocal(pw); 826 } 827 }, 1000); 828 } 829 830 private void dumpLocal(PrintWriter pw) { 831 pw.println(); 832 pw.println("Display Power Controller Thread State:"); 833 pw.println(" mPowerRequest=" + mPowerRequest); 834 pw.println(" mWaitingForNegativeProximity=" + mWaitingForNegativeProximity); 835 836 pw.println(" mProximitySensor=" + mProximitySensor); 837 pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled); 838 pw.println(" mProximityThreshold=" + mProximityThreshold); 839 pw.println(" mProximity=" + proximityToString(mProximity)); 840 pw.println(" mPendingProximity=" + proximityToString(mPendingProximity)); 841 pw.println(" mPendingProximityDebounceTime=" 842 + TimeUtils.formatUptime(mPendingProximityDebounceTime)); 843 pw.println(" mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity); 844 pw.println(" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness); 845 846 if (mElectronBeamOnAnimator != null) { 847 pw.println(" mElectronBeamOnAnimator.isStarted()=" + 848 mElectronBeamOnAnimator.isStarted()); 849 } 850 if (mElectronBeamOffAnimator != null) { 851 pw.println(" mElectronBeamOffAnimator.isStarted()=" + 852 mElectronBeamOffAnimator.isStarted()); 853 } 854 855 if (mPowerState != null) { 856 mPowerState.dump(pw); 857 } 858 859 if (mAutomaticBrightnessController != null) { 860 mAutomaticBrightnessController.dump(pw); 861 } 862 863 } 864 865 private static String proximityToString(int state) { 866 switch (state) { 867 case PROXIMITY_UNKNOWN: 868 return "Unknown"; 869 case PROXIMITY_NEGATIVE: 870 return "Negative"; 871 case PROXIMITY_POSITIVE: 872 return "Positive"; 873 default: 874 return Integer.toString(state); 875 } 876 } 877 878 private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) { 879 try { 880 final int n = brightness.length; 881 float[] x = new float[n]; 882 float[] y = new float[n]; 883 y[0] = normalizeAbsoluteBrightness(brightness[0]); 884 for (int i = 1; i < n; i++) { 885 x[i] = lux[i - 1]; 886 y[i] = normalizeAbsoluteBrightness(brightness[i]); 887 } 888 889 Spline spline = Spline.createMonotoneCubicSpline(x, y); 890 if (DEBUG) { 891 Slog.d(TAG, "Auto-brightness spline: " + spline); 892 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) { 893 Slog.d(TAG, String.format(" %7.1f: %7.1f", v, spline.interpolate(v))); 894 } 895 } 896 return spline; 897 } catch (IllegalArgumentException ex) { 898 Slog.e(TAG, "Could not create auto-brightness spline.", ex); 899 return null; 900 } 901 } 902 903 private static float normalizeAbsoluteBrightness(int value) { 904 return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON; 905 } 906 907 private static int clampAbsoluteBrightness(int value) { 908 return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON); 909 } 910 911 private final class DisplayControllerHandler extends Handler { 912 public DisplayControllerHandler(Looper looper) { 913 super(looper, null, true /*async*/); 914 } 915 916 @Override 917 public void handleMessage(Message msg) { 918 switch (msg.what) { 919 case MSG_UPDATE_POWER_STATE: 920 updatePowerState(); 921 break; 922 923 case MSG_PROXIMITY_SENSOR_DEBOUNCED: 924 debounceProximitySensor(); 925 break; 926 } 927 } 928 } 929 930 private final SensorEventListener mProximitySensorListener = new SensorEventListener() { 931 @Override 932 public void onSensorChanged(SensorEvent event) { 933 if (mProximitySensorEnabled) { 934 final long time = SystemClock.uptimeMillis(); 935 final float distance = event.values[0]; 936 boolean positive = distance >= 0.0f && distance < mProximityThreshold; 937 handleProximitySensorEvent(time, positive); 938 } 939 } 940 941 @Override 942 public void onAccuracyChanged(Sensor sensor, int accuracy) { 943 // Not used. 944 } 945 }; 946} 947