blob: f1be504e55499b5de6c7df246bca52b6b79d8c70 [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
Adam Lesinski182f73f2013-12-05 16:48:06 -080019import com.android.server.lights.LightsManager;
20import com.android.server.twilight.TwilightListener;
21import com.android.server.twilight.TwilightManager;
Adam Lesinski182f73f2013-12-05 16:48:06 -080022import com.android.server.twilight.TwilightState;
Jeff Brown96307042012-07-27 15:51:34 -070023
24import android.animation.Animator;
25import android.animation.ObjectAnimator;
26import android.content.Context;
27import android.content.res.Resources;
28import android.hardware.Sensor;
29import android.hardware.SensorEvent;
30import android.hardware.SensorEventListener;
31import android.hardware.SensorManager;
Jeff Brown96307042012-07-27 15:51:34 -070032import android.os.Handler;
33import android.os.Looper;
34import android.os.Message;
Jeff Brown330560f2012-08-21 22:10:57 -070035import android.os.PowerManager;
Jeff Brown96307042012-07-27 15:51:34 -070036import android.os.SystemClock;
Jeff Brown330560f2012-08-21 22:10:57 -070037import android.text.format.DateUtils;
38import android.util.FloatMath;
Jeff Brown96307042012-07-27 15:51:34 -070039import android.util.Slog;
Jeff Brown1a30b552012-08-16 01:31:11 -070040import android.util.Spline;
Jeff Brown96307042012-07-27 15:51:34 -070041import android.util.TimeUtils;
42
43import java.io.PrintWriter;
Jeff Brown96307042012-07-27 15:51:34 -070044
45/**
46 * Controls the power state of the display.
47 *
48 * Handles the proximity sensor, light sensor, and animations between states
49 * including the screen off animation.
50 *
51 * This component acts independently of the rest of the power manager service.
52 * In particular, it does not share any state and it only communicates
53 * via asynchronous callbacks to inform the power manager that something has
54 * changed.
55 *
56 * Everything this class does internally is serialized on its handler although
57 * it may be accessed by other threads from the outside.
58 *
59 * Note that the power manager service guarantees that it will hold a suspend
60 * blocker as long as the display is not ready. So most of the work done here
61 * does not need to worry about holding a suspend blocker unless it happens
62 * independently of the display ready signal.
63 *
64 * For debugging, you can make the electron beam and brightness animations run
65 * slower by changing the "animator duration scale" option in Development Settings.
66 */
67final class DisplayPowerController {
68 private static final String TAG = "DisplayPowerController";
69
70 private static boolean DEBUG = false;
71 private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
72 private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false;
73
Jeff Brown13c589b2012-08-16 16:20:54 -070074 // If true, uses the electron beam on animation.
75 // We might want to turn this off if we cannot get a guarantee that the screen
76 // actually turns on and starts showing new content after the call to set the
Jeff Brown5356c7dc2012-08-20 20:17:36 -070077 // screen state returns. Playing the animation can also be somewhat slow.
78 private static final boolean USE_ELECTRON_BEAM_ON_ANIMATION = false;
Jeff Brown13c589b2012-08-16 16:20:54 -070079
Jeff Brown330560f2012-08-21 22:10:57 -070080 // If true, enables the use of the screen auto-brightness adjustment setting.
Jeff Brown631938f2012-09-08 15:11:11 -070081 private static final boolean USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT =
82 PowerManager.useScreenAutoBrightnessAdjustmentFeature();
Jeff Brown330560f2012-08-21 22:10:57 -070083
84 // The maximum range of gamma adjustment possible using the screen
85 // auto-brightness adjustment setting.
86 private static final float SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA = 3.0f;
87
Jeff Brownb76eebff2012-10-05 22:26:44 -070088 // The minimum reduction in brightness when dimmed.
89 private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10;
90
Jeff Brownaa202a62012-08-21 22:14:26 -070091 // If true, enables the use of the current time as an auto-brightness adjustment.
92 // The basic idea here is to expand the dynamic range of auto-brightness
93 // when it is especially dark outside. The light sensor tends to perform
94 // poorly at low light levels so we compensate for it by making an
95 // assumption about the environment.
Jeff Browndb212842012-10-01 14:33:09 -070096 private static final boolean USE_TWILIGHT_ADJUSTMENT =
97 PowerManager.useTwilightAdjustmentFeature();
Jeff Brownaa202a62012-08-21 22:14:26 -070098
99 // Specifies the maximum magnitude of the time of day adjustment.
100 private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1.5f;
101
102 // The amount of time after or before sunrise over which to start adjusting
103 // the gamma. We want the change to happen gradually so that it is below the
104 // threshold of perceptibility and so that the adjustment has maximum effect
105 // well after dusk.
106 private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2;
107
Jeff Brown00a8f4f2012-08-21 23:11:46 -0700108 private static final int ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS = 250;
Jeff Brown3c584f22012-10-10 14:36:00 -0700109 private static final int ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS = 400;
Jeff Brown96307042012-07-27 15:51:34 -0700110
111 private static final int MSG_UPDATE_POWER_STATE = 1;
112 private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
113 private static final int MSG_LIGHT_SENSOR_DEBOUNCED = 3;
114
115 private static final int PROXIMITY_UNKNOWN = -1;
116 private static final int PROXIMITY_NEGATIVE = 0;
117 private static final int PROXIMITY_POSITIVE = 1;
118
Jeff Brown93cbbb22012-10-04 13:18:36 -0700119 // Proximity sensor debounce delay in milliseconds for positive or negative transitions.
120 private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0;
Jeff Brownec083212013-09-11 20:45:25 -0700121 private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 250;
Jeff Brown96307042012-07-27 15:51:34 -0700122
123 // Trigger proximity if distance is less than 5 cm.
124 private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
125
Jeff Browne941b1e2012-10-22 16:50:25 -0700126 // Light sensor event rate in milliseconds.
127 private static final int LIGHT_SENSOR_RATE_MILLIS = 1000;
128
129 // A rate for generating synthetic light sensor events in the case where the light
130 // sensor hasn't reported any new data in a while and we need it to update the
131 // debounce filter. We only synthesize light sensor measurements when needed.
132 private static final int SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS =
133 LIGHT_SENSOR_RATE_MILLIS * 2;
Jeff Brown96307042012-07-27 15:51:34 -0700134
135 // Brightness animation ramp rate in brightness units per second.
136 private static final int BRIGHTNESS_RAMP_RATE_FAST = 200;
Jeff Browne941b1e2012-10-22 16:50:25 -0700137 private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
Jeff Brown96307042012-07-27 15:51:34 -0700138
Jeff Brown4f0e9692012-10-18 16:14:16 -0700139 // IIR filter time constants in milliseconds for computing two moving averages of
140 // the light samples. One is a long-term average and the other is a short-term average.
141 // We can use these filters to assess trends in ambient brightness.
142 // The short term average gives us a filtered but relatively low latency measurement.
143 // The long term average informs us about the overall trend.
144 private static final long SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 1000;
Jeff Browne941b1e2012-10-22 16:50:25 -0700145 private static final long LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 5000;
Jeff Brown06565b62012-08-15 21:10:32 -0700146
147 // Stability requirements in milliseconds for accepting a new brightness
148 // level. This is used for debouncing the light sensor. Different constants
Jeff Brown4f0e9692012-10-18 16:14:16 -0700149 // are used to debounce the light sensor when adapting to brighter or darker environments.
Jeff Brown06565b62012-08-15 21:10:32 -0700150 // This parameter controls how quickly brightness changes occur in response to
Jeff Browne941b1e2012-10-22 16:50:25 -0700151 // an observed change in light level that exceeds the hysteresis threshold.
152 private static final long BRIGHTENING_LIGHT_DEBOUNCE = 4000;
153 private static final long DARKENING_LIGHT_DEBOUNCE = 8000;
Jeff Brown4f0e9692012-10-18 16:14:16 -0700154
155 // Hysteresis constraints for brightening or darkening.
156 // The recent lux must have changed by at least this fraction relative to the
157 // current ambient lux before a change will be considered.
158 private static final float BRIGHTENING_LIGHT_HYSTERESIS = 0.10f;
159 private static final float DARKENING_LIGHT_HYSTERESIS = 0.20f;
Jeff Brown96307042012-07-27 15:51:34 -0700160
161 private final Object mLock = new Object();
162
163 // Notifier for sending asynchronous notifications.
164 private final Notifier mNotifier;
165
Jeff Brownec083212013-09-11 20:45:25 -0700166 // The display suspend blocker.
167 // Held while there are pending state change notifications.
168 private final SuspendBlocker mDisplaySuspendBlocker;
169
Jeff Brown9e316a12012-10-08 19:17:06 -0700170 // The display blanker.
171 private final DisplayBlanker mDisplayBlanker;
172
Jeff Brown96307042012-07-27 15:51:34 -0700173 // Our handler.
174 private final DisplayControllerHandler mHandler;
175
176 // Asynchronous callbacks into the power manager service.
177 // Only invoked from the handler thread while no locks are held.
178 private final Callbacks mCallbacks;
179 private Handler mCallbackHandler;
180
181 // The lights service.
Adam Lesinski182f73f2013-12-05 16:48:06 -0800182 private final LightsManager mLights;
Jeff Brown96307042012-07-27 15:51:34 -0700183
Jeff Brownaa202a62012-08-21 22:14:26 -0700184 // The twilight service.
Adam Lesinski182f73f2013-12-05 16:48:06 -0800185 private final TwilightManager mTwilight;
Jeff Brownaa202a62012-08-21 22:14:26 -0700186
Jeff Brown96307042012-07-27 15:51:34 -0700187 // The sensor manager.
188 private final SensorManager mSensorManager;
189
190 // The proximity sensor, or null if not available or needed.
191 private Sensor mProximitySensor;
192
193 // The light sensor, or null if not available or needed.
194 private Sensor mLightSensor;
195
196 // The dim screen brightness.
197 private final int mScreenBrightnessDimConfig;
198
Jeff Brownb76eebff2012-10-05 22:26:44 -0700199 // The minimum allowed brightness.
200 private final int mScreenBrightnessRangeMinimum;
201
202 // The maximum allowed brightness.
203 private final int mScreenBrightnessRangeMaximum;
204
Jeff Brown330560f2012-08-21 22:10:57 -0700205 // True if auto-brightness should be used.
Jeff Brown96307042012-07-27 15:51:34 -0700206 private boolean mUseSoftwareAutoBrightnessConfig;
Jeff Brown330560f2012-08-21 22:10:57 -0700207
208 // The auto-brightness spline adjustment.
209 // The brightness values have been scaled to a range of 0..1.
Jeff Brown1a30b552012-08-16 01:31:11 -0700210 private Spline mScreenAutoBrightnessSpline;
Jeff Brown96307042012-07-27 15:51:34 -0700211
212 // Amount of time to delay auto-brightness after screen on while waiting for
213 // the light sensor to warm-up in milliseconds.
214 // May be 0 if no warm-up is required.
215 private int mLightSensorWarmUpTimeConfig;
216
Jeff Brown252c2062012-10-08 16:21:01 -0700217 // True if we should fade the screen while turning it off, false if we should play
218 // a stylish electron beam animation instead.
219 private boolean mElectronBeamFadesConfig;
Jeff Browna52772f2012-10-04 18:38:09 -0700220
Jeff Brown96307042012-07-27 15:51:34 -0700221 // The pending power request.
222 // Initially null until the first call to requestPowerState.
223 // Guarded by mLock.
224 private DisplayPowerRequest mPendingRequestLocked;
225
226 // True if a request has been made to wait for the proximity sensor to go negative.
227 // Guarded by mLock.
228 private boolean mPendingWaitForNegativeProximityLocked;
229
230 // True if the pending power request or wait for negative proximity flag
231 // has been changed since the last update occurred.
232 // Guarded by mLock.
233 private boolean mPendingRequestChangedLocked;
234
235 // Set to true when the important parts of the pending power request have been applied.
236 // The important parts are mainly the screen state. Brightness changes may occur
237 // concurrently.
238 // Guarded by mLock.
239 private boolean mDisplayReadyLocked;
240
241 // Set to true if a power state update is required.
242 // Guarded by mLock.
243 private boolean mPendingUpdatePowerStateLocked;
244
245 /* The following state must only be accessed by the handler thread. */
246
247 // The currently requested power state.
248 // The power controller will progressively update its internal state to match
249 // the requested power state. Initially null until the first update.
250 private DisplayPowerRequest mPowerRequest;
251
252 // The current power state.
253 // Must only be accessed on the handler thread.
254 private DisplayPowerState mPowerState;
255
256 // True if the device should wait for negative proximity sensor before
257 // waking up the screen. This is set to false as soon as a negative
258 // proximity sensor measurement is observed or when the device is forced to
259 // go to sleep by the user. While true, the screen remains off.
260 private boolean mWaitingForNegativeProximity;
261
262 // The actual proximity sensor threshold value.
263 private float mProximityThreshold;
264
265 // Set to true if the proximity sensor listener has been registered
266 // with the sensor manager.
267 private boolean mProximitySensorEnabled;
268
269 // The debounced proximity sensor state.
270 private int mProximity = PROXIMITY_UNKNOWN;
271
272 // The raw non-debounced proximity sensor state.
273 private int mPendingProximity = PROXIMITY_UNKNOWN;
Jeff Brownec083212013-09-11 20:45:25 -0700274 private long mPendingProximityDebounceTime = -1; // -1 if fully debounced
Jeff Brown96307042012-07-27 15:51:34 -0700275
276 // True if the screen was turned off because of the proximity sensor.
277 // When the screen turns on again, we report user activity to the power manager.
278 private boolean mScreenOffBecauseOfProximity;
279
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700280 // True if the screen on is being blocked.
281 private boolean mScreenOnWasBlocked;
282
283 // The elapsed real time when the screen on was blocked.
284 private long mScreenOnBlockStartRealTime;
285
Jeff Brown96307042012-07-27 15:51:34 -0700286 // Set to true if the light sensor is enabled.
287 private boolean mLightSensorEnabled;
288
289 // The time when the light sensor was enabled.
290 private long mLightSensorEnableTime;
291
Jeff Brown4f0e9692012-10-18 16:14:16 -0700292 // The currently accepted nominal ambient light level.
293 private float mAmbientLux;
Jeff Brown96307042012-07-27 15:51:34 -0700294
Jeff Brown4f0e9692012-10-18 16:14:16 -0700295 // True if mAmbientLux holds a valid value.
296 private boolean mAmbientLuxValid;
Jeff Brown96307042012-07-27 15:51:34 -0700297
Michael Wright65031a22013-11-04 19:07:49 -0800298 // The ambient light level threshold at which to brighten or darken the screen.
299 private float mBrighteningLuxThreshold;
300 private float mDarkeningLuxThreshold;
301
Jeff Brown96307042012-07-27 15:51:34 -0700302 // The most recent light sample.
Jeff Brown4f0e9692012-10-18 16:14:16 -0700303 private float mLastObservedLux;
Jeff Brown96307042012-07-27 15:51:34 -0700304
305 // The time of the most light recent sample.
Jeff Brown4f0e9692012-10-18 16:14:16 -0700306 private long mLastObservedLuxTime;
Jeff Brown96307042012-07-27 15:51:34 -0700307
Jeff Brown4f0e9692012-10-18 16:14:16 -0700308 // The number of light samples collected since the light sensor was enabled.
309 private int mRecentLightSamples;
Jeff Brown06565b62012-08-15 21:10:32 -0700310
Jeff Brown4f0e9692012-10-18 16:14:16 -0700311 // The long-term and short-term filtered light measurements.
312 private float mRecentShortTermAverageLux;
313 private float mRecentLongTermAverageLux;
Jeff Brown96307042012-07-27 15:51:34 -0700314
Jeff Browne941b1e2012-10-22 16:50:25 -0700315 // The direction in which the average lux is moving relative to the current ambient lux.
316 // 0 if not changing or within hysteresis threshold.
317 // 1 if brightening beyond hysteresis threshold.
318 // -1 if darkening beyond hysteresis threshold.
319 private int mDebounceLuxDirection;
320
321 // The time when the average lux last changed direction.
322 private long mDebounceLuxTime;
323
Jeff Brown96307042012-07-27 15:51:34 -0700324 // The screen brightness level that has been chosen by the auto-brightness
325 // algorithm. The actual brightness should ramp towards this value.
326 // We preserve this value even when we stop using the light sensor so
327 // that we can quickly revert to the previous auto-brightness level
328 // while the light sensor warms up.
329 // Use -1 if there is no current auto-brightness value available.
330 private int mScreenAutoBrightness = -1;
331
Jeff Brown330560f2012-08-21 22:10:57 -0700332 // The last screen auto-brightness gamma. (For printing in dump() only.)
333 private float mLastScreenAutoBrightnessGamma = 1.0f;
334
Jeff Brown96307042012-07-27 15:51:34 -0700335 // True if the screen auto-brightness value is actually being used to
336 // set the display brightness.
337 private boolean mUsingScreenAutoBrightness;
338
339 // Animators.
340 private ObjectAnimator mElectronBeamOnAnimator;
341 private ObjectAnimator mElectronBeamOffAnimator;
342 private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
343
Jeff Brownaa202a62012-08-21 22:14:26 -0700344 // Twilight changed. We might recalculate auto-brightness values.
345 private boolean mTwilightChanged;
346
Jeff Brown96307042012-07-27 15:51:34 -0700347 /**
348 * Creates the display power controller.
349 */
350 public DisplayPowerController(Looper looper, Context context, Notifier notifier,
Adam Lesinski182f73f2013-12-05 16:48:06 -0800351 LightsManager lights, TwilightManager twilight, SensorManager sensorManager,
Jeff Brownec083212013-09-11 20:45:25 -0700352 SuspendBlocker displaySuspendBlocker, DisplayBlanker displayBlanker,
Jeff Brown96307042012-07-27 15:51:34 -0700353 Callbacks callbacks, Handler callbackHandler) {
354 mHandler = new DisplayControllerHandler(looper);
355 mNotifier = notifier;
Jeff Brownec083212013-09-11 20:45:25 -0700356 mDisplaySuspendBlocker = displaySuspendBlocker;
Jeff Brown9e316a12012-10-08 19:17:06 -0700357 mDisplayBlanker = displayBlanker;
Jeff Brown96307042012-07-27 15:51:34 -0700358 mCallbacks = callbacks;
359 mCallbackHandler = callbackHandler;
360
361 mLights = lights;
Jeff Brownaa202a62012-08-21 22:14:26 -0700362 mTwilight = twilight;
Jeff Brown3b971592013-01-09 18:46:37 -0800363 mSensorManager = sensorManager;
Jeff Brown96307042012-07-27 15:51:34 -0700364
365 final Resources resources = context.getResources();
Jeff Brownb76eebff2012-10-05 22:26:44 -0700366
367 mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger(
368 com.android.internal.R.integer.config_screenBrightnessDim));
369
370 int screenBrightnessMinimum = Math.min(resources.getInteger(
371 com.android.internal.R.integer.config_screenBrightnessSettingMinimum),
372 mScreenBrightnessDimConfig);
373
Jeff Brown96307042012-07-27 15:51:34 -0700374 mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
375 com.android.internal.R.bool.config_automatic_brightness_available);
376 if (mUseSoftwareAutoBrightnessConfig) {
Jeff Brown1a30b552012-08-16 01:31:11 -0700377 int[] lux = resources.getIntArray(
Jeff Brown96307042012-07-27 15:51:34 -0700378 com.android.internal.R.array.config_autoBrightnessLevels);
Jeff Brown1a30b552012-08-16 01:31:11 -0700379 int[] screenBrightness = resources.getIntArray(
Jeff Brown96307042012-07-27 15:51:34 -0700380 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
Jeff Brown1a30b552012-08-16 01:31:11 -0700381
382 mScreenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
383 if (mScreenAutoBrightnessSpline == null) {
Jeff Brown96307042012-07-27 15:51:34 -0700384 Slog.e(TAG, "Error in config.xml. config_autoBrightnessLcdBacklightValues "
Jeff Brown1a30b552012-08-16 01:31:11 -0700385 + "(size " + screenBrightness.length + ") "
386 + "must be monotic and have exactly one more entry than "
387 + "config_autoBrightnessLevels (size " + lux.length + ") "
388 + "which must be strictly increasing. "
Jeff Brown96307042012-07-27 15:51:34 -0700389 + "Auto-brightness will be disabled.");
390 mUseSoftwareAutoBrightnessConfig = false;
Jeff Brownb76eebff2012-10-05 22:26:44 -0700391 } else {
392 if (screenBrightness[0] < screenBrightnessMinimum) {
393 screenBrightnessMinimum = screenBrightness[0];
394 }
Jeff Brown96307042012-07-27 15:51:34 -0700395 }
396
397 mLightSensorWarmUpTimeConfig = resources.getInteger(
398 com.android.internal.R.integer.config_lightSensorWarmupTime);
399 }
400
Jeff Brownb76eebff2012-10-05 22:26:44 -0700401 mScreenBrightnessRangeMinimum = clampAbsoluteBrightness(screenBrightnessMinimum);
402 mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON;
403
Jeff Brown252c2062012-10-08 16:21:01 -0700404 mElectronBeamFadesConfig = resources.getBoolean(
Jeff Browna52772f2012-10-04 18:38:09 -0700405 com.android.internal.R.bool.config_animateScreenLights);
406
Jeff Brown96307042012-07-27 15:51:34 -0700407 if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
408 mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
409 if (mProximitySensor != null) {
410 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
411 TYPICAL_PROXIMITY_THRESHOLD);
412 }
413 }
414
415 if (mUseSoftwareAutoBrightnessConfig
416 && !DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
417 mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
418 }
Jeff Brownaa202a62012-08-21 22:14:26 -0700419
420 if (mUseSoftwareAutoBrightnessConfig && USE_TWILIGHT_ADJUSTMENT) {
421 mTwilight.registerListener(mTwilightListener, mHandler);
422 }
Jeff Brown96307042012-07-27 15:51:34 -0700423 }
424
Jeff Brown1a30b552012-08-16 01:31:11 -0700425 private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) {
426 try {
427 final int n = brightness.length;
428 float[] x = new float[n];
429 float[] y = new float[n];
Jeff Brownb76eebff2012-10-05 22:26:44 -0700430 y[0] = normalizeAbsoluteBrightness(brightness[0]);
Jeff Brown1a30b552012-08-16 01:31:11 -0700431 for (int i = 1; i < n; i++) {
432 x[i] = lux[i - 1];
Jeff Brownb76eebff2012-10-05 22:26:44 -0700433 y[i] = normalizeAbsoluteBrightness(brightness[i]);
Jeff Brown1a30b552012-08-16 01:31:11 -0700434 }
435
436 Spline spline = Spline.createMonotoneCubicSpline(x, y);
Jeff Brownb76eebff2012-10-05 22:26:44 -0700437 if (DEBUG) {
Jeff Brown1a30b552012-08-16 01:31:11 -0700438 Slog.d(TAG, "Auto-brightness spline: " + spline);
439 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
440 Slog.d(TAG, String.format(" %7.1f: %7.1f", v, spline.interpolate(v)));
441 }
442 }
443 return spline;
444 } catch (IllegalArgumentException ex) {
445 Slog.e(TAG, "Could not create auto-brightness spline.", ex);
446 return null;
447 }
448 }
449
Jeff Brown96307042012-07-27 15:51:34 -0700450 /**
451 * Returns true if the proximity sensor screen-off function is available.
452 */
453 public boolean isProximitySensorAvailable() {
454 return mProximitySensor != null;
455 }
456
457 /**
458 * Requests a new power state.
459 * The controller makes a copy of the provided object and then
460 * begins adjusting the power state to match what was requested.
461 *
462 * @param request The requested power state.
463 * @param waitForNegativeProximity If true, issues a request to wait for
464 * negative proximity before turning the screen back on, assuming the screen
465 * was turned off by the proximity sensor.
466 * @return True if display is ready, false if there are important changes that must
467 * be made asynchronously (such as turning the screen on), in which case the caller
468 * should grab a wake lock, watch for {@link Callbacks#onStateChanged()} then try
469 * the request again later until the state converges.
470 */
471 public boolean requestPowerState(DisplayPowerRequest request,
472 boolean waitForNegativeProximity) {
473 if (DEBUG) {
474 Slog.d(TAG, "requestPowerState: "
475 + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
476 }
477
478 synchronized (mLock) {
479 boolean changed = false;
480
481 if (waitForNegativeProximity
482 && !mPendingWaitForNegativeProximityLocked) {
483 mPendingWaitForNegativeProximityLocked = true;
484 changed = true;
485 }
486
487 if (mPendingRequestLocked == null) {
488 mPendingRequestLocked = new DisplayPowerRequest(request);
489 changed = true;
490 } else if (!mPendingRequestLocked.equals(request)) {
491 mPendingRequestLocked.copyFrom(request);
492 changed = true;
493 }
494
495 if (changed) {
496 mDisplayReadyLocked = false;
497 }
498
499 if (changed && !mPendingRequestChangedLocked) {
500 mPendingRequestChangedLocked = true;
501 sendUpdatePowerStateLocked();
502 }
503
504 return mDisplayReadyLocked;
505 }
506 }
507
508 private void sendUpdatePowerState() {
509 synchronized (mLock) {
510 sendUpdatePowerStateLocked();
511 }
512 }
513
514 private void sendUpdatePowerStateLocked() {
515 if (!mPendingUpdatePowerStateLocked) {
516 mPendingUpdatePowerStateLocked = true;
517 Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
518 msg.setAsynchronous(true);
519 mHandler.sendMessage(msg);
520 }
521 }
522
523 private void initialize() {
Jeff Brown4ccb8232014-01-16 22:16:42 -0800524 mPowerState = new DisplayPowerState(new ElectronBeam(), mDisplayBlanker,
Adam Lesinski182f73f2013-12-05 16:48:06 -0800525 mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT));
Jeff Brown96307042012-07-27 15:51:34 -0700526
527 mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
528 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f);
529 mElectronBeamOnAnimator.setDuration(ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS);
530 mElectronBeamOnAnimator.addListener(mAnimatorListener);
531
532 mElectronBeamOffAnimator = ObjectAnimator.ofFloat(
533 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 1.0f, 0.0f);
534 mElectronBeamOffAnimator.setDuration(ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS);
535 mElectronBeamOffAnimator.addListener(mAnimatorListener);
536
537 mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
538 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
539 }
540
541 private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
542 @Override
543 public void onAnimationStart(Animator animation) {
544 }
545 @Override
546 public void onAnimationEnd(Animator animation) {
547 sendUpdatePowerState();
548 }
549 @Override
550 public void onAnimationRepeat(Animator animation) {
551 }
552 @Override
553 public void onAnimationCancel(Animator animation) {
554 }
555 };
556
557 private void updatePowerState() {
558 // Update the power state request.
559 final boolean mustNotify;
560 boolean mustInitialize = false;
Jeff Brownaa202a62012-08-21 22:14:26 -0700561 boolean updateAutoBrightness = mTwilightChanged;
Jeff Browne941b1e2012-10-22 16:50:25 -0700562 boolean wasDim = false;
Jeff Brownaa202a62012-08-21 22:14:26 -0700563 mTwilightChanged = false;
Jeff Brown330560f2012-08-21 22:10:57 -0700564
Jeff Brown96307042012-07-27 15:51:34 -0700565 synchronized (mLock) {
566 mPendingUpdatePowerStateLocked = false;
567 if (mPendingRequestLocked == null) {
568 return; // wait until first actual power request
569 }
570
571 if (mPowerRequest == null) {
572 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
573 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
Jeff Brown6307a152012-08-20 13:24:23 -0700574 mPendingWaitForNegativeProximityLocked = false;
Jeff Brown96307042012-07-27 15:51:34 -0700575 mPendingRequestChangedLocked = false;
576 mustInitialize = true;
577 } else if (mPendingRequestChangedLocked) {
Jeff Brown330560f2012-08-21 22:10:57 -0700578 if (mPowerRequest.screenAutoBrightnessAdjustment
579 != mPendingRequestLocked.screenAutoBrightnessAdjustment) {
580 updateAutoBrightness = true;
581 }
Jeff Browne941b1e2012-10-22 16:50:25 -0700582 wasDim = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM);
Jeff Brown96307042012-07-27 15:51:34 -0700583 mPowerRequest.copyFrom(mPendingRequestLocked);
584 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
Jeff Brown6307a152012-08-20 13:24:23 -0700585 mPendingWaitForNegativeProximityLocked = false;
Jeff Brown96307042012-07-27 15:51:34 -0700586 mPendingRequestChangedLocked = false;
587 mDisplayReadyLocked = false;
588 }
589
590 mustNotify = !mDisplayReadyLocked;
591 }
592
593 // Initialize things the first time the power state is changed.
594 if (mustInitialize) {
595 initialize();
596 }
597
Jeff Brown6307a152012-08-20 13:24:23 -0700598 // Apply the proximity sensor.
Jeff Brown96307042012-07-27 15:51:34 -0700599 if (mProximitySensor != null) {
Jeff Brown6307a152012-08-20 13:24:23 -0700600 if (mPowerRequest.useProximitySensor
601 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
602 setProximitySensorEnabled(true);
603 if (!mScreenOffBecauseOfProximity
604 && mProximity == PROXIMITY_POSITIVE) {
605 mScreenOffBecauseOfProximity = true;
Jeff Brownec083212013-09-11 20:45:25 -0700606 sendOnProximityPositiveWithWakelock();
Jeff Brown6307a152012-08-20 13:24:23 -0700607 setScreenOn(false);
608 }
609 } else if (mWaitingForNegativeProximity
610 && mScreenOffBecauseOfProximity
611 && mProximity == PROXIMITY_POSITIVE
612 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
613 setProximitySensorEnabled(true);
614 } else {
615 setProximitySensorEnabled(false);
616 mWaitingForNegativeProximity = false;
617 }
618 if (mScreenOffBecauseOfProximity
619 && mProximity != PROXIMITY_POSITIVE) {
Jeff Brown96307042012-07-27 15:51:34 -0700620 mScreenOffBecauseOfProximity = false;
Jeff Brownec083212013-09-11 20:45:25 -0700621 sendOnProximityNegativeWithWakelock();
Jeff Brown96307042012-07-27 15:51:34 -0700622 }
Jeff Brown6307a152012-08-20 13:24:23 -0700623 } else {
624 mWaitingForNegativeProximity = false;
Jeff Brown96307042012-07-27 15:51:34 -0700625 }
626
627 // Turn on the light sensor if needed.
628 if (mLightSensor != null) {
629 setLightSensorEnabled(mPowerRequest.useAutoBrightness
Jeff Brown330560f2012-08-21 22:10:57 -0700630 && wantScreenOn(mPowerRequest.screenState), updateAutoBrightness);
Jeff Brown96307042012-07-27 15:51:34 -0700631 }
632
633 // Set the screen brightness.
Jeff Brownb76eebff2012-10-05 22:26:44 -0700634 if (wantScreenOn(mPowerRequest.screenState)) {
635 int target;
636 boolean slow;
Jeff Brown96307042012-07-27 15:51:34 -0700637 if (mScreenAutoBrightness >= 0 && mLightSensorEnabled) {
638 // Use current auto-brightness value.
Jeff Brownb76eebff2012-10-05 22:26:44 -0700639 target = mScreenAutoBrightness;
640 slow = mUsingScreenAutoBrightness;
Jeff Brown96307042012-07-27 15:51:34 -0700641 mUsingScreenAutoBrightness = true;
642 } else {
643 // Light sensor is disabled or not ready yet.
644 // Use the current brightness setting from the request, which is expected
645 // provide a nominal default value for the case where auto-brightness
646 // is not ready yet.
Jeff Brownb76eebff2012-10-05 22:26:44 -0700647 target = mPowerRequest.screenBrightness;
648 slow = false;
Jeff Brown96307042012-07-27 15:51:34 -0700649 mUsingScreenAutoBrightness = false;
650 }
Jeff Brownb76eebff2012-10-05 22:26:44 -0700651 if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) {
Jeff Brown5244c932012-10-24 14:46:26 -0700652 // Dim quickly by at least some minimum amount.
Jeff Brownb76eebff2012-10-05 22:26:44 -0700653 target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION,
654 mScreenBrightnessDimConfig);
Jeff Brown5244c932012-10-24 14:46:26 -0700655 slow = false;
Jeff Browne941b1e2012-10-22 16:50:25 -0700656 } else if (wasDim) {
657 // Brighten quickly.
Jeff Brownb76eebff2012-10-05 22:26:44 -0700658 slow = false;
659 }
660 animateScreenBrightness(clampScreenBrightness(target),
661 slow ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
Jeff Brown96307042012-07-27 15:51:34 -0700662 } else {
663 // Screen is off. Don't bother changing the brightness.
664 mUsingScreenAutoBrightness = false;
665 }
666
667 // Animate the screen on or off.
668 if (!mScreenOffBecauseOfProximity) {
669 if (wantScreenOn(mPowerRequest.screenState)) {
670 // Want screen on.
671 // Wait for previous off animation to complete beforehand.
672 // It is relatively short but if we cancel it and switch to the
673 // on animation immediately then the results are pretty ugly.
674 if (!mElectronBeamOffAnimator.isStarted()) {
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700675 // Turn the screen on. The contents of the screen may not yet
676 // be visible if the electron beam has not been dismissed because
677 // its last frame of animation is solid black.
678 setScreenOn(true);
679
680 if (mPowerRequest.blockScreenOn
681 && mPowerState.getElectronBeamLevel() == 0.0f) {
682 blockScreenOn();
Jeff Brown13c589b2012-08-16 16:20:54 -0700683 } else {
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700684 unblockScreenOn();
Jeff Brownc38c9be2012-10-04 13:16:19 -0700685 if (USE_ELECTRON_BEAM_ON_ANIMATION) {
686 if (!mElectronBeamOnAnimator.isStarted()) {
687 if (mPowerState.getElectronBeamLevel() == 1.0f) {
688 mPowerState.dismissElectronBeam();
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700689 } else if (mPowerState.prepareElectronBeam(
Jeff Brown252c2062012-10-08 16:21:01 -0700690 mElectronBeamFadesConfig ?
691 ElectronBeam.MODE_FADE :
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700692 ElectronBeam.MODE_WARM_UP)) {
Jeff Brownc38c9be2012-10-04 13:16:19 -0700693 mElectronBeamOnAnimator.start();
694 } else {
695 mElectronBeamOnAnimator.end();
696 }
697 }
698 } else {
699 mPowerState.setElectronBeamLevel(1.0f);
700 mPowerState.dismissElectronBeam();
701 }
702 }
Jeff Brown96307042012-07-27 15:51:34 -0700703 }
704 } else {
705 // Want screen off.
706 // Wait for previous on animation to complete beforehand.
707 if (!mElectronBeamOnAnimator.isStarted()) {
708 if (!mElectronBeamOffAnimator.isStarted()) {
709 if (mPowerState.getElectronBeamLevel() == 0.0f) {
710 setScreenOn(false);
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700711 } else if (mPowerState.prepareElectronBeam(
Jeff Brown252c2062012-10-08 16:21:01 -0700712 mElectronBeamFadesConfig ?
713 ElectronBeam.MODE_FADE :
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700714 ElectronBeam.MODE_COOL_DOWN)
Jeff Brown96307042012-07-27 15:51:34 -0700715 && mPowerState.isScreenOn()) {
716 mElectronBeamOffAnimator.start();
717 } else {
718 mElectronBeamOffAnimator.end();
719 }
720 }
721 }
722 }
723 }
724
725 // Report whether the display is ready for use.
726 // We mostly care about the screen state here, ignoring brightness changes
727 // which will be handled asynchronously.
728 if (mustNotify
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700729 && !mScreenOnWasBlocked
Jeff Brown96307042012-07-27 15:51:34 -0700730 && !mElectronBeamOnAnimator.isStarted()
731 && !mElectronBeamOffAnimator.isStarted()
732 && mPowerState.waitUntilClean(mCleanListener)) {
733 synchronized (mLock) {
734 if (!mPendingRequestChangedLocked) {
735 mDisplayReadyLocked = true;
Jeff Brownc38c9be2012-10-04 13:16:19 -0700736
737 if (DEBUG) {
738 Slog.d(TAG, "Display ready!");
739 }
Jeff Brown96307042012-07-27 15:51:34 -0700740 }
741 }
Jeff Brownec083212013-09-11 20:45:25 -0700742 sendOnStateChangedWithWakelock();
Jeff Brown96307042012-07-27 15:51:34 -0700743 }
744 }
745
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700746 private void blockScreenOn() {
747 if (!mScreenOnWasBlocked) {
748 mScreenOnWasBlocked = true;
749 if (DEBUG) {
750 Slog.d(TAG, "Blocked screen on.");
751 mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
752 }
753 }
754 }
755
756 private void unblockScreenOn() {
757 if (mScreenOnWasBlocked) {
758 mScreenOnWasBlocked = false;
759 if (DEBUG) {
760 Slog.d(TAG, "Unblocked screen on after " +
761 (SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime) + " ms");
762 }
763 }
764 }
765
Jeff Brown96307042012-07-27 15:51:34 -0700766 private void setScreenOn(boolean on) {
767 if (!mPowerState.isScreenOn() == on) {
768 mPowerState.setScreenOn(on);
769 if (on) {
770 mNotifier.onScreenOn();
771 } else {
772 mNotifier.onScreenOff();
773 }
774 }
775 }
776
Jeff Brown330560f2012-08-21 22:10:57 -0700777 private int clampScreenBrightness(int value) {
Jeff Brownb76eebff2012-10-05 22:26:44 -0700778 return clamp(value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
779 }
780
781 private static int clampAbsoluteBrightness(int value) {
782 return clamp(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
783 }
784
785 private static int clamp(int value, int min, int max) {
786 if (value <= min) {
787 return min;
788 }
789 if (value >= max) {
790 return max;
791 }
792 return value;
793 }
794
795 private static float normalizeAbsoluteBrightness(int value) {
796 return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON;
Jeff Brown330560f2012-08-21 22:10:57 -0700797 }
798
Jeff Brown96307042012-07-27 15:51:34 -0700799 private void animateScreenBrightness(int target, int rate) {
800 if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
801 mNotifier.onScreenBrightness(target);
802 }
803 }
804
805 private final Runnable mCleanListener = new Runnable() {
806 @Override
807 public void run() {
808 sendUpdatePowerState();
809 }
810 };
811
812 private void setProximitySensorEnabled(boolean enable) {
813 if (enable) {
814 if (!mProximitySensorEnabled) {
Jeff Brownec083212013-09-11 20:45:25 -0700815 // Register the listener.
816 // Proximity sensor state already cleared initially.
Jeff Brown96307042012-07-27 15:51:34 -0700817 mProximitySensorEnabled = true;
Jeff Brown96307042012-07-27 15:51:34 -0700818 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
819 SensorManager.SENSOR_DELAY_NORMAL, mHandler);
820 }
821 } else {
822 if (mProximitySensorEnabled) {
Jeff Brownec083212013-09-11 20:45:25 -0700823 // Unregister the listener.
824 // Clear the proximity sensor state for next time.
Jeff Brown96307042012-07-27 15:51:34 -0700825 mProximitySensorEnabled = false;
826 mProximity = PROXIMITY_UNKNOWN;
Jeff Brownec083212013-09-11 20:45:25 -0700827 mPendingProximity = PROXIMITY_UNKNOWN;
Jeff Brown96307042012-07-27 15:51:34 -0700828 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
829 mSensorManager.unregisterListener(mProximitySensorListener);
Jeff Brownec083212013-09-11 20:45:25 -0700830 clearPendingProximityDebounceTime(); // release wake lock (must be last)
Jeff Brown96307042012-07-27 15:51:34 -0700831 }
832 }
833 }
834
835 private void handleProximitySensorEvent(long time, boolean positive) {
Jeff Brownec083212013-09-11 20:45:25 -0700836 if (mProximitySensorEnabled) {
837 if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
838 return; // no change
839 }
840 if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
841 return; // no change
842 }
Jeff Brown96307042012-07-27 15:51:34 -0700843
Jeff Brownec083212013-09-11 20:45:25 -0700844 // Only accept a proximity sensor reading if it remains
845 // stable for the entire debounce delay. We hold a wake lock while
846 // debouncing the sensor.
847 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
848 if (positive) {
849 mPendingProximity = PROXIMITY_POSITIVE;
850 setPendingProximityDebounceTime(
851 time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
852 } else {
853 mPendingProximity = PROXIMITY_NEGATIVE;
854 setPendingProximityDebounceTime(
855 time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
856 }
857
858 // Debounce the new sensor reading.
859 debounceProximitySensor();
Jeff Brown93cbbb22012-10-04 13:18:36 -0700860 }
Jeff Brown96307042012-07-27 15:51:34 -0700861 }
862
863 private void debounceProximitySensor() {
Jeff Brownec083212013-09-11 20:45:25 -0700864 if (mProximitySensorEnabled
865 && mPendingProximity != PROXIMITY_UNKNOWN
866 && mPendingProximityDebounceTime >= 0) {
Jeff Brown96307042012-07-27 15:51:34 -0700867 final long now = SystemClock.uptimeMillis();
868 if (mPendingProximityDebounceTime <= now) {
Jeff Brownec083212013-09-11 20:45:25 -0700869 // Sensor reading accepted. Apply the change then release the wake lock.
Jeff Brown96307042012-07-27 15:51:34 -0700870 mProximity = mPendingProximity;
Jeff Brownec083212013-09-11 20:45:25 -0700871 updatePowerState();
872 clearPendingProximityDebounceTime(); // release wake lock (must be last)
Jeff Brown96307042012-07-27 15:51:34 -0700873 } else {
Jeff Brownec083212013-09-11 20:45:25 -0700874 // Need to wait a little longer.
875 // Debounce again later. We continue holding a wake lock while waiting.
Jeff Brown96307042012-07-27 15:51:34 -0700876 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
877 msg.setAsynchronous(true);
878 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
879 }
880 }
881 }
882
Jeff Brownec083212013-09-11 20:45:25 -0700883 private void clearPendingProximityDebounceTime() {
884 if (mPendingProximityDebounceTime >= 0) {
885 mPendingProximityDebounceTime = -1;
886 mDisplaySuspendBlocker.release(); // release wake lock
887 }
888 }
889
890 private void setPendingProximityDebounceTime(long debounceTime) {
891 if (mPendingProximityDebounceTime < 0) {
892 mDisplaySuspendBlocker.acquire(); // acquire wake lock
893 }
894 mPendingProximityDebounceTime = debounceTime;
895 }
896
Jeff Brown330560f2012-08-21 22:10:57 -0700897 private void setLightSensorEnabled(boolean enable, boolean updateAutoBrightness) {
Jeff Brown96307042012-07-27 15:51:34 -0700898 if (enable) {
899 if (!mLightSensorEnabled) {
Jeff Brown330560f2012-08-21 22:10:57 -0700900 updateAutoBrightness = true;
Jeff Brown96307042012-07-27 15:51:34 -0700901 mLightSensorEnabled = true;
902 mLightSensorEnableTime = SystemClock.uptimeMillis();
903 mSensorManager.registerListener(mLightSensorListener, mLightSensor,
Jeff Browne941b1e2012-10-22 16:50:25 -0700904 LIGHT_SENSOR_RATE_MILLIS * 1000, mHandler);
Jeff Brown96307042012-07-27 15:51:34 -0700905 }
906 } else {
907 if (mLightSensorEnabled) {
908 mLightSensorEnabled = false;
Jeff Brown4f0e9692012-10-18 16:14:16 -0700909 mAmbientLuxValid = false;
910 mRecentLightSamples = 0;
Jeff Brown96307042012-07-27 15:51:34 -0700911 mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
912 mSensorManager.unregisterListener(mLightSensorListener);
913 }
914 }
Jeff Brown330560f2012-08-21 22:10:57 -0700915 if (updateAutoBrightness) {
916 updateAutoBrightness(false);
917 }
Jeff Brown96307042012-07-27 15:51:34 -0700918 }
919
920 private void handleLightSensorEvent(long time, float lux) {
Jeff Browne941b1e2012-10-22 16:50:25 -0700921 mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
922
923 applyLightSensorMeasurement(time, lux);
924 updateAmbientLux(time);
925 }
926
927 private void applyLightSensorMeasurement(long time, float lux) {
Jeff Brown4f0e9692012-10-18 16:14:16 -0700928 // Update our filters.
Jeff Brown96307042012-07-27 15:51:34 -0700929 mRecentLightSamples += 1;
Jeff Brown4f0e9692012-10-18 16:14:16 -0700930 if (mRecentLightSamples == 1) {
931 mRecentShortTermAverageLux = lux;
932 mRecentLongTermAverageLux = lux;
933 } else {
934 final long timeDelta = time - mLastObservedLuxTime;
935 mRecentShortTermAverageLux += (lux - mRecentShortTermAverageLux)
936 * timeDelta / (SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta);
937 mRecentLongTermAverageLux += (lux - mRecentLongTermAverageLux)
938 * timeDelta / (LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta);
939 }
940
941 // Remember this sample value.
942 mLastObservedLux = lux;
943 mLastObservedLuxTime = time;
Jeff Brown96307042012-07-27 15:51:34 -0700944 }
945
Michael Wright65031a22013-11-04 19:07:49 -0800946 private void setAmbientLux(float lux) {
947 mAmbientLux = lux;
948 mBrighteningLuxThreshold = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS);
949 mDarkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS);
950 }
951
Jeff Brown4f0e9692012-10-18 16:14:16 -0700952 private void updateAmbientLux(long time) {
953 // If the light sensor was just turned on then immediately update our initial
954 // estimate of the current ambient light level.
Michael Wright65031a22013-11-04 19:07:49 -0800955 if (!mAmbientLuxValid) {
956 final long timeWhenSensorWarmedUp =
957 mLightSensorWarmUpTimeConfig + mLightSensorEnableTime;
958 if (time < timeWhenSensorWarmedUp) {
959 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED,
960 timeWhenSensorWarmedUp);
961 return;
962 }
963 setAmbientLux(mRecentShortTermAverageLux);
Jeff Brown4f0e9692012-10-18 16:14:16 -0700964 mAmbientLuxValid = true;
Jeff Browne941b1e2012-10-22 16:50:25 -0700965 mDebounceLuxDirection = 0;
966 mDebounceLuxTime = time;
967 if (DEBUG) {
968 Slog.d(TAG, "updateAmbientLux: Initializing: "
969 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
970 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
971 + ", mAmbientLux=" + mAmbientLux);
972 }
Jeff Brown4f0e9692012-10-18 16:14:16 -0700973 updateAutoBrightness(true);
Michael Wright65031a22013-11-04 19:07:49 -0800974 } else if (mRecentShortTermAverageLux > mBrighteningLuxThreshold
975 && mRecentLongTermAverageLux > mBrighteningLuxThreshold) {
976 // The ambient environment appears to be brightening.
Jeff Browne941b1e2012-10-22 16:50:25 -0700977 if (mDebounceLuxDirection <= 0) {
978 mDebounceLuxDirection = 1;
979 mDebounceLuxTime = time;
980 if (DEBUG) {
981 Slog.d(TAG, "updateAmbientLux: Possibly brightened, waiting for "
982 + BRIGHTENING_LIGHT_DEBOUNCE + " ms: "
Michael Wright65031a22013-11-04 19:07:49 -0800983 + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold
Jeff Browne941b1e2012-10-22 16:50:25 -0700984 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
985 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
986 + ", mAmbientLux=" + mAmbientLux);
987 }
988 }
989 long debounceTime = mDebounceLuxTime + BRIGHTENING_LIGHT_DEBOUNCE;
Michael Wright65031a22013-11-04 19:07:49 -0800990 if (time < debounceTime) {
Jeff Brown4f0e9692012-10-18 16:14:16 -0700991 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
Michael Wright65031a22013-11-04 19:07:49 -0800992 return;
Jeff Brown4f0e9692012-10-18 16:14:16 -0700993 }
Michael Wright65031a22013-11-04 19:07:49 -0800994 setAmbientLux(mRecentShortTermAverageLux);
995 if (DEBUG) {
996 Slog.d(TAG, "updateAmbientLux: Brightened: "
997 + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold
998 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
999 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1000 + ", mAmbientLux=" + mAmbientLux);
1001 }
1002 updateAutoBrightness(true);
1003 } else if (mRecentShortTermAverageLux < mDarkeningLuxThreshold
1004 && mRecentLongTermAverageLux < mDarkeningLuxThreshold) {
1005 // The ambient environment appears to be darkening.
Jeff Browne941b1e2012-10-22 16:50:25 -07001006 if (mDebounceLuxDirection >= 0) {
1007 mDebounceLuxDirection = -1;
1008 mDebounceLuxTime = time;
1009 if (DEBUG) {
1010 Slog.d(TAG, "updateAmbientLux: Possibly darkened, waiting for "
1011 + DARKENING_LIGHT_DEBOUNCE + " ms: "
Michael Wright65031a22013-11-04 19:07:49 -08001012 + "mDarkeningLuxThreshold=" + mDarkeningLuxThreshold
Jeff Browne941b1e2012-10-22 16:50:25 -07001013 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1014 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1015 + ", mAmbientLux=" + mAmbientLux);
1016 }
1017 }
1018 long debounceTime = mDebounceLuxTime + DARKENING_LIGHT_DEBOUNCE;
Michael Wright65031a22013-11-04 19:07:49 -08001019 if (time < debounceTime) {
Jeff Brown4f0e9692012-10-18 16:14:16 -07001020 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
Michael Wright65031a22013-11-04 19:07:49 -08001021 return;
Jeff Brown96307042012-07-27 15:51:34 -07001022 }
Michael Wright65031a22013-11-04 19:07:49 -08001023 // Be conservative about reducing the brightness, only reduce it a little bit
1024 // at a time to avoid having to bump it up again soon.
1025 setAmbientLux(Math.max(mRecentShortTermAverageLux, mRecentLongTermAverageLux));
1026 if (DEBUG) {
1027 Slog.d(TAG, "updateAmbientLux: Darkened: "
1028 + "mDarkeningLuxThreshold=" + mDarkeningLuxThreshold
1029 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1030 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1031 + ", mAmbientLux=" + mAmbientLux);
1032 }
1033 updateAutoBrightness(true);
1034 } else if (mDebounceLuxDirection != 0) {
1035 // No change or change is within the hysteresis thresholds.
Jeff Browne941b1e2012-10-22 16:50:25 -07001036 mDebounceLuxDirection = 0;
1037 mDebounceLuxTime = time;
1038 if (DEBUG) {
1039 Slog.d(TAG, "updateAmbientLux: Canceled debounce: "
Michael Wright65031a22013-11-04 19:07:49 -08001040 + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold
1041 + ", mDarkeningLuxThreshold=" + mDarkeningLuxThreshold
Jeff Browne941b1e2012-10-22 16:50:25 -07001042 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1043 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1044 + ", mAmbientLux=" + mAmbientLux);
1045 }
1046 }
1047
Michael Wright65031a22013-11-04 19:07:49 -08001048 // Now that we've done all of that, we haven't yet posted a debounce
1049 // message. So consider the case where current lux is beyond the
1050 // threshold. It's possible that the light sensor may not report values
1051 // if the light level does not change, so we need to occasionally
1052 // synthesize sensor readings in order to make sure the brightness is
1053 // adjusted accordingly. Note these thresholds may have changed since
1054 // we entered the function because we called setAmbientLux and
1055 // updateAutoBrightness along the way.
1056 if (mLastObservedLux > mBrighteningLuxThreshold
1057 || mLastObservedLux < mDarkeningLuxThreshold) {
Jeff Browne941b1e2012-10-22 16:50:25 -07001058 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED,
1059 time + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS);
Jeff Brown96307042012-07-27 15:51:34 -07001060 }
1061 }
1062
Jeff Brown4f0e9692012-10-18 16:14:16 -07001063 private void debounceLightSensor() {
Jeff Browne941b1e2012-10-22 16:50:25 -07001064 if (mLightSensorEnabled) {
1065 long time = SystemClock.uptimeMillis();
1066 if (time >= mLastObservedLuxTime + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS) {
1067 if (DEBUG) {
1068 Slog.d(TAG, "debounceLightSensor: Synthesizing light sensor measurement "
1069 + "after " + (time - mLastObservedLuxTime) + " ms.");
1070 }
1071 applyLightSensorMeasurement(time, mLastObservedLux);
1072 }
1073 updateAmbientLux(time);
1074 }
Jeff Brown4f0e9692012-10-18 16:14:16 -07001075 }
1076
Jeff Brown96307042012-07-27 15:51:34 -07001077 private void updateAutoBrightness(boolean sendUpdate) {
Jeff Brown4f0e9692012-10-18 16:14:16 -07001078 if (!mAmbientLuxValid) {
Jeff Brown96307042012-07-27 15:51:34 -07001079 return;
1080 }
1081
Jeff Brown4f0e9692012-10-18 16:14:16 -07001082 float value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux);
Jeff Brown330560f2012-08-21 22:10:57 -07001083 float gamma = 1.0f;
1084
1085 if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT
1086 && mPowerRequest.screenAutoBrightnessAdjustment != 0.0f) {
1087 final float adjGamma = FloatMath.pow(SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA,
1088 Math.min(1.0f, Math.max(-1.0f,
1089 -mPowerRequest.screenAutoBrightnessAdjustment)));
1090 gamma *= adjGamma;
1091 if (DEBUG) {
1092 Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma);
1093 }
1094 }
1095
Jeff Brownaa202a62012-08-21 22:14:26 -07001096 if (USE_TWILIGHT_ADJUSTMENT) {
1097 TwilightState state = mTwilight.getCurrentState();
1098 if (state != null && state.isNight()) {
1099 final long now = System.currentTimeMillis();
1100 final float earlyGamma =
1101 getTwilightGamma(now, state.getYesterdaySunset(), state.getTodaySunrise());
1102 final float lateGamma =
1103 getTwilightGamma(now, state.getTodaySunset(), state.getTomorrowSunrise());
1104 gamma *= earlyGamma * lateGamma;
1105 if (DEBUG) {
1106 Slog.d(TAG, "updateAutoBrightness: earlyGamma=" + earlyGamma
1107 + ", lateGamma=" + lateGamma);
1108 }
1109 }
1110 }
1111
Jeff Brown330560f2012-08-21 22:10:57 -07001112 if (gamma != 1.0f) {
1113 final float in = value;
1114 value = FloatMath.pow(value, gamma);
1115 if (DEBUG) {
1116 Slog.d(TAG, "updateAutoBrightness: gamma=" + gamma
1117 + ", in=" + in + ", out=" + value);
1118 }
1119 }
1120
1121 int newScreenAutoBrightness = clampScreenBrightness(
Jeff Brown4f0e9692012-10-18 16:14:16 -07001122 Math.round(value * PowerManager.BRIGHTNESS_ON));
Jeff Brown96307042012-07-27 15:51:34 -07001123 if (mScreenAutoBrightness != newScreenAutoBrightness) {
1124 if (DEBUG) {
1125 Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness="
Jeff Brown330560f2012-08-21 22:10:57 -07001126 + mScreenAutoBrightness + ", newScreenAutoBrightness="
Jeff Brown1a30b552012-08-16 01:31:11 -07001127 + newScreenAutoBrightness);
Jeff Brown96307042012-07-27 15:51:34 -07001128 }
1129
1130 mScreenAutoBrightness = newScreenAutoBrightness;
Jeff Brown330560f2012-08-21 22:10:57 -07001131 mLastScreenAutoBrightnessGamma = gamma;
Jeff Brown96307042012-07-27 15:51:34 -07001132 if (sendUpdate) {
1133 sendUpdatePowerState();
1134 }
1135 }
1136 }
1137
Jeff Brownaa202a62012-08-21 22:14:26 -07001138 private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) {
1139 if (lastSunset < 0 || nextSunrise < 0
1140 || now < lastSunset || now > nextSunrise) {
1141 return 1.0f;
1142 }
1143
1144 if (now < lastSunset + TWILIGHT_ADJUSTMENT_TIME) {
1145 return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
1146 (float)(now - lastSunset) / TWILIGHT_ADJUSTMENT_TIME);
1147 }
1148
1149 if (now > nextSunrise - TWILIGHT_ADJUSTMENT_TIME) {
1150 return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
1151 (float)(nextSunrise - now) / TWILIGHT_ADJUSTMENT_TIME);
1152 }
1153
1154 return TWILIGHT_ADJUSTMENT_MAX_GAMMA;
1155 }
1156
1157 private static float lerp(float x, float y, float alpha) {
1158 return x + (y - x) * alpha;
1159 }
1160
Jeff Brownec083212013-09-11 20:45:25 -07001161 private void sendOnStateChangedWithWakelock() {
1162 mDisplaySuspendBlocker.acquire();
Jeff Brown96307042012-07-27 15:51:34 -07001163 mCallbackHandler.post(mOnStateChangedRunnable);
1164 }
1165
1166 private final Runnable mOnStateChangedRunnable = new Runnable() {
1167 @Override
1168 public void run() {
1169 mCallbacks.onStateChanged();
Jeff Brownec083212013-09-11 20:45:25 -07001170 mDisplaySuspendBlocker.release();
Jeff Brown96307042012-07-27 15:51:34 -07001171 }
1172 };
1173
Jeff Brownec083212013-09-11 20:45:25 -07001174 private void sendOnProximityPositiveWithWakelock() {
1175 mDisplaySuspendBlocker.acquire();
Jeff Brown93cbbb22012-10-04 13:18:36 -07001176 mCallbackHandler.post(mOnProximityPositiveRunnable);
1177 }
1178
1179 private final Runnable mOnProximityPositiveRunnable = new Runnable() {
1180 @Override
1181 public void run() {
1182 mCallbacks.onProximityPositive();
Jeff Brownec083212013-09-11 20:45:25 -07001183 mDisplaySuspendBlocker.release();
Jeff Brown93cbbb22012-10-04 13:18:36 -07001184 }
1185 };
1186
Jeff Brownec083212013-09-11 20:45:25 -07001187 private void sendOnProximityNegativeWithWakelock() {
1188 mDisplaySuspendBlocker.acquire();
Jeff Brown96307042012-07-27 15:51:34 -07001189 mCallbackHandler.post(mOnProximityNegativeRunnable);
1190 }
1191
1192 private final Runnable mOnProximityNegativeRunnable = new Runnable() {
1193 @Override
1194 public void run() {
1195 mCallbacks.onProximityNegative();
Jeff Brownec083212013-09-11 20:45:25 -07001196 mDisplaySuspendBlocker.release();
Jeff Brown96307042012-07-27 15:51:34 -07001197 }
1198 };
1199
Jeff Brownbd6e1502012-08-28 03:27:37 -07001200 public void dump(final PrintWriter pw) {
Jeff Brown96307042012-07-27 15:51:34 -07001201 synchronized (mLock) {
1202 pw.println();
1203 pw.println("Display Controller Locked State:");
1204 pw.println(" mDisplayReadyLocked=" + mDisplayReadyLocked);
1205 pw.println(" mPendingRequestLocked=" + mPendingRequestLocked);
1206 pw.println(" mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
1207 pw.println(" mPendingWaitForNegativeProximityLocked="
1208 + mPendingWaitForNegativeProximityLocked);
1209 pw.println(" mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
1210 }
1211
1212 pw.println();
1213 pw.println("Display Controller Configuration:");
1214 pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
Jeff Brownb76eebff2012-10-05 22:26:44 -07001215 pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
1216 pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
Jeff Brown96307042012-07-27 15:51:34 -07001217 pw.println(" mUseSoftwareAutoBrightnessConfig="
1218 + mUseSoftwareAutoBrightnessConfig);
Jeff Brown1a30b552012-08-16 01:31:11 -07001219 pw.println(" mScreenAutoBrightnessSpline=" + mScreenAutoBrightnessSpline);
Jeff Brown96307042012-07-27 15:51:34 -07001220 pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig);
1221
Jeff Brownbd6e1502012-08-28 03:27:37 -07001222 mHandler.runWithScissors(new Runnable() {
1223 @Override
1224 public void run() {
1225 dumpLocal(pw);
Jeff Brown96307042012-07-27 15:51:34 -07001226 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001227 }, 1000);
Jeff Brown96307042012-07-27 15:51:34 -07001228 }
1229
1230 private void dumpLocal(PrintWriter pw) {
1231 pw.println();
1232 pw.println("Display Controller Thread State:");
1233 pw.println(" mPowerRequest=" + mPowerRequest);
1234 pw.println(" mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
1235
1236 pw.println(" mProximitySensor=" + mProximitySensor);
1237 pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled);
1238 pw.println(" mProximityThreshold=" + mProximityThreshold);
1239 pw.println(" mProximity=" + proximityToString(mProximity));
1240 pw.println(" mPendingProximity=" + proximityToString(mPendingProximity));
1241 pw.println(" mPendingProximityDebounceTime="
1242 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
1243 pw.println(" mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
1244
1245 pw.println(" mLightSensor=" + mLightSensor);
1246 pw.println(" mLightSensorEnabled=" + mLightSensorEnabled);
1247 pw.println(" mLightSensorEnableTime="
1248 + TimeUtils.formatUptime(mLightSensorEnableTime));
Jeff Brown4f0e9692012-10-18 16:14:16 -07001249 pw.println(" mAmbientLux=" + mAmbientLux);
1250 pw.println(" mAmbientLuxValid=" + mAmbientLuxValid);
Jeff Brown4f0e9692012-10-18 16:14:16 -07001251 pw.println(" mLastObservedLux=" + mLastObservedLux);
1252 pw.println(" mLastObservedLuxTime="
1253 + TimeUtils.formatUptime(mLastObservedLuxTime));
Jeff Brown96307042012-07-27 15:51:34 -07001254 pw.println(" mRecentLightSamples=" + mRecentLightSamples);
Jeff Brown4f0e9692012-10-18 16:14:16 -07001255 pw.println(" mRecentShortTermAverageLux=" + mRecentShortTermAverageLux);
1256 pw.println(" mRecentLongTermAverageLux=" + mRecentLongTermAverageLux);
Jeff Browne941b1e2012-10-22 16:50:25 -07001257 pw.println(" mDebounceLuxDirection=" + mDebounceLuxDirection);
1258 pw.println(" mDebounceLuxTime=" + TimeUtils.formatUptime(mDebounceLuxTime));
Jeff Brown96307042012-07-27 15:51:34 -07001259 pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness);
1260 pw.println(" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness);
Jeff Brown330560f2012-08-21 22:10:57 -07001261 pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
Jeff Brownaa202a62012-08-21 22:14:26 -07001262 pw.println(" mTwilight.getCurrentState()=" + mTwilight.getCurrentState());
Jeff Brown96307042012-07-27 15:51:34 -07001263
1264 if (mElectronBeamOnAnimator != null) {
1265 pw.println(" mElectronBeamOnAnimator.isStarted()=" +
1266 mElectronBeamOnAnimator.isStarted());
1267 }
1268 if (mElectronBeamOffAnimator != null) {
1269 pw.println(" mElectronBeamOffAnimator.isStarted()=" +
1270 mElectronBeamOffAnimator.isStarted());
1271 }
1272
1273 if (mPowerState != null) {
1274 mPowerState.dump(pw);
1275 }
1276 }
1277
1278 private static String proximityToString(int state) {
1279 switch (state) {
1280 case PROXIMITY_UNKNOWN:
1281 return "Unknown";
1282 case PROXIMITY_NEGATIVE:
1283 return "Negative";
1284 case PROXIMITY_POSITIVE:
1285 return "Positive";
1286 default:
1287 return Integer.toString(state);
1288 }
1289 }
1290
1291 private static boolean wantScreenOn(int state) {
1292 switch (state) {
1293 case DisplayPowerRequest.SCREEN_STATE_BRIGHT:
1294 case DisplayPowerRequest.SCREEN_STATE_DIM:
1295 return true;
1296 }
1297 return false;
1298 }
1299
1300 /**
1301 * Asynchronous callbacks from the power controller to the power manager service.
1302 */
1303 public interface Callbacks {
1304 void onStateChanged();
Jeff Brown93cbbb22012-10-04 13:18:36 -07001305 void onProximityPositive();
Jeff Brown96307042012-07-27 15:51:34 -07001306 void onProximityNegative();
1307 }
1308
1309 private final class DisplayControllerHandler extends Handler {
1310 public DisplayControllerHandler(Looper looper) {
Jeff Browna2910d02012-08-25 12:29:46 -07001311 super(looper, null, true /*async*/);
Jeff Brown96307042012-07-27 15:51:34 -07001312 }
1313
1314 @Override
1315 public void handleMessage(Message msg) {
1316 switch (msg.what) {
1317 case MSG_UPDATE_POWER_STATE:
1318 updatePowerState();
1319 break;
1320
1321 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
1322 debounceProximitySensor();
1323 break;
1324
1325 case MSG_LIGHT_SENSOR_DEBOUNCED:
1326 debounceLightSensor();
1327 break;
1328 }
1329 }
1330 }
1331
1332 private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
1333 @Override
1334 public void onSensorChanged(SensorEvent event) {
1335 if (mProximitySensorEnabled) {
1336 final long time = SystemClock.uptimeMillis();
1337 final float distance = event.values[0];
1338 boolean positive = distance >= 0.0f && distance < mProximityThreshold;
1339 handleProximitySensorEvent(time, positive);
1340 }
1341 }
1342
1343 @Override
1344 public void onAccuracyChanged(Sensor sensor, int accuracy) {
1345 // Not used.
1346 }
1347 };
1348
1349 private final SensorEventListener mLightSensorListener = new SensorEventListener() {
1350 @Override
1351 public void onSensorChanged(SensorEvent event) {
1352 if (mLightSensorEnabled) {
1353 final long time = SystemClock.uptimeMillis();
1354 final float lux = event.values[0];
1355 handleLightSensorEvent(time, lux);
1356 }
1357 }
1358
1359 @Override
1360 public void onAccuracyChanged(Sensor sensor, int accuracy) {
1361 // Not used.
1362 }
1363 };
Jeff Brownaa202a62012-08-21 22:14:26 -07001364
Adam Lesinski182f73f2013-12-05 16:48:06 -08001365 private final TwilightListener mTwilightListener = new TwilightListener() {
Jeff Brownaa202a62012-08-21 22:14:26 -07001366 @Override
1367 public void onTwilightStateChanged() {
1368 mTwilightChanged = true;
1369 updatePowerState();
1370 }
1371 };
Jeff Brown96307042012-07-27 15:51:34 -07001372}