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