DisplayPowerController.java revision 9e316a1a2a8d734315bbd56a85308f9657a92913
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 // 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 average light sensor value. 288 private float mLightMeasurement; 289 290 // True if the light sensor measurement is valid. 291 private boolean mLightMeasurementValid; 292 293 // The number of light sensor samples that have been collected since the 294 // last time a light sensor reading was accepted. 295 private int mRecentLightSamples; 296 297 // The moving average of recent light sensor values. 298 private float mRecentLightAverage; 299 300 // True if recent light samples are getting brighter than the previous 301 // stable light measurement. 302 private boolean mRecentLightBrightening; 303 304 // The time constant to use for filtering based on whether the 305 // light appears to be brightening or dimming. 306 private long mRecentLightTimeConstant; 307 308 // The most recent light sample. 309 private float mLastLightSample; 310 311 // The time of the most light recent sample. 312 private long mLastLightSampleTime; 313 314 // The time when we accumulated the first recent light sample into mRecentLightSamples. 315 private long mFirstRecentLightSampleTime; 316 317 // The upcoming debounce light sensor time. 318 // This is only valid when mLightMeasurementValue && mRecentLightSamples >= 1. 319 private long mPendingLightSensorDebounceTime; 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, SuspendBlocker suspendBlocker, 349 DisplayBlanker displayBlanker, 350 Callbacks callbacks, Handler callbackHandler) { 351 mHandler = new DisplayControllerHandler(looper); 352 mNotifier = notifier; 353 mSuspendBlocker = suspendBlocker; 354 mDisplayBlanker = displayBlanker; 355 mCallbacks = callbacks; 356 mCallbackHandler = callbackHandler; 357 358 mLights = lights; 359 mTwilight = twilight; 360 mSensorManager = new SystemSensorManager(mHandler.getLooper()); 361 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 362 363 final Resources resources = context.getResources(); 364 365 mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger( 366 com.android.internal.R.integer.config_screenBrightnessDim)); 367 368 int screenBrightnessMinimum = Math.min(resources.getInteger( 369 com.android.internal.R.integer.config_screenBrightnessSettingMinimum), 370 mScreenBrightnessDimConfig); 371 372 mUseSoftwareAutoBrightnessConfig = resources.getBoolean( 373 com.android.internal.R.bool.config_automatic_brightness_available); 374 if (mUseSoftwareAutoBrightnessConfig) { 375 int[] lux = resources.getIntArray( 376 com.android.internal.R.array.config_autoBrightnessLevels); 377 int[] screenBrightness = resources.getIntArray( 378 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues); 379 380 mScreenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness); 381 if (mScreenAutoBrightnessSpline == null) { 382 Slog.e(TAG, "Error in config.xml. config_autoBrightnessLcdBacklightValues " 383 + "(size " + screenBrightness.length + ") " 384 + "must be monotic and have exactly one more entry than " 385 + "config_autoBrightnessLevels (size " + lux.length + ") " 386 + "which must be strictly increasing. " 387 + "Auto-brightness will be disabled."); 388 mUseSoftwareAutoBrightnessConfig = false; 389 } else { 390 if (screenBrightness[0] < screenBrightnessMinimum) { 391 screenBrightnessMinimum = screenBrightness[0]; 392 } 393 } 394 395 mLightSensorWarmUpTimeConfig = resources.getInteger( 396 com.android.internal.R.integer.config_lightSensorWarmupTime); 397 } 398 399 mScreenBrightnessRangeMinimum = clampAbsoluteBrightness(screenBrightnessMinimum); 400 mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON; 401 402 mElectronBeamFadesConfig = resources.getBoolean( 403 com.android.internal.R.bool.config_animateScreenLights); 404 405 if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) { 406 mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); 407 if (mProximitySensor != null) { 408 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(), 409 TYPICAL_PROXIMITY_THRESHOLD); 410 } 411 } 412 413 if (mUseSoftwareAutoBrightnessConfig 414 && !DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) { 415 mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); 416 } 417 418 if (mUseSoftwareAutoBrightnessConfig && USE_TWILIGHT_ADJUSTMENT) { 419 mTwilight.registerListener(mTwilightListener, mHandler); 420 } 421 } 422 423 private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) { 424 try { 425 final int n = brightness.length; 426 float[] x = new float[n]; 427 float[] y = new float[n]; 428 y[0] = normalizeAbsoluteBrightness(brightness[0]); 429 for (int i = 1; i < n; i++) { 430 x[i] = lux[i - 1]; 431 y[i] = normalizeAbsoluteBrightness(brightness[i]); 432 } 433 434 Spline spline = Spline.createMonotoneCubicSpline(x, y); 435 if (DEBUG) { 436 Slog.d(TAG, "Auto-brightness spline: " + spline); 437 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) { 438 Slog.d(TAG, String.format(" %7.1f: %7.1f", v, spline.interpolate(v))); 439 } 440 } 441 return spline; 442 } catch (IllegalArgumentException ex) { 443 Slog.e(TAG, "Could not create auto-brightness spline.", ex); 444 return null; 445 } 446 } 447 448 /** 449 * Returns true if the proximity sensor screen-off function is available. 450 */ 451 public boolean isProximitySensorAvailable() { 452 return mProximitySensor != null; 453 } 454 455 /** 456 * Requests a new power state. 457 * The controller makes a copy of the provided object and then 458 * begins adjusting the power state to match what was requested. 459 * 460 * @param request The requested power state. 461 * @param waitForNegativeProximity If true, issues a request to wait for 462 * negative proximity before turning the screen back on, assuming the screen 463 * was turned off by the proximity sensor. 464 * @return True if display is ready, false if there are important changes that must 465 * be made asynchronously (such as turning the screen on), in which case the caller 466 * should grab a wake lock, watch for {@link Callbacks#onStateChanged()} then try 467 * the request again later until the state converges. 468 */ 469 public boolean requestPowerState(DisplayPowerRequest request, 470 boolean waitForNegativeProximity) { 471 if (DEBUG) { 472 Slog.d(TAG, "requestPowerState: " 473 + request + ", waitForNegativeProximity=" + waitForNegativeProximity); 474 } 475 476 synchronized (mLock) { 477 boolean changed = false; 478 479 if (waitForNegativeProximity 480 && !mPendingWaitForNegativeProximityLocked) { 481 mPendingWaitForNegativeProximityLocked = true; 482 changed = true; 483 } 484 485 if (mPendingRequestLocked == null) { 486 mPendingRequestLocked = new DisplayPowerRequest(request); 487 changed = true; 488 } else if (!mPendingRequestLocked.equals(request)) { 489 mPendingRequestLocked.copyFrom(request); 490 changed = true; 491 } 492 493 if (changed) { 494 mDisplayReadyLocked = false; 495 } 496 497 if (changed && !mPendingRequestChangedLocked) { 498 mPendingRequestChangedLocked = true; 499 sendUpdatePowerStateLocked(); 500 } 501 502 return mDisplayReadyLocked; 503 } 504 } 505 506 private void sendUpdatePowerState() { 507 synchronized (mLock) { 508 sendUpdatePowerStateLocked(); 509 } 510 } 511 512 private void sendUpdatePowerStateLocked() { 513 if (!mPendingUpdatePowerStateLocked) { 514 mPendingUpdatePowerStateLocked = true; 515 Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE); 516 msg.setAsynchronous(true); 517 mHandler.sendMessage(msg); 518 } 519 } 520 521 private void initialize() { 522 final Executor executor = AsyncTask.THREAD_POOL_EXECUTOR; 523 Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); 524 mPowerState = new DisplayPowerState( 525 new ElectronBeam(display), 526 new PhotonicModulator(executor, 527 mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT), 528 mSuspendBlocker), 529 mDisplayBlanker); 530 531 mElectronBeamOnAnimator = ObjectAnimator.ofFloat( 532 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f); 533 mElectronBeamOnAnimator.setDuration(ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS); 534 mElectronBeamOnAnimator.addListener(mAnimatorListener); 535 536 mElectronBeamOffAnimator = ObjectAnimator.ofFloat( 537 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 1.0f, 0.0f); 538 mElectronBeamOffAnimator.setDuration(ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS); 539 mElectronBeamOffAnimator.addListener(mAnimatorListener); 540 541 mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>( 542 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS); 543 } 544 545 private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() { 546 @Override 547 public void onAnimationStart(Animator animation) { 548 } 549 @Override 550 public void onAnimationEnd(Animator animation) { 551 sendUpdatePowerState(); 552 } 553 @Override 554 public void onAnimationRepeat(Animator animation) { 555 } 556 @Override 557 public void onAnimationCancel(Animator animation) { 558 } 559 }; 560 561 private void updatePowerState() { 562 // Update the power state request. 563 final boolean mustNotify; 564 boolean mustInitialize = false; 565 boolean updateAutoBrightness = mTwilightChanged; 566 mTwilightChanged = false; 567 568 synchronized (mLock) { 569 mPendingUpdatePowerStateLocked = false; 570 if (mPendingRequestLocked == null) { 571 return; // wait until first actual power request 572 } 573 574 if (mPowerRequest == null) { 575 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked); 576 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked; 577 mPendingWaitForNegativeProximityLocked = false; 578 mPendingRequestChangedLocked = false; 579 mustInitialize = true; 580 } else if (mPendingRequestChangedLocked) { 581 if (mPowerRequest.screenAutoBrightnessAdjustment 582 != mPendingRequestLocked.screenAutoBrightnessAdjustment) { 583 updateAutoBrightness = true; 584 } 585 mPowerRequest.copyFrom(mPendingRequestLocked); 586 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked; 587 mPendingWaitForNegativeProximityLocked = false; 588 mPendingRequestChangedLocked = false; 589 mDisplayReadyLocked = false; 590 } 591 592 mustNotify = !mDisplayReadyLocked; 593 } 594 595 // Initialize things the first time the power state is changed. 596 if (mustInitialize) { 597 initialize(); 598 } 599 600 // Apply the proximity sensor. 601 if (mProximitySensor != null) { 602 if (mPowerRequest.useProximitySensor 603 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { 604 setProximitySensorEnabled(true); 605 if (!mScreenOffBecauseOfProximity 606 && mProximity == PROXIMITY_POSITIVE) { 607 mScreenOffBecauseOfProximity = true; 608 sendOnProximityPositive(); 609 setScreenOn(false); 610 } 611 } else if (mWaitingForNegativeProximity 612 && mScreenOffBecauseOfProximity 613 && mProximity == PROXIMITY_POSITIVE 614 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { 615 setProximitySensorEnabled(true); 616 } else { 617 setProximitySensorEnabled(false); 618 mWaitingForNegativeProximity = false; 619 } 620 if (mScreenOffBecauseOfProximity 621 && mProximity != PROXIMITY_POSITIVE) { 622 mScreenOffBecauseOfProximity = false; 623 sendOnProximityNegative(); 624 } 625 } else { 626 mWaitingForNegativeProximity = false; 627 } 628 629 // Turn on the light sensor if needed. 630 if (mLightSensor != null) { 631 setLightSensorEnabled(mPowerRequest.useAutoBrightness 632 && wantScreenOn(mPowerRequest.screenState), updateAutoBrightness); 633 } 634 635 // Set the screen brightness. 636 if (wantScreenOn(mPowerRequest.screenState)) { 637 int target; 638 boolean slow; 639 if (mScreenAutoBrightness >= 0 && mLightSensorEnabled) { 640 // Use current auto-brightness value. 641 target = mScreenAutoBrightness; 642 slow = mUsingScreenAutoBrightness; 643 mUsingScreenAutoBrightness = true; 644 } else { 645 // Light sensor is disabled or not ready yet. 646 // Use the current brightness setting from the request, which is expected 647 // provide a nominal default value for the case where auto-brightness 648 // is not ready yet. 649 target = mPowerRequest.screenBrightness; 650 slow = false; 651 mUsingScreenAutoBrightness = false; 652 } 653 if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) { 654 // Screen is dimmed. Sets an upper bound on everything else. 655 target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION, 656 mScreenBrightnessDimConfig); 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, mHandler); 872 } 873 } else { 874 if (mLightSensorEnabled) { 875 mLightSensorEnabled = false; 876 mLightMeasurementValid = false; 877 mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED); 878 mSensorManager.unregisterListener(mLightSensorListener); 879 } 880 } 881 if (updateAutoBrightness) { 882 updateAutoBrightness(false); 883 } 884 } 885 886 private void handleLightSensorEvent(long time, float lux) { 887 // Take the first few readings during the warm-up period and apply them 888 // immediately without debouncing. 889 if (!mLightMeasurementValid 890 || (time - mLightSensorEnableTime) < mLightSensorWarmUpTimeConfig) { 891 mLightMeasurement = lux; 892 mLightMeasurementValid = true; 893 mRecentLightSamples = 0; 894 updateAutoBrightness(true); 895 } 896 897 // Update our moving average. 898 if (lux != mLightMeasurement && (mRecentLightSamples == 0 899 || (lux < mLightMeasurement && mRecentLightBrightening) 900 || (lux > mLightMeasurement && !mRecentLightBrightening))) { 901 // If the newest light sample doesn't seem to be going in the 902 // same general direction as recent samples, then start over. 903 setRecentLight(time, lux, lux > mLightMeasurement); 904 } else if (mRecentLightSamples >= 1) { 905 // Add the newest light sample to the moving average. 906 accumulateRecentLight(time, lux); 907 } 908 if (DEBUG) { 909 Slog.d(TAG, "handleLightSensorEvent: lux=" + lux 910 + ", mLightMeasurementValid=" + mLightMeasurementValid 911 + ", mLightMeasurement=" + mLightMeasurement 912 + ", mRecentLightSamples=" + mRecentLightSamples 913 + ", mRecentLightAverage=" + mRecentLightAverage 914 + ", mRecentLightBrightening=" + mRecentLightBrightening 915 + ", mRecentLightTimeConstant=" + mRecentLightTimeConstant 916 + ", mFirstRecentLightSampleTime=" 917 + TimeUtils.formatUptime(mFirstRecentLightSampleTime) 918 + ", mPendingLightSensorDebounceTime=" 919 + TimeUtils.formatUptime(mPendingLightSensorDebounceTime)); 920 } 921 922 // Debounce. 923 mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED); 924 debounceLightSensor(); 925 } 926 927 private void setRecentLight(long time, float lux, boolean brightening) { 928 mRecentLightBrightening = brightening; 929 mRecentLightTimeConstant = brightening ? 930 BRIGHTENING_LIGHT_TIME_CONSTANT : DIMMING_LIGHT_TIME_CONSTANT; 931 mRecentLightSamples = 1; 932 mRecentLightAverage = lux; 933 mLastLightSample = lux; 934 mLastLightSampleTime = time; 935 mFirstRecentLightSampleTime = time; 936 mPendingLightSensorDebounceTime = time + (brightening ? 937 BRIGHTENING_LIGHT_DEBOUNCE : DIMMING_LIGHT_DEBOUNCE); 938 } 939 940 private void accumulateRecentLight(long time, float lux) { 941 final long timeDelta = time - mLastLightSampleTime; 942 mRecentLightSamples += 1; 943 mRecentLightAverage += (lux - mRecentLightAverage) * 944 timeDelta / (mRecentLightTimeConstant + timeDelta); 945 mLastLightSample = lux; 946 mLastLightSampleTime = time; 947 } 948 949 private void debounceLightSensor() { 950 if (mLightMeasurementValid && mRecentLightSamples >= 1) { 951 final long now = SystemClock.uptimeMillis(); 952 if (mPendingLightSensorDebounceTime <= now) { 953 accumulateRecentLight(now, mLastLightSample); 954 mLightMeasurement = mRecentLightAverage; 955 956 if (DEBUG) { 957 Slog.d(TAG, "debounceLightSensor: Accepted new measurement " 958 + mLightMeasurement + " after " 959 + (now - mFirstRecentLightSampleTime) + " ms based on " 960 + mRecentLightSamples + " recent samples."); 961 } 962 963 updateAutoBrightness(true); 964 965 // Now that we have debounced the light sensor data, we have the 966 // option of either leaving the sensor in a debounced state or 967 // restarting the debounce cycle by setting mRecentLightSamples to 0. 968 // 969 // If we leave the sensor debounced, then new average light measurements 970 // may be accepted immediately as long as they are trending in the same 971 // direction as they were before. If the measurements start 972 // jittering or trending in the opposite direction then the debounce 973 // cycle will automatically be restarted. The benefit is that the 974 // auto-brightness control can be more responsive to changes over a 975 // broad range. 976 // 977 // For now, we choose to be more responsive and leave the following line 978 // commented out. 979 // 980 // mRecentLightSamples = 0; 981 } else { 982 Message msg = mHandler.obtainMessage(MSG_LIGHT_SENSOR_DEBOUNCED); 983 msg.setAsynchronous(true); 984 mHandler.sendMessageAtTime(msg, mPendingLightSensorDebounceTime); 985 } 986 } 987 } 988 989 private void updateAutoBrightness(boolean sendUpdate) { 990 if (!mLightMeasurementValid) { 991 return; 992 } 993 994 float value = mScreenAutoBrightnessSpline.interpolate(mLightMeasurement); 995 float gamma = 1.0f; 996 997 if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT 998 && mPowerRequest.screenAutoBrightnessAdjustment != 0.0f) { 999 final float adjGamma = FloatMath.pow(SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA, 1000 Math.min(1.0f, Math.max(-1.0f, 1001 -mPowerRequest.screenAutoBrightnessAdjustment))); 1002 gamma *= adjGamma; 1003 if (DEBUG) { 1004 Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma); 1005 } 1006 } 1007 1008 if (USE_TWILIGHT_ADJUSTMENT) { 1009 TwilightState state = mTwilight.getCurrentState(); 1010 if (state != null && state.isNight()) { 1011 final long now = System.currentTimeMillis(); 1012 final float earlyGamma = 1013 getTwilightGamma(now, state.getYesterdaySunset(), state.getTodaySunrise()); 1014 final float lateGamma = 1015 getTwilightGamma(now, state.getTodaySunset(), state.getTomorrowSunrise()); 1016 gamma *= earlyGamma * lateGamma; 1017 if (DEBUG) { 1018 Slog.d(TAG, "updateAutoBrightness: earlyGamma=" + earlyGamma 1019 + ", lateGamma=" + lateGamma); 1020 } 1021 } 1022 } 1023 1024 if (gamma != 1.0f) { 1025 final float in = value; 1026 value = FloatMath.pow(value, gamma); 1027 if (DEBUG) { 1028 Slog.d(TAG, "updateAutoBrightness: gamma=" + gamma 1029 + ", in=" + in + ", out=" + value); 1030 } 1031 } 1032 1033 int newScreenAutoBrightness = clampScreenBrightness( 1034 (int)Math.round(value * PowerManager.BRIGHTNESS_ON)); 1035 if (mScreenAutoBrightness != newScreenAutoBrightness) { 1036 if (DEBUG) { 1037 Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness=" 1038 + mScreenAutoBrightness + ", newScreenAutoBrightness=" 1039 + newScreenAutoBrightness); 1040 } 1041 1042 mScreenAutoBrightness = newScreenAutoBrightness; 1043 mLastScreenAutoBrightnessGamma = gamma; 1044 if (sendUpdate) { 1045 sendUpdatePowerState(); 1046 } 1047 } 1048 } 1049 1050 private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) { 1051 if (lastSunset < 0 || nextSunrise < 0 1052 || now < lastSunset || now > nextSunrise) { 1053 return 1.0f; 1054 } 1055 1056 if (now < lastSunset + TWILIGHT_ADJUSTMENT_TIME) { 1057 return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA, 1058 (float)(now - lastSunset) / TWILIGHT_ADJUSTMENT_TIME); 1059 } 1060 1061 if (now > nextSunrise - TWILIGHT_ADJUSTMENT_TIME) { 1062 return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA, 1063 (float)(nextSunrise - now) / TWILIGHT_ADJUSTMENT_TIME); 1064 } 1065 1066 return TWILIGHT_ADJUSTMENT_MAX_GAMMA; 1067 } 1068 1069 private static float lerp(float x, float y, float alpha) { 1070 return x + (y - x) * alpha; 1071 } 1072 1073 private void sendOnStateChanged() { 1074 mCallbackHandler.post(mOnStateChangedRunnable); 1075 } 1076 1077 private final Runnable mOnStateChangedRunnable = new Runnable() { 1078 @Override 1079 public void run() { 1080 mCallbacks.onStateChanged(); 1081 } 1082 }; 1083 1084 private void sendOnProximityPositive() { 1085 mCallbackHandler.post(mOnProximityPositiveRunnable); 1086 } 1087 1088 private final Runnable mOnProximityPositiveRunnable = new Runnable() { 1089 @Override 1090 public void run() { 1091 mCallbacks.onProximityPositive(); 1092 } 1093 }; 1094 1095 private void sendOnProximityNegative() { 1096 mCallbackHandler.post(mOnProximityNegativeRunnable); 1097 } 1098 1099 private final Runnable mOnProximityNegativeRunnable = new Runnable() { 1100 @Override 1101 public void run() { 1102 mCallbacks.onProximityNegative(); 1103 } 1104 }; 1105 1106 public void dump(final PrintWriter pw) { 1107 synchronized (mLock) { 1108 pw.println(); 1109 pw.println("Display Controller Locked State:"); 1110 pw.println(" mDisplayReadyLocked=" + mDisplayReadyLocked); 1111 pw.println(" mPendingRequestLocked=" + mPendingRequestLocked); 1112 pw.println(" mPendingRequestChangedLocked=" + mPendingRequestChangedLocked); 1113 pw.println(" mPendingWaitForNegativeProximityLocked=" 1114 + mPendingWaitForNegativeProximityLocked); 1115 pw.println(" mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked); 1116 } 1117 1118 pw.println(); 1119 pw.println("Display Controller Configuration:"); 1120 pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig); 1121 pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum); 1122 pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum); 1123 pw.println(" mUseSoftwareAutoBrightnessConfig=" 1124 + mUseSoftwareAutoBrightnessConfig); 1125 pw.println(" mScreenAutoBrightnessSpline=" + mScreenAutoBrightnessSpline); 1126 pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig); 1127 1128 mHandler.runWithScissors(new Runnable() { 1129 @Override 1130 public void run() { 1131 dumpLocal(pw); 1132 } 1133 }, 1000); 1134 } 1135 1136 private void dumpLocal(PrintWriter pw) { 1137 pw.println(); 1138 pw.println("Display Controller Thread State:"); 1139 pw.println(" mPowerRequest=" + mPowerRequest); 1140 pw.println(" mWaitingForNegativeProximity=" + mWaitingForNegativeProximity); 1141 1142 pw.println(" mProximitySensor=" + mProximitySensor); 1143 pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled); 1144 pw.println(" mProximityThreshold=" + mProximityThreshold); 1145 pw.println(" mProximity=" + proximityToString(mProximity)); 1146 pw.println(" mPendingProximity=" + proximityToString(mPendingProximity)); 1147 pw.println(" mPendingProximityDebounceTime=" 1148 + TimeUtils.formatUptime(mPendingProximityDebounceTime)); 1149 pw.println(" mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity); 1150 1151 pw.println(" mLightSensor=" + mLightSensor); 1152 pw.println(" mLightSensorEnabled=" + mLightSensorEnabled); 1153 pw.println(" mLightSensorEnableTime=" 1154 + TimeUtils.formatUptime(mLightSensorEnableTime)); 1155 pw.println(" mLightMeasurement=" + mLightMeasurement); 1156 pw.println(" mLightMeasurementValid=" + mLightMeasurementValid); 1157 pw.println(" mLastLightSample=" + mLastLightSample); 1158 pw.println(" mLastLightSampleTime=" 1159 + TimeUtils.formatUptime(mLastLightSampleTime)); 1160 pw.println(" mRecentLightSamples=" + mRecentLightSamples); 1161 pw.println(" mRecentLightAverage=" + mRecentLightAverage); 1162 pw.println(" mRecentLightBrightening=" + mRecentLightBrightening); 1163 pw.println(" mRecentLightTimeConstant=" + mRecentLightTimeConstant); 1164 pw.println(" mFirstRecentLightSampleTime=" 1165 + TimeUtils.formatUptime(mFirstRecentLightSampleTime)); 1166 pw.println(" mPendingLightSensorDebounceTime=" 1167 + TimeUtils.formatUptime(mPendingLightSensorDebounceTime)); 1168 pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness); 1169 pw.println(" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness); 1170 pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma); 1171 pw.println(" mTwilight.getCurrentState()=" + mTwilight.getCurrentState()); 1172 1173 if (mElectronBeamOnAnimator != null) { 1174 pw.println(" mElectronBeamOnAnimator.isStarted()=" + 1175 mElectronBeamOnAnimator.isStarted()); 1176 } 1177 if (mElectronBeamOffAnimator != null) { 1178 pw.println(" mElectronBeamOffAnimator.isStarted()=" + 1179 mElectronBeamOffAnimator.isStarted()); 1180 } 1181 1182 if (mPowerState != null) { 1183 mPowerState.dump(pw); 1184 } 1185 } 1186 1187 private static String proximityToString(int state) { 1188 switch (state) { 1189 case PROXIMITY_UNKNOWN: 1190 return "Unknown"; 1191 case PROXIMITY_NEGATIVE: 1192 return "Negative"; 1193 case PROXIMITY_POSITIVE: 1194 return "Positive"; 1195 default: 1196 return Integer.toString(state); 1197 } 1198 } 1199 1200 private static boolean wantScreenOn(int state) { 1201 switch (state) { 1202 case DisplayPowerRequest.SCREEN_STATE_BRIGHT: 1203 case DisplayPowerRequest.SCREEN_STATE_DIM: 1204 return true; 1205 } 1206 return false; 1207 } 1208 1209 /** 1210 * Asynchronous callbacks from the power controller to the power manager service. 1211 */ 1212 public interface Callbacks { 1213 void onStateChanged(); 1214 void onProximityPositive(); 1215 void onProximityNegative(); 1216 } 1217 1218 private final class DisplayControllerHandler extends Handler { 1219 public DisplayControllerHandler(Looper looper) { 1220 super(looper, null, true /*async*/); 1221 } 1222 1223 @Override 1224 public void handleMessage(Message msg) { 1225 switch (msg.what) { 1226 case MSG_UPDATE_POWER_STATE: 1227 updatePowerState(); 1228 break; 1229 1230 case MSG_PROXIMITY_SENSOR_DEBOUNCED: 1231 debounceProximitySensor(); 1232 break; 1233 1234 case MSG_LIGHT_SENSOR_DEBOUNCED: 1235 debounceLightSensor(); 1236 break; 1237 } 1238 } 1239 } 1240 1241 private final SensorEventListener mProximitySensorListener = new SensorEventListener() { 1242 @Override 1243 public void onSensorChanged(SensorEvent event) { 1244 if (mProximitySensorEnabled) { 1245 final long time = SystemClock.uptimeMillis(); 1246 final float distance = event.values[0]; 1247 boolean positive = distance >= 0.0f && distance < mProximityThreshold; 1248 handleProximitySensorEvent(time, positive); 1249 } 1250 } 1251 1252 @Override 1253 public void onAccuracyChanged(Sensor sensor, int accuracy) { 1254 // Not used. 1255 } 1256 }; 1257 1258 private final SensorEventListener mLightSensorListener = new SensorEventListener() { 1259 @Override 1260 public void onSensorChanged(SensorEvent event) { 1261 if (mLightSensorEnabled) { 1262 final long time = SystemClock.uptimeMillis(); 1263 final float lux = event.values[0]; 1264 handleLightSensorEvent(time, lux); 1265 } 1266 } 1267 1268 @Override 1269 public void onAccuracyChanged(Sensor sensor, int accuracy) { 1270 // Not used. 1271 } 1272 }; 1273 1274 private final TwilightService.TwilightListener mTwilightListener = 1275 new TwilightService.TwilightListener() { 1276 @Override 1277 public void onTwilightStateChanged() { 1278 mTwilightChanged = true; 1279 updatePowerState(); 1280 } 1281 }; 1282} 1283