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