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