OSDN Git Service

Fix window manager policy state when waking from doze.
[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     // The elapsed real time when the screen on was blocked.
231     private long mScreenOnBlockStartRealTime;
232
233     // Remembers whether certain kinds of brightness adjustments
234     // were recently applied so that we can decide how to transition.
235     private boolean mAppliedAutoBrightness;
236     private boolean mAppliedDimming;
237     private boolean mAppliedLowPower;
238
239     // The controller for the automatic brightness level.
240     private AutomaticBrightnessController mAutomaticBrightnessController;
241
242     // Animators.
243     private ObjectAnimator mColorFadeOnAnimator;
244     private ObjectAnimator mColorFadeOffAnimator;
245     private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
246
247     /**
248      * Creates the display power controller.
249      */
250     public DisplayPowerController(Context context,
251             DisplayPowerCallbacks callbacks, Handler handler,
252             SensorManager sensorManager, DisplayBlanker blanker) {
253         mHandler = new DisplayControllerHandler(handler.getLooper());
254         mCallbacks = callbacks;
255
256         mBatteryStats = BatteryStatsService.getService();
257         mLights = LocalServices.getService(LightsManager.class);
258         mSensorManager = sensorManager;
259         mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
260         mBlanker = blanker;
261         mContext = context;
262
263         final Resources resources = context.getResources();
264         final int screenBrightnessSettingMinimum = clampAbsoluteBrightness(resources.getInteger(
265                 com.android.internal.R.integer.config_screenBrightnessSettingMinimum));
266
267         mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger(
268                 com.android.internal.R.integer.config_screenBrightnessDoze));
269
270         mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger(
271                 com.android.internal.R.integer.config_screenBrightnessDim));
272
273         mScreenBrightnessDarkConfig = clampAbsoluteBrightness(resources.getInteger(
274                 com.android.internal.R.integer.config_screenBrightnessDark));
275         if (mScreenBrightnessDarkConfig > mScreenBrightnessDimConfig) {
276             Slog.w(TAG, "Expected config_screenBrightnessDark ("
277                     + mScreenBrightnessDarkConfig + ") to be less than or equal to "
278                     + "config_screenBrightnessDim (" + mScreenBrightnessDimConfig + ").");
279         }
280         if (mScreenBrightnessDarkConfig > mScreenBrightnessDimConfig) {
281             Slog.w(TAG, "Expected config_screenBrightnessDark ("
282                     + mScreenBrightnessDarkConfig + ") to be less than or equal to "
283                     + "config_screenBrightnessSettingMinimum ("
284                     + screenBrightnessSettingMinimum + ").");
285         }
286
287         int screenBrightnessRangeMinimum = Math.min(Math.min(
288                 screenBrightnessSettingMinimum, mScreenBrightnessDimConfig),
289                 mScreenBrightnessDarkConfig);
290
291         mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON;
292
293         mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
294                 com.android.internal.R.bool.config_automatic_brightness_available);
295         if (mUseSoftwareAutoBrightnessConfig) {
296             int[] lux = resources.getIntArray(
297                     com.android.internal.R.array.config_autoBrightnessLevels);
298             int[] screenBrightness = resources.getIntArray(
299                     com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
300             int lightSensorWarmUpTimeConfig = resources.getInteger(
301                     com.android.internal.R.integer.config_lightSensorWarmupTime);
302
303             Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
304             if (screenAutoBrightnessSpline == null) {
305                 Slog.e(TAG, "Error in config.xml.  config_autoBrightnessLcdBacklightValues "
306                         + "(size " + screenBrightness.length + ") "
307                         + "must be monotic and have exactly one more entry than "
308                         + "config_autoBrightnessLevels (size " + lux.length + ") "
309                         + "which must be strictly increasing.  "
310                         + "Auto-brightness will be disabled.");
311                 mUseSoftwareAutoBrightnessConfig = false;
312             } else {
313                 int bottom = clampAbsoluteBrightness(screenBrightness[0]);
314                 if (mScreenBrightnessDarkConfig > bottom) {
315                     Slog.w(TAG, "config_screenBrightnessDark (" + mScreenBrightnessDarkConfig
316                             + ") should be less than or equal to the first value of "
317                             + "config_autoBrightnessLcdBacklightValues ("
318                             + bottom + ").");
319                 }
320                 if (bottom < screenBrightnessRangeMinimum) {
321                     screenBrightnessRangeMinimum = bottom;
322                 }
323                 mAutomaticBrightnessController = new AutomaticBrightnessController(this,
324                         handler.getLooper(), sensorManager, screenAutoBrightnessSpline,
325                         lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
326                         mScreenBrightnessRangeMaximum);
327             }
328         }
329
330         mScreenBrightnessRangeMinimum = screenBrightnessRangeMinimum;
331
332         mColorFadeFadesConfig = resources.getBoolean(
333                 com.android.internal.R.bool.config_animateScreenLights);
334
335         if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
336             mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
337             if (mProximitySensor != null) {
338                 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
339                         TYPICAL_PROXIMITY_THRESHOLD);
340             }
341         }
342
343     }
344
345     /**
346      * Returns true if the proximity sensor screen-off function is available.
347      */
348     public boolean isProximitySensorAvailable() {
349         return mProximitySensor != null;
350     }
351
352     /**
353      * Requests a new power state.
354      * The controller makes a copy of the provided object and then
355      * begins adjusting the power state to match what was requested.
356      *
357      * @param request The requested power state.
358      * @param waitForNegativeProximity If true, issues a request to wait for
359      * negative proximity before turning the screen back on, assuming the screen
360      * was turned off by the proximity sensor.
361      * @return True if display is ready, false if there are important changes that must
362      * be made asynchronously (such as turning the screen on), in which case the caller
363      * should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged()}
364      * then try the request again later until the state converges.
365      */
366     public boolean requestPowerState(DisplayPowerRequest request,
367             boolean waitForNegativeProximity) {
368         if (DEBUG) {
369             Slog.d(TAG, "requestPowerState: "
370                     + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
371         }
372
373         synchronized (mLock) {
374             boolean changed = false;
375
376             if (waitForNegativeProximity
377                     && !mPendingWaitForNegativeProximityLocked) {
378                 mPendingWaitForNegativeProximityLocked = true;
379                 changed = true;
380             }
381
382             if (mPendingRequestLocked == null) {
383                 mPendingRequestLocked = new DisplayPowerRequest(request);
384                 changed = true;
385             } else if (!mPendingRequestLocked.equals(request)) {
386                 mPendingRequestLocked.copyFrom(request);
387                 changed = true;
388             }
389
390             if (changed) {
391                 mDisplayReadyLocked = false;
392             }
393
394             if (changed && !mPendingRequestChangedLocked) {
395                 mPendingRequestChangedLocked = true;
396                 sendUpdatePowerStateLocked();
397             }
398
399             return mDisplayReadyLocked;
400         }
401     }
402
403     private void sendUpdatePowerState() {
404         synchronized (mLock) {
405             sendUpdatePowerStateLocked();
406         }
407     }
408
409     private void sendUpdatePowerStateLocked() {
410         if (!mPendingUpdatePowerStateLocked) {
411             mPendingUpdatePowerStateLocked = true;
412             Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
413             msg.setAsynchronous(true);
414             mHandler.sendMessage(msg);
415         }
416     }
417
418     private void initialize() {
419         // Initialize the power state object for the default display.
420         // In the future, we might manage multiple displays independently.
421         mPowerState = new DisplayPowerState(mBlanker,
422                 mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT),
423                 new ColorFade(Display.DEFAULT_DISPLAY));
424
425         mColorFadeOnAnimator = ObjectAnimator.ofFloat(
426                 mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 0.0f, 1.0f);
427         mColorFadeOnAnimator.setDuration(COLOR_FADE_ON_ANIMATION_DURATION_MILLIS);
428         mColorFadeOnAnimator.addListener(mAnimatorListener);
429
430         mColorFadeOffAnimator = ObjectAnimator.ofFloat(
431                 mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 1.0f, 0.0f);
432         mColorFadeOffAnimator.setDuration(COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS);
433         mColorFadeOffAnimator.addListener(mAnimatorListener);
434
435         mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
436                 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
437         mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
438
439         // Initialize screen state for battery stats.
440         try {
441             mBatteryStats.noteScreenState(mPowerState.getScreenState());
442             mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness());
443         } catch (RemoteException ex) {
444             // same process
445         }
446     }
447
448     private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
449         @Override
450         public void onAnimationStart(Animator animation) {
451         }
452         @Override
453         public void onAnimationEnd(Animator animation) {
454             sendUpdatePowerState();
455         }
456         @Override
457         public void onAnimationRepeat(Animator animation) {
458         }
459         @Override
460         public void onAnimationCancel(Animator animation) {
461         }
462     };
463
464     private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
465         @Override
466         public void onAnimationEnd() {
467             sendUpdatePowerState();
468         }
469     };
470
471     private void updatePowerState() {
472         // Update the power state request.
473         final boolean mustNotify;
474         boolean mustInitialize = false;
475         boolean autoBrightnessAdjustmentChanged = false;
476
477         synchronized (mLock) {
478             mPendingUpdatePowerStateLocked = false;
479             if (mPendingRequestLocked == null) {
480                 return; // wait until first actual power request
481             }
482
483             if (mPowerRequest == null) {
484                 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
485                 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
486                 mPendingWaitForNegativeProximityLocked = false;
487                 mPendingRequestChangedLocked = false;
488                 mustInitialize = true;
489             } else if (mPendingRequestChangedLocked) {
490                 autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
491                         != mPendingRequestLocked.screenAutoBrightnessAdjustment);
492                 mPowerRequest.copyFrom(mPendingRequestLocked);
493                 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
494                 mPendingWaitForNegativeProximityLocked = false;
495                 mPendingRequestChangedLocked = false;
496                 mDisplayReadyLocked = false;
497             }
498
499             mustNotify = !mDisplayReadyLocked;
500         }
501
502         // Initialize things the first time the power state is changed.
503         if (mustInitialize) {
504             initialize();
505         }
506
507         // Compute the basic display state using the policy.
508         // We might override this below based on other factors.
509         int state;
510         int brightness = PowerManager.BRIGHTNESS_DEFAULT;
511         boolean performScreenOffTransition = false;
512         switch (mPowerRequest.policy) {
513             case DisplayPowerRequest.POLICY_OFF:
514                 state = Display.STATE_OFF;
515                 performScreenOffTransition = true;
516                 break;
517             case DisplayPowerRequest.POLICY_DOZE:
518                 if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
519                     state = mPowerRequest.dozeScreenState;
520                 } else {
521                     state = Display.STATE_DOZE;
522                 }
523                 brightness = mPowerRequest.dozeScreenBrightness;
524                 break;
525             case DisplayPowerRequest.POLICY_DIM:
526             case DisplayPowerRequest.POLICY_BRIGHT:
527             default:
528                 state = Display.STATE_ON;
529                 break;
530         }
531         assert(state != Display.STATE_UNKNOWN);
532
533         // Apply the proximity sensor.
534         if (mProximitySensor != null) {
535             if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
536                 setProximitySensorEnabled(true);
537                 if (!mScreenOffBecauseOfProximity
538                         && mProximity == PROXIMITY_POSITIVE) {
539                     mScreenOffBecauseOfProximity = true;
540                     sendOnProximityPositiveWithWakelock();
541                 }
542             } else if (mWaitingForNegativeProximity
543                     && mScreenOffBecauseOfProximity
544                     && mProximity == PROXIMITY_POSITIVE
545                     && state != Display.STATE_OFF) {
546                 setProximitySensorEnabled(true);
547             } else {
548                 setProximitySensorEnabled(false);
549                 mWaitingForNegativeProximity = false;
550             }
551             if (mScreenOffBecauseOfProximity
552                     && mProximity != PROXIMITY_POSITIVE) {
553                 mScreenOffBecauseOfProximity = false;
554                 sendOnProximityNegativeWithWakelock();
555             }
556         } else {
557             mWaitingForNegativeProximity = false;
558         }
559         if (mScreenOffBecauseOfProximity) {
560             state = Display.STATE_OFF;
561         }
562
563         // Use zero brightness when screen is off.
564         if (state == Display.STATE_OFF) {
565             brightness = PowerManager.BRIGHTNESS_OFF;
566         }
567
568         // Use default brightness when dozing unless overridden.
569         if (brightness < 0 && (state == Display.STATE_DOZE
570                 || state == Display.STATE_DOZE_SUSPEND)) {
571             brightness = mScreenBrightnessDozeConfig;
572         }
573
574         // Configure auto-brightness.
575         boolean autoBrightnessEnabled = false;
576         if (mAutomaticBrightnessController != null) {
577             autoBrightnessEnabled = mPowerRequest.useAutoBrightness
578                     && state == Display.STATE_ON && brightness < 0;
579             mAutomaticBrightnessController.configure(autoBrightnessEnabled,
580                     mPowerRequest.screenAutoBrightnessAdjustment);
581         }
582
583         // Apply auto-brightness.
584         boolean slowChange = false;
585         if (brightness < 0) {
586             if (autoBrightnessEnabled) {
587                 brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();
588             }
589             if (brightness >= 0) {
590                 // Use current auto-brightness value and slowly adjust to changes.
591                 brightness = clampScreenBrightness(brightness);
592                 if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
593                     slowChange = true; // slowly adapt to auto-brightness
594                 }
595                 mAppliedAutoBrightness = true;
596             } else {
597                 mAppliedAutoBrightness = false;
598             }
599         } else {
600             mAppliedAutoBrightness = false;
601         }
602
603         // Apply manual brightness.
604         // Use the current brightness setting from the request, which is expected
605         // provide a nominal default value for the case where auto-brightness
606         // is not ready yet.
607         if (brightness < 0) {
608             brightness = clampScreenBrightness(mPowerRequest.screenBrightness);
609         }
610
611         // Apply dimming by at least some minimum amount when user activity
612         // timeout is about to expire.
613         if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
614             if (brightness > mScreenBrightnessRangeMinimum) {
615                 brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,
616                         mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
617             }
618             if (!mAppliedDimming) {
619                 slowChange = false;
620             }
621             mAppliedDimming = true;
622         }
623
624         // If low power mode is enabled, cut the brightness level by half
625         // as long as it is above the minimum threshold.
626         if (mPowerRequest.lowPowerMode) {
627             if (brightness > mScreenBrightnessRangeMinimum) {
628                 brightness = Math.max(brightness / 2, mScreenBrightnessRangeMinimum);
629             }
630             if (!mAppliedLowPower) {
631                 slowChange = false;
632             }
633             mAppliedLowPower = true;
634         }
635
636         // Animate the screen brightness when the screen is on.
637         if (state != Display.STATE_OFF) {
638             animateScreenBrightness(brightness, slowChange
639                     ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
640         }
641
642         // Animate the screen state change unless already animating.
643         animateScreenStateChange(state, performScreenOffTransition);
644
645         // Report whether the display is ready for use and all changes have been applied.
646         if (mustNotify
647                 && mPendingScreenOnUnblocker == null
648                 && !mColorFadeOnAnimator.isStarted()
649                 && !mColorFadeOffAnimator.isStarted()
650                 && !mScreenBrightnessRampAnimator.isAnimating()
651                 && mPowerState.waitUntilClean(mCleanListener)) {
652             synchronized (mLock) {
653                 if (!mPendingRequestChangedLocked) {
654                     mDisplayReadyLocked = true;
655
656                     if (DEBUG) {
657                         Slog.d(TAG, "Display ready!");
658                     }
659                 }
660             }
661             sendOnStateChangedWithWakelock();
662         }
663     }
664
665     @Override
666     public void updateBrightness() {
667         sendUpdatePowerState();
668     }
669
670     private void blockScreenOn() {
671         if (mPendingScreenOnUnblocker == null) {
672             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
673             mPendingScreenOnUnblocker = new ScreenOnUnblocker();
674             mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
675             Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
676         }
677     }
678
679     private void unblockScreenOn() {
680         if (mPendingScreenOnUnblocker != null) {
681             mPendingScreenOnUnblocker = null;
682             long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
683             Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
684             Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
685         }
686     }
687
688     private boolean setScreenState(int state) {
689         if (mPowerState.getScreenState() != state) {
690             final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
691             mPowerState.setScreenState(state);
692
693             // Tell battery stats about the transition.
694             try {
695                 mBatteryStats.noteScreenState(state);
696             } catch (RemoteException ex) {
697                 // same process
698             }
699
700             // Tell the window manager what's happening.
701             // Temporarily block turning the screen on until the window manager is ready
702             // by leaving a black surface covering the screen.  This surface is essentially
703             // the final state of the color fade animation.
704             boolean isOn = (state != Display.STATE_OFF);
705             if (wasOn && !isOn) {
706                 unblockScreenOn();
707                 mWindowManagerPolicy.screenTurnedOff();
708             } else if (!wasOn && isOn) {
709                 if (mPowerState.getColorFadeLevel() == 0.0f) {
710                     blockScreenOn();
711                 } else {
712                     unblockScreenOn();
713                 }
714                 mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
715             }
716         }
717         return mPendingScreenOnUnblocker == null;
718     }
719
720     private int clampScreenBrightness(int value) {
721         return MathUtils.constrain(
722                 value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
723     }
724
725     private void animateScreenBrightness(int target, int rate) {
726         if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
727             try {
728                 mBatteryStats.noteScreenBrightness(target);
729             } catch (RemoteException ex) {
730                 // same process
731             }
732         }
733     }
734
735     private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
736         // If there is already an animation in progress, don't interfere with it.
737         if (mColorFadeOnAnimator.isStarted()
738                 || mColorFadeOffAnimator.isStarted()) {
739             return;
740         }
741
742         // If we were in the process of turning off the screen but didn't quite
743         // finish.  Then finish up now to prevent a jarring transition back
744         // to screen on if we skipped blocking screen on as usual.
745         if (mPendingScreenOff && target != Display.STATE_OFF) {
746             setScreenState(Display.STATE_OFF);
747             mPendingScreenOff = false;
748         }
749
750         if (target == Display.STATE_ON) {
751             // Want screen on.  The contents of the screen may not yet
752             // be visible if the color fade has not been dismissed because
753             // its last frame of animation is solid black.
754             if (!setScreenState(Display.STATE_ON)) {
755                 return; // screen on blocked
756             }
757             if (USE_COLOR_FADE_ON_ANIMATION && mPowerRequest.isBrightOrDim()) {
758                 // Perform screen on animation.
759                 if (mPowerState.getColorFadeLevel() == 1.0f) {
760                     mPowerState.dismissColorFade();
761                 } else if (mPowerState.prepareColorFade(mContext,
762                         mColorFadeFadesConfig ?
763                                 ColorFade.MODE_FADE :
764                                         ColorFade.MODE_WARM_UP)) {
765                     mColorFadeOnAnimator.start();
766                 } else {
767                     mColorFadeOnAnimator.end();
768                 }
769             } else {
770                 // Skip screen on animation.
771                 mPowerState.setColorFadeLevel(1.0f);
772                 mPowerState.dismissColorFade();
773             }
774         } else if (target == Display.STATE_DOZE) {
775             // Want screen dozing.
776             // Wait for brightness animation to complete beforehand when entering doze
777             // from screen on to prevent a perceptible jump because brightness may operate
778             // differently when the display is configured for dozing.
779             if (mScreenBrightnessRampAnimator.isAnimating()
780                     && mPowerState.getScreenState() == Display.STATE_ON) {
781                 return;
782             }
783
784             // Set screen state.
785             if (!setScreenState(Display.STATE_DOZE)) {
786                 return; // screen on blocked
787             }
788
789             // Dismiss the black surface without fanfare.
790             mPowerState.setColorFadeLevel(1.0f);
791             mPowerState.dismissColorFade();
792         } else if (target == Display.STATE_DOZE_SUSPEND) {
793             // Want screen dozing and suspended.
794             // Wait for brightness animation to complete beforehand unless already
795             // suspended because we may not be able to change it after suspension.
796             if (mScreenBrightnessRampAnimator.isAnimating()
797                     && mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
798                 return;
799             }
800
801             // If not already suspending, temporarily set the state to doze until the
802             // screen on is unblocked, then suspend.
803             if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
804                 if (!setScreenState(Display.STATE_DOZE)) {
805                     return; // screen on blocked
806                 }
807                 setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
808             }
809
810             // Dismiss the black surface without fanfare.
811             mPowerState.setColorFadeLevel(1.0f);
812             mPowerState.dismissColorFade();
813         } else {
814             // Want screen off.
815             mPendingScreenOff = true;
816             if (mPowerState.getColorFadeLevel() == 0.0f) {
817                 // Turn the screen off.
818                 // A black surface is already hiding the contents of the screen.
819                 setScreenState(Display.STATE_OFF);
820                 mPendingScreenOff = false;
821             } else if (performScreenOffTransition
822                     && mPowerState.prepareColorFade(mContext,
823                             mColorFadeFadesConfig ?
824                                     ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
825                     && mPowerState.getScreenState() != Display.STATE_OFF) {
826                 // Perform the screen off animation.
827                 mColorFadeOffAnimator.start();
828             } else {
829                 // Skip the screen off animation and add a black surface to hide the
830                 // contents of the screen.
831                 mColorFadeOffAnimator.end();
832             }
833         }
834     }
835
836     private final Runnable mCleanListener = new Runnable() {
837         @Override
838         public void run() {
839             sendUpdatePowerState();
840         }
841     };
842
843     private void setProximitySensorEnabled(boolean enable) {
844         if (enable) {
845             if (!mProximitySensorEnabled) {
846                 // Register the listener.
847                 // Proximity sensor state already cleared initially.
848                 mProximitySensorEnabled = true;
849                 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
850                         SensorManager.SENSOR_DELAY_NORMAL, mHandler);
851             }
852         } else {
853             if (mProximitySensorEnabled) {
854                 // Unregister the listener.
855                 // Clear the proximity sensor state for next time.
856                 mProximitySensorEnabled = false;
857                 mProximity = PROXIMITY_UNKNOWN;
858                 mPendingProximity = PROXIMITY_UNKNOWN;
859                 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
860                 mSensorManager.unregisterListener(mProximitySensorListener);
861                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
862             }
863         }
864     }
865
866     private void handleProximitySensorEvent(long time, boolean positive) {
867         if (mProximitySensorEnabled) {
868             if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
869                 return; // no change
870             }
871             if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
872                 return; // no change
873             }
874
875             // Only accept a proximity sensor reading if it remains
876             // stable for the entire debounce delay.  We hold a wake lock while
877             // debouncing the sensor.
878             mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
879             if (positive) {
880                 mPendingProximity = PROXIMITY_POSITIVE;
881                 setPendingProximityDebounceTime(
882                         time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
883             } else {
884                 mPendingProximity = PROXIMITY_NEGATIVE;
885                 setPendingProximityDebounceTime(
886                         time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
887             }
888
889             // Debounce the new sensor reading.
890             debounceProximitySensor();
891         }
892     }
893
894     private void debounceProximitySensor() {
895         if (mProximitySensorEnabled
896                 && mPendingProximity != PROXIMITY_UNKNOWN
897                 && mPendingProximityDebounceTime >= 0) {
898             final long now = SystemClock.uptimeMillis();
899             if (mPendingProximityDebounceTime <= now) {
900                 // Sensor reading accepted.  Apply the change then release the wake lock.
901                 mProximity = mPendingProximity;
902                 updatePowerState();
903                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
904             } else {
905                 // Need to wait a little longer.
906                 // Debounce again later.  We continue holding a wake lock while waiting.
907                 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
908                 msg.setAsynchronous(true);
909                 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
910             }
911         }
912     }
913
914     private void clearPendingProximityDebounceTime() {
915         if (mPendingProximityDebounceTime >= 0) {
916             mPendingProximityDebounceTime = -1;
917             mCallbacks.releaseSuspendBlocker(); // release wake lock
918         }
919     }
920
921     private void setPendingProximityDebounceTime(long debounceTime) {
922         if (mPendingProximityDebounceTime < 0) {
923             mCallbacks.acquireSuspendBlocker(); // acquire wake lock
924         }
925         mPendingProximityDebounceTime = debounceTime;
926     }
927
928     private void sendOnStateChangedWithWakelock() {
929         mCallbacks.acquireSuspendBlocker();
930         mHandler.post(mOnStateChangedRunnable);
931     }
932
933     private final Runnable mOnStateChangedRunnable = new Runnable() {
934         @Override
935         public void run() {
936             mCallbacks.onStateChanged();
937             mCallbacks.releaseSuspendBlocker();
938         }
939     };
940
941     private void sendOnProximityPositiveWithWakelock() {
942         mCallbacks.acquireSuspendBlocker();
943         mHandler.post(mOnProximityPositiveRunnable);
944     }
945
946     private final Runnable mOnProximityPositiveRunnable = new Runnable() {
947         @Override
948         public void run() {
949             mCallbacks.onProximityPositive();
950             mCallbacks.releaseSuspendBlocker();
951         }
952     };
953
954     private void sendOnProximityNegativeWithWakelock() {
955         mCallbacks.acquireSuspendBlocker();
956         mHandler.post(mOnProximityNegativeRunnable);
957     }
958
959     private final Runnable mOnProximityNegativeRunnable = new Runnable() {
960         @Override
961         public void run() {
962             mCallbacks.onProximityNegative();
963             mCallbacks.releaseSuspendBlocker();
964         }
965     };
966
967     public void dump(final PrintWriter pw) {
968         synchronized (mLock) {
969             pw.println();
970             pw.println("Display Power Controller Locked State:");
971             pw.println("  mDisplayReadyLocked=" + mDisplayReadyLocked);
972             pw.println("  mPendingRequestLocked=" + mPendingRequestLocked);
973             pw.println("  mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
974             pw.println("  mPendingWaitForNegativeProximityLocked="
975                     + mPendingWaitForNegativeProximityLocked);
976             pw.println("  mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
977         }
978
979         pw.println();
980         pw.println("Display Power Controller Configuration:");
981         pw.println("  mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
982         pw.println("  mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
983         pw.println("  mScreenBrightnessDarkConfig=" + mScreenBrightnessDarkConfig);
984         pw.println("  mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
985         pw.println("  mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
986         pw.println("  mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
987         pw.println("  mColorFadeFadesConfig=" + mColorFadeFadesConfig);
988
989         mHandler.runWithScissors(new Runnable() {
990             @Override
991             public void run() {
992                 dumpLocal(pw);
993             }
994         }, 1000);
995     }
996
997     private void dumpLocal(PrintWriter pw) {
998         pw.println();
999         pw.println("Display Power Controller Thread State:");
1000         pw.println("  mPowerRequest=" + mPowerRequest);
1001         pw.println("  mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
1002
1003         pw.println("  mProximitySensor=" + mProximitySensor);
1004         pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
1005         pw.println("  mProximityThreshold=" + mProximityThreshold);
1006         pw.println("  mProximity=" + proximityToString(mProximity));
1007         pw.println("  mPendingProximity=" + proximityToString(mPendingProximity));
1008         pw.println("  mPendingProximityDebounceTime="
1009                 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
1010         pw.println("  mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
1011         pw.println("  mAppliedAutoBrightness=" + mAppliedAutoBrightness);
1012         pw.println("  mAppliedDimming=" + mAppliedDimming);
1013         pw.println("  mAppliedLowPower=" + mAppliedLowPower);
1014         pw.println("  mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
1015         pw.println("  mPendingScreenOff=" + mPendingScreenOff);
1016
1017         pw.println("  mScreenBrightnessRampAnimator.isAnimating()=" +
1018                 mScreenBrightnessRampAnimator.isAnimating());
1019
1020         if (mColorFadeOnAnimator != null) {
1021             pw.println("  mColorFadeOnAnimator.isStarted()=" +
1022                     mColorFadeOnAnimator.isStarted());
1023         }
1024         if (mColorFadeOffAnimator != null) {
1025             pw.println("  mColorFadeOffAnimator.isStarted()=" +
1026                     mColorFadeOffAnimator.isStarted());
1027         }
1028
1029         if (mPowerState != null) {
1030             mPowerState.dump(pw);
1031         }
1032
1033         if (mAutomaticBrightnessController != null) {
1034             mAutomaticBrightnessController.dump(pw);
1035         }
1036
1037     }
1038
1039     private static String proximityToString(int state) {
1040         switch (state) {
1041             case PROXIMITY_UNKNOWN:
1042                 return "Unknown";
1043             case PROXIMITY_NEGATIVE:
1044                 return "Negative";
1045             case PROXIMITY_POSITIVE:
1046                 return "Positive";
1047             default:
1048                 return Integer.toString(state);
1049         }
1050     }
1051
1052     private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) {
1053         try {
1054             final int n = brightness.length;
1055             float[] x = new float[n];
1056             float[] y = new float[n];
1057             y[0] = normalizeAbsoluteBrightness(brightness[0]);
1058             for (int i = 1; i < n; i++) {
1059                 x[i] = lux[i - 1];
1060                 y[i] = normalizeAbsoluteBrightness(brightness[i]);
1061             }
1062
1063             Spline spline = Spline.createSpline(x, y);
1064             if (DEBUG) {
1065                 Slog.d(TAG, "Auto-brightness spline: " + spline);
1066                 for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
1067                     Slog.d(TAG, String.format("  %7.1f: %7.1f", v, spline.interpolate(v)));
1068                 }
1069             }
1070             return spline;
1071         } catch (IllegalArgumentException ex) {
1072             Slog.e(TAG, "Could not create auto-brightness spline.", ex);
1073             return null;
1074         }
1075     }
1076
1077     private static float normalizeAbsoluteBrightness(int value) {
1078         return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON;
1079     }
1080
1081     private static int clampAbsoluteBrightness(int value) {
1082         return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
1083     }
1084
1085     private final class DisplayControllerHandler extends Handler {
1086         public DisplayControllerHandler(Looper looper) {
1087             super(looper, null, true /*async*/);
1088         }
1089
1090         @Override
1091         public void handleMessage(Message msg) {
1092             switch (msg.what) {
1093                 case MSG_UPDATE_POWER_STATE:
1094                     updatePowerState();
1095                     break;
1096
1097                 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
1098                     debounceProximitySensor();
1099                     break;
1100
1101                 case MSG_SCREEN_ON_UNBLOCKED:
1102                     if (mPendingScreenOnUnblocker == msg.obj) {
1103                         unblockScreenOn();
1104                         updatePowerState();
1105                     }
1106                     break;
1107             }
1108         }
1109     }
1110
1111     private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
1112         @Override
1113         public void onSensorChanged(SensorEvent event) {
1114             if (mProximitySensorEnabled) {
1115                 final long time = SystemClock.uptimeMillis();
1116                 final float distance = event.values[0];
1117                 boolean positive = distance >= 0.0f && distance < mProximityThreshold;
1118                 handleProximitySensorEvent(time, positive);
1119             }
1120         }
1121
1122         @Override
1123         public void onAccuracyChanged(Sensor sensor, int accuracy) {
1124             // Not used.
1125         }
1126     };
1127
1128     private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
1129         @Override
1130         public void onScreenOn() {
1131             Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
1132             msg.setAsynchronous(true);
1133             mHandler.sendMessage(msg);
1134         }
1135     }
1136 }