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