OSDN Git Service

Fix a bug with screen brightness during screen off animation.
[android-x86/frameworks-base.git] / services / core / java / com / android / server / display / DisplayPowerController.java
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.server.display;
18
19 import com.android.internal.app.IBatteryStats;
20 import com.android.server.LocalServices;
21 import com.android.server.am.BatteryStatsService;
22 import com.android.server.lights.LightsManager;
23
24 import android.animation.Animator;
25 import android.animation.ObjectAnimator;
26 import android.content.Context;
27 import android.content.res.Resources;
28 import android.hardware.Sensor;
29 import android.hardware.SensorEvent;
30 import android.hardware.SensorEventListener;
31 import android.hardware.SensorManager;
32 import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
33 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
34 import android.os.Handler;
35 import android.os.Looper;
36 import android.os.Message;
37 import android.os.PowerManager;
38 import android.os.RemoteException;
39 import android.os.SystemClock;
40 import android.os.Trace;
41 import android.util.MathUtils;
42 import android.util.Slog;
43 import android.util.Spline;
44 import android.util.TimeUtils;
45 import android.view.Display;
46 import android.view.WindowManagerPolicy;
47
48 import java.io.PrintWriter;
49
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.
68    *
69  * For debugging, you can make the color fade and brightness animations run
70  * slower by changing the "animator duration scale" option in Development Settings.
71  */
72 final class DisplayPowerController implements AutomaticBrightnessController.Callbacks {
73     private static final String TAG = "DisplayPowerController";
74
75     private static boolean DEBUG = false;
76     private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
77
78     private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
79
80     // If true, uses the color fade on animation.
81     // 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
83     // screen state returns.  Playing the animation can also be somewhat slow.
84     private static final boolean USE_COLOR_FADE_ON_ANIMATION = false;
85
86     // The minimum reduction in brightness when dimmed.
87     private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10;
88
89     private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
90     private static final int COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS = 400;
91
92     private static final int MSG_UPDATE_POWER_STATE = 1;
93     private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
94     private static final int MSG_SCREEN_ON_UNBLOCKED = 3;
95
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
100     // Proximity sensor debounce delay in milliseconds for positive or negative transitions.
101     private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0;
102     private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 250;
103
104     // Trigger proximity if distance is less than 5 cm.
105     private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
106
107     // Brightness animation ramp rate in brightness units per second.
108     private static final int BRIGHTNESS_RAMP_RATE_FAST = 200;
109     private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
110
111     private final Object mLock = new Object();
112
113     private final Context mContext;
114
115     // 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.
120     private final DisplayPowerCallbacks mCallbacks;
121
122     // Battery stats.
123     private final IBatteryStats mBatteryStats;
124
125     // The lights service.
126     private final LightsManager mLights;
127
128     // The sensor manager.
129     private final SensorManager mSensorManager;
130
131     // The window manager policy.
132     private final WindowManagerPolicy mWindowManagerPolicy;
133
134     // The display blanker.
135     private final DisplayBlanker mBlanker;
136
137     // The proximity sensor, or null if not available or needed.
138     private Sensor mProximitySensor;
139
140     // The doze screen brightness.
141     private final int mScreenBrightnessDozeConfig;
142
143     // The dim screen brightness.
144     private final int mScreenBrightnessDimConfig;
145
146     // The minimum screen brightness to use in a very dark room.
147     private final int mScreenBrightnessDarkConfig;
148
149     // The minimum allowed brightness.
150     private final int mScreenBrightnessRangeMinimum;
151
152     // The maximum allowed brightness.
153     private final int mScreenBrightnessRangeMaximum;
154
155     // True if auto-brightness should be used.
156     private boolean mUseSoftwareAutoBrightnessConfig;
157
158     // True if we should fade the screen while turning it off, false if we should play
159     // a stylish color fade animation instead.
160     private boolean mColorFadeFadesConfig;
161
162     // 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;
215     private long mPendingProximityDebounceTime = -1; // -1 if fully debounced
216
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
221     // 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;
229
230     // True if we have unfinished business and are holding a suspend blocker.
231     private boolean mUnfinishedBusiness;
232
233     // The elapsed real time when the screen on was blocked.
234     private long mScreenOnBlockStartRealTime;
235
236     // 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;
241
242     // The controller for the automatic brightness level.
243     private AutomaticBrightnessController mAutomaticBrightnessController;
244
245     // Animators.
246     private ObjectAnimator mColorFadeOnAnimator;
247     private ObjectAnimator mColorFadeOffAnimator;
248     private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
249
250     /**
251      * Creates the display power controller.
252      */
253     public DisplayPowerController(Context context,
254             DisplayPowerCallbacks callbacks, Handler handler,
255             SensorManager sensorManager, DisplayBlanker blanker) {
256         mHandler = new DisplayControllerHandler(handler.getLooper());
257         mCallbacks = callbacks;
258
259         mBatteryStats = BatteryStatsService.getService();
260         mLights = LocalServices.getService(LightsManager.class);
261         mSensorManager = sensorManager;
262         mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
263         mBlanker = blanker;
264         mContext = context;
265
266         final Resources resources = context.getResources();
267         final int screenBrightnessSettingMinimum = clampAbsoluteBrightness(resources.getInteger(
268                 com.android.internal.R.integer.config_screenBrightnessSettingMinimum));
269
270         mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger(
271                 com.android.internal.R.integer.config_screenBrightnessDoze));
272
273         mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger(
274                 com.android.internal.R.integer.config_screenBrightnessDim));
275
276         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);
293
294         mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON;
295
296         mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
297                 com.android.internal.R.bool.config_automatic_brightness_available);
298         if (mUseSoftwareAutoBrightnessConfig) {
299             int[] lux = resources.getIntArray(
300                     com.android.internal.R.array.config_autoBrightnessLevels);
301             int[] screenBrightness = resources.getIntArray(
302                     com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
303             int lightSensorWarmUpTimeConfig = resources.getInteger(
304                     com.android.internal.R.integer.config_lightSensorWarmupTime);
305
306             Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
307             if (screenAutoBrightnessSpline == null) {
308                 Slog.e(TAG, "Error in config.xml.  config_autoBrightnessLcdBacklightValues "
309                         + "(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.  "
313                         + "Auto-brightness will be disabled.");
314                 mUseSoftwareAutoBrightnessConfig = false;
315             } else {
316                 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;
325                 }
326                 mAutomaticBrightnessController = new AutomaticBrightnessController(this,
327                         handler.getLooper(), sensorManager, screenAutoBrightnessSpline,
328                         lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
329                         mScreenBrightnessRangeMaximum);
330             }
331         }
332
333         mScreenBrightnessRangeMinimum = screenBrightnessRangeMinimum;
334
335         mColorFadeFadesConfig = resources.getBoolean(
336                 com.android.internal.R.bool.config_animateScreenLights);
337
338         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
346     }
347
348     /**
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
366      * should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged()}
367      * then try the request again later until the state converges.
368      */
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() {
422         // 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),
426                 new ColorFade(Display.DEFAULT_DISPLAY));
427
428         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);
432
433         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);
437
438         mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
439                 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
440         mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
441
442         // Initialize screen state for battery stats.
443         try {
444             mBatteryStats.noteScreenState(mPowerState.getScreenState());
445             mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness());
446         } catch (RemoteException ex) {
447             // same process
448         }
449     }
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
467     private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
468         @Override
469         public void onAnimationEnd() {
470             sendUpdatePowerState();
471         }
472     };
473
474     private void updatePowerState() {
475         // Update the power state request.
476         final boolean mustNotify;
477         boolean mustInitialize = false;
478         boolean autoBrightnessAdjustmentChanged = false;
479
480         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;
489                 mPendingWaitForNegativeProximityLocked = false;
490                 mPendingRequestChangedLocked = false;
491                 mustInitialize = true;
492             } else if (mPendingRequestChangedLocked) {
493                 autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
494                         != mPendingRequestLocked.screenAutoBrightnessAdjustment);
495                 mPowerRequest.copyFrom(mPendingRequestLocked);
496                 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
497                 mPendingWaitForNegativeProximityLocked = false;
498                 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
510         // 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;
514         boolean performScreenOffTransition = false;
515         switch (mPowerRequest.policy) {
516             case DisplayPowerRequest.POLICY_OFF:
517                 state = Display.STATE_OFF;
518                 performScreenOffTransition = true;
519                 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         }
534         assert(state != Display.STATE_UNKNOWN);
535
536         // Apply the proximity sensor.
537         if (mProximitySensor != null) {
538             if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
539                 setProximitySensorEnabled(true);
540                 if (!mScreenOffBecauseOfProximity
541                         && mProximity == PROXIMITY_POSITIVE) {
542                     mScreenOffBecauseOfProximity = true;
543                     sendOnProximityPositiveWithWakelock();
544                 }
545             } else if (mWaitingForNegativeProximity
546                     && mScreenOffBecauseOfProximity
547                     && mProximity == PROXIMITY_POSITIVE
548                     && state != Display.STATE_OFF) {
549                 setProximitySensorEnabled(true);
550             } else {
551                 setProximitySensorEnabled(false);
552                 mWaitingForNegativeProximity = false;
553             }
554             if (mScreenOffBecauseOfProximity
555                     && mProximity != PROXIMITY_POSITIVE) {
556                 mScreenOffBecauseOfProximity = false;
557                 sendOnProximityNegativeWithWakelock();
558             }
559         } else {
560             mWaitingForNegativeProximity = false;
561         }
562         if (mScreenOffBecauseOfProximity) {
563             state = Display.STATE_OFF;
564         }
565
566         // 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
572         // Use zero brightness when screen is off.
573         if (state == Display.STATE_OFF) {
574             brightness = PowerManager.BRIGHTNESS_OFF;
575         }
576
577         // Use default brightness when dozing unless overridden.
578         if (brightness < 0 && (state == Display.STATE_DOZE
579                 || state == Display.STATE_DOZE_SUSPEND)) {
580             brightness = mScreenBrightnessDozeConfig;
581         }
582
583         // Configure auto-brightness.
584         boolean autoBrightnessEnabled = false;
585         if (mAutomaticBrightnessController != null) {
586             autoBrightnessEnabled = mPowerRequest.useAutoBrightness
587                     && state == Display.STATE_ON && brightness < 0;
588             mAutomaticBrightnessController.configure(autoBrightnessEnabled,
589                     mPowerRequest.screenAutoBrightnessAdjustment);
590         }
591
592         // Apply auto-brightness.
593         boolean slowChange = false;
594         if (brightness < 0) {
595             if (autoBrightnessEnabled) {
596                 brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();
597             }
598             if (brightness >= 0) {
599                 // Use current auto-brightness value and slowly adjust to changes.
600                 brightness = clampScreenBrightness(brightness);
601                 if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
602                     slowChange = true; // slowly adapt to auto-brightness
603                 }
604                 mAppliedAutoBrightness = true;
605             } else {
606                 mAppliedAutoBrightness = false;
607             }
608         } else {
609             mAppliedAutoBrightness = false;
610         }
611
612         // Apply manual brightness.
613         // Use the current brightness setting from the request, which is expected
614         // provide a nominal default value for the case where auto-brightness
615         // is not ready yet.
616         if (brightness < 0) {
617             brightness = clampScreenBrightness(mPowerRequest.screenBrightness);
618         }
619
620         // Apply dimming by at least some minimum amount when user activity
621         // timeout is about to expire.
622         if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
623             if (brightness > mScreenBrightnessRangeMinimum) {
624                 brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,
625                         mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
626             }
627             if (!mAppliedDimming) {
628                 slowChange = false;
629             }
630             mAppliedDimming = true;
631         }
632
633         // If low power mode is enabled, cut the brightness level by half
634         // as long as it is above the minimum threshold.
635         if (mPowerRequest.lowPowerMode) {
636             if (brightness > mScreenBrightnessRangeMinimum) {
637                 brightness = Math.max(brightness / 2, mScreenBrightnessRangeMinimum);
638             }
639             if (!mAppliedLowPower) {
640                 slowChange = false;
641             }
642             mAppliedLowPower = true;
643         }
644
645         // Animate the screen brightness when the screen is on or dozing.
646         // Skip the animation when the screen is off or suspended.
647         if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
648             animateScreenBrightness(brightness,
649                     slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
650         } else {
651             animateScreenBrightness(brightness, 0);
652         }
653
654         // Determine whether the display is ready for use in the newly requested state.
655         // Note that we do not wait for the brightness ramp animation to complete before
656         // reporting the display is ready because we only need to ensure the screen is in the
657         // right power state even as it continues to converge on the desired brightness.
658         final boolean ready = mPendingScreenOnUnblocker == null
659                 && !mColorFadeOnAnimator.isStarted()
660                 && !mColorFadeOffAnimator.isStarted()
661                 && mPowerState.waitUntilClean(mCleanListener);
662         final boolean finished = ready
663                 && !mScreenBrightnessRampAnimator.isAnimating();
664
665         // Grab a wake lock if we have unfinished business.
666         if (!finished && !mUnfinishedBusiness) {
667             if (DEBUG) {
668                 Slog.d(TAG, "Unfinished business...");
669             }
670             mCallbacks.acquireSuspendBlocker();
671             mUnfinishedBusiness = true;
672         }
673
674         // Notify the power manager when ready.
675         if (ready && mustNotify) {
676             // Send state change.
677             synchronized (mLock) {
678                 if (!mPendingRequestChangedLocked) {
679                     mDisplayReadyLocked = true;
680
681                     if (DEBUG) {
682                         Slog.d(TAG, "Display ready!");
683                     }
684                 }
685             }
686             sendOnStateChangedWithWakelock();
687         }
688
689         // Release the wake lock when we have no unfinished business.
690         if (finished && mUnfinishedBusiness) {
691             if (DEBUG) {
692                 Slog.d(TAG, "Finished business...");
693             }
694             mUnfinishedBusiness = false;
695             mCallbacks.releaseSuspendBlocker();
696         }
697     }
698
699     @Override
700     public void updateBrightness() {
701         sendUpdatePowerState();
702     }
703
704     private void blockScreenOn() {
705         if (mPendingScreenOnUnblocker == null) {
706             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
707             mPendingScreenOnUnblocker = new ScreenOnUnblocker();
708             mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
709             Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
710         }
711     }
712
713     private void unblockScreenOn() {
714         if (mPendingScreenOnUnblocker != null) {
715             mPendingScreenOnUnblocker = null;
716             long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
717             Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
718             Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
719         }
720     }
721
722     private boolean setScreenState(int state) {
723         if (mPowerState.getScreenState() != state) {
724             final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
725             mPowerState.setScreenState(state);
726
727             // Tell battery stats about the transition.
728             try {
729                 mBatteryStats.noteScreenState(state);
730             } catch (RemoteException ex) {
731                 // same process
732             }
733
734             // Tell the window manager what's happening.
735             // Temporarily block turning the screen on until the window manager is ready
736             // by leaving a black surface covering the screen.  This surface is essentially
737             // the final state of the color fade animation.
738             boolean isOn = (state != Display.STATE_OFF);
739             if (wasOn && !isOn) {
740                 unblockScreenOn();
741                 mWindowManagerPolicy.screenTurnedOff();
742             } else if (!wasOn && isOn) {
743                 if (mPowerState.getColorFadeLevel() == 0.0f) {
744                     blockScreenOn();
745                 } else {
746                     unblockScreenOn();
747                 }
748                 mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
749             }
750         }
751         return mPendingScreenOnUnblocker == null;
752     }
753
754     private int clampScreenBrightness(int value) {
755         return MathUtils.constrain(
756                 value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
757     }
758
759     private void animateScreenBrightness(int target, int rate) {
760         if (DEBUG) {
761             Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
762         }
763         if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
764             try {
765                 mBatteryStats.noteScreenBrightness(target);
766             } catch (RemoteException ex) {
767                 // same process
768             }
769         }
770     }
771
772     private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
773         // If there is already an animation in progress, don't interfere with it.
774         if (mColorFadeOnAnimator.isStarted()
775                 || mColorFadeOffAnimator.isStarted()) {
776             return;
777         }
778
779         // If we were in the process of turning off the screen but didn't quite
780         // finish.  Then finish up now to prevent a jarring transition back
781         // to screen on if we skipped blocking screen on as usual.
782         if (mPendingScreenOff && target != Display.STATE_OFF) {
783             setScreenState(Display.STATE_OFF);
784             mPendingScreenOff = false;
785         }
786
787         if (target == Display.STATE_ON) {
788             // Want screen on.  The contents of the screen may not yet
789             // be visible if the color fade has not been dismissed because
790             // its last frame of animation is solid black.
791             if (!setScreenState(Display.STATE_ON)) {
792                 return; // screen on blocked
793             }
794             if (USE_COLOR_FADE_ON_ANIMATION && mPowerRequest.isBrightOrDim()) {
795                 // Perform screen on animation.
796                 if (mPowerState.getColorFadeLevel() == 1.0f) {
797                     mPowerState.dismissColorFade();
798                 } else if (mPowerState.prepareColorFade(mContext,
799                         mColorFadeFadesConfig ?
800                                 ColorFade.MODE_FADE :
801                                         ColorFade.MODE_WARM_UP)) {
802                     mColorFadeOnAnimator.start();
803                 } else {
804                     mColorFadeOnAnimator.end();
805                 }
806             } else {
807                 // Skip screen on animation.
808                 mPowerState.setColorFadeLevel(1.0f);
809                 mPowerState.dismissColorFade();
810             }
811         } else if (target == Display.STATE_DOZE) {
812             // Want screen dozing.
813             // Wait for brightness animation to complete beforehand when entering doze
814             // from screen on to prevent a perceptible jump because brightness may operate
815             // differently when the display is configured for dozing.
816             if (mScreenBrightnessRampAnimator.isAnimating()
817                     && mPowerState.getScreenState() == Display.STATE_ON) {
818                 return;
819             }
820
821             // Set screen state.
822             if (!setScreenState(Display.STATE_DOZE)) {
823                 return; // screen on blocked
824             }
825
826             // Dismiss the black surface without fanfare.
827             mPowerState.setColorFadeLevel(1.0f);
828             mPowerState.dismissColorFade();
829         } else if (target == Display.STATE_DOZE_SUSPEND) {
830             // Want screen dozing and suspended.
831             // Wait for brightness animation to complete beforehand unless already
832             // suspended because we may not be able to change it after suspension.
833             if (mScreenBrightnessRampAnimator.isAnimating()
834                     && mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
835                 return;
836             }
837
838             // If not already suspending, temporarily set the state to doze until the
839             // screen on is unblocked, then suspend.
840             if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
841                 if (!setScreenState(Display.STATE_DOZE)) {
842                     return; // screen on blocked
843                 }
844                 setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
845             }
846
847             // Dismiss the black surface without fanfare.
848             mPowerState.setColorFadeLevel(1.0f);
849             mPowerState.dismissColorFade();
850         } else {
851             // Want screen off.
852             mPendingScreenOff = true;
853             if (mPowerState.getColorFadeLevel() == 0.0f) {
854                 // Turn the screen off.
855                 // A black surface is already hiding the contents of the screen.
856                 setScreenState(Display.STATE_OFF);
857                 mPendingScreenOff = false;
858             } else if (performScreenOffTransition
859                     && mPowerState.prepareColorFade(mContext,
860                             mColorFadeFadesConfig ?
861                                     ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
862                     && mPowerState.getScreenState() != Display.STATE_OFF) {
863                 // Perform the screen off animation.
864                 mColorFadeOffAnimator.start();
865             } else {
866                 // Skip the screen off animation and add a black surface to hide the
867                 // contents of the screen.
868                 mColorFadeOffAnimator.end();
869             }
870         }
871     }
872
873     private final Runnable mCleanListener = new Runnable() {
874         @Override
875         public void run() {
876             sendUpdatePowerState();
877         }
878     };
879
880     private void setProximitySensorEnabled(boolean enable) {
881         if (enable) {
882             if (!mProximitySensorEnabled) {
883                 // Register the listener.
884                 // Proximity sensor state already cleared initially.
885                 mProximitySensorEnabled = true;
886                 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
887                         SensorManager.SENSOR_DELAY_NORMAL, mHandler);
888             }
889         } else {
890             if (mProximitySensorEnabled) {
891                 // Unregister the listener.
892                 // Clear the proximity sensor state for next time.
893                 mProximitySensorEnabled = false;
894                 mProximity = PROXIMITY_UNKNOWN;
895                 mPendingProximity = PROXIMITY_UNKNOWN;
896                 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
897                 mSensorManager.unregisterListener(mProximitySensorListener);
898                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
899             }
900         }
901     }
902
903     private void handleProximitySensorEvent(long time, boolean positive) {
904         if (mProximitySensorEnabled) {
905             if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
906                 return; // no change
907             }
908             if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
909                 return; // no change
910             }
911
912             // Only accept a proximity sensor reading if it remains
913             // stable for the entire debounce delay.  We hold a wake lock while
914             // debouncing the sensor.
915             mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
916             if (positive) {
917                 mPendingProximity = PROXIMITY_POSITIVE;
918                 setPendingProximityDebounceTime(
919                         time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
920             } else {
921                 mPendingProximity = PROXIMITY_NEGATIVE;
922                 setPendingProximityDebounceTime(
923                         time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
924             }
925
926             // Debounce the new sensor reading.
927             debounceProximitySensor();
928         }
929     }
930
931     private void debounceProximitySensor() {
932         if (mProximitySensorEnabled
933                 && mPendingProximity != PROXIMITY_UNKNOWN
934                 && mPendingProximityDebounceTime >= 0) {
935             final long now = SystemClock.uptimeMillis();
936             if (mPendingProximityDebounceTime <= now) {
937                 // Sensor reading accepted.  Apply the change then release the wake lock.
938                 mProximity = mPendingProximity;
939                 updatePowerState();
940                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
941             } else {
942                 // Need to wait a little longer.
943                 // Debounce again later.  We continue holding a wake lock while waiting.
944                 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
945                 msg.setAsynchronous(true);
946                 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
947             }
948         }
949     }
950
951     private void clearPendingProximityDebounceTime() {
952         if (mPendingProximityDebounceTime >= 0) {
953             mPendingProximityDebounceTime = -1;
954             mCallbacks.releaseSuspendBlocker(); // release wake lock
955         }
956     }
957
958     private void setPendingProximityDebounceTime(long debounceTime) {
959         if (mPendingProximityDebounceTime < 0) {
960             mCallbacks.acquireSuspendBlocker(); // acquire wake lock
961         }
962         mPendingProximityDebounceTime = debounceTime;
963     }
964
965     private void sendOnStateChangedWithWakelock() {
966         mCallbacks.acquireSuspendBlocker();
967         mHandler.post(mOnStateChangedRunnable);
968     }
969
970     private final Runnable mOnStateChangedRunnable = new Runnable() {
971         @Override
972         public void run() {
973             mCallbacks.onStateChanged();
974             mCallbacks.releaseSuspendBlocker();
975         }
976     };
977
978     private void sendOnProximityPositiveWithWakelock() {
979         mCallbacks.acquireSuspendBlocker();
980         mHandler.post(mOnProximityPositiveRunnable);
981     }
982
983     private final Runnable mOnProximityPositiveRunnable = new Runnable() {
984         @Override
985         public void run() {
986             mCallbacks.onProximityPositive();
987             mCallbacks.releaseSuspendBlocker();
988         }
989     };
990
991     private void sendOnProximityNegativeWithWakelock() {
992         mCallbacks.acquireSuspendBlocker();
993         mHandler.post(mOnProximityNegativeRunnable);
994     }
995
996     private final Runnable mOnProximityNegativeRunnable = new Runnable() {
997         @Override
998         public void run() {
999             mCallbacks.onProximityNegative();
1000             mCallbacks.releaseSuspendBlocker();
1001         }
1002     };
1003
1004     public void dump(final PrintWriter pw) {
1005         synchronized (mLock) {
1006             pw.println();
1007             pw.println("Display Power Controller Locked State:");
1008             pw.println("  mDisplayReadyLocked=" + mDisplayReadyLocked);
1009             pw.println("  mPendingRequestLocked=" + mPendingRequestLocked);
1010             pw.println("  mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
1011             pw.println("  mPendingWaitForNegativeProximityLocked="
1012                     + mPendingWaitForNegativeProximityLocked);
1013             pw.println("  mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
1014         }
1015
1016         pw.println();
1017         pw.println("Display Power Controller Configuration:");
1018         pw.println("  mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
1019         pw.println("  mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
1020         pw.println("  mScreenBrightnessDarkConfig=" + mScreenBrightnessDarkConfig);
1021         pw.println("  mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
1022         pw.println("  mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
1023         pw.println("  mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
1024         pw.println("  mColorFadeFadesConfig=" + mColorFadeFadesConfig);
1025
1026         mHandler.runWithScissors(new Runnable() {
1027             @Override
1028             public void run() {
1029                 dumpLocal(pw);
1030             }
1031         }, 1000);
1032     }
1033
1034     private void dumpLocal(PrintWriter pw) {
1035         pw.println();
1036         pw.println("Display Power Controller Thread State:");
1037         pw.println("  mPowerRequest=" + mPowerRequest);
1038         pw.println("  mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
1039
1040         pw.println("  mProximitySensor=" + mProximitySensor);
1041         pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
1042         pw.println("  mProximityThreshold=" + mProximityThreshold);
1043         pw.println("  mProximity=" + proximityToString(mProximity));
1044         pw.println("  mPendingProximity=" + proximityToString(mPendingProximity));
1045         pw.println("  mPendingProximityDebounceTime="
1046                 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
1047         pw.println("  mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
1048         pw.println("  mAppliedAutoBrightness=" + mAppliedAutoBrightness);
1049         pw.println("  mAppliedDimming=" + mAppliedDimming);
1050         pw.println("  mAppliedLowPower=" + mAppliedLowPower);
1051         pw.println("  mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
1052         pw.println("  mPendingScreenOff=" + mPendingScreenOff);
1053
1054         pw.println("  mScreenBrightnessRampAnimator.isAnimating()=" +
1055                 mScreenBrightnessRampAnimator.isAnimating());
1056
1057         if (mColorFadeOnAnimator != null) {
1058             pw.println("  mColorFadeOnAnimator.isStarted()=" +
1059                     mColorFadeOnAnimator.isStarted());
1060         }
1061         if (mColorFadeOffAnimator != null) {
1062             pw.println("  mColorFadeOffAnimator.isStarted()=" +
1063                     mColorFadeOffAnimator.isStarted());
1064         }
1065
1066         if (mPowerState != null) {
1067             mPowerState.dump(pw);
1068         }
1069
1070         if (mAutomaticBrightnessController != null) {
1071             mAutomaticBrightnessController.dump(pw);
1072         }
1073
1074     }
1075
1076     private static String proximityToString(int state) {
1077         switch (state) {
1078             case PROXIMITY_UNKNOWN:
1079                 return "Unknown";
1080             case PROXIMITY_NEGATIVE:
1081                 return "Negative";
1082             case PROXIMITY_POSITIVE:
1083                 return "Positive";
1084             default:
1085                 return Integer.toString(state);
1086         }
1087     }
1088
1089     private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) {
1090         try {
1091             final int n = brightness.length;
1092             float[] x = new float[n];
1093             float[] y = new float[n];
1094             y[0] = normalizeAbsoluteBrightness(brightness[0]);
1095             for (int i = 1; i < n; i++) {
1096                 x[i] = lux[i - 1];
1097                 y[i] = normalizeAbsoluteBrightness(brightness[i]);
1098             }
1099
1100             Spline spline = Spline.createSpline(x, y);
1101             if (DEBUG) {
1102                 Slog.d(TAG, "Auto-brightness spline: " + spline);
1103                 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
1104                     Slog.d(TAG, String.format("  %7.1f: %7.1f", v, spline.interpolate(v)));
1105                 }
1106             }
1107             return spline;
1108         } catch (IllegalArgumentException ex) {
1109             Slog.e(TAG, "Could not create auto-brightness spline.", ex);
1110             return null;
1111         }
1112     }
1113
1114     private static float normalizeAbsoluteBrightness(int value) {
1115         return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON;
1116     }
1117
1118     private static int clampAbsoluteBrightness(int value) {
1119         return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
1120     }
1121
1122     private final class DisplayControllerHandler extends Handler {
1123         public DisplayControllerHandler(Looper looper) {
1124             super(looper, null, true /*async*/);
1125         }
1126
1127         @Override
1128         public void handleMessage(Message msg) {
1129             switch (msg.what) {
1130                 case MSG_UPDATE_POWER_STATE:
1131                     updatePowerState();
1132                     break;
1133
1134                 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
1135                     debounceProximitySensor();
1136                     break;
1137
1138                 case MSG_SCREEN_ON_UNBLOCKED:
1139                     if (mPendingScreenOnUnblocker == msg.obj) {
1140                         unblockScreenOn();
1141                         updatePowerState();
1142                     }
1143                     break;
1144             }
1145         }
1146     }
1147
1148     private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
1149         @Override
1150         public void onSensorChanged(SensorEvent event) {
1151             if (mProximitySensorEnabled) {
1152                 final long time = SystemClock.uptimeMillis();
1153                 final float distance = event.values[0];
1154                 boolean positive = distance >= 0.0f && distance < mProximityThreshold;
1155                 handleProximitySensorEvent(time, positive);
1156             }
1157         }
1158
1159         @Override
1160         public void onAccuracyChanged(Sensor sensor, int accuracy) {
1161             // Not used.
1162         }
1163     };
1164
1165     private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
1166         @Override
1167         public void onScreenOn() {
1168             Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
1169             msg.setAsynchronous(true);
1170             mHandler.sendMessage(msg);
1171         }
1172     }
1173 }