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