blob: 4f8cdde9994149f1e43c417b7ac1ae38edff0e17 [file] [log] [blame]
Jeff Brown96307042012-07-27 15:51:34 -07001/*
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;
Jeff Brownaa202a62012-08-21 22:14:26 -070020import com.android.server.TwilightService;
21import com.android.server.TwilightService.TwilightState;
Jeff Brown96307042012-07-27 15:51:34 -070022
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;
Jeff Brown98365d72012-08-19 20:30:52 -070032import android.hardware.display.DisplayManager;
Jeff Brown96307042012-07-27 15:51:34 -070033import android.os.AsyncTask;
34import android.os.Handler;
35import android.os.Looper;
36import android.os.Message;
Jeff Brown330560f2012-08-21 22:10:57 -070037import android.os.PowerManager;
Jeff Brown96307042012-07-27 15:51:34 -070038import android.os.SystemClock;
Jeff Brown330560f2012-08-21 22:10:57 -070039import android.text.format.DateUtils;
40import android.util.FloatMath;
Jeff Brown96307042012-07-27 15:51:34 -070041import android.util.Slog;
Jeff Brown1a30b552012-08-16 01:31:11 -070042import android.util.Spline;
Jeff Brown96307042012-07-27 15:51:34 -070043import android.util.TimeUtils;
Jeff Brown98365d72012-08-19 20:30:52 -070044import android.view.Display;
Jeff Brown96307042012-07-27 15:51:34 -070045
46import java.io.PrintWriter;
Jeff Brown96307042012-07-27 15:51:34 -070047import 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
Jeff Brown13c589b2012-08-16 16:20:54 -070078 // 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
Jeff Brown5356c7dc2012-08-20 20:17:36 -070081 // screen state returns. Playing the animation can also be somewhat slow.
82 private static final boolean USE_ELECTRON_BEAM_ON_ANIMATION = false;
Jeff Brown13c589b2012-08-16 16:20:54 -070083
Jeff Brown330560f2012-08-21 22:10:57 -070084 // If true, enables the use of the screen auto-brightness adjustment setting.
Jeff Brown631938f2012-09-08 15:11:11 -070085 private static final boolean USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT =
86 PowerManager.useScreenAutoBrightnessAdjustmentFeature();
Jeff Brown330560f2012-08-21 22:10:57 -070087
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
Jeff Brownaa202a62012-08-21 22:14:26 -070092 // If true, enables the use of the current time as an auto-brightness adjustment.
93 // The basic idea here is to expand the dynamic range of auto-brightness
94 // when it is especially dark outside. The light sensor tends to perform
95 // poorly at low light levels so we compensate for it by making an
96 // assumption about the environment.
Jeff Browndb212842012-10-01 14:33:09 -070097 private static final boolean USE_TWILIGHT_ADJUSTMENT =
98 PowerManager.useTwilightAdjustmentFeature();
Jeff Brownaa202a62012-08-21 22:14:26 -070099
100 // Specifies the maximum magnitude of the time of day adjustment.
101 private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1.5f;
102
103 // The amount of time after or before sunrise over which to start adjusting
104 // the gamma. We want the change to happen gradually so that it is below the
105 // threshold of perceptibility and so that the adjustment has maximum effect
106 // well after dusk.
107 private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2;
108
Jeff Brown00a8f4f2012-08-21 23:11:46 -0700109 private static final int ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS = 250;
110 private static final int ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS = 450;
Jeff Brown96307042012-07-27 15:51:34 -0700111
112 private static final int MSG_UPDATE_POWER_STATE = 1;
113 private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
114 private static final int MSG_LIGHT_SENSOR_DEBOUNCED = 3;
115
116 private static final int PROXIMITY_UNKNOWN = -1;
117 private static final int PROXIMITY_NEGATIVE = 0;
118 private static final int PROXIMITY_POSITIVE = 1;
119
120 // Proximity sensor debounce delay in milliseconds.
121 private static final int PROXIMITY_SENSOR_DEBOUNCE_DELAY = 250;
122
123 // Trigger proximity if distance is less than 5 cm.
124 private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
125
126 // Light sensor event rate in microseconds.
127 private static final int LIGHT_SENSOR_RATE = 1000000;
128
129 // Brightness animation ramp rate in brightness units per second.
130 private static final int BRIGHTNESS_RAMP_RATE_FAST = 200;
Jeff Brown5f47ba42012-08-20 14:02:12 -0700131 private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
Jeff Brown96307042012-07-27 15:51:34 -0700132
133 // Filter time constant in milliseconds for computing a moving
134 // average of light samples. Different constants are used
Jeff Brown06565b62012-08-15 21:10:32 -0700135 // to calculate the average light level when adapting to brighter or
136 // dimmer environments.
Jeff Brown1a30b552012-08-16 01:31:11 -0700137 // This parameter only controls the filtering of light samples.
Jeff Brown5f47ba42012-08-20 14:02:12 -0700138 private static final long BRIGHTENING_LIGHT_TIME_CONSTANT = 600;
139 private static final long DIMMING_LIGHT_TIME_CONSTANT = 4000;
Jeff Brown06565b62012-08-15 21:10:32 -0700140
141 // Stability requirements in milliseconds for accepting a new brightness
142 // level. This is used for debouncing the light sensor. Different constants
143 // are used to debounce the light sensor when adapting to brighter or dimmer
144 // environments.
145 // This parameter controls how quickly brightness changes occur in response to
146 // an observed change in light level.
147 private static final long BRIGHTENING_LIGHT_DEBOUNCE = 2500;
148 private static final long DIMMING_LIGHT_DEBOUNCE = 10000;
Jeff Brown96307042012-07-27 15:51:34 -0700149
150 private final Object mLock = new Object();
151
152 // Notifier for sending asynchronous notifications.
153 private final Notifier mNotifier;
154
155 // A suspend blocker.
156 private final SuspendBlocker mSuspendBlocker;
157
158 // Our handler.
159 private final DisplayControllerHandler mHandler;
160
161 // Asynchronous callbacks into the power manager service.
162 // Only invoked from the handler thread while no locks are held.
163 private final Callbacks mCallbacks;
164 private Handler mCallbackHandler;
165
166 // The lights service.
167 private final LightsService mLights;
168
Jeff Brownaa202a62012-08-21 22:14:26 -0700169 // The twilight service.
170 private final TwilightService mTwilight;
171
Jeff Brownbd6e1502012-08-28 03:27:37 -0700172 // The display manager.
173 private final DisplayManager mDisplayManager;
174
Jeff Brown96307042012-07-27 15:51:34 -0700175 // The sensor manager.
176 private final SensorManager mSensorManager;
177
178 // The proximity sensor, or null if not available or needed.
179 private Sensor mProximitySensor;
180
181 // The light sensor, or null if not available or needed.
182 private Sensor mLightSensor;
183
184 // The dim screen brightness.
185 private final int mScreenBrightnessDimConfig;
186
Jeff Brown330560f2012-08-21 22:10:57 -0700187 // True if auto-brightness should be used.
Jeff Brown96307042012-07-27 15:51:34 -0700188 private boolean mUseSoftwareAutoBrightnessConfig;
Jeff Brown330560f2012-08-21 22:10:57 -0700189
190 // The auto-brightness spline adjustment.
191 // The brightness values have been scaled to a range of 0..1.
Jeff Brown1a30b552012-08-16 01:31:11 -0700192 private Spline mScreenAutoBrightnessSpline;
Jeff Brown96307042012-07-27 15:51:34 -0700193
194 // Amount of time to delay auto-brightness after screen on while waiting for
195 // the light sensor to warm-up in milliseconds.
196 // May be 0 if no warm-up is required.
197 private int mLightSensorWarmUpTimeConfig;
198
199 // The pending power request.
200 // Initially null until the first call to requestPowerState.
201 // Guarded by mLock.
202 private DisplayPowerRequest mPendingRequestLocked;
203
204 // True if a request has been made to wait for the proximity sensor to go negative.
205 // Guarded by mLock.
206 private boolean mPendingWaitForNegativeProximityLocked;
207
208 // True if the pending power request or wait for negative proximity flag
209 // has been changed since the last update occurred.
210 // Guarded by mLock.
211 private boolean mPendingRequestChangedLocked;
212
213 // Set to true when the important parts of the pending power request have been applied.
214 // The important parts are mainly the screen state. Brightness changes may occur
215 // concurrently.
216 // Guarded by mLock.
217 private boolean mDisplayReadyLocked;
218
219 // Set to true if a power state update is required.
220 // Guarded by mLock.
221 private boolean mPendingUpdatePowerStateLocked;
222
223 /* The following state must only be accessed by the handler thread. */
224
225 // The currently requested power state.
226 // The power controller will progressively update its internal state to match
227 // the requested power state. Initially null until the first update.
228 private DisplayPowerRequest mPowerRequest;
229
230 // The current power state.
231 // Must only be accessed on the handler thread.
232 private DisplayPowerState mPowerState;
233
234 // True if the device should wait for negative proximity sensor before
235 // waking up the screen. This is set to false as soon as a negative
236 // proximity sensor measurement is observed or when the device is forced to
237 // go to sleep by the user. While true, the screen remains off.
238 private boolean mWaitingForNegativeProximity;
239
240 // The actual proximity sensor threshold value.
241 private float mProximityThreshold;
242
243 // Set to true if the proximity sensor listener has been registered
244 // with the sensor manager.
245 private boolean mProximitySensorEnabled;
246
247 // The debounced proximity sensor state.
248 private int mProximity = PROXIMITY_UNKNOWN;
249
250 // The raw non-debounced proximity sensor state.
251 private int mPendingProximity = PROXIMITY_UNKNOWN;
252 private long mPendingProximityDebounceTime;
253
254 // True if the screen was turned off because of the proximity sensor.
255 // When the screen turns on again, we report user activity to the power manager.
256 private boolean mScreenOffBecauseOfProximity;
257
258 // Set to true if the light sensor is enabled.
259 private boolean mLightSensorEnabled;
260
261 // The time when the light sensor was enabled.
262 private long mLightSensorEnableTime;
263
264 // The currently accepted average light sensor value.
265 private float mLightMeasurement;
266
267 // True if the light sensor measurement is valid.
268 private boolean mLightMeasurementValid;
269
270 // The number of light sensor samples that have been collected since the
271 // last time a light sensor reading was accepted.
272 private int mRecentLightSamples;
273
274 // The moving average of recent light sensor values.
275 private float mRecentLightAverage;
276
277 // True if recent light samples are getting brighter than the previous
278 // stable light measurement.
279 private boolean mRecentLightBrightening;
280
281 // The time constant to use for filtering based on whether the
282 // light appears to be brightening or dimming.
283 private long mRecentLightTimeConstant;
284
285 // The most recent light sample.
286 private float mLastLightSample;
287
288 // The time of the most light recent sample.
289 private long mLastLightSampleTime;
290
Jeff Brown06565b62012-08-15 21:10:32 -0700291 // The time when we accumulated the first recent light sample into mRecentLightSamples.
292 private long mFirstRecentLightSampleTime;
293
Jeff Brown96307042012-07-27 15:51:34 -0700294 // The upcoming debounce light sensor time.
295 // This is only valid when mLightMeasurementValue && mRecentLightSamples >= 1.
296 private long mPendingLightSensorDebounceTime;
297
298 // The screen brightness level that has been chosen by the auto-brightness
299 // algorithm. The actual brightness should ramp towards this value.
300 // We preserve this value even when we stop using the light sensor so
301 // that we can quickly revert to the previous auto-brightness level
302 // while the light sensor warms up.
303 // Use -1 if there is no current auto-brightness value available.
304 private int mScreenAutoBrightness = -1;
305
Jeff Brown330560f2012-08-21 22:10:57 -0700306 // The last screen auto-brightness gamma. (For printing in dump() only.)
307 private float mLastScreenAutoBrightnessGamma = 1.0f;
308
Jeff Brown96307042012-07-27 15:51:34 -0700309 // True if the screen auto-brightness value is actually being used to
310 // set the display brightness.
311 private boolean mUsingScreenAutoBrightness;
312
313 // Animators.
314 private ObjectAnimator mElectronBeamOnAnimator;
315 private ObjectAnimator mElectronBeamOffAnimator;
316 private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
317
Jeff Brownaa202a62012-08-21 22:14:26 -0700318 // Twilight changed. We might recalculate auto-brightness values.
319 private boolean mTwilightChanged;
320
Jeff Brown96307042012-07-27 15:51:34 -0700321 /**
322 * Creates the display power controller.
323 */
324 public DisplayPowerController(Looper looper, Context context, Notifier notifier,
Jeff Brownaa202a62012-08-21 22:14:26 -0700325 LightsService lights, TwilightService twilight, SuspendBlocker suspendBlocker,
Jeff Brown96307042012-07-27 15:51:34 -0700326 Callbacks callbacks, Handler callbackHandler) {
327 mHandler = new DisplayControllerHandler(looper);
328 mNotifier = notifier;
329 mSuspendBlocker = suspendBlocker;
330 mCallbacks = callbacks;
331 mCallbackHandler = callbackHandler;
332
333 mLights = lights;
Jeff Brownaa202a62012-08-21 22:14:26 -0700334 mTwilight = twilight;
Jeff Brown96307042012-07-27 15:51:34 -0700335 mSensorManager = new SystemSensorManager(mHandler.getLooper());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700336 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
Jeff Brown96307042012-07-27 15:51:34 -0700337
338 final Resources resources = context.getResources();
339 mScreenBrightnessDimConfig = resources.getInteger(
340 com.android.internal.R.integer.config_screenBrightnessDim);
341 mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
342 com.android.internal.R.bool.config_automatic_brightness_available);
343 if (mUseSoftwareAutoBrightnessConfig) {
Jeff Brown1a30b552012-08-16 01:31:11 -0700344 int[] lux = resources.getIntArray(
Jeff Brown96307042012-07-27 15:51:34 -0700345 com.android.internal.R.array.config_autoBrightnessLevels);
Jeff Brown1a30b552012-08-16 01:31:11 -0700346 int[] screenBrightness = resources.getIntArray(
Jeff Brown96307042012-07-27 15:51:34 -0700347 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
Jeff Brown1a30b552012-08-16 01:31:11 -0700348
349 mScreenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
350 if (mScreenAutoBrightnessSpline == null) {
Jeff Brown96307042012-07-27 15:51:34 -0700351 Slog.e(TAG, "Error in config.xml. config_autoBrightnessLcdBacklightValues "
Jeff Brown1a30b552012-08-16 01:31:11 -0700352 + "(size " + screenBrightness.length + ") "
353 + "must be monotic and have exactly one more entry than "
354 + "config_autoBrightnessLevels (size " + lux.length + ") "
355 + "which must be strictly increasing. "
Jeff Brown96307042012-07-27 15:51:34 -0700356 + "Auto-brightness will be disabled.");
357 mUseSoftwareAutoBrightnessConfig = false;
358 }
359
360 mLightSensorWarmUpTimeConfig = resources.getInteger(
361 com.android.internal.R.integer.config_lightSensorWarmupTime);
362 }
363
364 if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
365 mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
366 if (mProximitySensor != null) {
367 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
368 TYPICAL_PROXIMITY_THRESHOLD);
369 }
370 }
371
372 if (mUseSoftwareAutoBrightnessConfig
373 && !DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
374 mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
375 }
Jeff Brownaa202a62012-08-21 22:14:26 -0700376
377 if (mUseSoftwareAutoBrightnessConfig && USE_TWILIGHT_ADJUSTMENT) {
378 mTwilight.registerListener(mTwilightListener, mHandler);
379 }
Jeff Brown96307042012-07-27 15:51:34 -0700380 }
381
Jeff Brown1a30b552012-08-16 01:31:11 -0700382 private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) {
383 try {
384 final int n = brightness.length;
385 float[] x = new float[n];
386 float[] y = new float[n];
Jeff Brown330560f2012-08-21 22:10:57 -0700387 y[0] = (float)brightness[0] / PowerManager.BRIGHTNESS_ON;
Jeff Brown1a30b552012-08-16 01:31:11 -0700388 for (int i = 1; i < n; i++) {
389 x[i] = lux[i - 1];
Jeff Brown330560f2012-08-21 22:10:57 -0700390 y[i] = (float)brightness[i] / PowerManager.BRIGHTNESS_ON;
Jeff Brown1a30b552012-08-16 01:31:11 -0700391 }
392
393 Spline spline = Spline.createMonotoneCubicSpline(x, y);
394 if (false) {
395 Slog.d(TAG, "Auto-brightness spline: " + spline);
396 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
397 Slog.d(TAG, String.format(" %7.1f: %7.1f", v, spline.interpolate(v)));
398 }
399 }
400 return spline;
401 } catch (IllegalArgumentException ex) {
402 Slog.e(TAG, "Could not create auto-brightness spline.", ex);
403 return null;
404 }
405 }
406
Jeff Brown96307042012-07-27 15:51:34 -0700407 /**
408 * Returns true if the proximity sensor screen-off function is available.
409 */
410 public boolean isProximitySensorAvailable() {
411 return mProximitySensor != null;
412 }
413
414 /**
415 * Requests a new power state.
416 * The controller makes a copy of the provided object and then
417 * begins adjusting the power state to match what was requested.
418 *
419 * @param request The requested power state.
420 * @param waitForNegativeProximity If true, issues a request to wait for
421 * negative proximity before turning the screen back on, assuming the screen
422 * was turned off by the proximity sensor.
423 * @return True if display is ready, false if there are important changes that must
424 * be made asynchronously (such as turning the screen on), in which case the caller
425 * should grab a wake lock, watch for {@link Callbacks#onStateChanged()} then try
426 * the request again later until the state converges.
427 */
428 public boolean requestPowerState(DisplayPowerRequest request,
429 boolean waitForNegativeProximity) {
430 if (DEBUG) {
431 Slog.d(TAG, "requestPowerState: "
432 + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
433 }
434
435 synchronized (mLock) {
436 boolean changed = false;
437
438 if (waitForNegativeProximity
439 && !mPendingWaitForNegativeProximityLocked) {
440 mPendingWaitForNegativeProximityLocked = true;
441 changed = true;
442 }
443
444 if (mPendingRequestLocked == null) {
445 mPendingRequestLocked = new DisplayPowerRequest(request);
446 changed = true;
447 } else if (!mPendingRequestLocked.equals(request)) {
448 mPendingRequestLocked.copyFrom(request);
449 changed = true;
450 }
451
452 if (changed) {
453 mDisplayReadyLocked = false;
454 }
455
456 if (changed && !mPendingRequestChangedLocked) {
457 mPendingRequestChangedLocked = true;
458 sendUpdatePowerStateLocked();
459 }
460
461 return mDisplayReadyLocked;
462 }
463 }
464
465 private void sendUpdatePowerState() {
466 synchronized (mLock) {
467 sendUpdatePowerStateLocked();
468 }
469 }
470
471 private void sendUpdatePowerStateLocked() {
472 if (!mPendingUpdatePowerStateLocked) {
473 mPendingUpdatePowerStateLocked = true;
474 Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
475 msg.setAsynchronous(true);
476 mHandler.sendMessage(msg);
477 }
478 }
479
480 private void initialize() {
481 final Executor executor = AsyncTask.THREAD_POOL_EXECUTOR;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700482 Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
Jeff Brown98365d72012-08-19 20:30:52 -0700483 mPowerState = new DisplayPowerState(new ElectronBeam(display),
Jeff Brown96307042012-07-27 15:51:34 -0700484 new PhotonicModulator(executor,
485 mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT),
486 mSuspendBlocker));
487
488 mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
489 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f);
490 mElectronBeamOnAnimator.setDuration(ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS);
491 mElectronBeamOnAnimator.addListener(mAnimatorListener);
492
493 mElectronBeamOffAnimator = ObjectAnimator.ofFloat(
494 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 1.0f, 0.0f);
495 mElectronBeamOffAnimator.setDuration(ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS);
496 mElectronBeamOffAnimator.addListener(mAnimatorListener);
497
498 mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
499 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
500 }
501
502 private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
503 @Override
504 public void onAnimationStart(Animator animation) {
505 }
506 @Override
507 public void onAnimationEnd(Animator animation) {
508 sendUpdatePowerState();
509 }
510 @Override
511 public void onAnimationRepeat(Animator animation) {
512 }
513 @Override
514 public void onAnimationCancel(Animator animation) {
515 }
516 };
517
518 private void updatePowerState() {
519 // Update the power state request.
520 final boolean mustNotify;
521 boolean mustInitialize = false;
Jeff Brownaa202a62012-08-21 22:14:26 -0700522 boolean updateAutoBrightness = mTwilightChanged;
523 mTwilightChanged = false;
Jeff Brown330560f2012-08-21 22:10:57 -0700524
Jeff Brown96307042012-07-27 15:51:34 -0700525 synchronized (mLock) {
526 mPendingUpdatePowerStateLocked = false;
527 if (mPendingRequestLocked == null) {
528 return; // wait until first actual power request
529 }
530
531 if (mPowerRequest == null) {
532 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
533 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
Jeff Brown6307a152012-08-20 13:24:23 -0700534 mPendingWaitForNegativeProximityLocked = false;
Jeff Brown96307042012-07-27 15:51:34 -0700535 mPendingRequestChangedLocked = false;
536 mustInitialize = true;
537 } else if (mPendingRequestChangedLocked) {
Jeff Brown330560f2012-08-21 22:10:57 -0700538 if (mPowerRequest.screenAutoBrightnessAdjustment
539 != mPendingRequestLocked.screenAutoBrightnessAdjustment) {
540 updateAutoBrightness = true;
541 }
Jeff Brown96307042012-07-27 15:51:34 -0700542 mPowerRequest.copyFrom(mPendingRequestLocked);
543 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
Jeff Brown6307a152012-08-20 13:24:23 -0700544 mPendingWaitForNegativeProximityLocked = false;
Jeff Brown96307042012-07-27 15:51:34 -0700545 mPendingRequestChangedLocked = false;
546 mDisplayReadyLocked = false;
547 }
548
549 mustNotify = !mDisplayReadyLocked;
550 }
551
552 // Initialize things the first time the power state is changed.
553 if (mustInitialize) {
554 initialize();
555 }
556
Jeff Brown6307a152012-08-20 13:24:23 -0700557 // Apply the proximity sensor.
Jeff Brown96307042012-07-27 15:51:34 -0700558 if (mProximitySensor != null) {
Jeff Brown6307a152012-08-20 13:24:23 -0700559 if (mPowerRequest.useProximitySensor
560 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
561 setProximitySensorEnabled(true);
562 if (!mScreenOffBecauseOfProximity
563 && mProximity == PROXIMITY_POSITIVE) {
564 mScreenOffBecauseOfProximity = true;
565 setScreenOn(false);
566 }
567 } else if (mWaitingForNegativeProximity
568 && mScreenOffBecauseOfProximity
569 && mProximity == PROXIMITY_POSITIVE
570 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
571 setProximitySensorEnabled(true);
572 } else {
573 setProximitySensorEnabled(false);
574 mWaitingForNegativeProximity = false;
575 }
576 if (mScreenOffBecauseOfProximity
577 && mProximity != PROXIMITY_POSITIVE) {
Jeff Brown96307042012-07-27 15:51:34 -0700578 mScreenOffBecauseOfProximity = false;
Jeff Brown6307a152012-08-20 13:24:23 -0700579 setScreenOn(true);
Jeff Brown96307042012-07-27 15:51:34 -0700580 sendOnProximityNegative();
581 }
Jeff Brown6307a152012-08-20 13:24:23 -0700582 } else {
583 mWaitingForNegativeProximity = false;
Jeff Brown96307042012-07-27 15:51:34 -0700584 }
585
586 // Turn on the light sensor if needed.
587 if (mLightSensor != null) {
588 setLightSensorEnabled(mPowerRequest.useAutoBrightness
Jeff Brown330560f2012-08-21 22:10:57 -0700589 && wantScreenOn(mPowerRequest.screenState), updateAutoBrightness);
Jeff Brown96307042012-07-27 15:51:34 -0700590 }
591
592 // Set the screen brightness.
593 if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) {
594 // Screen is dimmed. Overrides everything else.
Jeff Brown330560f2012-08-21 22:10:57 -0700595 animateScreenBrightness(
596 clampScreenBrightness(mScreenBrightnessDimConfig),
597 BRIGHTNESS_RAMP_RATE_FAST);
Jeff Brown96307042012-07-27 15:51:34 -0700598 mUsingScreenAutoBrightness = false;
599 } else if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT) {
600 if (mScreenAutoBrightness >= 0 && mLightSensorEnabled) {
601 // Use current auto-brightness value.
602 animateScreenBrightness(
Jeff Brown330560f2012-08-21 22:10:57 -0700603 clampScreenBrightness(mScreenAutoBrightness),
Jeff Brown96307042012-07-27 15:51:34 -0700604 mUsingScreenAutoBrightness ? BRIGHTNESS_RAMP_RATE_SLOW :
605 BRIGHTNESS_RAMP_RATE_FAST);
606 mUsingScreenAutoBrightness = true;
607 } else {
608 // Light sensor is disabled or not ready yet.
609 // Use the current brightness setting from the request, which is expected
610 // provide a nominal default value for the case where auto-brightness
611 // is not ready yet.
612 animateScreenBrightness(
Jeff Brown330560f2012-08-21 22:10:57 -0700613 clampScreenBrightness(mPowerRequest.screenBrightness),
Jeff Brown96307042012-07-27 15:51:34 -0700614 BRIGHTNESS_RAMP_RATE_FAST);
615 mUsingScreenAutoBrightness = false;
616 }
617 } else {
618 // Screen is off. Don't bother changing the brightness.
619 mUsingScreenAutoBrightness = false;
620 }
621
622 // Animate the screen on or off.
623 if (!mScreenOffBecauseOfProximity) {
624 if (wantScreenOn(mPowerRequest.screenState)) {
625 // Want screen on.
626 // Wait for previous off animation to complete beforehand.
627 // It is relatively short but if we cancel it and switch to the
628 // on animation immediately then the results are pretty ugly.
629 if (!mElectronBeamOffAnimator.isStarted()) {
630 setScreenOn(true);
Jeff Brown13c589b2012-08-16 16:20:54 -0700631 if (USE_ELECTRON_BEAM_ON_ANIMATION) {
632 if (!mElectronBeamOnAnimator.isStarted()) {
633 if (mPowerState.getElectronBeamLevel() == 1.0f) {
634 mPowerState.dismissElectronBeam();
635 } else if (mPowerState.prepareElectronBeam(true)) {
636 mElectronBeamOnAnimator.start();
637 } else {
638 mElectronBeamOnAnimator.end();
639 }
Jeff Brown96307042012-07-27 15:51:34 -0700640 }
Jeff Brown13c589b2012-08-16 16:20:54 -0700641 } else {
642 mPowerState.setElectronBeamLevel(1.0f);
643 mPowerState.dismissElectronBeam();
Jeff Brown96307042012-07-27 15:51:34 -0700644 }
645 }
646 } else {
647 // Want screen off.
648 // Wait for previous on animation to complete beforehand.
649 if (!mElectronBeamOnAnimator.isStarted()) {
650 if (!mElectronBeamOffAnimator.isStarted()) {
651 if (mPowerState.getElectronBeamLevel() == 0.0f) {
652 setScreenOn(false);
653 } else if (mPowerState.prepareElectronBeam(false)
654 && mPowerState.isScreenOn()) {
655 mElectronBeamOffAnimator.start();
656 } else {
657 mElectronBeamOffAnimator.end();
658 }
659 }
660 }
661 }
662 }
663
664 // Report whether the display is ready for use.
665 // We mostly care about the screen state here, ignoring brightness changes
666 // which will be handled asynchronously.
667 if (mustNotify
668 && !mElectronBeamOnAnimator.isStarted()
669 && !mElectronBeamOffAnimator.isStarted()
670 && mPowerState.waitUntilClean(mCleanListener)) {
671 synchronized (mLock) {
672 if (!mPendingRequestChangedLocked) {
673 mDisplayReadyLocked = true;
674 }
675 }
676 sendOnStateChanged();
677 }
678 }
679
680 private void setScreenOn(boolean on) {
681 if (!mPowerState.isScreenOn() == on) {
682 mPowerState.setScreenOn(on);
683 if (on) {
684 mNotifier.onScreenOn();
685 } else {
686 mNotifier.onScreenOff();
687 }
688 }
689 }
690
Jeff Brown330560f2012-08-21 22:10:57 -0700691 private int clampScreenBrightness(int value) {
692 return Math.min(Math.max(Math.max(value, mScreenBrightnessDimConfig), 0), 255);
693 }
694
Jeff Brown96307042012-07-27 15:51:34 -0700695 private void animateScreenBrightness(int target, int rate) {
696 if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
697 mNotifier.onScreenBrightness(target);
698 }
699 }
700
701 private final Runnable mCleanListener = new Runnable() {
702 @Override
703 public void run() {
704 sendUpdatePowerState();
705 }
706 };
707
708 private void setProximitySensorEnabled(boolean enable) {
709 if (enable) {
710 if (!mProximitySensorEnabled) {
711 mProximitySensorEnabled = true;
712 mPendingProximity = PROXIMITY_UNKNOWN;
713 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
714 SensorManager.SENSOR_DELAY_NORMAL, mHandler);
715 }
716 } else {
717 if (mProximitySensorEnabled) {
718 mProximitySensorEnabled = false;
719 mProximity = PROXIMITY_UNKNOWN;
720 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
721 mSensorManager.unregisterListener(mProximitySensorListener);
722 }
723 }
724 }
725
726 private void handleProximitySensorEvent(long time, boolean positive) {
727 if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
728 return; // no change
729 }
730 if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
731 return; // no change
732 }
733
734 // Only accept a proximity sensor reading if it remains
735 // stable for the entire debounce delay.
736 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
737 mPendingProximity = positive ? PROXIMITY_POSITIVE : PROXIMITY_NEGATIVE;
738 mPendingProximityDebounceTime = time + PROXIMITY_SENSOR_DEBOUNCE_DELAY;
739 debounceProximitySensor();
740 }
741
742 private void debounceProximitySensor() {
743 if (mPendingProximity != PROXIMITY_UNKNOWN) {
744 final long now = SystemClock.uptimeMillis();
745 if (mPendingProximityDebounceTime <= now) {
746 mProximity = mPendingProximity;
747 sendUpdatePowerState();
748 } else {
749 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
750 msg.setAsynchronous(true);
751 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
752 }
753 }
754 }
755
Jeff Brown330560f2012-08-21 22:10:57 -0700756 private void setLightSensorEnabled(boolean enable, boolean updateAutoBrightness) {
Jeff Brown96307042012-07-27 15:51:34 -0700757 if (enable) {
758 if (!mLightSensorEnabled) {
Jeff Brown330560f2012-08-21 22:10:57 -0700759 updateAutoBrightness = true;
Jeff Brown96307042012-07-27 15:51:34 -0700760 mLightSensorEnabled = true;
761 mLightSensorEnableTime = SystemClock.uptimeMillis();
762 mSensorManager.registerListener(mLightSensorListener, mLightSensor,
763 LIGHT_SENSOR_RATE, mHandler);
764 }
765 } else {
766 if (mLightSensorEnabled) {
767 mLightSensorEnabled = false;
768 mLightMeasurementValid = false;
Jeff Brown96307042012-07-27 15:51:34 -0700769 mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
770 mSensorManager.unregisterListener(mLightSensorListener);
771 }
772 }
Jeff Brown330560f2012-08-21 22:10:57 -0700773 if (updateAutoBrightness) {
774 updateAutoBrightness(false);
775 }
Jeff Brown96307042012-07-27 15:51:34 -0700776 }
777
778 private void handleLightSensorEvent(long time, float lux) {
779 // Take the first few readings during the warm-up period and apply them
780 // immediately without debouncing.
781 if (!mLightMeasurementValid
782 || (time - mLightSensorEnableTime) < mLightSensorWarmUpTimeConfig) {
783 mLightMeasurement = lux;
784 mLightMeasurementValid = true;
785 mRecentLightSamples = 0;
786 updateAutoBrightness(true);
787 }
788
789 // Update our moving average.
790 if (lux != mLightMeasurement && (mRecentLightSamples == 0
791 || (lux < mLightMeasurement && mRecentLightBrightening)
792 || (lux > mLightMeasurement && !mRecentLightBrightening))) {
793 // If the newest light sample doesn't seem to be going in the
794 // same general direction as recent samples, then start over.
795 setRecentLight(time, lux, lux > mLightMeasurement);
Jeff Brown96307042012-07-27 15:51:34 -0700796 } else if (mRecentLightSamples >= 1) {
797 // Add the newest light sample to the moving average.
798 accumulateRecentLight(time, lux);
799 }
800 if (DEBUG) {
801 Slog.d(TAG, "handleLightSensorEvent: lux=" + lux
802 + ", mLightMeasurementValid=" + mLightMeasurementValid
803 + ", mLightMeasurement=" + mLightMeasurement
804 + ", mRecentLightSamples=" + mRecentLightSamples
805 + ", mRecentLightAverage=" + mRecentLightAverage
806 + ", mRecentLightBrightening=" + mRecentLightBrightening
807 + ", mRecentLightTimeConstant=" + mRecentLightTimeConstant
Jeff Brown06565b62012-08-15 21:10:32 -0700808 + ", mFirstRecentLightSampleTime="
809 + TimeUtils.formatUptime(mFirstRecentLightSampleTime)
Jeff Brown96307042012-07-27 15:51:34 -0700810 + ", mPendingLightSensorDebounceTime="
811 + TimeUtils.formatUptime(mPendingLightSensorDebounceTime));
812 }
813
814 // Debounce.
815 mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
816 debounceLightSensor();
817 }
818
819 private void setRecentLight(long time, float lux, boolean brightening) {
820 mRecentLightBrightening = brightening;
821 mRecentLightTimeConstant = brightening ?
822 BRIGHTENING_LIGHT_TIME_CONSTANT : DIMMING_LIGHT_TIME_CONSTANT;
823 mRecentLightSamples = 1;
824 mRecentLightAverage = lux;
825 mLastLightSample = lux;
826 mLastLightSampleTime = time;
Jeff Brown06565b62012-08-15 21:10:32 -0700827 mFirstRecentLightSampleTime = time;
828 mPendingLightSensorDebounceTime = time + (brightening ?
829 BRIGHTENING_LIGHT_DEBOUNCE : DIMMING_LIGHT_DEBOUNCE);
Jeff Brown96307042012-07-27 15:51:34 -0700830 }
831
832 private void accumulateRecentLight(long time, float lux) {
833 final long timeDelta = time - mLastLightSampleTime;
834 mRecentLightSamples += 1;
835 mRecentLightAverage += (lux - mRecentLightAverage) *
836 timeDelta / (mRecentLightTimeConstant + timeDelta);
837 mLastLightSample = lux;
838 mLastLightSampleTime = time;
839 }
840
841 private void debounceLightSensor() {
842 if (mLightMeasurementValid && mRecentLightSamples >= 1) {
843 final long now = SystemClock.uptimeMillis();
844 if (mPendingLightSensorDebounceTime <= now) {
845 accumulateRecentLight(now, mLastLightSample);
846 mLightMeasurement = mRecentLightAverage;
847
848 if (DEBUG) {
849 Slog.d(TAG, "debounceLightSensor: Accepted new measurement "
850 + mLightMeasurement + " after "
Jeff Brown06565b62012-08-15 21:10:32 -0700851 + (now - mFirstRecentLightSampleTime) + " ms based on "
Jeff Brown96307042012-07-27 15:51:34 -0700852 + mRecentLightSamples + " recent samples.");
853 }
854
855 updateAutoBrightness(true);
856
857 // Now that we have debounced the light sensor data, we have the
858 // option of either leaving the sensor in a debounced state or
859 // restarting the debounce cycle by setting mRecentLightSamples to 0.
860 //
861 // If we leave the sensor debounced, then new average light measurements
862 // may be accepted immediately as long as they are trending in the same
863 // direction as they were before. If the measurements start
864 // jittering or trending in the opposite direction then the debounce
865 // cycle will automatically be restarted. The benefit is that the
866 // auto-brightness control can be more responsive to changes over a
867 // broad range.
868 //
869 // For now, we choose to be more responsive and leave the following line
870 // commented out.
871 //
872 // mRecentLightSamples = 0;
873 } else {
874 Message msg = mHandler.obtainMessage(MSG_LIGHT_SENSOR_DEBOUNCED);
875 msg.setAsynchronous(true);
876 mHandler.sendMessageAtTime(msg, mPendingLightSensorDebounceTime);
877 }
878 }
879 }
880
881 private void updateAutoBrightness(boolean sendUpdate) {
882 if (!mLightMeasurementValid) {
883 return;
884 }
885
Jeff Brown330560f2012-08-21 22:10:57 -0700886 float value = mScreenAutoBrightnessSpline.interpolate(mLightMeasurement);
887 float gamma = 1.0f;
888
889 if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT
890 && mPowerRequest.screenAutoBrightnessAdjustment != 0.0f) {
891 final float adjGamma = FloatMath.pow(SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA,
892 Math.min(1.0f, Math.max(-1.0f,
893 -mPowerRequest.screenAutoBrightnessAdjustment)));
894 gamma *= adjGamma;
895 if (DEBUG) {
896 Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma);
897 }
898 }
899
Jeff Brownaa202a62012-08-21 22:14:26 -0700900 if (USE_TWILIGHT_ADJUSTMENT) {
901 TwilightState state = mTwilight.getCurrentState();
902 if (state != null && state.isNight()) {
903 final long now = System.currentTimeMillis();
904 final float earlyGamma =
905 getTwilightGamma(now, state.getYesterdaySunset(), state.getTodaySunrise());
906 final float lateGamma =
907 getTwilightGamma(now, state.getTodaySunset(), state.getTomorrowSunrise());
908 gamma *= earlyGamma * lateGamma;
909 if (DEBUG) {
910 Slog.d(TAG, "updateAutoBrightness: earlyGamma=" + earlyGamma
911 + ", lateGamma=" + lateGamma);
912 }
913 }
914 }
915
Jeff Brown330560f2012-08-21 22:10:57 -0700916 if (gamma != 1.0f) {
917 final float in = value;
918 value = FloatMath.pow(value, gamma);
919 if (DEBUG) {
920 Slog.d(TAG, "updateAutoBrightness: gamma=" + gamma
921 + ", in=" + in + ", out=" + value);
922 }
923 }
924
925 int newScreenAutoBrightness = clampScreenBrightness(
926 (int)Math.round(value * PowerManager.BRIGHTNESS_ON));
Jeff Brown96307042012-07-27 15:51:34 -0700927 if (mScreenAutoBrightness != newScreenAutoBrightness) {
928 if (DEBUG) {
929 Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness="
Jeff Brown330560f2012-08-21 22:10:57 -0700930 + mScreenAutoBrightness + ", newScreenAutoBrightness="
Jeff Brown1a30b552012-08-16 01:31:11 -0700931 + newScreenAutoBrightness);
Jeff Brown96307042012-07-27 15:51:34 -0700932 }
933
934 mScreenAutoBrightness = newScreenAutoBrightness;
Jeff Brown330560f2012-08-21 22:10:57 -0700935 mLastScreenAutoBrightnessGamma = gamma;
Jeff Brown96307042012-07-27 15:51:34 -0700936 if (sendUpdate) {
937 sendUpdatePowerState();
938 }
939 }
940 }
941
Jeff Brownaa202a62012-08-21 22:14:26 -0700942 private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) {
943 if (lastSunset < 0 || nextSunrise < 0
944 || now < lastSunset || now > nextSunrise) {
945 return 1.0f;
946 }
947
948 if (now < lastSunset + TWILIGHT_ADJUSTMENT_TIME) {
949 return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
950 (float)(now - lastSunset) / TWILIGHT_ADJUSTMENT_TIME);
951 }
952
953 if (now > nextSunrise - TWILIGHT_ADJUSTMENT_TIME) {
954 return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
955 (float)(nextSunrise - now) / TWILIGHT_ADJUSTMENT_TIME);
956 }
957
958 return TWILIGHT_ADJUSTMENT_MAX_GAMMA;
959 }
960
961 private static float lerp(float x, float y, float alpha) {
962 return x + (y - x) * alpha;
963 }
964
Jeff Brown96307042012-07-27 15:51:34 -0700965 private void sendOnStateChanged() {
966 mCallbackHandler.post(mOnStateChangedRunnable);
967 }
968
969 private final Runnable mOnStateChangedRunnable = new Runnable() {
970 @Override
971 public void run() {
972 mCallbacks.onStateChanged();
973 }
974 };
975
976 private void sendOnProximityNegative() {
977 mCallbackHandler.post(mOnProximityNegativeRunnable);
978 }
979
980 private final Runnable mOnProximityNegativeRunnable = new Runnable() {
981 @Override
982 public void run() {
983 mCallbacks.onProximityNegative();
984 }
985 };
986
Jeff Brownbd6e1502012-08-28 03:27:37 -0700987 public void dump(final PrintWriter pw) {
Jeff Brown96307042012-07-27 15:51:34 -0700988 synchronized (mLock) {
989 pw.println();
990 pw.println("Display Controller Locked State:");
991 pw.println(" mDisplayReadyLocked=" + mDisplayReadyLocked);
992 pw.println(" mPendingRequestLocked=" + mPendingRequestLocked);
993 pw.println(" mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
994 pw.println(" mPendingWaitForNegativeProximityLocked="
995 + mPendingWaitForNegativeProximityLocked);
996 pw.println(" mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
997 }
998
999 pw.println();
1000 pw.println("Display Controller Configuration:");
1001 pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
1002 pw.println(" mUseSoftwareAutoBrightnessConfig="
1003 + mUseSoftwareAutoBrightnessConfig);
Jeff Brown1a30b552012-08-16 01:31:11 -07001004 pw.println(" mScreenAutoBrightnessSpline=" + mScreenAutoBrightnessSpline);
Jeff Brown96307042012-07-27 15:51:34 -07001005 pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig);
1006
Jeff Brownbd6e1502012-08-28 03:27:37 -07001007 mHandler.runWithScissors(new Runnable() {
1008 @Override
1009 public void run() {
1010 dumpLocal(pw);
Jeff Brown96307042012-07-27 15:51:34 -07001011 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001012 }, 1000);
Jeff Brown96307042012-07-27 15:51:34 -07001013 }
1014
1015 private void dumpLocal(PrintWriter pw) {
1016 pw.println();
1017 pw.println("Display Controller Thread State:");
1018 pw.println(" mPowerRequest=" + mPowerRequest);
1019 pw.println(" mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
1020
1021 pw.println(" mProximitySensor=" + mProximitySensor);
1022 pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled);
1023 pw.println(" mProximityThreshold=" + mProximityThreshold);
1024 pw.println(" mProximity=" + proximityToString(mProximity));
1025 pw.println(" mPendingProximity=" + proximityToString(mPendingProximity));
1026 pw.println(" mPendingProximityDebounceTime="
1027 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
1028 pw.println(" mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
1029
1030 pw.println(" mLightSensor=" + mLightSensor);
1031 pw.println(" mLightSensorEnabled=" + mLightSensorEnabled);
1032 pw.println(" mLightSensorEnableTime="
1033 + TimeUtils.formatUptime(mLightSensorEnableTime));
1034 pw.println(" mLightMeasurement=" + mLightMeasurement);
1035 pw.println(" mLightMeasurementValid=" + mLightMeasurementValid);
1036 pw.println(" mLastLightSample=" + mLastLightSample);
1037 pw.println(" mLastLightSampleTime="
1038 + TimeUtils.formatUptime(mLastLightSampleTime));
1039 pw.println(" mRecentLightSamples=" + mRecentLightSamples);
1040 pw.println(" mRecentLightAverage=" + mRecentLightAverage);
1041 pw.println(" mRecentLightBrightening=" + mRecentLightBrightening);
1042 pw.println(" mRecentLightTimeConstant=" + mRecentLightTimeConstant);
Jeff Brown06565b62012-08-15 21:10:32 -07001043 pw.println(" mFirstRecentLightSampleTime="
1044 + TimeUtils.formatUptime(mFirstRecentLightSampleTime));
Jeff Brown96307042012-07-27 15:51:34 -07001045 pw.println(" mPendingLightSensorDebounceTime="
1046 + TimeUtils.formatUptime(mPendingLightSensorDebounceTime));
1047 pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness);
1048 pw.println(" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness);
Jeff Brown330560f2012-08-21 22:10:57 -07001049 pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
Jeff Brownaa202a62012-08-21 22:14:26 -07001050 pw.println(" mTwilight.getCurrentState()=" + mTwilight.getCurrentState());
Jeff Brown96307042012-07-27 15:51:34 -07001051
1052 if (mElectronBeamOnAnimator != null) {
1053 pw.println(" mElectronBeamOnAnimator.isStarted()=" +
1054 mElectronBeamOnAnimator.isStarted());
1055 }
1056 if (mElectronBeamOffAnimator != null) {
1057 pw.println(" mElectronBeamOffAnimator.isStarted()=" +
1058 mElectronBeamOffAnimator.isStarted());
1059 }
1060
1061 if (mPowerState != null) {
1062 mPowerState.dump(pw);
1063 }
1064 }
1065
1066 private static String proximityToString(int state) {
1067 switch (state) {
1068 case PROXIMITY_UNKNOWN:
1069 return "Unknown";
1070 case PROXIMITY_NEGATIVE:
1071 return "Negative";
1072 case PROXIMITY_POSITIVE:
1073 return "Positive";
1074 default:
1075 return Integer.toString(state);
1076 }
1077 }
1078
1079 private static boolean wantScreenOn(int state) {
1080 switch (state) {
1081 case DisplayPowerRequest.SCREEN_STATE_BRIGHT:
1082 case DisplayPowerRequest.SCREEN_STATE_DIM:
1083 return true;
1084 }
1085 return false;
1086 }
1087
1088 /**
1089 * Asynchronous callbacks from the power controller to the power manager service.
1090 */
1091 public interface Callbacks {
1092 void onStateChanged();
1093 void onProximityNegative();
1094 }
1095
1096 private final class DisplayControllerHandler extends Handler {
1097 public DisplayControllerHandler(Looper looper) {
Jeff Browna2910d02012-08-25 12:29:46 -07001098 super(looper, null, true /*async*/);
Jeff Brown96307042012-07-27 15:51:34 -07001099 }
1100
1101 @Override
1102 public void handleMessage(Message msg) {
1103 switch (msg.what) {
1104 case MSG_UPDATE_POWER_STATE:
1105 updatePowerState();
1106 break;
1107
1108 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
1109 debounceProximitySensor();
1110 break;
1111
1112 case MSG_LIGHT_SENSOR_DEBOUNCED:
1113 debounceLightSensor();
1114 break;
1115 }
1116 }
1117 }
1118
1119 private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
1120 @Override
1121 public void onSensorChanged(SensorEvent event) {
1122 if (mProximitySensorEnabled) {
1123 final long time = SystemClock.uptimeMillis();
1124 final float distance = event.values[0];
1125 boolean positive = distance >= 0.0f && distance < mProximityThreshold;
1126 handleProximitySensorEvent(time, positive);
1127 }
1128 }
1129
1130 @Override
1131 public void onAccuracyChanged(Sensor sensor, int accuracy) {
1132 // Not used.
1133 }
1134 };
1135
1136 private final SensorEventListener mLightSensorListener = new SensorEventListener() {
1137 @Override
1138 public void onSensorChanged(SensorEvent event) {
1139 if (mLightSensorEnabled) {
1140 final long time = SystemClock.uptimeMillis();
1141 final float lux = event.values[0];
1142 handleLightSensorEvent(time, lux);
1143 }
1144 }
1145
1146 @Override
1147 public void onAccuracyChanged(Sensor sensor, int accuracy) {
1148 // Not used.
1149 }
1150 };
Jeff Brownaa202a62012-08-21 22:14:26 -07001151
1152 private final TwilightService.TwilightListener mTwilightListener =
1153 new TwilightService.TwilightListener() {
1154 @Override
1155 public void onTwilightStateChanged() {
1156 mTwilightChanged = true;
1157 updatePowerState();
1158 }
1159 };
Jeff Brown96307042012-07-27 15:51:34 -07001160}