blob: 1d8003b9b721ff34606d174bd01b42e0839d8d2d [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
Jeff Brown131206b2014-04-08 17:27:14 -070017package com.android.server.display;
Jeff Brown96307042012-07-27 15:51:34 -070018
Jeff Brown131206b2014-04-08 17:27:14 -070019import com.android.internal.app.IBatteryStats;
20import com.android.server.LocalServices;
21import com.android.server.am.BatteryStatsService;
Adam Lesinski182f73f2013-12-05 16:48:06 -080022import com.android.server.lights.LightsManager;
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 Brown131206b2014-04-08 17:27:14 -070032import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
33import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
Jeff Brown96307042012-07-27 15:51:34 -070034import android.os.Handler;
35import android.os.Looper;
36import android.os.Message;
Jeff Brown330560f2012-08-21 22:10:57 -070037import android.os.PowerManager;
Jeff Brown131206b2014-04-08 17:27:14 -070038import android.os.RemoteException;
Jeff Brown96307042012-07-27 15:51:34 -070039import android.os.SystemClock;
Jeff Brown3edf5272014-08-14 19:25:14 -070040import android.os.Trace;
Michael Wright41a5cdf2013-11-13 16:18:32 -080041import android.util.MathUtils;
Jeff Brown96307042012-07-27 15:51:34 -070042import android.util.Slog;
Jeff Brown1a30b552012-08-16 01:31:11 -070043import android.util.Spline;
Jeff Brown96307042012-07-27 15:51:34 -070044import android.util.TimeUtils;
Jeff Brown037c33e2014-04-09 00:31:55 -070045import android.view.Display;
Jeff Brown3ee549c2014-09-22 20:14:39 -070046import android.view.WindowManagerPolicy;
Jeff Brown96307042012-07-27 15:51:34 -070047
48import java.io.PrintWriter;
Jeff Brown96307042012-07-27 15:51:34 -070049
50/**
51 * Controls the power state of the display.
52 *
53 * Handles the proximity sensor, light sensor, and animations between states
54 * including the screen off animation.
55 *
56 * This component acts independently of the rest of the power manager service.
57 * In particular, it does not share any state and it only communicates
58 * via asynchronous callbacks to inform the power manager that something has
59 * changed.
60 *
61 * Everything this class does internally is serialized on its handler although
62 * it may be accessed by other threads from the outside.
63 *
64 * Note that the power manager service guarantees that it will hold a suspend
65 * blocker as long as the display is not ready. So most of the work done here
66 * does not need to worry about holding a suspend blocker unless it happens
67 * independently of the display ready signal.
Michael Lentine0839adb2014-07-29 18:47:56 -070068 *
Jeff Brown3ee549c2014-09-22 20:14:39 -070069 * For debugging, you can make the color fade and brightness animations run
Jeff Brown96307042012-07-27 15:51:34 -070070 * slower by changing the "animator duration scale" option in Development Settings.
71 */
Michael Wright639c8be2014-01-17 18:29:12 -080072final class DisplayPowerController implements AutomaticBrightnessController.Callbacks {
Jeff Brown96307042012-07-27 15:51:34 -070073 private static final String TAG = "DisplayPowerController";
74
Michael Wright639c8be2014-01-17 18:29:12 -080075 private static boolean DEBUG = false;
Jeff Brown96307042012-07-27 15:51:34 -070076 private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
Jeff Brown96307042012-07-27 15:51:34 -070077
Jeff Brown3edf5272014-08-14 19:25:14 -070078 private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
79
Jeff Brown3ee549c2014-09-22 20:14:39 -070080 // If true, uses the color fade on animation.
Jeff Brown13c589b2012-08-16 16:20:54 -070081 // We might want to turn this off if we cannot get a guarantee that the screen
82 // actually turns on and starts showing new content after the call to set the
Jeff Brown5356c7dc2012-08-20 20:17:36 -070083 // screen state returns. Playing the animation can also be somewhat slow.
Michael Lentine0839adb2014-07-29 18:47:56 -070084 private static final boolean USE_COLOR_FADE_ON_ANIMATION = false;
Jeff Brown13c589b2012-08-16 16:20:54 -070085
Jeff Brownb76eebff2012-10-05 22:26:44 -070086 // The minimum reduction in brightness when dimmed.
87 private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10;
88
Michael Lentine0839adb2014-07-29 18:47:56 -070089 private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
Michael Lentine0c9a62d2014-08-20 09:19:07 -070090 private static final int COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS = 400;
Jeff Brown96307042012-07-27 15:51:34 -070091
92 private static final int MSG_UPDATE_POWER_STATE = 1;
93 private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
Jeff Brown3ee549c2014-09-22 20:14:39 -070094 private static final int MSG_SCREEN_ON_UNBLOCKED = 3;
Jeff Brown96307042012-07-27 15:51:34 -070095
96 private static final int PROXIMITY_UNKNOWN = -1;
97 private static final int PROXIMITY_NEGATIVE = 0;
98 private static final int PROXIMITY_POSITIVE = 1;
99
Jeff Brown93cbbb22012-10-04 13:18:36 -0700100 // Proximity sensor debounce delay in milliseconds for positive or negative transitions.
101 private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0;
Jeff Brownec083212013-09-11 20:45:25 -0700102 private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 250;
Jeff Brown96307042012-07-27 15:51:34 -0700103
104 // Trigger proximity if distance is less than 5 cm.
105 private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
106
Jeff Brown96307042012-07-27 15:51:34 -0700107 // Brightness animation ramp rate in brightness units per second.
108 private static final int BRIGHTNESS_RAMP_RATE_FAST = 200;
Jeff Browne941b1e2012-10-22 16:50:25 -0700109 private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
Jeff Brown96307042012-07-27 15:51:34 -0700110
Jeff Brown96307042012-07-27 15:51:34 -0700111 private final Object mLock = new Object();
112
Michael Lentine0839adb2014-07-29 18:47:56 -0700113 private final Context mContext;
114
Jeff Brown96307042012-07-27 15:51:34 -0700115 // Our handler.
116 private final DisplayControllerHandler mHandler;
117
118 // Asynchronous callbacks into the power manager service.
119 // Only invoked from the handler thread while no locks are held.
Jeff Brown131206b2014-04-08 17:27:14 -0700120 private final DisplayPowerCallbacks mCallbacks;
121
122 // Battery stats.
123 private final IBatteryStats mBatteryStats;
Jeff Brown96307042012-07-27 15:51:34 -0700124
125 // The lights service.
Adam Lesinski182f73f2013-12-05 16:48:06 -0800126 private final LightsManager mLights;
Jeff Brown96307042012-07-27 15:51:34 -0700127
128 // The sensor manager.
129 private final SensorManager mSensorManager;
130
Jeff Brown3ee549c2014-09-22 20:14:39 -0700131 // The window manager policy.
132 private final WindowManagerPolicy mWindowManagerPolicy;
133
Jeff Brown037c33e2014-04-09 00:31:55 -0700134 // The display blanker.
135 private final DisplayBlanker mBlanker;
136
Jeff Brown96307042012-07-27 15:51:34 -0700137 // The proximity sensor, or null if not available or needed.
138 private Sensor mProximitySensor;
139
Jeff Brown26875502014-01-30 21:47:47 -0800140 // The doze screen brightness.
141 private final int mScreenBrightnessDozeConfig;
142
Jeff Brown96307042012-07-27 15:51:34 -0700143 // The dim screen brightness.
144 private final int mScreenBrightnessDimConfig;
145
Jeff Brown1bfd0f42014-08-22 01:59:06 -0700146 // The minimum screen brightness to use in a very dark room.
147 private final int mScreenBrightnessDarkConfig;
148
Jeff Brownb76eebff2012-10-05 22:26:44 -0700149 // The minimum allowed brightness.
150 private final int mScreenBrightnessRangeMinimum;
151
152 // The maximum allowed brightness.
153 private final int mScreenBrightnessRangeMaximum;
154
Jeff Brown330560f2012-08-21 22:10:57 -0700155 // True if auto-brightness should be used.
Jeff Brown96307042012-07-27 15:51:34 -0700156 private boolean mUseSoftwareAutoBrightnessConfig;
Jeff Brown330560f2012-08-21 22:10:57 -0700157
Jeff Brown252c2062012-10-08 16:21:01 -0700158 // True if we should fade the screen while turning it off, false if we should play
Jeff Brown3ee549c2014-09-22 20:14:39 -0700159 // a stylish color fade animation instead.
Michael Lentine0839adb2014-07-29 18:47:56 -0700160 private boolean mColorFadeFadesConfig;
Jeff Browna52772f2012-10-04 18:38:09 -0700161
Jeff Brown96307042012-07-27 15:51:34 -0700162 // The pending power request.
163 // Initially null until the first call to requestPowerState.
164 // Guarded by mLock.
165 private DisplayPowerRequest mPendingRequestLocked;
166
167 // True if a request has been made to wait for the proximity sensor to go negative.
168 // Guarded by mLock.
169 private boolean mPendingWaitForNegativeProximityLocked;
170
171 // True if the pending power request or wait for negative proximity flag
172 // has been changed since the last update occurred.
173 // Guarded by mLock.
174 private boolean mPendingRequestChangedLocked;
175
176 // Set to true when the important parts of the pending power request have been applied.
177 // The important parts are mainly the screen state. Brightness changes may occur
178 // concurrently.
179 // Guarded by mLock.
180 private boolean mDisplayReadyLocked;
181
182 // Set to true if a power state update is required.
183 // Guarded by mLock.
184 private boolean mPendingUpdatePowerStateLocked;
185
186 /* The following state must only be accessed by the handler thread. */
187
188 // The currently requested power state.
189 // The power controller will progressively update its internal state to match
190 // the requested power state. Initially null until the first update.
191 private DisplayPowerRequest mPowerRequest;
192
193 // The current power state.
194 // Must only be accessed on the handler thread.
195 private DisplayPowerState mPowerState;
196
197 // True if the device should wait for negative proximity sensor before
198 // waking up the screen. This is set to false as soon as a negative
199 // proximity sensor measurement is observed or when the device is forced to
200 // go to sleep by the user. While true, the screen remains off.
201 private boolean mWaitingForNegativeProximity;
202
203 // The actual proximity sensor threshold value.
204 private float mProximityThreshold;
205
206 // Set to true if the proximity sensor listener has been registered
207 // with the sensor manager.
208 private boolean mProximitySensorEnabled;
209
210 // The debounced proximity sensor state.
211 private int mProximity = PROXIMITY_UNKNOWN;
212
213 // The raw non-debounced proximity sensor state.
214 private int mPendingProximity = PROXIMITY_UNKNOWN;
Jeff Brownec083212013-09-11 20:45:25 -0700215 private long mPendingProximityDebounceTime = -1; // -1 if fully debounced
Jeff Brown96307042012-07-27 15:51:34 -0700216
217 // True if the screen was turned off because of the proximity sensor.
218 // When the screen turns on again, we report user activity to the power manager.
219 private boolean mScreenOffBecauseOfProximity;
220
Jeff Brown3ee549c2014-09-22 20:14:39 -0700221 // The currently active screen on unblocker. This field is non-null whenever
222 // we are waiting for a callback to release it and unblock the screen.
223 private ScreenOnUnblocker mPendingScreenOnUnblocker;
224
225 // True if we were in the process of turning off the screen.
226 // This allows us to recover more gracefully from situations where we abort
227 // turning off the screen.
228 private boolean mPendingScreenOff;
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700229
Jeff Brown0a434772014-09-30 14:42:27 -0700230 // True if we have unfinished business and are holding a suspend blocker.
231 private boolean mUnfinishedBusiness;
232
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700233 // The elapsed real time when the screen on was blocked.
234 private long mScreenOnBlockStartRealTime;
235
Jeff Brown970d4132014-07-19 11:33:47 -0700236 // Remembers whether certain kinds of brightness adjustments
237 // were recently applied so that we can decide how to transition.
238 private boolean mAppliedAutoBrightness;
239 private boolean mAppliedDimming;
240 private boolean mAppliedLowPower;
Jeff Brown96307042012-07-27 15:51:34 -0700241
Michael Wright639c8be2014-01-17 18:29:12 -0800242 // The controller for the automatic brightness level.
243 private AutomaticBrightnessController mAutomaticBrightnessController;
244
Jeff Brown96307042012-07-27 15:51:34 -0700245 // Animators.
Michael Lentine0839adb2014-07-29 18:47:56 -0700246 private ObjectAnimator mColorFadeOnAnimator;
247 private ObjectAnimator mColorFadeOffAnimator;
Jeff Brown96307042012-07-27 15:51:34 -0700248 private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
249
250 /**
251 * Creates the display power controller.
252 */
Jeff Brown131206b2014-04-08 17:27:14 -0700253 public DisplayPowerController(Context context,
Jeff Brown037c33e2014-04-09 00:31:55 -0700254 DisplayPowerCallbacks callbacks, Handler handler,
255 SensorManager sensorManager, DisplayBlanker blanker) {
Jeff Brown131206b2014-04-08 17:27:14 -0700256 mHandler = new DisplayControllerHandler(handler.getLooper());
Jeff Brown96307042012-07-27 15:51:34 -0700257 mCallbacks = callbacks;
Jeff Brown96307042012-07-27 15:51:34 -0700258
Jeff Brown131206b2014-04-08 17:27:14 -0700259 mBatteryStats = BatteryStatsService.getService();
260 mLights = LocalServices.getService(LightsManager.class);
Jeff Brown3b971592013-01-09 18:46:37 -0800261 mSensorManager = sensorManager;
Jeff Brown3ee549c2014-09-22 20:14:39 -0700262 mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
Jeff Brown037c33e2014-04-09 00:31:55 -0700263 mBlanker = blanker;
Michael Lentine0839adb2014-07-29 18:47:56 -0700264 mContext = context;
Jeff Brown96307042012-07-27 15:51:34 -0700265
266 final Resources resources = context.getResources();
Jeff Brown1bfd0f42014-08-22 01:59:06 -0700267 final int screenBrightnessSettingMinimum = clampAbsoluteBrightness(resources.getInteger(
268 com.android.internal.R.integer.config_screenBrightnessSettingMinimum));
Jeff Brownb76eebff2012-10-05 22:26:44 -0700269
Jeff Brown26875502014-01-30 21:47:47 -0800270 mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger(
271 com.android.internal.R.integer.config_screenBrightnessDoze));
272
Jeff Brownb76eebff2012-10-05 22:26:44 -0700273 mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger(
274 com.android.internal.R.integer.config_screenBrightnessDim));
275
Jeff Brown1bfd0f42014-08-22 01:59:06 -0700276 mScreenBrightnessDarkConfig = clampAbsoluteBrightness(resources.getInteger(
277 com.android.internal.R.integer.config_screenBrightnessDark));
278 if (mScreenBrightnessDarkConfig > mScreenBrightnessDimConfig) {
279 Slog.w(TAG, "Expected config_screenBrightnessDark ("
280 + mScreenBrightnessDarkConfig + ") to be less than or equal to "
281 + "config_screenBrightnessDim (" + mScreenBrightnessDimConfig + ").");
282 }
283 if (mScreenBrightnessDarkConfig > mScreenBrightnessDimConfig) {
284 Slog.w(TAG, "Expected config_screenBrightnessDark ("
285 + mScreenBrightnessDarkConfig + ") to be less than or equal to "
286 + "config_screenBrightnessSettingMinimum ("
287 + screenBrightnessSettingMinimum + ").");
288 }
289
290 int screenBrightnessRangeMinimum = Math.min(Math.min(
291 screenBrightnessSettingMinimum, mScreenBrightnessDimConfig),
292 mScreenBrightnessDarkConfig);
Michael Wright639c8be2014-01-17 18:29:12 -0800293
294 mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON;
Jeff Brownb76eebff2012-10-05 22:26:44 -0700295
Jeff Brown96307042012-07-27 15:51:34 -0700296 mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
297 com.android.internal.R.bool.config_automatic_brightness_available);
298 if (mUseSoftwareAutoBrightnessConfig) {
Jeff Brown1a30b552012-08-16 01:31:11 -0700299 int[] lux = resources.getIntArray(
Jeff Brown96307042012-07-27 15:51:34 -0700300 com.android.internal.R.array.config_autoBrightnessLevels);
Jeff Brown1a30b552012-08-16 01:31:11 -0700301 int[] screenBrightness = resources.getIntArray(
Jeff Brown96307042012-07-27 15:51:34 -0700302 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
Michael Wright639c8be2014-01-17 18:29:12 -0800303 int lightSensorWarmUpTimeConfig = resources.getInteger(
304 com.android.internal.R.integer.config_lightSensorWarmupTime);
Jeff Brown1a30b552012-08-16 01:31:11 -0700305
Michael Wright639c8be2014-01-17 18:29:12 -0800306 Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
307 if (screenAutoBrightnessSpline == null) {
Jeff Brown96307042012-07-27 15:51:34 -0700308 Slog.e(TAG, "Error in config.xml. config_autoBrightnessLcdBacklightValues "
Jeff Brown1a30b552012-08-16 01:31:11 -0700309 + "(size " + screenBrightness.length + ") "
310 + "must be monotic and have exactly one more entry than "
311 + "config_autoBrightnessLevels (size " + lux.length + ") "
312 + "which must be strictly increasing. "
Jeff Brown96307042012-07-27 15:51:34 -0700313 + "Auto-brightness will be disabled.");
314 mUseSoftwareAutoBrightnessConfig = false;
Jeff Brownb76eebff2012-10-05 22:26:44 -0700315 } else {
Jeff Brown1bfd0f42014-08-22 01:59:06 -0700316 int bottom = clampAbsoluteBrightness(screenBrightness[0]);
317 if (mScreenBrightnessDarkConfig > bottom) {
318 Slog.w(TAG, "config_screenBrightnessDark (" + mScreenBrightnessDarkConfig
319 + ") should be less than or equal to the first value of "
320 + "config_autoBrightnessLcdBacklightValues ("
321 + bottom + ").");
322 }
323 if (bottom < screenBrightnessRangeMinimum) {
324 screenBrightnessRangeMinimum = bottom;
Jeff Brownb76eebff2012-10-05 22:26:44 -0700325 }
Jeff Brown131206b2014-04-08 17:27:14 -0700326 mAutomaticBrightnessController = new AutomaticBrightnessController(this,
327 handler.getLooper(), sensorManager, screenAutoBrightnessSpline,
Michael Wright639c8be2014-01-17 18:29:12 -0800328 lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
329 mScreenBrightnessRangeMaximum);
Jeff Brown96307042012-07-27 15:51:34 -0700330 }
Jeff Brown96307042012-07-27 15:51:34 -0700331 }
332
Michael Wright639c8be2014-01-17 18:29:12 -0800333 mScreenBrightnessRangeMinimum = screenBrightnessRangeMinimum;
Jeff Brownb76eebff2012-10-05 22:26:44 -0700334
Michael Lentine0839adb2014-07-29 18:47:56 -0700335 mColorFadeFadesConfig = resources.getBoolean(
Jeff Browna52772f2012-10-04 18:38:09 -0700336 com.android.internal.R.bool.config_animateScreenLights);
337
Jeff Brown96307042012-07-27 15:51:34 -0700338 if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
339 mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
340 if (mProximitySensor != null) {
341 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
342 TYPICAL_PROXIMITY_THRESHOLD);
343 }
344 }
345
Jeff Brown1a30b552012-08-16 01:31:11 -0700346 }
347
Jeff Brown96307042012-07-27 15:51:34 -0700348 /**
349 * Returns true if the proximity sensor screen-off function is available.
350 */
351 public boolean isProximitySensorAvailable() {
352 return mProximitySensor != null;
353 }
354
355 /**
356 * Requests a new power state.
357 * The controller makes a copy of the provided object and then
358 * begins adjusting the power state to match what was requested.
359 *
360 * @param request The requested power state.
361 * @param waitForNegativeProximity If true, issues a request to wait for
362 * negative proximity before turning the screen back on, assuming the screen
363 * was turned off by the proximity sensor.
364 * @return True if display is ready, false if there are important changes that must
365 * be made asynchronously (such as turning the screen on), in which case the caller
Jeff Brown606e4e82014-09-18 15:22:26 -0700366 * should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged()}
367 * then try the request again later until the state converges.
Jeff Brown96307042012-07-27 15:51:34 -0700368 */
369 public boolean requestPowerState(DisplayPowerRequest request,
370 boolean waitForNegativeProximity) {
371 if (DEBUG) {
372 Slog.d(TAG, "requestPowerState: "
373 + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
374 }
375
376 synchronized (mLock) {
377 boolean changed = false;
378
379 if (waitForNegativeProximity
380 && !mPendingWaitForNegativeProximityLocked) {
381 mPendingWaitForNegativeProximityLocked = true;
382 changed = true;
383 }
384
385 if (mPendingRequestLocked == null) {
386 mPendingRequestLocked = new DisplayPowerRequest(request);
387 changed = true;
388 } else if (!mPendingRequestLocked.equals(request)) {
389 mPendingRequestLocked.copyFrom(request);
390 changed = true;
391 }
392
393 if (changed) {
394 mDisplayReadyLocked = false;
395 }
396
397 if (changed && !mPendingRequestChangedLocked) {
398 mPendingRequestChangedLocked = true;
399 sendUpdatePowerStateLocked();
400 }
401
402 return mDisplayReadyLocked;
403 }
404 }
405
406 private void sendUpdatePowerState() {
407 synchronized (mLock) {
408 sendUpdatePowerStateLocked();
409 }
410 }
411
412 private void sendUpdatePowerStateLocked() {
413 if (!mPendingUpdatePowerStateLocked) {
414 mPendingUpdatePowerStateLocked = true;
415 Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
416 msg.setAsynchronous(true);
417 mHandler.sendMessage(msg);
418 }
419 }
420
421 private void initialize() {
Jeff Brown037c33e2014-04-09 00:31:55 -0700422 // Initialize the power state object for the default display.
423 // In the future, we might manage multiple displays independently.
424 mPowerState = new DisplayPowerState(mBlanker,
425 mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT),
Michael Lentine0839adb2014-07-29 18:47:56 -0700426 new ColorFade(Display.DEFAULT_DISPLAY));
Jeff Brown96307042012-07-27 15:51:34 -0700427
Michael Lentine0839adb2014-07-29 18:47:56 -0700428 mColorFadeOnAnimator = ObjectAnimator.ofFloat(
429 mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 0.0f, 1.0f);
430 mColorFadeOnAnimator.setDuration(COLOR_FADE_ON_ANIMATION_DURATION_MILLIS);
431 mColorFadeOnAnimator.addListener(mAnimatorListener);
Jeff Brown96307042012-07-27 15:51:34 -0700432
Michael Lentine0839adb2014-07-29 18:47:56 -0700433 mColorFadeOffAnimator = ObjectAnimator.ofFloat(
434 mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 1.0f, 0.0f);
435 mColorFadeOffAnimator.setDuration(COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS);
436 mColorFadeOffAnimator.addListener(mAnimatorListener);
Jeff Brown96307042012-07-27 15:51:34 -0700437
438 mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
439 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
Jeff Brown42558692014-05-20 22:02:46 -0700440 mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800441
Jeff Brown131206b2014-04-08 17:27:14 -0700442 // Initialize screen state for battery stats.
443 try {
Jeff Browne95c3cd2014-05-02 16:59:26 -0700444 mBatteryStats.noteScreenState(mPowerState.getScreenState());
Jeff Brown131206b2014-04-08 17:27:14 -0700445 mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness());
446 } catch (RemoteException ex) {
447 // same process
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800448 }
Jeff Brown96307042012-07-27 15:51:34 -0700449 }
450
451 private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
452 @Override
453 public void onAnimationStart(Animator animation) {
454 }
455 @Override
456 public void onAnimationEnd(Animator animation) {
457 sendUpdatePowerState();
458 }
459 @Override
460 public void onAnimationRepeat(Animator animation) {
461 }
462 @Override
463 public void onAnimationCancel(Animator animation) {
464 }
465 };
466
Jeff Brown42558692014-05-20 22:02:46 -0700467 private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
468 @Override
469 public void onAnimationEnd() {
470 sendUpdatePowerState();
471 }
472 };
473
Jeff Brown96307042012-07-27 15:51:34 -0700474 private void updatePowerState() {
475 // Update the power state request.
476 final boolean mustNotify;
477 boolean mustInitialize = false;
Adrian Roos6da87ab2014-05-16 23:09:41 +0200478 boolean autoBrightnessAdjustmentChanged = false;
Jeff Brown330560f2012-08-21 22:10:57 -0700479
Jeff Brown96307042012-07-27 15:51:34 -0700480 synchronized (mLock) {
481 mPendingUpdatePowerStateLocked = false;
482 if (mPendingRequestLocked == null) {
483 return; // wait until first actual power request
484 }
485
486 if (mPowerRequest == null) {
487 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
488 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
Jeff Brown6307a152012-08-20 13:24:23 -0700489 mPendingWaitForNegativeProximityLocked = false;
Jeff Brown96307042012-07-27 15:51:34 -0700490 mPendingRequestChangedLocked = false;
491 mustInitialize = true;
492 } else if (mPendingRequestChangedLocked) {
Adrian Roos6da87ab2014-05-16 23:09:41 +0200493 autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
494 != mPendingRequestLocked.screenAutoBrightnessAdjustment);
Jeff Brown96307042012-07-27 15:51:34 -0700495 mPowerRequest.copyFrom(mPendingRequestLocked);
496 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
Jeff Brown6307a152012-08-20 13:24:23 -0700497 mPendingWaitForNegativeProximityLocked = false;
Jeff Brown96307042012-07-27 15:51:34 -0700498 mPendingRequestChangedLocked = false;
499 mDisplayReadyLocked = false;
500 }
501
502 mustNotify = !mDisplayReadyLocked;
503 }
504
505 // Initialize things the first time the power state is changed.
506 if (mustInitialize) {
507 initialize();
508 }
509
Jeff Brown970d4132014-07-19 11:33:47 -0700510 // Compute the basic display state using the policy.
511 // We might override this below based on other factors.
512 int state;
513 int brightness = PowerManager.BRIGHTNESS_DEFAULT;
Jeff Brown2175e9c2014-09-12 16:11:07 -0700514 boolean performScreenOffTransition = false;
Jeff Brown970d4132014-07-19 11:33:47 -0700515 switch (mPowerRequest.policy) {
516 case DisplayPowerRequest.POLICY_OFF:
517 state = Display.STATE_OFF;
Jeff Brown2175e9c2014-09-12 16:11:07 -0700518 performScreenOffTransition = true;
Jeff Brown970d4132014-07-19 11:33:47 -0700519 break;
520 case DisplayPowerRequest.POLICY_DOZE:
521 if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
522 state = mPowerRequest.dozeScreenState;
523 } else {
524 state = Display.STATE_DOZE;
525 }
526 brightness = mPowerRequest.dozeScreenBrightness;
527 break;
528 case DisplayPowerRequest.POLICY_DIM:
529 case DisplayPowerRequest.POLICY_BRIGHT:
530 default:
531 state = Display.STATE_ON;
532 break;
533 }
Jeff Brown2175e9c2014-09-12 16:11:07 -0700534 assert(state != Display.STATE_UNKNOWN);
Jeff Brown970d4132014-07-19 11:33:47 -0700535
Jeff Brown6307a152012-08-20 13:24:23 -0700536 // Apply the proximity sensor.
Jeff Brown96307042012-07-27 15:51:34 -0700537 if (mProximitySensor != null) {
Jeff Brown970d4132014-07-19 11:33:47 -0700538 if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
Jeff Brown6307a152012-08-20 13:24:23 -0700539 setProximitySensorEnabled(true);
540 if (!mScreenOffBecauseOfProximity
541 && mProximity == PROXIMITY_POSITIVE) {
542 mScreenOffBecauseOfProximity = true;
Jeff Brownec083212013-09-11 20:45:25 -0700543 sendOnProximityPositiveWithWakelock();
Jeff Brown6307a152012-08-20 13:24:23 -0700544 }
545 } else if (mWaitingForNegativeProximity
546 && mScreenOffBecauseOfProximity
547 && mProximity == PROXIMITY_POSITIVE
Jeff Brown970d4132014-07-19 11:33:47 -0700548 && state != Display.STATE_OFF) {
Jeff Brown6307a152012-08-20 13:24:23 -0700549 setProximitySensorEnabled(true);
550 } else {
551 setProximitySensorEnabled(false);
552 mWaitingForNegativeProximity = false;
553 }
554 if (mScreenOffBecauseOfProximity
555 && mProximity != PROXIMITY_POSITIVE) {
Jeff Brown96307042012-07-27 15:51:34 -0700556 mScreenOffBecauseOfProximity = false;
Jeff Brownec083212013-09-11 20:45:25 -0700557 sendOnProximityNegativeWithWakelock();
Jeff Brown96307042012-07-27 15:51:34 -0700558 }
Jeff Brown6307a152012-08-20 13:24:23 -0700559 } else {
560 mWaitingForNegativeProximity = false;
Jeff Brown96307042012-07-27 15:51:34 -0700561 }
Jeff Brown970d4132014-07-19 11:33:47 -0700562 if (mScreenOffBecauseOfProximity) {
563 state = Display.STATE_OFF;
Jeff Brown96307042012-07-27 15:51:34 -0700564 }
565
Jeff Brownbf4e4142014-10-02 13:08:05 -0700566 // Animate the screen state change unless already animating.
567 // The transition may be deferred, so after this point we will use the
568 // actual state instead of the desired one.
569 animateScreenStateChange(state, performScreenOffTransition);
570 state = mPowerState.getScreenState();
571
Jeff Brown970d4132014-07-19 11:33:47 -0700572 // Use zero brightness when screen is off.
Jeff Browne333e672014-10-28 13:48:55 -0700573 // Use full brightness when screen brightness is boosted.
Jeff Brown970d4132014-07-19 11:33:47 -0700574 if (state == Display.STATE_OFF) {
575 brightness = PowerManager.BRIGHTNESS_OFF;
Jeff Browne333e672014-10-28 13:48:55 -0700576 } else if (mPowerRequest.boostScreenBrightness) {
577 brightness = PowerManager.BRIGHTNESS_ON;
Jeff Brown970d4132014-07-19 11:33:47 -0700578 }
579
580 // Use default brightness when dozing unless overridden.
581 if (brightness < 0 && (state == Display.STATE_DOZE
582 || state == Display.STATE_DOZE_SUSPEND)) {
583 brightness = mScreenBrightnessDozeConfig;
584 }
585
586 // Configure auto-brightness.
587 boolean autoBrightnessEnabled = false;
588 if (mAutomaticBrightnessController != null) {
589 autoBrightnessEnabled = mPowerRequest.useAutoBrightness
590 && state == Display.STATE_ON && brightness < 0;
591 mAutomaticBrightnessController.configure(autoBrightnessEnabled,
592 mPowerRequest.screenAutoBrightnessAdjustment);
593 }
594
595 // Apply auto-brightness.
596 boolean slowChange = false;
597 if (brightness < 0) {
598 if (autoBrightnessEnabled) {
599 brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();
600 }
601 if (brightness >= 0) {
602 // Use current auto-brightness value and slowly adjust to changes.
603 brightness = clampScreenBrightness(brightness);
604 if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
605 slowChange = true; // slowly adapt to auto-brightness
606 }
607 mAppliedAutoBrightness = true;
Jeff Brown96307042012-07-27 15:51:34 -0700608 } else {
Jeff Brown970d4132014-07-19 11:33:47 -0700609 mAppliedAutoBrightness = false;
Jeff Brown96307042012-07-27 15:51:34 -0700610 }
611 } else {
Jeff Brown970d4132014-07-19 11:33:47 -0700612 mAppliedAutoBrightness = false;
613 }
614
615 // Apply manual brightness.
616 // Use the current brightness setting from the request, which is expected
617 // provide a nominal default value for the case where auto-brightness
618 // is not ready yet.
619 if (brightness < 0) {
620 brightness = clampScreenBrightness(mPowerRequest.screenBrightness);
621 }
622
623 // Apply dimming by at least some minimum amount when user activity
624 // timeout is about to expire.
625 if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
Jeff Brown5c8ea082014-07-24 19:30:31 -0700626 if (brightness > mScreenBrightnessRangeMinimum) {
627 brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,
628 mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
629 }
Jeff Brown970d4132014-07-19 11:33:47 -0700630 if (!mAppliedDimming) {
631 slowChange = false;
632 }
633 mAppliedDimming = true;
634 }
635
636 // If low power mode is enabled, cut the brightness level by half
637 // as long as it is above the minimum threshold.
638 if (mPowerRequest.lowPowerMode) {
639 if (brightness > mScreenBrightnessRangeMinimum) {
640 brightness = Math.max(brightness / 2, mScreenBrightnessRangeMinimum);
641 }
642 if (!mAppliedLowPower) {
643 slowChange = false;
644 }
645 mAppliedLowPower = true;
646 }
647
Jeff Brown0a434772014-09-30 14:42:27 -0700648 // Animate the screen brightness when the screen is on or dozing.
649 // Skip the animation when the screen is off or suspended.
Jeff Brownbf4e4142014-10-02 13:08:05 -0700650 if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
Jeff Brown0a434772014-09-30 14:42:27 -0700651 animateScreenBrightness(brightness,
652 slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
653 } else {
654 animateScreenBrightness(brightness, 0);
655 }
656
657 // Determine whether the display is ready for use in the newly requested state.
658 // Note that we do not wait for the brightness ramp animation to complete before
659 // reporting the display is ready because we only need to ensure the screen is in the
660 // right power state even as it continues to converge on the desired brightness.
661 final boolean ready = mPendingScreenOnUnblocker == null
Michael Lentine0839adb2014-07-29 18:47:56 -0700662 && !mColorFadeOnAnimator.isStarted()
663 && !mColorFadeOffAnimator.isStarted()
Jeff Brown0a434772014-09-30 14:42:27 -0700664 && mPowerState.waitUntilClean(mCleanListener);
665 final boolean finished = ready
666 && !mScreenBrightnessRampAnimator.isAnimating();
667
668 // Grab a wake lock if we have unfinished business.
669 if (!finished && !mUnfinishedBusiness) {
670 if (DEBUG) {
671 Slog.d(TAG, "Unfinished business...");
672 }
673 mCallbacks.acquireSuspendBlocker();
674 mUnfinishedBusiness = true;
675 }
676
677 // Notify the power manager when ready.
678 if (ready && mustNotify) {
679 // Send state change.
Jeff Brown96307042012-07-27 15:51:34 -0700680 synchronized (mLock) {
681 if (!mPendingRequestChangedLocked) {
682 mDisplayReadyLocked = true;
Jeff Brownc38c9be2012-10-04 13:16:19 -0700683
684 if (DEBUG) {
685 Slog.d(TAG, "Display ready!");
686 }
Jeff Brown96307042012-07-27 15:51:34 -0700687 }
688 }
Jeff Brownec083212013-09-11 20:45:25 -0700689 sendOnStateChangedWithWakelock();
Jeff Brown96307042012-07-27 15:51:34 -0700690 }
Jeff Brown0a434772014-09-30 14:42:27 -0700691
692 // Release the wake lock when we have no unfinished business.
693 if (finished && mUnfinishedBusiness) {
694 if (DEBUG) {
695 Slog.d(TAG, "Finished business...");
696 }
697 mUnfinishedBusiness = false;
698 mCallbacks.releaseSuspendBlocker();
699 }
Jeff Brown96307042012-07-27 15:51:34 -0700700 }
701
Michael Wright639c8be2014-01-17 18:29:12 -0800702 @Override
703 public void updateBrightness() {
704 sendUpdatePowerState();
705 }
706
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700707 private void blockScreenOn() {
Jeff Brown3ee549c2014-09-22 20:14:39 -0700708 if (mPendingScreenOnUnblocker == null) {
Jeff Brown3edf5272014-08-14 19:25:14 -0700709 Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
Jeff Brown3ee549c2014-09-22 20:14:39 -0700710 mPendingScreenOnUnblocker = new ScreenOnUnblocker();
Jeff Brown037c33e2014-04-09 00:31:55 -0700711 mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
Jeff Brown3edf5272014-08-14 19:25:14 -0700712 Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700713 }
714 }
715
716 private void unblockScreenOn() {
Jeff Brown3ee549c2014-09-22 20:14:39 -0700717 if (mPendingScreenOnUnblocker != null) {
718 mPendingScreenOnUnblocker = null;
Jeff Brown2d8a3902014-03-11 23:02:35 -0700719 long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
Jeff Brown3edf5272014-08-14 19:25:14 -0700720 Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
721 Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
Jeff Brown8b9cf1c2012-10-07 14:54:17 -0700722 }
723 }
724
Jeff Brown3ee549c2014-09-22 20:14:39 -0700725 private boolean setScreenState(int state) {
Jeff Brown037c33e2014-04-09 00:31:55 -0700726 if (mPowerState.getScreenState() != state) {
Jeff Brown3ee549c2014-09-22 20:14:39 -0700727 final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
Jeff Brown037c33e2014-04-09 00:31:55 -0700728 mPowerState.setScreenState(state);
Jeff Brown3ee549c2014-09-22 20:14:39 -0700729
730 // Tell battery stats about the transition.
Jeff Brown131206b2014-04-08 17:27:14 -0700731 try {
Jeff Browne95c3cd2014-05-02 16:59:26 -0700732 mBatteryStats.noteScreenState(state);
Jeff Brown131206b2014-04-08 17:27:14 -0700733 } catch (RemoteException ex) {
734 // same process
Jeff Brown96307042012-07-27 15:51:34 -0700735 }
Jeff Brown3ee549c2014-09-22 20:14:39 -0700736
737 // Tell the window manager what's happening.
738 // Temporarily block turning the screen on until the window manager is ready
739 // by leaving a black surface covering the screen. This surface is essentially
740 // the final state of the color fade animation.
741 boolean isOn = (state != Display.STATE_OFF);
742 if (wasOn && !isOn) {
743 unblockScreenOn();
744 mWindowManagerPolicy.screenTurnedOff();
745 } else if (!wasOn && isOn) {
746 if (mPowerState.getColorFadeLevel() == 0.0f) {
747 blockScreenOn();
748 } else {
749 unblockScreenOn();
750 }
751 mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
752 }
Jeff Brown96307042012-07-27 15:51:34 -0700753 }
Jeff Brown3ee549c2014-09-22 20:14:39 -0700754 return mPendingScreenOnUnblocker == null;
Jeff Brown96307042012-07-27 15:51:34 -0700755 }
756
Jeff Brown330560f2012-08-21 22:10:57 -0700757 private int clampScreenBrightness(int value) {
Michael Wright639c8be2014-01-17 18:29:12 -0800758 return MathUtils.constrain(
759 value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
Jeff Brown330560f2012-08-21 22:10:57 -0700760 }
761
Jeff Brown96307042012-07-27 15:51:34 -0700762 private void animateScreenBrightness(int target, int rate) {
Jeff Brown0a434772014-09-30 14:42:27 -0700763 if (DEBUG) {
764 Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
765 }
Jeff Brown96307042012-07-27 15:51:34 -0700766 if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
Jeff Brown131206b2014-04-08 17:27:14 -0700767 try {
768 mBatteryStats.noteScreenBrightness(target);
769 } catch (RemoteException ex) {
770 // same process
771 }
Jeff Brown96307042012-07-27 15:51:34 -0700772 }
773 }
774
Jeff Brown606e4e82014-09-18 15:22:26 -0700775 private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
776 // If there is already an animation in progress, don't interfere with it.
777 if (mColorFadeOnAnimator.isStarted()
778 || mColorFadeOffAnimator.isStarted()) {
779 return;
780 }
781
Jeff Brown3ee549c2014-09-22 20:14:39 -0700782 // If we were in the process of turning off the screen but didn't quite
783 // finish. Then finish up now to prevent a jarring transition back
784 // to screen on if we skipped blocking screen on as usual.
785 if (mPendingScreenOff && target != Display.STATE_OFF) {
786 setScreenState(Display.STATE_OFF);
787 mPendingScreenOff = false;
Jeff Brown606e4e82014-09-18 15:22:26 -0700788 }
789
790 if (target == Display.STATE_ON) {
791 // Want screen on. The contents of the screen may not yet
Jeff Brown3ee549c2014-09-22 20:14:39 -0700792 // be visible if the color fade has not been dismissed because
Jeff Brown606e4e82014-09-18 15:22:26 -0700793 // its last frame of animation is solid black.
Jeff Brown3ee549c2014-09-22 20:14:39 -0700794 if (!setScreenState(Display.STATE_ON)) {
795 return; // screen on blocked
796 }
Jeff Brown606e4e82014-09-18 15:22:26 -0700797 if (USE_COLOR_FADE_ON_ANIMATION && mPowerRequest.isBrightOrDim()) {
798 // Perform screen on animation.
799 if (mPowerState.getColorFadeLevel() == 1.0f) {
800 mPowerState.dismissColorFade();
801 } else if (mPowerState.prepareColorFade(mContext,
802 mColorFadeFadesConfig ?
803 ColorFade.MODE_FADE :
804 ColorFade.MODE_WARM_UP)) {
805 mColorFadeOnAnimator.start();
806 } else {
807 mColorFadeOnAnimator.end();
808 }
809 } else {
810 // Skip screen on animation.
811 mPowerState.setColorFadeLevel(1.0f);
812 mPowerState.dismissColorFade();
813 }
814 } else if (target == Display.STATE_DOZE) {
815 // Want screen dozing.
816 // Wait for brightness animation to complete beforehand when entering doze
817 // from screen on to prevent a perceptible jump because brightness may operate
818 // differently when the display is configured for dozing.
819 if (mScreenBrightnessRampAnimator.isAnimating()
820 && mPowerState.getScreenState() == Display.STATE_ON) {
821 return;
822 }
823
Jeff Brown3ee549c2014-09-22 20:14:39 -0700824 // Set screen state.
825 if (!setScreenState(Display.STATE_DOZE)) {
826 return; // screen on blocked
827 }
828
829 // Dismiss the black surface without fanfare.
Jeff Brown606e4e82014-09-18 15:22:26 -0700830 mPowerState.setColorFadeLevel(1.0f);
831 mPowerState.dismissColorFade();
832 } else if (target == Display.STATE_DOZE_SUSPEND) {
833 // Want screen dozing and suspended.
834 // Wait for brightness animation to complete beforehand unless already
835 // suspended because we may not be able to change it after suspension.
836 if (mScreenBrightnessRampAnimator.isAnimating()
837 && mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
838 return;
839 }
840
Jeff Brown3ee549c2014-09-22 20:14:39 -0700841 // If not already suspending, temporarily set the state to doze until the
842 // screen on is unblocked, then suspend.
843 if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
844 if (!setScreenState(Display.STATE_DOZE)) {
845 return; // screen on blocked
846 }
847 setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
848 }
849
850 // Dismiss the black surface without fanfare.
Jeff Brown606e4e82014-09-18 15:22:26 -0700851 mPowerState.setColorFadeLevel(1.0f);
852 mPowerState.dismissColorFade();
853 } else {
854 // Want screen off.
Jeff Brown3ee549c2014-09-22 20:14:39 -0700855 mPendingScreenOff = true;
Jeff Brown606e4e82014-09-18 15:22:26 -0700856 if (mPowerState.getColorFadeLevel() == 0.0f) {
857 // Turn the screen off.
858 // A black surface is already hiding the contents of the screen.
859 setScreenState(Display.STATE_OFF);
Jeff Brown3ee549c2014-09-22 20:14:39 -0700860 mPendingScreenOff = false;
Jeff Brown606e4e82014-09-18 15:22:26 -0700861 } else if (performScreenOffTransition
862 && mPowerState.prepareColorFade(mContext,
863 mColorFadeFadesConfig ?
864 ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
865 && mPowerState.getScreenState() != Display.STATE_OFF) {
866 // Perform the screen off animation.
867 mColorFadeOffAnimator.start();
868 } else {
869 // Skip the screen off animation and add a black surface to hide the
870 // contents of the screen.
871 mColorFadeOffAnimator.end();
872 }
873 }
874 }
875
Jeff Brown96307042012-07-27 15:51:34 -0700876 private final Runnable mCleanListener = new Runnable() {
877 @Override
878 public void run() {
879 sendUpdatePowerState();
880 }
881 };
882
883 private void setProximitySensorEnabled(boolean enable) {
884 if (enable) {
885 if (!mProximitySensorEnabled) {
Jeff Brownec083212013-09-11 20:45:25 -0700886 // Register the listener.
887 // Proximity sensor state already cleared initially.
Jeff Brown96307042012-07-27 15:51:34 -0700888 mProximitySensorEnabled = true;
Jeff Brown96307042012-07-27 15:51:34 -0700889 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
890 SensorManager.SENSOR_DELAY_NORMAL, mHandler);
891 }
892 } else {
893 if (mProximitySensorEnabled) {
Jeff Brownec083212013-09-11 20:45:25 -0700894 // Unregister the listener.
895 // Clear the proximity sensor state for next time.
Jeff Brown96307042012-07-27 15:51:34 -0700896 mProximitySensorEnabled = false;
897 mProximity = PROXIMITY_UNKNOWN;
Jeff Brownec083212013-09-11 20:45:25 -0700898 mPendingProximity = PROXIMITY_UNKNOWN;
Jeff Brown96307042012-07-27 15:51:34 -0700899 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
900 mSensorManager.unregisterListener(mProximitySensorListener);
Jeff Brownec083212013-09-11 20:45:25 -0700901 clearPendingProximityDebounceTime(); // release wake lock (must be last)
Jeff Brown96307042012-07-27 15:51:34 -0700902 }
903 }
904 }
905
906 private void handleProximitySensorEvent(long time, boolean positive) {
Jeff Brownec083212013-09-11 20:45:25 -0700907 if (mProximitySensorEnabled) {
908 if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
909 return; // no change
910 }
911 if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
912 return; // no change
913 }
Jeff Brown96307042012-07-27 15:51:34 -0700914
Jeff Brownec083212013-09-11 20:45:25 -0700915 // Only accept a proximity sensor reading if it remains
916 // stable for the entire debounce delay. We hold a wake lock while
917 // debouncing the sensor.
918 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
919 if (positive) {
920 mPendingProximity = PROXIMITY_POSITIVE;
921 setPendingProximityDebounceTime(
922 time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
923 } else {
924 mPendingProximity = PROXIMITY_NEGATIVE;
925 setPendingProximityDebounceTime(
926 time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
927 }
928
929 // Debounce the new sensor reading.
930 debounceProximitySensor();
Jeff Brown93cbbb22012-10-04 13:18:36 -0700931 }
Jeff Brown96307042012-07-27 15:51:34 -0700932 }
933
934 private void debounceProximitySensor() {
Jeff Brownec083212013-09-11 20:45:25 -0700935 if (mProximitySensorEnabled
936 && mPendingProximity != PROXIMITY_UNKNOWN
937 && mPendingProximityDebounceTime >= 0) {
Jeff Brown96307042012-07-27 15:51:34 -0700938 final long now = SystemClock.uptimeMillis();
939 if (mPendingProximityDebounceTime <= now) {
Jeff Brownec083212013-09-11 20:45:25 -0700940 // Sensor reading accepted. Apply the change then release the wake lock.
Jeff Brown96307042012-07-27 15:51:34 -0700941 mProximity = mPendingProximity;
Jeff Brownec083212013-09-11 20:45:25 -0700942 updatePowerState();
943 clearPendingProximityDebounceTime(); // release wake lock (must be last)
Jeff Brown96307042012-07-27 15:51:34 -0700944 } else {
Jeff Brownec083212013-09-11 20:45:25 -0700945 // Need to wait a little longer.
946 // Debounce again later. We continue holding a wake lock while waiting.
Jeff Brown96307042012-07-27 15:51:34 -0700947 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
948 msg.setAsynchronous(true);
949 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
950 }
951 }
952 }
953
Jeff Brownec083212013-09-11 20:45:25 -0700954 private void clearPendingProximityDebounceTime() {
955 if (mPendingProximityDebounceTime >= 0) {
956 mPendingProximityDebounceTime = -1;
Jeff Brown131206b2014-04-08 17:27:14 -0700957 mCallbacks.releaseSuspendBlocker(); // release wake lock
Jeff Brownec083212013-09-11 20:45:25 -0700958 }
959 }
960
961 private void setPendingProximityDebounceTime(long debounceTime) {
962 if (mPendingProximityDebounceTime < 0) {
Jeff Brown131206b2014-04-08 17:27:14 -0700963 mCallbacks.acquireSuspendBlocker(); // acquire wake lock
Jeff Brownec083212013-09-11 20:45:25 -0700964 }
965 mPendingProximityDebounceTime = debounceTime;
966 }
967
Jeff Brownec083212013-09-11 20:45:25 -0700968 private void sendOnStateChangedWithWakelock() {
Jeff Brown131206b2014-04-08 17:27:14 -0700969 mCallbacks.acquireSuspendBlocker();
970 mHandler.post(mOnStateChangedRunnable);
Jeff Brown96307042012-07-27 15:51:34 -0700971 }
972
973 private final Runnable mOnStateChangedRunnable = new Runnable() {
974 @Override
975 public void run() {
976 mCallbacks.onStateChanged();
Jeff Brown131206b2014-04-08 17:27:14 -0700977 mCallbacks.releaseSuspendBlocker();
Jeff Brown96307042012-07-27 15:51:34 -0700978 }
979 };
980
Jeff Brownec083212013-09-11 20:45:25 -0700981 private void sendOnProximityPositiveWithWakelock() {
Jeff Brown131206b2014-04-08 17:27:14 -0700982 mCallbacks.acquireSuspendBlocker();
983 mHandler.post(mOnProximityPositiveRunnable);
Jeff Brown93cbbb22012-10-04 13:18:36 -0700984 }
985
986 private final Runnable mOnProximityPositiveRunnable = new Runnable() {
987 @Override
988 public void run() {
989 mCallbacks.onProximityPositive();
Jeff Brown131206b2014-04-08 17:27:14 -0700990 mCallbacks.releaseSuspendBlocker();
Jeff Brown93cbbb22012-10-04 13:18:36 -0700991 }
992 };
993
Jeff Brownec083212013-09-11 20:45:25 -0700994 private void sendOnProximityNegativeWithWakelock() {
Jeff Brown131206b2014-04-08 17:27:14 -0700995 mCallbacks.acquireSuspendBlocker();
996 mHandler.post(mOnProximityNegativeRunnable);
Jeff Brown96307042012-07-27 15:51:34 -0700997 }
998
999 private final Runnable mOnProximityNegativeRunnable = new Runnable() {
1000 @Override
1001 public void run() {
1002 mCallbacks.onProximityNegative();
Jeff Brown131206b2014-04-08 17:27:14 -07001003 mCallbacks.releaseSuspendBlocker();
Jeff Brown96307042012-07-27 15:51:34 -07001004 }
1005 };
1006
Jeff Brownbd6e1502012-08-28 03:27:37 -07001007 public void dump(final PrintWriter pw) {
Jeff Brown96307042012-07-27 15:51:34 -07001008 synchronized (mLock) {
1009 pw.println();
Jeff Brown131206b2014-04-08 17:27:14 -07001010 pw.println("Display Power Controller Locked State:");
Jeff Brown96307042012-07-27 15:51:34 -07001011 pw.println(" mDisplayReadyLocked=" + mDisplayReadyLocked);
1012 pw.println(" mPendingRequestLocked=" + mPendingRequestLocked);
1013 pw.println(" mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
1014 pw.println(" mPendingWaitForNegativeProximityLocked="
1015 + mPendingWaitForNegativeProximityLocked);
1016 pw.println(" mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
1017 }
1018
1019 pw.println();
Jeff Brown131206b2014-04-08 17:27:14 -07001020 pw.println("Display Power Controller Configuration:");
Jeff Brown26875502014-01-30 21:47:47 -08001021 pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
Jeff Brown96307042012-07-27 15:51:34 -07001022 pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
Jeff Brown1bfd0f42014-08-22 01:59:06 -07001023 pw.println(" mScreenBrightnessDarkConfig=" + mScreenBrightnessDarkConfig);
Jeff Brownb76eebff2012-10-05 22:26:44 -07001024 pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
1025 pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
Jeff Brown2175e9c2014-09-12 16:11:07 -07001026 pw.println(" mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
1027 pw.println(" mColorFadeFadesConfig=" + mColorFadeFadesConfig);
Jeff Brown96307042012-07-27 15:51:34 -07001028
Jeff Brownbd6e1502012-08-28 03:27:37 -07001029 mHandler.runWithScissors(new Runnable() {
1030 @Override
1031 public void run() {
1032 dumpLocal(pw);
Jeff Brown96307042012-07-27 15:51:34 -07001033 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001034 }, 1000);
Jeff Brown96307042012-07-27 15:51:34 -07001035 }
1036
1037 private void dumpLocal(PrintWriter pw) {
1038 pw.println();
Jeff Brown131206b2014-04-08 17:27:14 -07001039 pw.println("Display Power Controller Thread State:");
Jeff Brown96307042012-07-27 15:51:34 -07001040 pw.println(" mPowerRequest=" + mPowerRequest);
1041 pw.println(" mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
1042
1043 pw.println(" mProximitySensor=" + mProximitySensor);
1044 pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled);
1045 pw.println(" mProximityThreshold=" + mProximityThreshold);
1046 pw.println(" mProximity=" + proximityToString(mProximity));
1047 pw.println(" mPendingProximity=" + proximityToString(mPendingProximity));
1048 pw.println(" mPendingProximityDebounceTime="
1049 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
1050 pw.println(" mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
Jeff Brown970d4132014-07-19 11:33:47 -07001051 pw.println(" mAppliedAutoBrightness=" + mAppliedAutoBrightness);
1052 pw.println(" mAppliedDimming=" + mAppliedDimming);
1053 pw.println(" mAppliedLowPower=" + mAppliedLowPower);
Jeff Brown3ee549c2014-09-22 20:14:39 -07001054 pw.println(" mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
1055 pw.println(" mPendingScreenOff=" + mPendingScreenOff);
Jeff Brown96307042012-07-27 15:51:34 -07001056
Jeff Brown42558692014-05-20 22:02:46 -07001057 pw.println(" mScreenBrightnessRampAnimator.isAnimating()=" +
1058 mScreenBrightnessRampAnimator.isAnimating());
1059
Michael Lentine0839adb2014-07-29 18:47:56 -07001060 if (mColorFadeOnAnimator != null) {
1061 pw.println(" mColorFadeOnAnimator.isStarted()=" +
1062 mColorFadeOnAnimator.isStarted());
Jeff Brown96307042012-07-27 15:51:34 -07001063 }
Michael Lentine0839adb2014-07-29 18:47:56 -07001064 if (mColorFadeOffAnimator != null) {
1065 pw.println(" mColorFadeOffAnimator.isStarted()=" +
1066 mColorFadeOffAnimator.isStarted());
Jeff Brown96307042012-07-27 15:51:34 -07001067 }
1068
1069 if (mPowerState != null) {
1070 mPowerState.dump(pw);
1071 }
Michael Wright639c8be2014-01-17 18:29:12 -08001072
1073 if (mAutomaticBrightnessController != null) {
1074 mAutomaticBrightnessController.dump(pw);
1075 }
1076
Jeff Brown96307042012-07-27 15:51:34 -07001077 }
1078
1079 private static String proximityToString(int state) {
1080 switch (state) {
1081 case PROXIMITY_UNKNOWN:
1082 return "Unknown";
1083 case PROXIMITY_NEGATIVE:
1084 return "Negative";
1085 case PROXIMITY_POSITIVE:
1086 return "Positive";
1087 default:
1088 return Integer.toString(state);
1089 }
1090 }
1091
Michael Wright639c8be2014-01-17 18:29:12 -08001092 private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) {
1093 try {
1094 final int n = brightness.length;
1095 float[] x = new float[n];
1096 float[] y = new float[n];
1097 y[0] = normalizeAbsoluteBrightness(brightness[0]);
1098 for (int i = 1; i < n; i++) {
1099 x[i] = lux[i - 1];
1100 y[i] = normalizeAbsoluteBrightness(brightness[i]);
1101 }
1102
Michael Wright3e9a1342014-08-28 17:42:16 -07001103 Spline spline = Spline.createSpline(x, y);
Michael Wright639c8be2014-01-17 18:29:12 -08001104 if (DEBUG) {
1105 Slog.d(TAG, "Auto-brightness spline: " + spline);
1106 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
1107 Slog.d(TAG, String.format(" %7.1f: %7.1f", v, spline.interpolate(v)));
1108 }
1109 }
1110 return spline;
1111 } catch (IllegalArgumentException ex) {
1112 Slog.e(TAG, "Could not create auto-brightness spline.", ex);
1113 return null;
Jeff Brown96307042012-07-27 15:51:34 -07001114 }
Michael Wright639c8be2014-01-17 18:29:12 -08001115 }
1116
1117 private static float normalizeAbsoluteBrightness(int value) {
1118 return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON;
1119 }
1120
1121 private static int clampAbsoluteBrightness(int value) {
1122 return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
Jeff Brown96307042012-07-27 15:51:34 -07001123 }
1124
Jeff Brown96307042012-07-27 15:51:34 -07001125 private final class DisplayControllerHandler extends Handler {
1126 public DisplayControllerHandler(Looper looper) {
Jeff Browna2910d02012-08-25 12:29:46 -07001127 super(looper, null, true /*async*/);
Jeff Brown96307042012-07-27 15:51:34 -07001128 }
1129
1130 @Override
1131 public void handleMessage(Message msg) {
1132 switch (msg.what) {
1133 case MSG_UPDATE_POWER_STATE:
1134 updatePowerState();
1135 break;
1136
1137 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
1138 debounceProximitySensor();
1139 break;
Jeff Brown3ee549c2014-09-22 20:14:39 -07001140
1141 case MSG_SCREEN_ON_UNBLOCKED:
1142 if (mPendingScreenOnUnblocker == msg.obj) {
1143 unblockScreenOn();
1144 updatePowerState();
1145 }
1146 break;
Jeff Brown96307042012-07-27 15:51:34 -07001147 }
1148 }
1149 }
1150
1151 private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
1152 @Override
1153 public void onSensorChanged(SensorEvent event) {
1154 if (mProximitySensorEnabled) {
1155 final long time = SystemClock.uptimeMillis();
1156 final float distance = event.values[0];
1157 boolean positive = distance >= 0.0f && distance < mProximityThreshold;
1158 handleProximitySensorEvent(time, positive);
1159 }
1160 }
1161
1162 @Override
1163 public void onAccuracyChanged(Sensor sensor, int accuracy) {
1164 // Not used.
1165 }
1166 };
Jeff Brown3ee549c2014-09-22 20:14:39 -07001167
1168 private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
1169 @Override
1170 public void onScreenOn() {
1171 Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
1172 msg.setAsynchronous(true);
1173 mHandler.sendMessage(msg);
1174 }
1175 }
Jeff Brown96307042012-07-27 15:51:34 -07001176}