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 17 package com.android.server.power; 18 19 import com.android.server.LightsService; 20 import com.android.server.TwilightService; 21 import com.android.server.TwilightService.TwilightState; 22 import com.android.server.display.DisplayManagerService; 23 24 import android.animation.Animator; 25 import android.animation.ObjectAnimator; 26 import android.content.Context; 27 import android.content.res.Resources; 28 import android.hardware.Sensor; 29 import android.hardware.SensorEvent; 30 import android.hardware.SensorEventListener; 31 import android.hardware.SensorManager; 32 import android.os.Handler; 33 import android.os.Looper; 34 import android.os.Message; 35 import android.os.PowerManager; 36 import android.os.SystemClock; 37 import android.text.format.DateUtils; 38 import android.util.FloatMath; 39 import android.util.Slog; 40 import android.util.Spline; 41 import android.util.TimeUtils; 42 43 import java.io.PrintWriter; 44 45 /** 46 * Controls the power state of the display. 47 * 48 * Handles the proximity sensor, light sensor, and animations between states 49 * including the screen off animation. 50 * 51 * This component acts independently of the rest of the power manager service. 52 * In particular, it does not share any state and it only communicates 53 * via asynchronous callbacks to inform the power manager that something has 54 * changed. 55 * 56 * Everything this class does internally is serialized on its handler although 57 * it may be accessed by other threads from the outside. 58 * 59 * Note that the power manager service guarantees that it will hold a suspend 60 * blocker as long as the display is not ready. So most of the work done here 61 * does not need to worry about holding a suspend blocker unless it happens 62 * independently of the display ready signal. 63 * 64 * For debugging, you can make the electron beam and brightness animations run 65 * slower by changing the "animator duration scale" option in Development Settings. 66 */ 67 final class DisplayPowerController { 68 private static final String TAG = "DisplayPowerController"; 69 70 private static boolean DEBUG = false; 71 private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false; 72 private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false; 73 74 // If true, uses the electron beam on animation. 75 // We might want to turn this off if we cannot get a guarantee that the screen 76 // actually turns on and starts showing new content after the call to set the 77 // screen state returns. Playing the animation can also be somewhat slow. 78 private static final boolean USE_ELECTRON_BEAM_ON_ANIMATION = false; 79 80 // If true, enables the use of the screen auto-brightness adjustment setting. 81 private static final boolean USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT = 82 PowerManager.useScreenAutoBrightnessAdjustmentFeature(); 83 84 // The maximum range of gamma adjustment possible using the screen 85 // auto-brightness adjustment setting. 86 private static final float SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA = 3.0f; 87 88 // The minimum reduction in brightness when dimmed. 89 private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10; 90 91 // If true, enables the use of the current time as an auto-brightness adjustment. 92 // The basic idea here is to expand the dynamic range of auto-brightness 93 // when it is especially dark outside. The light sensor tends to perform 94 // poorly at low light levels so we compensate for it by making an 95 // assumption about the environment. 96 private static final boolean USE_TWILIGHT_ADJUSTMENT = 97 PowerManager.useTwilightAdjustmentFeature(); 98 99 // Specifies the maximum magnitude of the time of day adjustment. 100 private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1.5f; 101 102 // The amount of time after or before sunrise over which to start adjusting 103 // the gamma. We want the change to happen gradually so that it is below the 104 // threshold of perceptibility and so that the adjustment has maximum effect 105 // well after dusk. 106 private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2; 107 108 private static final int ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS = 250; 109 private static final int ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS = 400; 110 111 private static final int MSG_UPDATE_POWER_STATE = 1; 112 private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2; 113 private static final int MSG_LIGHT_SENSOR_DEBOUNCED = 3; 114 115 private static final int PROXIMITY_UNKNOWN = -1; 116 private static final int PROXIMITY_NEGATIVE = 0; 117 private static final int PROXIMITY_POSITIVE = 1; 118 119 // Proximity sensor debounce delay in milliseconds for positive or negative transitions. 120 private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0; 121 private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 250; 122 123 // Trigger proximity if distance is less than 5 cm. 124 private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f; 125 126 // Light sensor event rate in milliseconds. 127 private static final int LIGHT_SENSOR_RATE_MILLIS = 1000; 128 129 // A rate for generating synthetic light sensor events in the case where the light 130 // sensor hasn't reported any new data in a while and we need it to update the 131 // debounce filter. We only synthesize light sensor measurements when needed. 132 private static final int SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS = 133 LIGHT_SENSOR_RATE_MILLIS * 2; 134 135 // Brightness animation ramp rate in brightness units per second. 136 private static final int BRIGHTNESS_RAMP_RATE_FAST = 200; 137 private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40; 138 139 // IIR filter time constants in milliseconds for computing two moving averages of 140 // the light samples. One is a long-term average and the other is a short-term average. 141 // We can use these filters to assess trends in ambient brightness. 142 // The short term average gives us a filtered but relatively low latency measurement. 143 // The long term average informs us about the overall trend. 144 private static final long SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 1000; 145 private static final long LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 5000; 146 147 // Stability requirements in milliseconds for accepting a new brightness 148 // level. This is used for debouncing the light sensor. Different constants 149 // are used to debounce the light sensor when adapting to brighter or darker environments. 150 // This parameter controls how quickly brightness changes occur in response to 151 // an observed change in light level that exceeds the hysteresis threshold. 152 private static final long BRIGHTENING_LIGHT_DEBOUNCE = 4000; 153 private static final long DARKENING_LIGHT_DEBOUNCE = 8000; 154 155 // Hysteresis constraints for brightening or darkening. 156 // The recent lux must have changed by at least this fraction relative to the 157 // current ambient lux before a change will be considered. 158 private static final float BRIGHTENING_LIGHT_HYSTERESIS = 0.10f; 159 private static final float DARKENING_LIGHT_HYSTERESIS = 0.20f; 160 161 private final Object mLock = new Object(); 162 163 // Notifier for sending asynchronous notifications. 164 private final Notifier mNotifier; 165 166 // The display suspend blocker. 167 // Held while there are pending state change notifications. 168 private final SuspendBlocker mDisplaySuspendBlocker; 169 170 // The display blanker. 171 private final DisplayBlanker mDisplayBlanker; 172 173 // Our handler. 174 private final DisplayControllerHandler mHandler; 175 176 // Asynchronous callbacks into the power manager service. 177 // Only invoked from the handler thread while no locks are held. 178 private final Callbacks mCallbacks; 179 private Handler mCallbackHandler; 180 181 // The lights service. 182 private final LightsService mLights; 183 184 // The twilight service. 185 private final TwilightService mTwilight; 186 187 // The display manager. 188 private final DisplayManagerService mDisplayManager; 189 190 // The sensor manager. 191 private final SensorManager mSensorManager; 192 193 // The proximity sensor, or null if not available or needed. 194 private Sensor mProximitySensor; 195 196 // The light sensor, or null if not available or needed. 197 private Sensor mLightSensor; 198 199 // The dim screen brightness. 200 private final int mScreenBrightnessDimConfig; 201 202 // The minimum allowed brightness. 203 private final int mScreenBrightnessRangeMinimum; 204 205 // The maximum allowed brightness. 206 private final int mScreenBrightnessRangeMaximum; 207 208 // True if auto-brightness should be used. 209 private boolean mUseSoftwareAutoBrightnessConfig; 210 211 // The auto-brightness spline adjustment. 212 // The brightness values have been scaled to a range of 0..1. 213 private Spline mScreenAutoBrightnessSpline; 214 215 // Amount of time to delay auto-brightness after screen on while waiting for 216 // the light sensor to warm-up in milliseconds. 217 // May be 0 if no warm-up is required. 218 private int mLightSensorWarmUpTimeConfig; 219 220 // True if we should fade the screen while turning it off, false if we should play 221 // a stylish electron beam animation instead. 222 private boolean mElectronBeamFadesConfig; 223 224 // The pending power request. 225 // Initially null until the first call to requestPowerState. 226 // Guarded by mLock. 227 private DisplayPowerRequest mPendingRequestLocked; 228 229 // True if a request has been made to wait for the proximity sensor to go negative. 230 // Guarded by mLock. 231 private boolean mPendingWaitForNegativeProximityLocked; 232 233 // True if the pending power request or wait for negative proximity flag 234 // has been changed since the last update occurred. 235 // Guarded by mLock. 236 private boolean mPendingRequestChangedLocked; 237 238 // Set to true when the important parts of the pending power request have been applied. 239 // The important parts are mainly the screen state. Brightness changes may occur 240 // concurrently. 241 // Guarded by mLock. 242 private boolean mDisplayReadyLocked; 243 244 // Set to true if a power state update is required. 245 // Guarded by mLock. 246 private boolean mPendingUpdatePowerStateLocked; 247 248 /* The following state must only be accessed by the handler thread. */ 249 250 // The currently requested power state. 251 // The power controller will progressively update its internal state to match 252 // the requested power state. Initially null until the first update. 253 private DisplayPowerRequest mPowerRequest; 254 255 // The current power state. 256 // Must only be accessed on the handler thread. 257 private DisplayPowerState mPowerState; 258 259 // True if the device should wait for negative proximity sensor before 260 // waking up the screen. This is set to false as soon as a negative 261 // proximity sensor measurement is observed or when the device is forced to 262 // go to sleep by the user. While true, the screen remains off. 263 private boolean mWaitingForNegativeProximity; 264 265 // The actual proximity sensor threshold value. 266 private float mProximityThreshold; 267 268 // Set to true if the proximity sensor listener has been registered 269 // with the sensor manager. 270 private boolean mProximitySensorEnabled; 271 272 // The debounced proximity sensor state. 273 private int mProximity = PROXIMITY_UNKNOWN; 274 275 // The raw non-debounced proximity sensor state. 276 private int mPendingProximity = PROXIMITY_UNKNOWN; 277 private long mPendingProximityDebounceTime = -1; // -1 if fully debounced 278 279 // True if the screen was turned off because of the proximity sensor. 280 // When the screen turns on again, we report user activity to the power manager. 281 private boolean mScreenOffBecauseOfProximity; 282 283 // True if the screen on is being blocked. 284 private boolean mScreenOnWasBlocked; 285 286 // The elapsed real time when the screen on was blocked. 287 private long mScreenOnBlockStartRealTime; 288 289 // Set to true if the light sensor is enabled. 290 private boolean mLightSensorEnabled; 291 292 // The time when the light sensor was enabled. 293 private long mLightSensorEnableTime; 294 295 // The currently accepted nominal ambient light level. 296 private float mAmbientLux; 297 298 // True if mAmbientLux holds a valid value. 299 private boolean mAmbientLuxValid; 300 301 // The ambient light level threshold at which to brighten or darken the screen. 302 private float mBrighteningLuxThreshold; 303 private float mDarkeningLuxThreshold; 304 305 // The most recent light sample. 306 private float mLastObservedLux; 307 308 // The time of the most light recent sample. 309 private long mLastObservedLuxTime; 310 311 // The number of light samples collected since the light sensor was enabled. 312 private int mRecentLightSamples; 313 314 // The long-term and short-term filtered light measurements. 315 private float mRecentShortTermAverageLux; 316 private float mRecentLongTermAverageLux; 317 318 // The direction in which the average lux is moving relative to the current ambient lux. 319 // 0 if not changing or within hysteresis threshold. 320 // 1 if brightening beyond hysteresis threshold. 321 // -1 if darkening beyond hysteresis threshold. 322 private int mDebounceLuxDirection; 323 324 // The time when the average lux last changed direction. 325 private long mDebounceLuxTime; 326 327 // The screen brightness level that has been chosen by the auto-brightness 328 // algorithm. The actual brightness should ramp towards this value. 329 // We preserve this value even when we stop using the light sensor so 330 // that we can quickly revert to the previous auto-brightness level 331 // while the light sensor warms up. 332 // Use -1 if there is no current auto-brightness value available. 333 private int mScreenAutoBrightness = -1; 334 335 // The last screen auto-brightness gamma. (For printing in dump() only.) 336 private float mLastScreenAutoBrightnessGamma = 1.0f; 337 338 // True if the screen auto-brightness value is actually being used to 339 // set the display brightness. 340 private boolean mUsingScreenAutoBrightness; 341 342 // Animators. 343 private ObjectAnimator mElectronBeamOnAnimator; 344 private ObjectAnimator mElectronBeamOffAnimator; 345 private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator; 346 347 // Twilight changed. We might recalculate auto-brightness values. 348 private boolean mTwilightChanged; 349 350 /** 351 * Creates the display power controller. 352 */ 353 public DisplayPowerController(Looper looper, Context context, Notifier notifier, 354 LightsService lights, TwilightService twilight, SensorManager sensorManager, 355 DisplayManagerService displayManager, 356 SuspendBlocker displaySuspendBlocker, DisplayBlanker displayBlanker, 357 Callbacks callbacks, Handler callbackHandler) { 358 mHandler = new DisplayControllerHandler(looper); 359 mNotifier = notifier; 360 mDisplaySuspendBlocker = displaySuspendBlocker; 361 mDisplayBlanker = displayBlanker; 362 mCallbacks = callbacks; 363 mCallbackHandler = callbackHandler; 364 365 mLights = lights; 366 mTwilight = twilight; 367 mSensorManager = sensorManager; 368 mDisplayManager = displayManager; 369 370 final Resources resources = context.getResources(); 371 372 mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger( 373 com.android.internal.R.integer.config_screenBrightnessDim)); 374 375 int screenBrightnessMinimum = Math.min(resources.getInteger( 376 com.android.internal.R.integer.config_screenBrightnessSettingMinimum), 377 mScreenBrightnessDimConfig); 378 379 mUseSoftwareAutoBrightnessConfig = resources.getBoolean( 380 com.android.internal.R.bool.config_automatic_brightness_available); 381 if (mUseSoftwareAutoBrightnessConfig) { 382 int[] lux = resources.getIntArray( 383 com.android.internal.R.array.config_autoBrightnessLevels); 384 int[] screenBrightness = resources.getIntArray( 385 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues); 386 387 mScreenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness); 388 if (mScreenAutoBrightnessSpline == null) { 389 Slog.e(TAG, "Error in config.xml. config_autoBrightnessLcdBacklightValues " 390 + "(size " + screenBrightness.length + ") " 391 + "must be monotic and have exactly one more entry than " 392 + "config_autoBrightnessLevels (size " + lux.length + ") " 393 + "which must be strictly increasing. " 394 + "Auto-brightness will be disabled."); 395 mUseSoftwareAutoBrightnessConfig = false; 396 } else { 397 if (screenBrightness[0] < screenBrightnessMinimum) { 398 screenBrightnessMinimum = screenBrightness[0]; 399 } 400 } 401 402 mLightSensorWarmUpTimeConfig = resources.getInteger( 403 com.android.internal.R.integer.config_lightSensorWarmupTime); 404 } 405 406 mScreenBrightnessRangeMinimum = clampAbsoluteBrightness(screenBrightnessMinimum); 407 mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON; 408 409 mElectronBeamFadesConfig = resources.getBoolean( 410 com.android.internal.R.bool.config_animateScreenLights); 411 412 if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) { 413 mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); 414 if (mProximitySensor != null) { 415 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(), 416 TYPICAL_PROXIMITY_THRESHOLD); 417 } 418 } 419 420 if (mUseSoftwareAutoBrightnessConfig 421 && !DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) { 422 mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); 423 } 424 425 if (mUseSoftwareAutoBrightnessConfig && USE_TWILIGHT_ADJUSTMENT) { 426 mTwilight.registerListener(mTwilightListener, mHandler); 427 } 428 } 429 430 private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) { 431 try { 432 final int n = brightness.length; 433 float[] x = new float[n]; 434 float[] y = new float[n]; 435 y[0] = normalizeAbsoluteBrightness(brightness[0]); 436 for (int i = 1; i < n; i++) { 437 x[i] = lux[i - 1]; 438 y[i] = normalizeAbsoluteBrightness(brightness[i]); 439 } 440 441 Spline spline = Spline.createMonotoneCubicSpline(x, y); 442 if (DEBUG) { 443 Slog.d(TAG, "Auto-brightness spline: " + spline); 444 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) { 445 Slog.d(TAG, String.format(" %7.1f: %7.1f", v, spline.interpolate(v))); 446 } 447 } 448 return spline; 449 } catch (IllegalArgumentException ex) { 450 Slog.e(TAG, "Could not create auto-brightness spline.", ex); 451 return null; 452 } 453 } 454 455 /** 456 * Returns true if the proximity sensor screen-off function is available. 457 */ 458 public boolean isProximitySensorAvailable() { 459 return mProximitySensor != null; 460 } 461 462 /** 463 * Requests a new power state. 464 * The controller makes a copy of the provided object and then 465 * begins adjusting the power state to match what was requested. 466 * 467 * @param request The requested power state. 468 * @param waitForNegativeProximity If true, issues a request to wait for 469 * negative proximity before turning the screen back on, assuming the screen 470 * was turned off by the proximity sensor. 471 * @return True if display is ready, false if there are important changes that must 472 * be made asynchronously (such as turning the screen on), in which case the caller 473 * should grab a wake lock, watch for {@link Callbacks#onStateChanged()} then try 474 * the request again later until the state converges. 475 */ 476 public boolean requestPowerState(DisplayPowerRequest request, 477 boolean waitForNegativeProximity) { 478 if (DEBUG) { 479 Slog.d(TAG, "requestPowerState: " 480 + request + ", waitForNegativeProximity=" + waitForNegativeProximity); 481 } 482 483 synchronized (mLock) { 484 boolean changed = false; 485 486 if (waitForNegativeProximity 487 && !mPendingWaitForNegativeProximityLocked) { 488 mPendingWaitForNegativeProximityLocked = true; 489 changed = true; 490 } 491 492 if (mPendingRequestLocked == null) { 493 mPendingRequestLocked = new DisplayPowerRequest(request); 494 changed = true; 495 } else if (!mPendingRequestLocked.equals(request)) { 496 mPendingRequestLocked.copyFrom(request); 497 changed = true; 498 } 499 500 if (changed) { 501 mDisplayReadyLocked = false; 502 } 503 504 if (changed && !mPendingRequestChangedLocked) { 505 mPendingRequestChangedLocked = true; 506 sendUpdatePowerStateLocked(); 507 } 508 509 return mDisplayReadyLocked; 510 } 511 } 512 513 private void sendUpdatePowerState() { 514 synchronized (mLock) { 515 sendUpdatePowerStateLocked(); 516 } 517 } 518 519 private void sendUpdatePowerStateLocked() { 520 if (!mPendingUpdatePowerStateLocked) { 521 mPendingUpdatePowerStateLocked = true; 522 Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE); 523 msg.setAsynchronous(true); 524 mHandler.sendMessage(msg); 525 } 526 } 527 528 private void initialize() { 529 mPowerState = new DisplayPowerState( 530 new ElectronBeam(mDisplayManager), mDisplayBlanker, 531 mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT)); 532 533 mElectronBeamOnAnimator = ObjectAnimator.ofFloat( 534 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f); 535 mElectronBeamOnAnimator.setDuration(ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS); 536 mElectronBeamOnAnimator.addListener(mAnimatorListener); 537 538 mElectronBeamOffAnimator = ObjectAnimator.ofFloat( 539 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 1.0f, 0.0f); 540 mElectronBeamOffAnimator.setDuration(ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS); 541 mElectronBeamOffAnimator.addListener(mAnimatorListener); 542 543 mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>( 544 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS); 545 } 546 547 private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() { 548 @Override 549 public void onAnimationStart(Animator animation) { 550 } 551 @Override 552 public void onAnimationEnd(Animator animation) { 553 sendUpdatePowerState(); 554 } 555 @Override 556 public void onAnimationRepeat(Animator animation) { 557 } 558 @Override 559 public void onAnimationCancel(Animator animation) { 560 } 561 }; 562 563 private void updatePowerState() { 564 // Update the power state request. 565 final boolean mustNotify; 566 boolean mustInitialize = false; 567 boolean updateAutoBrightness = mTwilightChanged; 568 boolean wasDim = false; 569 mTwilightChanged = false; 570 571 synchronized (mLock) { 572 mPendingUpdatePowerStateLocked = false; 573 if (mPendingRequestLocked == null) { 574 return; // wait until first actual power request 575 } 576 577 if (mPowerRequest == null) { 578 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked); 579 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked; 580 mPendingWaitForNegativeProximityLocked = false; 581 mPendingRequestChangedLocked = false; 582 mustInitialize = true; 583 } else if (mPendingRequestChangedLocked) { 584 if (mPowerRequest.screenAutoBrightnessAdjustment 585 != mPendingRequestLocked.screenAutoBrightnessAdjustment) { 586 updateAutoBrightness = true; 587 } 588 wasDim = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM); 589 mPowerRequest.copyFrom(mPendingRequestLocked); 590 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked; 591 mPendingWaitForNegativeProximityLocked = false; 592 mPendingRequestChangedLocked = false; 593 mDisplayReadyLocked = false; 594 } 595 596 mustNotify = !mDisplayReadyLocked; 597 } 598 599 // Initialize things the first time the power state is changed. 600 if (mustInitialize) { 601 initialize(); 602 } 603 604 // Apply the proximity sensor. 605 if (mProximitySensor != null) { 606 if (mPowerRequest.useProximitySensor 607 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { 608 setProximitySensorEnabled(true); 609 if (!mScreenOffBecauseOfProximity 610 && mProximity == PROXIMITY_POSITIVE) { 611 mScreenOffBecauseOfProximity = true; 612 sendOnProximityPositiveWithWakelock(); 613 } 614 } else if (mWaitingForNegativeProximity 615 && mScreenOffBecauseOfProximity 616 && mProximity == PROXIMITY_POSITIVE 617 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { 618 setProximitySensorEnabled(true); 619 } else { 620 setProximitySensorEnabled(false); 621 mWaitingForNegativeProximity = false; 622 } 623 if (mScreenOffBecauseOfProximity 624 && mProximity != PROXIMITY_POSITIVE) { 625 mScreenOffBecauseOfProximity = false; 626 sendOnProximityNegativeWithWakelock(); 627 } 628 } else { 629 mWaitingForNegativeProximity = false; 630 } 631 632 // Turn on the light sensor if needed. 633 if (mLightSensor != null) { 634 setLightSensorEnabled(mPowerRequest.useAutoBrightness 635 && wantScreenOn(mPowerRequest.screenState), updateAutoBrightness); 636 } 637 638 // Set the screen brightness. 639 if (wantScreenOn(mPowerRequest.screenState)) { 640 int target; 641 boolean slow; 642 if (mScreenAutoBrightness >= 0 && mLightSensorEnabled) { 643 // Use current auto-brightness value. 644 target = mScreenAutoBrightness; 645 slow = mUsingScreenAutoBrightness; 646 mUsingScreenAutoBrightness = true; 647 } else { 648 // Light sensor is disabled or not ready yet. 649 // Use the current brightness setting from the request, which is expected 650 // provide a nominal default value for the case where auto-brightness 651 // is not ready yet. 652 target = mPowerRequest.screenBrightness; 653 slow = false; 654 mUsingScreenAutoBrightness = false; 655 } 656 if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) { 657 // Dim quickly by at least some minimum amount. 658 target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION, 659 mScreenBrightnessDimConfig); 660 slow = false; 661 } else if (wasDim) { 662 // Brighten quickly. 663 slow = false; 664 } 665 animateScreenBrightness(clampScreenBrightness(target), 666 slow ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST); 667 } else { 668 // Screen is off. Don't bother changing the brightness. 669 mUsingScreenAutoBrightness = false; 670 } 671 672 // Animate the screen on or off unless blocked. 673 if (mScreenOffBecauseOfProximity) { 674 // Screen off due to proximity. 675 setScreenOn(false); 676 unblockScreenOn(); 677 } else if (wantScreenOn(mPowerRequest.screenState)) { 678 // Want screen on. 679 // Wait for previous off animation to complete beforehand. 680 // It is relatively short but if we cancel it and switch to the 681 // on animation immediately then the results are pretty ugly. 682 if (!mElectronBeamOffAnimator.isStarted()) { 683 // Turn the screen on. The contents of the screen may not yet 684 // be visible if the electron beam has not been dismissed because 685 // its last frame of animation is solid black. 686 setScreenOn(true); 687 688 if (mPowerRequest.blockScreenOn 689 && mPowerState.getElectronBeamLevel() == 0.0f) { 690 blockScreenOn(); 691 } else { 692 unblockScreenOn(); 693 if (USE_ELECTRON_BEAM_ON_ANIMATION) { 694 if (!mElectronBeamOnAnimator.isStarted()) { 695 if (mPowerState.getElectronBeamLevel() == 1.0f) { 696 mPowerState.dismissElectronBeam(); 697 } else if (mPowerState.prepareElectronBeam( 698 mElectronBeamFadesConfig ? 699 ElectronBeam.MODE_FADE : 700 ElectronBeam.MODE_WARM_UP)) { 701 mElectronBeamOnAnimator.start(); 702 } else { 703 mElectronBeamOnAnimator.end(); 704 } 705 } 706 } else { 707 mPowerState.setElectronBeamLevel(1.0f); 708 mPowerState.dismissElectronBeam(); 709 } 710 } 711 } 712 } else { 713 // Want screen off. 714 // Wait for previous on animation to complete beforehand. 715 unblockScreenOn(); 716 if (!mElectronBeamOnAnimator.isStarted()) { 717 if (!mElectronBeamOffAnimator.isStarted()) { 718 if (mPowerState.getElectronBeamLevel() == 0.0f) { 719 setScreenOn(false); 720 } else if (mPowerState.prepareElectronBeam( 721 mElectronBeamFadesConfig ? 722 ElectronBeam.MODE_FADE : 723 ElectronBeam.MODE_COOL_DOWN) 724 && mPowerState.isScreenOn()) { 725 mElectronBeamOffAnimator.start(); 726 } else { 727 mElectronBeamOffAnimator.end(); 728 } 729 } 730 } 731 } 732 733 // Report whether the display is ready for use. 734 // We mostly care about the screen state here, ignoring brightness changes 735 // which will be handled asynchronously. 736 if (mustNotify 737 && !mScreenOnWasBlocked 738 && !mElectronBeamOnAnimator.isStarted() 739 && !mElectronBeamOffAnimator.isStarted() 740 && mPowerState.waitUntilClean(mCleanListener)) { 741 synchronized (mLock) { 742 if (!mPendingRequestChangedLocked) { 743 mDisplayReadyLocked = true; 744 745 if (DEBUG) { 746 Slog.d(TAG, "Display ready!"); 747 } 748 } 749 } 750 sendOnStateChangedWithWakelock(); 751 } 752 } 753 754 private void blockScreenOn() { 755 if (!mScreenOnWasBlocked) { 756 mScreenOnWasBlocked = true; 757 if (DEBUG) { 758 Slog.d(TAG, "Blocked screen on."); 759 mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime(); 760 } 761 } 762 } 763 764 private void unblockScreenOn() { 765 if (mScreenOnWasBlocked) { 766 mScreenOnWasBlocked = false; 767 long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime; 768 if (delay > 1000 || DEBUG) { 769 Slog.d(TAG, "Unblocked screen on after " + delay + " ms"); 770 } 771 } 772 } 773 774 private void setScreenOn(boolean on) { 775 if (mPowerState.isScreenOn() != on) { 776 mPowerState.setScreenOn(on); 777 if (on) { 778 mNotifier.onScreenOn(); 779 } else { 780 mNotifier.onScreenOff(); 781 } 782 } 783 } 784 785 private int clampScreenBrightness(int value) { 786 return clamp(value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum); 787 } 788 789 private static int clampAbsoluteBrightness(int value) { 790 return clamp(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON); 791 } 792 793 private static int clamp(int value, int min, int max) { 794 if (value <= min) { 795 return min; 796 } 797 if (value >= max) { 798 return max; 799 } 800 return value; 801 } 802 803 private static float normalizeAbsoluteBrightness(int value) { 804 return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON; 805 } 806 807 private void animateScreenBrightness(int target, int rate) { 808 if (mScreenBrightnessRampAnimator.animateTo(target, rate)) { 809 mNotifier.onScreenBrightness(target); 810 } 811 } 812 813 private final Runnable mCleanListener = new Runnable() { 814 @Override 815 public void run() { 816 sendUpdatePowerState(); 817 } 818 }; 819 820 private void setProximitySensorEnabled(boolean enable) { 821 if (enable) { 822 if (!mProximitySensorEnabled) { 823 // Register the listener. 824 // Proximity sensor state already cleared initially. 825 mProximitySensorEnabled = true; 826 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor, 827 SensorManager.SENSOR_DELAY_NORMAL, mHandler); 828 } 829 } else { 830 if (mProximitySensorEnabled) { 831 // Unregister the listener. 832 // Clear the proximity sensor state for next time. 833 mProximitySensorEnabled = false; 834 mProximity = PROXIMITY_UNKNOWN; 835 mPendingProximity = PROXIMITY_UNKNOWN; 836 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED); 837 mSensorManager.unregisterListener(mProximitySensorListener); 838 clearPendingProximityDebounceTime(); // release wake lock (must be last) 839 } 840 } 841 } 842 843 private void handleProximitySensorEvent(long time, boolean positive) { 844 if (mProximitySensorEnabled) { 845 if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) { 846 return; // no change 847 } 848 if (mPendingProximity == PROXIMITY_POSITIVE && positive) { 849 return; // no change 850 } 851 852 // Only accept a proximity sensor reading if it remains 853 // stable for the entire debounce delay. We hold a wake lock while 854 // debouncing the sensor. 855 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED); 856 if (positive) { 857 mPendingProximity = PROXIMITY_POSITIVE; 858 setPendingProximityDebounceTime( 859 time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock 860 } else { 861 mPendingProximity = PROXIMITY_NEGATIVE; 862 setPendingProximityDebounceTime( 863 time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock 864 } 865 866 // Debounce the new sensor reading. 867 debounceProximitySensor(); 868 } 869 } 870 871 private void debounceProximitySensor() { 872 if (mProximitySensorEnabled 873 && mPendingProximity != PROXIMITY_UNKNOWN 874 && mPendingProximityDebounceTime >= 0) { 875 final long now = SystemClock.uptimeMillis(); 876 if (mPendingProximityDebounceTime <= now) { 877 // Sensor reading accepted. Apply the change then release the wake lock. 878 mProximity = mPendingProximity; 879 updatePowerState(); 880 clearPendingProximityDebounceTime(); // release wake lock (must be last) 881 } else { 882 // Need to wait a little longer. 883 // Debounce again later. We continue holding a wake lock while waiting. 884 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED); 885 msg.setAsynchronous(true); 886 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime); 887 } 888 } 889 } 890 891 private void clearPendingProximityDebounceTime() { 892 if (mPendingProximityDebounceTime >= 0) { 893 mPendingProximityDebounceTime = -1; 894 mDisplaySuspendBlocker.release(); // release wake lock 895 } 896 } 897 898 private void setPendingProximityDebounceTime(long debounceTime) { 899 if (mPendingProximityDebounceTime < 0) { 900 mDisplaySuspendBlocker.acquire(); // acquire wake lock 901 } 902 mPendingProximityDebounceTime = debounceTime; 903 } 904 905 private void setLightSensorEnabled(boolean enable, boolean updateAutoBrightness) { 906 if (enable) { 907 if (!mLightSensorEnabled) { 908 updateAutoBrightness = true; 909 mLightSensorEnabled = true; 910 mLightSensorEnableTime = SystemClock.uptimeMillis(); 911 mSensorManager.registerListener(mLightSensorListener, mLightSensor, 912 LIGHT_SENSOR_RATE_MILLIS * 1000, mHandler); 913 } 914 } else { 915 if (mLightSensorEnabled) { 916 mLightSensorEnabled = false; 917 mAmbientLuxValid = false; 918 mRecentLightSamples = 0; 919 mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED); 920 mSensorManager.unregisterListener(mLightSensorListener); 921 } 922 } 923 if (updateAutoBrightness) { 924 updateAutoBrightness(false); 925 } 926 } 927 928 private void handleLightSensorEvent(long time, float lux) { 929 mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED); 930 931 applyLightSensorMeasurement(time, lux); 932 updateAmbientLux(time); 933 } 934 935 private void applyLightSensorMeasurement(long time, float lux) { 936 // Update our filters. 937 mRecentLightSamples += 1; 938 if (mRecentLightSamples == 1) { 939 mRecentShortTermAverageLux = lux; 940 mRecentLongTermAverageLux = lux; 941 } else { 942 final long timeDelta = time - mLastObservedLuxTime; 943 mRecentShortTermAverageLux += (lux - mRecentShortTermAverageLux) 944 * timeDelta / (SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta); 945 mRecentLongTermAverageLux += (lux - mRecentLongTermAverageLux) 946 * timeDelta / (LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta); 947 } 948 949 // Remember this sample value. 950 mLastObservedLux = lux; 951 mLastObservedLuxTime = time; 952 } 953 954 private void setAmbientLux(float lux) { 955 mAmbientLux = lux; 956 mBrighteningLuxThreshold = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS); 957 mDarkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS); 958 } 959 960 private void updateAmbientLux(long time) { 961 // If the light sensor was just turned on then immediately update our initial 962 // estimate of the current ambient light level. 963 if (!mAmbientLuxValid) { 964 final long timeWhenSensorWarmedUp = 965 mLightSensorWarmUpTimeConfig + mLightSensorEnableTime; 966 if (time < timeWhenSensorWarmedUp) { 967 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, 968 timeWhenSensorWarmedUp); 969 return; 970 } 971 setAmbientLux(mRecentShortTermAverageLux); 972 mAmbientLuxValid = true; 973 mDebounceLuxDirection = 0; 974 mDebounceLuxTime = time; 975 if (DEBUG) { 976 Slog.d(TAG, "updateAmbientLux: Initializing: " 977 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux 978 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux 979 + ", mAmbientLux=" + mAmbientLux); 980 } 981 updateAutoBrightness(true); 982 } else if (mRecentShortTermAverageLux > mBrighteningLuxThreshold 983 && mRecentLongTermAverageLux > mBrighteningLuxThreshold) { 984 // The ambient environment appears to be brightening. 985 if (mDebounceLuxDirection <= 0) { 986 mDebounceLuxDirection = 1; 987 mDebounceLuxTime = time; 988 if (DEBUG) { 989 Slog.d(TAG, "updateAmbientLux: Possibly brightened, waiting for " 990 + BRIGHTENING_LIGHT_DEBOUNCE + " ms: " 991 + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold 992 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux 993 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux 994 + ", mAmbientLux=" + mAmbientLux); 995 } 996 } 997 long debounceTime = mDebounceLuxTime + BRIGHTENING_LIGHT_DEBOUNCE; 998 if (time < debounceTime) { 999 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime); 1000 return; 1001 } 1002 setAmbientLux(mRecentShortTermAverageLux); 1003 if (DEBUG) { 1004 Slog.d(TAG, "updateAmbientLux: Brightened: " 1005 + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold 1006 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux 1007 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux 1008 + ", mAmbientLux=" + mAmbientLux); 1009 } 1010 updateAutoBrightness(true); 1011 } else if (mRecentShortTermAverageLux < mDarkeningLuxThreshold 1012 && mRecentLongTermAverageLux < mDarkeningLuxThreshold) { 1013 // The ambient environment appears to be darkening. 1014 if (mDebounceLuxDirection >= 0) { 1015 mDebounceLuxDirection = -1; 1016 mDebounceLuxTime = time; 1017 if (DEBUG) { 1018 Slog.d(TAG, "updateAmbientLux: Possibly darkened, waiting for " 1019 + DARKENING_LIGHT_DEBOUNCE + " ms: " 1020 + "mDarkeningLuxThreshold=" + mDarkeningLuxThreshold 1021 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux 1022 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux 1023 + ", mAmbientLux=" + mAmbientLux); 1024 } 1025 } 1026 long debounceTime = mDebounceLuxTime + DARKENING_LIGHT_DEBOUNCE; 1027 if (time < debounceTime) { 1028 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime); 1029 return; 1030 } 1031 // Be conservative about reducing the brightness, only reduce it a little bit 1032 // at a time to avoid having to bump it up again soon. 1033 setAmbientLux(Math.max(mRecentShortTermAverageLux, mRecentLongTermAverageLux)); 1034 if (DEBUG) { 1035 Slog.d(TAG, "updateAmbientLux: Darkened: " 1036 + "mDarkeningLuxThreshold=" + mDarkeningLuxThreshold 1037 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux 1038 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux 1039 + ", mAmbientLux=" + mAmbientLux); 1040 } 1041 updateAutoBrightness(true); 1042 } else if (mDebounceLuxDirection != 0) { 1043 // No change or change is within the hysteresis thresholds. 1044 mDebounceLuxDirection = 0; 1045 mDebounceLuxTime = time; 1046 if (DEBUG) { 1047 Slog.d(TAG, "updateAmbientLux: Canceled debounce: " 1048 + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold 1049 + ", mDarkeningLuxThreshold=" + mDarkeningLuxThreshold 1050 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux 1051 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux 1052 + ", mAmbientLux=" + mAmbientLux); 1053 } 1054 } 1055 1056 // Now that we've done all of that, we haven't yet posted a debounce 1057 // message. So consider the case where current lux is beyond the 1058 // threshold. It's possible that the light sensor may not report values 1059 // if the light level does not change, so we need to occasionally 1060 // synthesize sensor readings in order to make sure the brightness is 1061 // adjusted accordingly. Note these thresholds may have changed since 1062 // we entered the function because we called setAmbientLux and 1063 // updateAutoBrightness along the way. 1064 if (mLastObservedLux > mBrighteningLuxThreshold 1065 || mLastObservedLux < mDarkeningLuxThreshold) { 1066 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, 1067 time + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS); 1068 } 1069 } 1070 1071 private void debounceLightSensor() { 1072 if (mLightSensorEnabled) { 1073 long time = SystemClock.uptimeMillis(); 1074 if (time >= mLastObservedLuxTime + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS) { 1075 if (DEBUG) { 1076 Slog.d(TAG, "debounceLightSensor: Synthesizing light sensor measurement " 1077 + "after " + (time - mLastObservedLuxTime) + " ms."); 1078 } 1079 applyLightSensorMeasurement(time, mLastObservedLux); 1080 } 1081 updateAmbientLux(time); 1082 } 1083 } 1084 1085 private void updateAutoBrightness(boolean sendUpdate) { 1086 if (!mAmbientLuxValid) { 1087 return; 1088 } 1089 1090 float value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux); 1091 float gamma = 1.0f; 1092 1093 if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT 1094 && mPowerRequest.screenAutoBrightnessAdjustment != 0.0f) { 1095 final float adjGamma = FloatMath.pow(SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA, 1096 Math.min(1.0f, Math.max(-1.0f, 1097 -mPowerRequest.screenAutoBrightnessAdjustment))); 1098 gamma *= adjGamma; 1099 if (DEBUG) { 1100 Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma); 1101 } 1102 } 1103 1104 if (USE_TWILIGHT_ADJUSTMENT) { 1105 TwilightState state = mTwilight.getCurrentState(); 1106 if (state != null && state.isNight()) { 1107 final long now = System.currentTimeMillis(); 1108 final float earlyGamma = 1109 getTwilightGamma(now, state.getYesterdaySunset(), state.getTodaySunrise()); 1110 final float lateGamma = 1111 getTwilightGamma(now, state.getTodaySunset(), state.getTomorrowSunrise()); 1112 gamma *= earlyGamma * lateGamma; 1113 if (DEBUG) { 1114 Slog.d(TAG, "updateAutoBrightness: earlyGamma=" + earlyGamma 1115 + ", lateGamma=" + lateGamma); 1116 } 1117 } 1118 } 1119 1120 if (gamma != 1.0f) { 1121 final float in = value; 1122 value = FloatMath.pow(value, gamma); 1123 if (DEBUG) { 1124 Slog.d(TAG, "updateAutoBrightness: gamma=" + gamma 1125 + ", in=" + in + ", out=" + value); 1126 } 1127 } 1128 1129 int newScreenAutoBrightness = clampScreenBrightness( 1130 Math.round(value * PowerManager.BRIGHTNESS_ON)); 1131 if (mScreenAutoBrightness != newScreenAutoBrightness) { 1132 if (DEBUG) { 1133 Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness=" 1134 + mScreenAutoBrightness + ", newScreenAutoBrightness=" 1135 + newScreenAutoBrightness); 1136 } 1137 1138 mScreenAutoBrightness = newScreenAutoBrightness; 1139 mLastScreenAutoBrightnessGamma = gamma; 1140 if (sendUpdate) { 1141 sendUpdatePowerState(); 1142 } 1143 } 1144 } 1145 1146 private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) { 1147 if (lastSunset < 0 || nextSunrise < 0 1148 || now < lastSunset || now > nextSunrise) { 1149 return 1.0f; 1150 } 1151 1152 if (now < lastSunset + TWILIGHT_ADJUSTMENT_TIME) { 1153 return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA, 1154 (float)(now - lastSunset) / TWILIGHT_ADJUSTMENT_TIME); 1155 } 1156 1157 if (now > nextSunrise - TWILIGHT_ADJUSTMENT_TIME) { 1158 return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA, 1159 (float)(nextSunrise - now) / TWILIGHT_ADJUSTMENT_TIME); 1160 } 1161 1162 return TWILIGHT_ADJUSTMENT_MAX_GAMMA; 1163 } 1164 1165 private static float lerp(float x, float y, float alpha) { 1166 return x + (y - x) * alpha; 1167 } 1168 1169 private void sendOnStateChangedWithWakelock() { 1170 mDisplaySuspendBlocker.acquire(); 1171 mCallbackHandler.post(mOnStateChangedRunnable); 1172 } 1173 1174 private final Runnable mOnStateChangedRunnable = new Runnable() { 1175 @Override 1176 public void run() { 1177 mCallbacks.onStateChanged(); 1178 mDisplaySuspendBlocker.release(); 1179 } 1180 }; 1181 1182 private void sendOnProximityPositiveWithWakelock() { 1183 mDisplaySuspendBlocker.acquire(); 1184 mCallbackHandler.post(mOnProximityPositiveRunnable); 1185 } 1186 1187 private final Runnable mOnProximityPositiveRunnable = new Runnable() { 1188 @Override 1189 public void run() { 1190 mCallbacks.onProximityPositive(); 1191 mDisplaySuspendBlocker.release(); 1192 } 1193 }; 1194 1195 private void sendOnProximityNegativeWithWakelock() { 1196 mDisplaySuspendBlocker.acquire(); 1197 mCallbackHandler.post(mOnProximityNegativeRunnable); 1198 } 1199 1200 private final Runnable mOnProximityNegativeRunnable = new Runnable() { 1201 @Override 1202 public void run() { 1203 mCallbacks.onProximityNegative(); 1204 mDisplaySuspendBlocker.release(); 1205 } 1206 }; 1207 1208 public void dump(final PrintWriter pw) { 1209 synchronized (mLock) { 1210 pw.println(); 1211 pw.println("Display Controller Locked State:"); 1212 pw.println(" mDisplayReadyLocked=" + mDisplayReadyLocked); 1213 pw.println(" mPendingRequestLocked=" + mPendingRequestLocked); 1214 pw.println(" mPendingRequestChangedLocked=" + mPendingRequestChangedLocked); 1215 pw.println(" mPendingWaitForNegativeProximityLocked=" 1216 + mPendingWaitForNegativeProximityLocked); 1217 pw.println(" mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked); 1218 } 1219 1220 pw.println(); 1221 pw.println("Display Controller Configuration:"); 1222 pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig); 1223 pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum); 1224 pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum); 1225 pw.println(" mUseSoftwareAutoBrightnessConfig=" 1226 + mUseSoftwareAutoBrightnessConfig); 1227 pw.println(" mScreenAutoBrightnessSpline=" + mScreenAutoBrightnessSpline); 1228 pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig); 1229 1230 mHandler.runWithScissors(new Runnable() { 1231 @Override 1232 public void run() { 1233 dumpLocal(pw); 1234 } 1235 }, 1000); 1236 } 1237 1238 private void dumpLocal(PrintWriter pw) { 1239 pw.println(); 1240 pw.println("Display Controller Thread State:"); 1241 pw.println(" mPowerRequest=" + mPowerRequest); 1242 pw.println(" mWaitingForNegativeProximity=" + mWaitingForNegativeProximity); 1243 1244 pw.println(" mProximitySensor=" + mProximitySensor); 1245 pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled); 1246 pw.println(" mProximityThreshold=" + mProximityThreshold); 1247 pw.println(" mProximity=" + proximityToString(mProximity)); 1248 pw.println(" mPendingProximity=" + proximityToString(mPendingProximity)); 1249 pw.println(" mPendingProximityDebounceTime=" 1250 + TimeUtils.formatUptime(mPendingProximityDebounceTime)); 1251 pw.println(" mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity); 1252 1253 pw.println(" mLightSensor=" + mLightSensor); 1254 pw.println(" mLightSensorEnabled=" + mLightSensorEnabled); 1255 pw.println(" mLightSensorEnableTime=" 1256 + TimeUtils.formatUptime(mLightSensorEnableTime)); 1257 pw.println(" mAmbientLux=" + mAmbientLux); 1258 pw.println(" mAmbientLuxValid=" + mAmbientLuxValid); 1259 pw.println(" mLastObservedLux=" + mLastObservedLux); 1260 pw.println(" mLastObservedLuxTime=" 1261 + TimeUtils.formatUptime(mLastObservedLuxTime)); 1262 pw.println(" mRecentLightSamples=" + mRecentLightSamples); 1263 pw.println(" mRecentShortTermAverageLux=" + mRecentShortTermAverageLux); 1264 pw.println(" mRecentLongTermAverageLux=" + mRecentLongTermAverageLux); 1265 pw.println(" mDebounceLuxDirection=" + mDebounceLuxDirection); 1266 pw.println(" mDebounceLuxTime=" + TimeUtils.formatUptime(mDebounceLuxTime)); 1267 pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness); 1268 pw.println(" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness); 1269 pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma); 1270 pw.println(" mTwilight.getCurrentState()=" + mTwilight.getCurrentState()); 1271 1272 if (mElectronBeamOnAnimator != null) { 1273 pw.println(" mElectronBeamOnAnimator.isStarted()=" + 1274 mElectronBeamOnAnimator.isStarted()); 1275 } 1276 if (mElectronBeamOffAnimator != null) { 1277 pw.println(" mElectronBeamOffAnimator.isStarted()=" + 1278 mElectronBeamOffAnimator.isStarted()); 1279 } 1280 1281 if (mPowerState != null) { 1282 mPowerState.dump(pw); 1283 } 1284 } 1285 1286 private static String proximityToString(int state) { 1287 switch (state) { 1288 case PROXIMITY_UNKNOWN: 1289 return "Unknown"; 1290 case PROXIMITY_NEGATIVE: 1291 return "Negative"; 1292 case PROXIMITY_POSITIVE: 1293 return "Positive"; 1294 default: 1295 return Integer.toString(state); 1296 } 1297 } 1298 1299 private static boolean wantScreenOn(int state) { 1300 switch (state) { 1301 case DisplayPowerRequest.SCREEN_STATE_BRIGHT: 1302 case DisplayPowerRequest.SCREEN_STATE_DIM: 1303 return true; 1304 } 1305 return false; 1306 } 1307 1308 /** 1309 * Asynchronous callbacks from the power controller to the power manager service. 1310 */ 1311 public interface Callbacks { 1312 void onStateChanged(); 1313 void onProximityPositive(); 1314 void onProximityNegative(); 1315 } 1316 1317 private final class DisplayControllerHandler extends Handler { 1318 public DisplayControllerHandler(Looper looper) { 1319 super(looper, null, true /*async*/); 1320 } 1321 1322 @Override 1323 public void handleMessage(Message msg) { 1324 switch (msg.what) { 1325 case MSG_UPDATE_POWER_STATE: 1326 updatePowerState(); 1327 break; 1328 1329 case MSG_PROXIMITY_SENSOR_DEBOUNCED: 1330 debounceProximitySensor(); 1331 break; 1332 1333 case MSG_LIGHT_SENSOR_DEBOUNCED: 1334 debounceLightSensor(); 1335 break; 1336 } 1337 } 1338 } 1339 1340 private final SensorEventListener mProximitySensorListener = new SensorEventListener() { 1341 @Override 1342 public void onSensorChanged(SensorEvent event) { 1343 if (mProximitySensorEnabled) { 1344 final long time = SystemClock.uptimeMillis(); 1345 final float distance = event.values[0]; 1346 boolean positive = distance >= 0.0f && distance < mProximityThreshold; 1347 handleProximitySensorEvent(time, positive); 1348 } 1349 } 1350 1351 @Override 1352 public void onAccuracyChanged(Sensor sensor, int accuracy) { 1353 // Not used. 1354 } 1355 }; 1356 1357 private final SensorEventListener mLightSensorListener = new SensorEventListener() { 1358 @Override 1359 public void onSensorChanged(SensorEvent event) { 1360 if (mLightSensorEnabled) { 1361 final long time = SystemClock.uptimeMillis(); 1362 final float lux = event.values[0]; 1363 handleLightSensorEvent(time, lux); 1364 } 1365 } 1366 1367 @Override 1368 public void onAccuracyChanged(Sensor sensor, int accuracy) { 1369 // Not used. 1370 } 1371 }; 1372 1373 private final TwilightService.TwilightListener mTwilightListener = 1374 new TwilightService.TwilightListener() { 1375 @Override 1376 public void onTwilightStateChanged() { 1377 mTwilightChanged = true; 1378 updatePowerState(); 1379 } 1380 }; 1381 } 1382