blob: b63f625596f5a077c76841c6f0ec4956163e3b60 [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);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800539
540 // Initialize screen on state.
541 if (mPowerState.isScreenOn()) {
542 mNotifier.onScreenOn();
543 } else {
544 mNotifier.onScreenOff();
545 }
546 mNotifier.onScreenBrightness(mPowerState.getScreenBrightness());
Jeff Brown96307042012-07-27 15:51:34 -0700547 }
548
549 private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
550 @Override
551 public void onAnimationStart(Animator animation) {
552 }
553 @Override
554 public void onAnimationEnd(Animator animation) {
555 sendUpdatePowerState();
556 }
557 @Override
558 public void onAnimationRepeat(Animator animation) {
559 }
560 @Override
561 public void onAnimationCancel(Animator animation) {
562 }
563 };
564
565 private void updatePowerState() {
566 // Update the power state request.
567 final boolean mustNotify;
568 boolean mustInitialize = false;
Jeff Brownaa202a62012-08-21 22:14:26 -0700569 boolean updateAutoBrightness = mTwilightChanged;
Jeff Browne941b1e2012-10-22 16:50:25 -0700570 boolean wasDim = false;
Jeff Brownaa202a62012-08-21 22:14:26 -0700571 mTwilightChanged = false;
Jeff Brown330560f2012-08-21 22:10:57 -0700572
Jeff Brown96307042012-07-27 15:51:34 -0700573 synchronized (mLock) {
574 mPendingUpdatePowerStateLocked = false;
575 if (mPendingRequestLocked == null) {
576 return; // wait until first actual power request
577 }
578
579 if (mPowerRequest == null) {
580 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
581 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
Jeff Brown6307a152012-08-20 13:24:23 -0700582 mPendingWaitForNegativeProximityLocked = false;
Jeff Brown96307042012-07-27 15:51:34 -0700583 mPendingRequestChangedLocked = false;
584 mustInitialize = true;
585 } else if (mPendingRequestChangedLocked) {
Jeff Brown330560f2012-08-21 22:10:57 -0700586 if (mPowerRequest.screenAutoBrightnessAdjustment
587 != mPendingRequestLocked.screenAutoBrightnessAdjustment) {
588 updateAutoBrightness = true;
589 }
Jeff Browne941b1e2012-10-22 16:50:25 -0700590 wasDim = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM);
Jeff Brown96307042012-07-27 15:51:34 -0700591 mPowerRequest.copyFrom(mPendingRequestLocked);
592 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
Jeff Brown6307a152012-08-20 13:24:23 -0700593 mPendingWaitForNegativeProximityLocked = false;
Jeff Brown96307042012-07-27 15:51:34 -0700594 mPendingRequestChangedLocked = false;
595 mDisplayReadyLocked = false;
596 }
597
598 mustNotify = !mDisplayReadyLocked;
599 }
600
601 // Initialize things the first time the power state is changed.
602 if (mustInitialize) {
603 initialize();
604 }
605
Jeff Brown6307a152012-08-20 13:24:23 -0700606 // Apply the proximity sensor.
Jeff Brown96307042012-07-27 15:51:34 -0700607 if (mProximitySensor != null) {
Jeff Brown6307a152012-08-20 13:24:23 -0700608 if (mPowerRequest.useProximitySensor
609 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
610 setProximitySensorEnabled(true);
611 if (!mScreenOffBecauseOfProximity
612 && mProximity == PROXIMITY_POSITIVE) {
613 mScreenOffBecauseOfProximity = true;
Jeff Brownec083212013-09-11 20:45:25 -0700614 sendOnProximityPositiveWithWakelock();
Jeff Brown6307a152012-08-20 13:24:23 -0700615 setScreenOn(false);
616 }
617 } else if (mWaitingForNegativeProximity
618 && mScreenOffBecauseOfProximity
619 && mProximity == PROXIMITY_POSITIVE
620 && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
621 setProximitySensorEnabled(true);
622 } else {
623 setProximitySensorEnabled(false);
624 mWaitingForNegativeProximity = false;
625 }
626 if (mScreenOffBecauseOfProximity
627 && mProximity != PROXIMITY_POSITIVE) {
Jeff Brown96307042012-07-27 15:51:34 -0700628 mScreenOffBecauseOfProximity = false;
Jeff Brownec083212013-09-11 20:45:25 -0700629 sendOnProximityNegativeWithWakelock();
Jeff Brown96307042012-07-27 15:51:34 -0700630 }
Jeff Brown6307a152012-08-20 13:24:23 -0700631 } else {
632 mWaitingForNegativeProximity = false;
Jeff Brown96307042012-07-27 15:51:34 -0700633 }
634
635 // Turn on the light sensor if needed.
636 if (mLightSensor != null) {
637 setLightSensorEnabled(mPowerRequest.useAutoBrightness
Jeff Brown330560f2012-08-21 22:10:57 -0700638 && wantScreenOn(mPowerRequest.screenState), updateAutoBrightness);
Jeff Brown96307042012-07-27 15:51:34 -0700639 }
640
641 // Set the screen brightness.
Jeff Brownb76eebff2012-10-05 22:26:44 -0700642 if (wantScreenOn(mPowerRequest.screenState)) {
643 int target;
644 boolean slow;
Jeff Brown96307042012-07-27 15:51:34 -0700645 if (mScreenAutoBrightness >= 0 && mLightSensorEnabled) {
646 // Use current auto-brightness value.
Jeff Brownb76eebff2012-10-05 22:26:44 -0700647 target = mScreenAutoBrightness;
648 slow = mUsingScreenAutoBrightness;
Jeff Brown96307042012-07-27 15:51:34 -0700649 mUsingScreenAutoBrightness = true;
650 } else {
651 // Light sensor is disabled or not ready yet.
652 // Use the current brightness setting from the request, which is expected
653 // provide a nominal default value for the case where auto-brightness
654 // is not ready yet.
Jeff Brownb76eebff2012-10-05 22:26:44 -0700655 target = mPowerRequest.screenBrightness;
656 slow = false;
Jeff Brown96307042012-07-27 15:51:34 -0700657 mUsingScreenAutoBrightness = false;
658 }
Jeff Brownb76eebff2012-10-05 22:26:44 -0700659 if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) {
Jeff Brown5244c932012-10-24 14:46:26 -0700660 // Dim quickly by at least some minimum amount.
Jeff Brownb76eebff2012-10-05 22:26:44 -0700661 target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION,
662 mScreenBrightnessDimConfig);
Jeff Brown5244c932012-10-24 14:46:26 -0700663 slow = false;
Jeff Browne941b1e2012-10-22 16:50:25 -0700664 } else if (wasDim) {
665 // Brighten quickly.
Jeff Brownb76eebff2012-10-05 22:26:44 -0700666 slow = false;
667 }
668 animateScreenBrightness(clampScreenBrightness(target),
669 slow ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
Jeff Brown96307042012-07-27 15:51:34 -0700670 } else {
671 // Screen is off. Don't bother changing the brightness.
672 mUsingScreenAutoBrightness = false;
673 }
674
675 // Animate the screen on or off.
676 if (!mScreenOffBecauseOfProximity) {
677 if (wantScreenOn(mPowerRequest.screenState)) {
678 // Want screen on.
679 // Wait for previous off animation to complete beforehand.
680 // It is relatively short but if we cancel it and switch to the
681 // on animation immediately then the results are pretty ugly.
682 if (!mElectronBeamOffAnimator.isStarted()) {
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700683 // Turn the screen on. The contents of the screen may not yet
684 // be visible if the electron beam has not been dismissed because
685 // its last frame of animation is solid black.
686 setScreenOn(true);
687
688 if (mPowerRequest.blockScreenOn
689 && mPowerState.getElectronBeamLevel() == 0.0f) {
690 blockScreenOn();
Jeff Brown13c589b2012-08-16 16:20:54 -0700691 } else {
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700692 unblockScreenOn();
Jeff Brownc38c9be2012-10-04 13:16:19 -0700693 if (USE_ELECTRON_BEAM_ON_ANIMATION) {
694 if (!mElectronBeamOnAnimator.isStarted()) {
695 if (mPowerState.getElectronBeamLevel() == 1.0f) {
696 mPowerState.dismissElectronBeam();
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700697 } else if (mPowerState.prepareElectronBeam(
Jeff Brown252c2062012-10-08 16:21:01 -0700698 mElectronBeamFadesConfig ?
699 ElectronBeam.MODE_FADE :
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700700 ElectronBeam.MODE_WARM_UP)) {
Jeff Brownc38c9be2012-10-04 13:16:19 -0700701 mElectronBeamOnAnimator.start();
702 } else {
703 mElectronBeamOnAnimator.end();
704 }
705 }
706 } else {
707 mPowerState.setElectronBeamLevel(1.0f);
708 mPowerState.dismissElectronBeam();
709 }
710 }
Jeff Brown96307042012-07-27 15:51:34 -0700711 }
712 } else {
713 // Want screen off.
714 // Wait for previous on animation to complete beforehand.
715 if (!mElectronBeamOnAnimator.isStarted()) {
716 if (!mElectronBeamOffAnimator.isStarted()) {
717 if (mPowerState.getElectronBeamLevel() == 0.0f) {
718 setScreenOn(false);
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700719 } else if (mPowerState.prepareElectronBeam(
Jeff Brown252c2062012-10-08 16:21:01 -0700720 mElectronBeamFadesConfig ?
721 ElectronBeam.MODE_FADE :
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700722 ElectronBeam.MODE_COOL_DOWN)
Jeff Brown96307042012-07-27 15:51:34 -0700723 && mPowerState.isScreenOn()) {
724 mElectronBeamOffAnimator.start();
725 } else {
726 mElectronBeamOffAnimator.end();
727 }
728 }
729 }
730 }
731 }
732
733 // Report whether the display is ready for use.
734 // We mostly care about the screen state here, ignoring brightness changes
735 // which will be handled asynchronously.
736 if (mustNotify
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700737 && !mScreenOnWasBlocked
Jeff Brown96307042012-07-27 15:51:34 -0700738 && !mElectronBeamOnAnimator.isStarted()
739 && !mElectronBeamOffAnimator.isStarted()
740 && mPowerState.waitUntilClean(mCleanListener)) {
741 synchronized (mLock) {
742 if (!mPendingRequestChangedLocked) {
743 mDisplayReadyLocked = true;
Jeff Brownc38c9be2012-10-04 13:16:19 -0700744
745 if (DEBUG) {
746 Slog.d(TAG, "Display ready!");
747 }
Jeff Brown96307042012-07-27 15:51:34 -0700748 }
749 }
Jeff Brownec083212013-09-11 20:45:25 -0700750 sendOnStateChangedWithWakelock();
Jeff Brown96307042012-07-27 15:51:34 -0700751 }
752 }
753
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700754 private void blockScreenOn() {
755 if (!mScreenOnWasBlocked) {
756 mScreenOnWasBlocked = true;
757 if (DEBUG) {
758 Slog.d(TAG, "Blocked screen on.");
759 mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
760 }
761 }
762 }
763
764 private void unblockScreenOn() {
765 if (mScreenOnWasBlocked) {
766 mScreenOnWasBlocked = false;
767 if (DEBUG) {
768 Slog.d(TAG, "Unblocked screen on after " +
769 (SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime) + " ms");
770 }
771 }
772 }
773
Jeff Brown96307042012-07-27 15:51:34 -0700774 private void setScreenOn(boolean on) {
775 if (!mPowerState.isScreenOn() == on) {
776 mPowerState.setScreenOn(on);
777 if (on) {
778 mNotifier.onScreenOn();
779 } else {
780 mNotifier.onScreenOff();
781 }
782 }
783 }
784
Jeff Brown330560f2012-08-21 22:10:57 -0700785 private int clampScreenBrightness(int value) {
Jeff Brownb76eebff2012-10-05 22:26:44 -0700786 return clamp(value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
787 }
788
789 private static int clampAbsoluteBrightness(int value) {
790 return clamp(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
791 }
792
793 private static int clamp(int value, int min, int max) {
794 if (value <= min) {
795 return min;
796 }
797 if (value >= max) {
798 return max;
799 }
800 return value;
801 }
802
803 private static float normalizeAbsoluteBrightness(int value) {
804 return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON;
Jeff Brown330560f2012-08-21 22:10:57 -0700805 }
806
Jeff Brown96307042012-07-27 15:51:34 -0700807 private void animateScreenBrightness(int target, int rate) {
808 if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
809 mNotifier.onScreenBrightness(target);
810 }
811 }
812
813 private final Runnable mCleanListener = new Runnable() {
814 @Override
815 public void run() {
816 sendUpdatePowerState();
817 }
818 };
819
820 private void setProximitySensorEnabled(boolean enable) {
821 if (enable) {
822 if (!mProximitySensorEnabled) {
Jeff Brownec083212013-09-11 20:45:25 -0700823 // Register the listener.
824 // Proximity sensor state already cleared initially.
Jeff Brown96307042012-07-27 15:51:34 -0700825 mProximitySensorEnabled = true;
Jeff Brown96307042012-07-27 15:51:34 -0700826 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
827 SensorManager.SENSOR_DELAY_NORMAL, mHandler);
828 }
829 } else {
830 if (mProximitySensorEnabled) {
Jeff Brownec083212013-09-11 20:45:25 -0700831 // Unregister the listener.
832 // Clear the proximity sensor state for next time.
Jeff Brown96307042012-07-27 15:51:34 -0700833 mProximitySensorEnabled = false;
834 mProximity = PROXIMITY_UNKNOWN;
Jeff Brownec083212013-09-11 20:45:25 -0700835 mPendingProximity = PROXIMITY_UNKNOWN;
Jeff Brown96307042012-07-27 15:51:34 -0700836 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
837 mSensorManager.unregisterListener(mProximitySensorListener);
Jeff Brownec083212013-09-11 20:45:25 -0700838 clearPendingProximityDebounceTime(); // release wake lock (must be last)
Jeff Brown96307042012-07-27 15:51:34 -0700839 }
840 }
841 }
842
843 private void handleProximitySensorEvent(long time, boolean positive) {
Jeff Brownec083212013-09-11 20:45:25 -0700844 if (mProximitySensorEnabled) {
845 if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
846 return; // no change
847 }
848 if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
849 return; // no change
850 }
Jeff Brown96307042012-07-27 15:51:34 -0700851
Jeff Brownec083212013-09-11 20:45:25 -0700852 // Only accept a proximity sensor reading if it remains
853 // stable for the entire debounce delay. We hold a wake lock while
854 // debouncing the sensor.
855 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
856 if (positive) {
857 mPendingProximity = PROXIMITY_POSITIVE;
858 setPendingProximityDebounceTime(
859 time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
860 } else {
861 mPendingProximity = PROXIMITY_NEGATIVE;
862 setPendingProximityDebounceTime(
863 time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
864 }
865
866 // Debounce the new sensor reading.
867 debounceProximitySensor();
Jeff Brown93cbbb22012-10-04 13:18:36 -0700868 }
Jeff Brown96307042012-07-27 15:51:34 -0700869 }
870
871 private void debounceProximitySensor() {
Jeff Brownec083212013-09-11 20:45:25 -0700872 if (mProximitySensorEnabled
873 && mPendingProximity != PROXIMITY_UNKNOWN
874 && mPendingProximityDebounceTime >= 0) {
Jeff Brown96307042012-07-27 15:51:34 -0700875 final long now = SystemClock.uptimeMillis();
876 if (mPendingProximityDebounceTime <= now) {
Jeff Brownec083212013-09-11 20:45:25 -0700877 // Sensor reading accepted. Apply the change then release the wake lock.
Jeff Brown96307042012-07-27 15:51:34 -0700878 mProximity = mPendingProximity;
Jeff Brownec083212013-09-11 20:45:25 -0700879 updatePowerState();
880 clearPendingProximityDebounceTime(); // release wake lock (must be last)
Jeff Brown96307042012-07-27 15:51:34 -0700881 } else {
Jeff Brownec083212013-09-11 20:45:25 -0700882 // Need to wait a little longer.
883 // Debounce again later. We continue holding a wake lock while waiting.
Jeff Brown96307042012-07-27 15:51:34 -0700884 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
885 msg.setAsynchronous(true);
886 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
887 }
888 }
889 }
890
Jeff Brownec083212013-09-11 20:45:25 -0700891 private void clearPendingProximityDebounceTime() {
892 if (mPendingProximityDebounceTime >= 0) {
893 mPendingProximityDebounceTime = -1;
894 mDisplaySuspendBlocker.release(); // release wake lock
895 }
896 }
897
898 private void setPendingProximityDebounceTime(long debounceTime) {
899 if (mPendingProximityDebounceTime < 0) {
900 mDisplaySuspendBlocker.acquire(); // acquire wake lock
901 }
902 mPendingProximityDebounceTime = debounceTime;
903 }
904
Jeff Brown330560f2012-08-21 22:10:57 -0700905 private void setLightSensorEnabled(boolean enable, boolean updateAutoBrightness) {
Jeff Brown96307042012-07-27 15:51:34 -0700906 if (enable) {
907 if (!mLightSensorEnabled) {
Jeff Brown330560f2012-08-21 22:10:57 -0700908 updateAutoBrightness = true;
Jeff Brown96307042012-07-27 15:51:34 -0700909 mLightSensorEnabled = true;
910 mLightSensorEnableTime = SystemClock.uptimeMillis();
911 mSensorManager.registerListener(mLightSensorListener, mLightSensor,
Jeff Browne941b1e2012-10-22 16:50:25 -0700912 LIGHT_SENSOR_RATE_MILLIS * 1000, mHandler);
Jeff Brown96307042012-07-27 15:51:34 -0700913 }
914 } else {
915 if (mLightSensorEnabled) {
916 mLightSensorEnabled = false;
Jeff Brown4f0e9692012-10-18 16:14:16 -0700917 mAmbientLuxValid = false;
918 mRecentLightSamples = 0;
Jeff Brown96307042012-07-27 15:51:34 -0700919 mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
920 mSensorManager.unregisterListener(mLightSensorListener);
921 }
922 }
Jeff Brown330560f2012-08-21 22:10:57 -0700923 if (updateAutoBrightness) {
924 updateAutoBrightness(false);
925 }
Jeff Brown96307042012-07-27 15:51:34 -0700926 }
927
928 private void handleLightSensorEvent(long time, float lux) {
Jeff Browne941b1e2012-10-22 16:50:25 -0700929 mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
930
931 applyLightSensorMeasurement(time, lux);
932 updateAmbientLux(time);
933 }
934
935 private void applyLightSensorMeasurement(long time, float lux) {
Jeff Brown4f0e9692012-10-18 16:14:16 -0700936 // Update our filters.
Jeff Brown96307042012-07-27 15:51:34 -0700937 mRecentLightSamples += 1;
Jeff Brown4f0e9692012-10-18 16:14:16 -0700938 if (mRecentLightSamples == 1) {
939 mRecentShortTermAverageLux = lux;
940 mRecentLongTermAverageLux = lux;
941 } else {
942 final long timeDelta = time - mLastObservedLuxTime;
943 mRecentShortTermAverageLux += (lux - mRecentShortTermAverageLux)
944 * timeDelta / (SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta);
945 mRecentLongTermAverageLux += (lux - mRecentLongTermAverageLux)
946 * timeDelta / (LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta);
947 }
948
949 // Remember this sample value.
950 mLastObservedLux = lux;
951 mLastObservedLuxTime = time;
Jeff Brown96307042012-07-27 15:51:34 -0700952 }
953
Michael Wright65031a22013-11-04 19:07:49 -0800954 private void setAmbientLux(float lux) {
955 mAmbientLux = lux;
956 mBrighteningLuxThreshold = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS);
957 mDarkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS);
958 }
959
Jeff Brown4f0e9692012-10-18 16:14:16 -0700960 private void updateAmbientLux(long time) {
961 // If the light sensor was just turned on then immediately update our initial
962 // estimate of the current ambient light level.
Michael Wright65031a22013-11-04 19:07:49 -0800963 if (!mAmbientLuxValid) {
964 final long timeWhenSensorWarmedUp =
965 mLightSensorWarmUpTimeConfig + mLightSensorEnableTime;
966 if (time < timeWhenSensorWarmedUp) {
967 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED,
968 timeWhenSensorWarmedUp);
969 return;
970 }
971 setAmbientLux(mRecentShortTermAverageLux);
Jeff Brown4f0e9692012-10-18 16:14:16 -0700972 mAmbientLuxValid = true;
Jeff Browne941b1e2012-10-22 16:50:25 -0700973 mDebounceLuxDirection = 0;
974 mDebounceLuxTime = time;
975 if (DEBUG) {
976 Slog.d(TAG, "updateAmbientLux: Initializing: "
977 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
978 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
979 + ", mAmbientLux=" + mAmbientLux);
980 }
Jeff Brown4f0e9692012-10-18 16:14:16 -0700981 updateAutoBrightness(true);
Michael Wright65031a22013-11-04 19:07:49 -0800982 } else if (mRecentShortTermAverageLux > mBrighteningLuxThreshold
983 && mRecentLongTermAverageLux > mBrighteningLuxThreshold) {
984 // The ambient environment appears to be brightening.
Jeff Browne941b1e2012-10-22 16:50:25 -0700985 if (mDebounceLuxDirection <= 0) {
986 mDebounceLuxDirection = 1;
987 mDebounceLuxTime = time;
988 if (DEBUG) {
989 Slog.d(TAG, "updateAmbientLux: Possibly brightened, waiting for "
990 + BRIGHTENING_LIGHT_DEBOUNCE + " ms: "
Michael Wright65031a22013-11-04 19:07:49 -0800991 + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold
Jeff Browne941b1e2012-10-22 16:50:25 -0700992 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
993 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
994 + ", mAmbientLux=" + mAmbientLux);
995 }
996 }
997 long debounceTime = mDebounceLuxTime + BRIGHTENING_LIGHT_DEBOUNCE;
Michael Wright65031a22013-11-04 19:07:49 -0800998 if (time < debounceTime) {
Jeff Brown4f0e9692012-10-18 16:14:16 -0700999 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
Michael Wright65031a22013-11-04 19:07:49 -08001000 return;
Jeff Brown4f0e9692012-10-18 16:14:16 -07001001 }
Michael Wright65031a22013-11-04 19:07:49 -08001002 setAmbientLux(mRecentShortTermAverageLux);
1003 if (DEBUG) {
1004 Slog.d(TAG, "updateAmbientLux: Brightened: "
1005 + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold
1006 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1007 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1008 + ", mAmbientLux=" + mAmbientLux);
1009 }
1010 updateAutoBrightness(true);
1011 } else if (mRecentShortTermAverageLux < mDarkeningLuxThreshold
1012 && mRecentLongTermAverageLux < mDarkeningLuxThreshold) {
1013 // The ambient environment appears to be darkening.
Jeff Browne941b1e2012-10-22 16:50:25 -07001014 if (mDebounceLuxDirection >= 0) {
1015 mDebounceLuxDirection = -1;
1016 mDebounceLuxTime = time;
1017 if (DEBUG) {
1018 Slog.d(TAG, "updateAmbientLux: Possibly darkened, waiting for "
1019 + DARKENING_LIGHT_DEBOUNCE + " ms: "
Michael Wright65031a22013-11-04 19:07:49 -08001020 + "mDarkeningLuxThreshold=" + mDarkeningLuxThreshold
Jeff Browne941b1e2012-10-22 16:50:25 -07001021 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1022 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1023 + ", mAmbientLux=" + mAmbientLux);
1024 }
1025 }
1026 long debounceTime = mDebounceLuxTime + DARKENING_LIGHT_DEBOUNCE;
Michael Wright65031a22013-11-04 19:07:49 -08001027 if (time < debounceTime) {
Jeff Brown4f0e9692012-10-18 16:14:16 -07001028 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
Michael Wright65031a22013-11-04 19:07:49 -08001029 return;
Jeff Brown96307042012-07-27 15:51:34 -07001030 }
Michael Wright65031a22013-11-04 19:07:49 -08001031 // Be conservative about reducing the brightness, only reduce it a little bit
1032 // at a time to avoid having to bump it up again soon.
1033 setAmbientLux(Math.max(mRecentShortTermAverageLux, mRecentLongTermAverageLux));
1034 if (DEBUG) {
1035 Slog.d(TAG, "updateAmbientLux: Darkened: "
1036 + "mDarkeningLuxThreshold=" + mDarkeningLuxThreshold
1037 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1038 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1039 + ", mAmbientLux=" + mAmbientLux);
1040 }
1041 updateAutoBrightness(true);
1042 } else if (mDebounceLuxDirection != 0) {
1043 // No change or change is within the hysteresis thresholds.
Jeff Browne941b1e2012-10-22 16:50:25 -07001044 mDebounceLuxDirection = 0;
1045 mDebounceLuxTime = time;
1046 if (DEBUG) {
1047 Slog.d(TAG, "updateAmbientLux: Canceled debounce: "
Michael Wright65031a22013-11-04 19:07:49 -08001048 + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold
1049 + ", mDarkeningLuxThreshold=" + mDarkeningLuxThreshold
Jeff Browne941b1e2012-10-22 16:50:25 -07001050 + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
1051 + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
1052 + ", mAmbientLux=" + mAmbientLux);
1053 }
1054 }
1055
Michael Wright65031a22013-11-04 19:07:49 -08001056 // Now that we've done all of that, we haven't yet posted a debounce
1057 // message. So consider the case where current lux is beyond the
1058 // threshold. It's possible that the light sensor may not report values
1059 // if the light level does not change, so we need to occasionally
1060 // synthesize sensor readings in order to make sure the brightness is
1061 // adjusted accordingly. Note these thresholds may have changed since
1062 // we entered the function because we called setAmbientLux and
1063 // updateAutoBrightness along the way.
1064 if (mLastObservedLux > mBrighteningLuxThreshold
1065 || mLastObservedLux < mDarkeningLuxThreshold) {
Jeff Browne941b1e2012-10-22 16:50:25 -07001066 mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED,
1067 time + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS);
Jeff Brown96307042012-07-27 15:51:34 -07001068 }
1069 }
1070
Jeff Brown4f0e9692012-10-18 16:14:16 -07001071 private void debounceLightSensor() {
Jeff Browne941b1e2012-10-22 16:50:25 -07001072 if (mLightSensorEnabled) {
1073 long time = SystemClock.uptimeMillis();
1074 if (time >= mLastObservedLuxTime + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS) {
1075 if (DEBUG) {
1076 Slog.d(TAG, "debounceLightSensor: Synthesizing light sensor measurement "
1077 + "after " + (time - mLastObservedLuxTime) + " ms.");
1078 }
1079 applyLightSensorMeasurement(time, mLastObservedLux);
1080 }
1081 updateAmbientLux(time);
1082 }
Jeff Brown4f0e9692012-10-18 16:14:16 -07001083 }
1084
Jeff Brown96307042012-07-27 15:51:34 -07001085 private void updateAutoBrightness(boolean sendUpdate) {
Jeff Brown4f0e9692012-10-18 16:14:16 -07001086 if (!mAmbientLuxValid) {
Jeff Brown96307042012-07-27 15:51:34 -07001087 return;
1088 }
1089
Jeff Brown4f0e9692012-10-18 16:14:16 -07001090 float value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux);
Jeff Brown330560f2012-08-21 22:10:57 -07001091 float gamma = 1.0f;
1092
1093 if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT
1094 && mPowerRequest.screenAutoBrightnessAdjustment != 0.0f) {
1095 final float adjGamma = FloatMath.pow(SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA,
1096 Math.min(1.0f, Math.max(-1.0f,
1097 -mPowerRequest.screenAutoBrightnessAdjustment)));
1098 gamma *= adjGamma;
1099 if (DEBUG) {
1100 Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma);
1101 }
1102 }
1103
Jeff Brownaa202a62012-08-21 22:14:26 -07001104 if (USE_TWILIGHT_ADJUSTMENT) {
1105 TwilightState state = mTwilight.getCurrentState();
1106 if (state != null && state.isNight()) {
1107 final long now = System.currentTimeMillis();
1108 final float earlyGamma =
1109 getTwilightGamma(now, state.getYesterdaySunset(), state.getTodaySunrise());
1110 final float lateGamma =
1111 getTwilightGamma(now, state.getTodaySunset(), state.getTomorrowSunrise());
1112 gamma *= earlyGamma * lateGamma;
1113 if (DEBUG) {
1114 Slog.d(TAG, "updateAutoBrightness: earlyGamma=" + earlyGamma
1115 + ", lateGamma=" + lateGamma);
1116 }
1117 }
1118 }
1119
Jeff Brown330560f2012-08-21 22:10:57 -07001120 if (gamma != 1.0f) {
1121 final float in = value;
1122 value = FloatMath.pow(value, gamma);
1123 if (DEBUG) {
1124 Slog.d(TAG, "updateAutoBrightness: gamma=" + gamma
1125 + ", in=" + in + ", out=" + value);
1126 }
1127 }
1128
1129 int newScreenAutoBrightness = clampScreenBrightness(
Jeff Brown4f0e9692012-10-18 16:14:16 -07001130 Math.round(value * PowerManager.BRIGHTNESS_ON));
Jeff Brown96307042012-07-27 15:51:34 -07001131 if (mScreenAutoBrightness != newScreenAutoBrightness) {
1132 if (DEBUG) {
1133 Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness="
Jeff Brown330560f2012-08-21 22:10:57 -07001134 + mScreenAutoBrightness + ", newScreenAutoBrightness="
Jeff Brown1a30b552012-08-16 01:31:11 -07001135 + newScreenAutoBrightness);
Jeff Brown96307042012-07-27 15:51:34 -07001136 }
1137
1138 mScreenAutoBrightness = newScreenAutoBrightness;
Jeff Brown330560f2012-08-21 22:10:57 -07001139 mLastScreenAutoBrightnessGamma = gamma;
Jeff Brown96307042012-07-27 15:51:34 -07001140 if (sendUpdate) {
1141 sendUpdatePowerState();
1142 }
1143 }
1144 }
1145
Jeff Brownaa202a62012-08-21 22:14:26 -07001146 private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) {
1147 if (lastSunset < 0 || nextSunrise < 0
1148 || now < lastSunset || now > nextSunrise) {
1149 return 1.0f;
1150 }
1151
1152 if (now < lastSunset + TWILIGHT_ADJUSTMENT_TIME) {
1153 return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
1154 (float)(now - lastSunset) / TWILIGHT_ADJUSTMENT_TIME);
1155 }
1156
1157 if (now > nextSunrise - TWILIGHT_ADJUSTMENT_TIME) {
1158 return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
1159 (float)(nextSunrise - now) / TWILIGHT_ADJUSTMENT_TIME);
1160 }
1161
1162 return TWILIGHT_ADJUSTMENT_MAX_GAMMA;
1163 }
1164
1165 private static float lerp(float x, float y, float alpha) {
1166 return x + (y - x) * alpha;
1167 }
1168
Jeff Brownec083212013-09-11 20:45:25 -07001169 private void sendOnStateChangedWithWakelock() {
1170 mDisplaySuspendBlocker.acquire();
Jeff Brown96307042012-07-27 15:51:34 -07001171 mCallbackHandler.post(mOnStateChangedRunnable);
1172 }
1173
1174 private final Runnable mOnStateChangedRunnable = new Runnable() {
1175 @Override
1176 public void run() {
1177 mCallbacks.onStateChanged();
Jeff Brownec083212013-09-11 20:45:25 -07001178 mDisplaySuspendBlocker.release();
Jeff Brown96307042012-07-27 15:51:34 -07001179 }
1180 };
1181
Jeff Brownec083212013-09-11 20:45:25 -07001182 private void sendOnProximityPositiveWithWakelock() {
1183 mDisplaySuspendBlocker.acquire();
Jeff Brown93cbbb22012-10-04 13:18:36 -07001184 mCallbackHandler.post(mOnProximityPositiveRunnable);
1185 }
1186
1187 private final Runnable mOnProximityPositiveRunnable = new Runnable() {
1188 @Override
1189 public void run() {
1190 mCallbacks.onProximityPositive();
Jeff Brownec083212013-09-11 20:45:25 -07001191 mDisplaySuspendBlocker.release();
Jeff Brown93cbbb22012-10-04 13:18:36 -07001192 }
1193 };
1194
Jeff Brownec083212013-09-11 20:45:25 -07001195 private void sendOnProximityNegativeWithWakelock() {
1196 mDisplaySuspendBlocker.acquire();
Jeff Brown96307042012-07-27 15:51:34 -07001197 mCallbackHandler.post(mOnProximityNegativeRunnable);
1198 }
1199
1200 private final Runnable mOnProximityNegativeRunnable = new Runnable() {
1201 @Override
1202 public void run() {
1203 mCallbacks.onProximityNegative();
Jeff Brownec083212013-09-11 20:45:25 -07001204 mDisplaySuspendBlocker.release();
Jeff Brown96307042012-07-27 15:51:34 -07001205 }
1206 };
1207
Jeff Brownbd6e1502012-08-28 03:27:37 -07001208 public void dump(final PrintWriter pw) {
Jeff Brown96307042012-07-27 15:51:34 -07001209 synchronized (mLock) {
1210 pw.println();
1211 pw.println("Display Controller Locked State:");
1212 pw.println(" mDisplayReadyLocked=" + mDisplayReadyLocked);
1213 pw.println(" mPendingRequestLocked=" + mPendingRequestLocked);
1214 pw.println(" mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
1215 pw.println(" mPendingWaitForNegativeProximityLocked="
1216 + mPendingWaitForNegativeProximityLocked);
1217 pw.println(" mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
1218 }
1219
1220 pw.println();
1221 pw.println("Display Controller Configuration:");
1222 pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
Jeff Brownb76eebff2012-10-05 22:26:44 -07001223 pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
1224 pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
Jeff Brown96307042012-07-27 15:51:34 -07001225 pw.println(" mUseSoftwareAutoBrightnessConfig="
1226 + mUseSoftwareAutoBrightnessConfig);
Jeff Brown1a30b552012-08-16 01:31:11 -07001227 pw.println(" mScreenAutoBrightnessSpline=" + mScreenAutoBrightnessSpline);
Jeff Brown96307042012-07-27 15:51:34 -07001228 pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig);
1229
Jeff Brownbd6e1502012-08-28 03:27:37 -07001230 mHandler.runWithScissors(new Runnable() {
1231 @Override
1232 public void run() {
1233 dumpLocal(pw);
Jeff Brown96307042012-07-27 15:51:34 -07001234 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001235 }, 1000);
Jeff Brown96307042012-07-27 15:51:34 -07001236 }
1237
1238 private void dumpLocal(PrintWriter pw) {
1239 pw.println();
1240 pw.println("Display Controller Thread State:");
1241 pw.println(" mPowerRequest=" + mPowerRequest);
1242 pw.println(" mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
1243
1244 pw.println(" mProximitySensor=" + mProximitySensor);
1245 pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled);
1246 pw.println(" mProximityThreshold=" + mProximityThreshold);
1247 pw.println(" mProximity=" + proximityToString(mProximity));
1248 pw.println(" mPendingProximity=" + proximityToString(mPendingProximity));
1249 pw.println(" mPendingProximityDebounceTime="
1250 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
1251 pw.println(" mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
1252
1253 pw.println(" mLightSensor=" + mLightSensor);
1254 pw.println(" mLightSensorEnabled=" + mLightSensorEnabled);
1255 pw.println(" mLightSensorEnableTime="
1256 + TimeUtils.formatUptime(mLightSensorEnableTime));
Jeff Brown4f0e9692012-10-18 16:14:16 -07001257 pw.println(" mAmbientLux=" + mAmbientLux);
1258 pw.println(" mAmbientLuxValid=" + mAmbientLuxValid);
Jeff Brown4f0e9692012-10-18 16:14:16 -07001259 pw.println(" mLastObservedLux=" + mLastObservedLux);
1260 pw.println(" mLastObservedLuxTime="
1261 + TimeUtils.formatUptime(mLastObservedLuxTime));
Jeff Brown96307042012-07-27 15:51:34 -07001262 pw.println(" mRecentLightSamples=" + mRecentLightSamples);
Jeff Brown4f0e9692012-10-18 16:14:16 -07001263 pw.println(" mRecentShortTermAverageLux=" + mRecentShortTermAverageLux);
1264 pw.println(" mRecentLongTermAverageLux=" + mRecentLongTermAverageLux);
Jeff Browne941b1e2012-10-22 16:50:25 -07001265 pw.println(" mDebounceLuxDirection=" + mDebounceLuxDirection);
1266 pw.println(" mDebounceLuxTime=" + TimeUtils.formatUptime(mDebounceLuxTime));
Jeff Brown96307042012-07-27 15:51:34 -07001267 pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness);
1268 pw.println(" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness);
Jeff Brown330560f2012-08-21 22:10:57 -07001269 pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
Jeff Brownaa202a62012-08-21 22:14:26 -07001270 pw.println(" mTwilight.getCurrentState()=" + mTwilight.getCurrentState());
Jeff Brown96307042012-07-27 15:51:34 -07001271
1272 if (mElectronBeamOnAnimator != null) {
1273 pw.println(" mElectronBeamOnAnimator.isStarted()=" +
1274 mElectronBeamOnAnimator.isStarted());
1275 }
1276 if (mElectronBeamOffAnimator != null) {
1277 pw.println(" mElectronBeamOffAnimator.isStarted()=" +
1278 mElectronBeamOffAnimator.isStarted());
1279 }
1280
1281 if (mPowerState != null) {
1282 mPowerState.dump(pw);
1283 }
1284 }
1285
1286 private static String proximityToString(int state) {
1287 switch (state) {
1288 case PROXIMITY_UNKNOWN:
1289 return "Unknown";
1290 case PROXIMITY_NEGATIVE:
1291 return "Negative";
1292 case PROXIMITY_POSITIVE:
1293 return "Positive";
1294 default:
1295 return Integer.toString(state);
1296 }
1297 }
1298
1299 private static boolean wantScreenOn(int state) {
1300 switch (state) {
1301 case DisplayPowerRequest.SCREEN_STATE_BRIGHT:
1302 case DisplayPowerRequest.SCREEN_STATE_DIM:
1303 return true;
1304 }
1305 return false;
1306 }
1307
1308 /**
1309 * Asynchronous callbacks from the power controller to the power manager service.
1310 */
1311 public interface Callbacks {
1312 void onStateChanged();
Jeff Brown93cbbb22012-10-04 13:18:36 -07001313 void onProximityPositive();
Jeff Brown96307042012-07-27 15:51:34 -07001314 void onProximityNegative();
1315 }
1316
1317 private final class DisplayControllerHandler extends Handler {
1318 public DisplayControllerHandler(Looper looper) {
Jeff Browna2910d02012-08-25 12:29:46 -07001319 super(looper, null, true /*async*/);
Jeff Brown96307042012-07-27 15:51:34 -07001320 }
1321
1322 @Override
1323 public void handleMessage(Message msg) {
1324 switch (msg.what) {
1325 case MSG_UPDATE_POWER_STATE:
1326 updatePowerState();
1327 break;
1328
1329 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
1330 debounceProximitySensor();
1331 break;
1332
1333 case MSG_LIGHT_SENSOR_DEBOUNCED:
1334 debounceLightSensor();
1335 break;
1336 }
1337 }
1338 }
1339
1340 private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
1341 @Override
1342 public void onSensorChanged(SensorEvent event) {
1343 if (mProximitySensorEnabled) {
1344 final long time = SystemClock.uptimeMillis();
1345 final float distance = event.values[0];
1346 boolean positive = distance >= 0.0f && distance < mProximityThreshold;
1347 handleProximitySensorEvent(time, positive);
1348 }
1349 }
1350
1351 @Override
1352 public void onAccuracyChanged(Sensor sensor, int accuracy) {
1353 // Not used.
1354 }
1355 };
1356
1357 private final SensorEventListener mLightSensorListener = new SensorEventListener() {
1358 @Override
1359 public void onSensorChanged(SensorEvent event) {
1360 if (mLightSensorEnabled) {
1361 final long time = SystemClock.uptimeMillis();
1362 final float lux = event.values[0];
1363 handleLightSensorEvent(time, lux);
1364 }
1365 }
1366
1367 @Override
1368 public void onAccuracyChanged(Sensor sensor, int accuracy) {
1369 // Not used.
1370 }
1371 };
Jeff Brownaa202a62012-08-21 22:14:26 -07001372
Adam Lesinski182f73f2013-12-05 16:48:06 -08001373 private final TwilightListener mTwilightListener = new TwilightListener() {
Jeff Brownaa202a62012-08-21 22:14:26 -07001374 @Override
1375 public void onTwilightStateChanged() {
1376 mTwilightChanged = true;
1377 updatePowerState();
1378 }
1379 };
Jeff Brown96307042012-07-27 15:51:34 -07001380}