• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.animation.Animator;
20 import android.animation.ObjectAnimator;
21 import android.annotation.Nullable;
22 import android.annotation.UserIdInt;
23 import android.app.ActivityManager;
24 import android.content.Context;
25 import android.content.pm.ParceledListSlice;
26 import android.content.res.Resources;
27 import android.database.ContentObserver;
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.AmbientBrightnessDayStats;
33 import android.hardware.display.BrightnessChangeEvent;
34 import android.hardware.display.BrightnessConfiguration;
35 import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
36 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
37 import android.metrics.LogMaker;
38 import android.net.Uri;
39 import android.os.Handler;
40 import android.os.Looper;
41 import android.os.Message;
42 import android.os.PowerManager;
43 import android.os.RemoteException;
44 import android.os.SystemClock;
45 import android.os.SystemProperties;
46 import android.os.Trace;
47 import android.os.UserHandle;
48 import android.provider.Settings;
49 import android.text.TextUtils;
50 import android.util.MathUtils;
51 import android.util.Slog;
52 import android.util.TimeUtils;
53 import android.view.Display;
54 
55 import com.android.internal.BrightnessSynchronizer;
56 import com.android.internal.app.IBatteryStats;
57 import com.android.internal.logging.MetricsLogger;
58 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
59 import com.android.server.LocalServices;
60 import com.android.server.am.BatteryStatsService;
61 import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
62 import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory;
63 import com.android.server.display.whitebalance.DisplayWhiteBalanceSettings;
64 import com.android.server.policy.WindowManagerPolicy;
65 
66 import java.io.PrintWriter;
67 import java.util.List;
68 
69 /**
70  * Controls the power state of the display.
71  *
72  * Handles the proximity sensor, light sensor, and animations between states
73  * including the screen off animation.
74  *
75  * This component acts independently of the rest of the power manager service.
76  * In particular, it does not share any state and it only communicates
77  * via asynchronous callbacks to inform the power manager that something has
78  * changed.
79  *
80  * Everything this class does internally is serialized on its handler although
81  * it may be accessed by other threads from the outside.
82  *
83  * Note that the power manager service guarantees that it will hold a suspend
84  * blocker as long as the display is not ready.  So most of the work done here
85  * does not need to worry about holding a suspend blocker unless it happens
86  * independently of the display ready signal.
87    *
88  * For debugging, you can make the color fade and brightness animations run
89  * slower by changing the "animator duration scale" option in Development Settings.
90  */
91 final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
92         DisplayWhiteBalanceController.Callbacks {
93     private static final String TAG = "DisplayPowerController";
94     private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
95     private static final String SCREEN_OFF_BLOCKED_TRACE_NAME = "Screen off blocked";
96 
97     private static final boolean DEBUG = false;
98     private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
99 
100     // If true, uses the color fade on animation.
101     // We might want to turn this off if we cannot get a guarantee that the screen
102     // actually turns on and starts showing new content after the call to set the
103     // screen state returns.  Playing the animation can also be somewhat slow.
104     private static final boolean USE_COLOR_FADE_ON_ANIMATION = false;
105 
106     // The minimum reduction in brightness when dimmed.
107     private static final float SCREEN_DIM_MINIMUM_REDUCTION_FLOAT = 0.04f;
108     private static final float SCREEN_ANIMATION_RATE_MINIMUM = 0.0f;
109 
110     private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
111     private static final int COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS = 400;
112 
113     private static final int MSG_UPDATE_POWER_STATE = 1;
114     private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
115     private static final int MSG_SCREEN_ON_UNBLOCKED = 3;
116     private static final int MSG_SCREEN_OFF_UNBLOCKED = 4;
117     private static final int MSG_CONFIGURE_BRIGHTNESS = 5;
118     private static final int MSG_SET_TEMPORARY_BRIGHTNESS = 6;
119     private static final int MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT = 7;
120 
121     private static final int PROXIMITY_UNKNOWN = -1;
122     private static final int PROXIMITY_NEGATIVE = 0;
123     private static final int PROXIMITY_POSITIVE = 1;
124 
125     // Proximity sensor debounce delay in milliseconds for positive or negative transitions.
126     private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0;
127     private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 250;
128 
129     // Trigger proximity if distance is less than 5 cm.
130     private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
131 
132     // State machine constants for tracking initial brightness ramp skipping when enabled.
133     private static final int RAMP_STATE_SKIP_NONE = 0;
134     private static final int RAMP_STATE_SKIP_INITIAL = 1;
135     private static final int RAMP_STATE_SKIP_AUTOBRIGHT = 2;
136 
137     private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
138     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
139     private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
140     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_OFF = 3;
141 
142     private final Object mLock = new Object();
143 
144     private final Context mContext;
145 
146     // Our handler.
147     private final DisplayControllerHandler mHandler;
148 
149     // Asynchronous callbacks into the power manager service.
150     // Only invoked from the handler thread while no locks are held.
151     private final DisplayPowerCallbacks mCallbacks;
152 
153     // Battery stats.
154     private final IBatteryStats mBatteryStats;
155 
156     // The sensor manager.
157     private final SensorManager mSensorManager;
158 
159     // The window manager policy.
160     private final WindowManagerPolicy mWindowManagerPolicy;
161 
162     // The display blanker.
163     private final DisplayBlanker mBlanker;
164 
165     // The display device.
166     private final DisplayDevice mDisplayDevice;
167 
168     // Tracker for brightness changes.
169     private final BrightnessTracker mBrightnessTracker;
170 
171     // Tracker for brightness settings changes.
172     private final SettingsObserver mSettingsObserver;
173 
174     // The proximity sensor, or null if not available or needed.
175     private Sensor mProximitySensor;
176 
177     // The doze screen brightness.
178     private final float mScreenBrightnessDozeConfig;
179 
180     // The dim screen brightness.
181     private final float mScreenBrightnessDimConfig;
182 
183     // The minimum allowed brightness.
184     private final float mScreenBrightnessRangeMinimum;
185 
186     // The maximum allowed brightness.
187     private final float mScreenBrightnessRangeMaximum;
188 
189     private final float mScreenBrightnessDefault;
190 
191     // The minimum allowed brightness while in VR.
192     private final float mScreenBrightnessForVrRangeMinimum;
193 
194     // The maximum allowed brightness while in VR.
195     private final float mScreenBrightnessForVrRangeMaximum;
196 
197     // The default screen brightness for VR.
198     private final float mScreenBrightnessForVrDefault;
199 
200     // True if auto-brightness should be used.
201     private boolean mUseSoftwareAutoBrightnessConfig;
202 
203     // True if should use light sensor to automatically determine doze screen brightness.
204     private final boolean mAllowAutoBrightnessWhileDozingConfig;
205 
206     // Whether or not the color fade on screen on / off is enabled.
207     private final boolean mColorFadeEnabled;
208 
209     // True if we should fade the screen while turning it off, false if we should play
210     // a stylish color fade animation instead.
211     private boolean mColorFadeFadesConfig;
212 
213     // True if we need to fake a transition to off when coming out of a doze state.
214     // Some display hardware will blank itself when coming out of doze in order to hide
215     // artifacts. For these displays we fake a transition into OFF so that policy can appropriately
216     // blank itself and begin an appropriate power on animation.
217     private boolean mDisplayBlanksAfterDozeConfig;
218 
219     // True if there are only buckets of brightness values when the display is in the doze state,
220     // rather than a full range of values. If this is true, then we'll avoid animating the screen
221     // brightness since it'd likely be multiple jarring brightness transitions instead of just one
222     // to reach the final state.
223     private boolean mBrightnessBucketsInDozeConfig;
224 
225     // The pending power request.
226     // Initially null until the first call to requestPowerState.
227     // Guarded by mLock.
228     private DisplayPowerRequest mPendingRequestLocked;
229 
230     // True if a request has been made to wait for the proximity sensor to go negative.
231     // Guarded by mLock.
232     private boolean mPendingWaitForNegativeProximityLocked;
233 
234     // True if the pending power request or wait for negative proximity flag
235     // has been changed since the last update occurred.
236     // Guarded by mLock.
237     private boolean mPendingRequestChangedLocked;
238 
239     // Set to true when the important parts of the pending power request have been applied.
240     // The important parts are mainly the screen state.  Brightness changes may occur
241     // concurrently.
242     // Guarded by mLock.
243     private boolean mDisplayReadyLocked;
244 
245     // Set to true if a power state update is required.
246     // Guarded by mLock.
247     private boolean mPendingUpdatePowerStateLocked;
248 
249     /* The following state must only be accessed by the handler thread. */
250 
251     // The currently requested power state.
252     // The power controller will progressively update its internal state to match
253     // the requested power state.  Initially null until the first update.
254     private DisplayPowerRequest mPowerRequest;
255 
256     // The current power state.
257     // Must only be accessed on the handler thread.
258     private DisplayPowerState mPowerState;
259 
260     // True if the device should wait for negative proximity sensor before
261     // waking up the screen.  This is set to false as soon as a negative
262     // proximity sensor measurement is observed or when the device is forced to
263     // go to sleep by the user.  While true, the screen remains off.
264     private boolean mWaitingForNegativeProximity;
265 
266     // The actual proximity sensor threshold value.
267     private float mProximityThreshold;
268 
269     // Set to true if the proximity sensor listener has been registered
270     // with the sensor manager.
271     private boolean mProximitySensorEnabled;
272 
273     // The debounced proximity sensor state.
274     private int mProximity = PROXIMITY_UNKNOWN;
275 
276     // The raw non-debounced proximity sensor state.
277     private int mPendingProximity = PROXIMITY_UNKNOWN;
278     private long mPendingProximityDebounceTime = -1; // -1 if fully debounced
279 
280     // True if the screen was turned off because of the proximity sensor.
281     // When the screen turns on again, we report user activity to the power manager.
282     private boolean mScreenOffBecauseOfProximity;
283 
284     // The currently active screen on unblocker.  This field is non-null whenever
285     // we are waiting for a callback to release it and unblock the screen.
286     private ScreenOnUnblocker mPendingScreenOnUnblocker;
287     private ScreenOffUnblocker mPendingScreenOffUnblocker;
288 
289     // True if we were in the process of turning off the screen.
290     // This allows us to recover more gracefully from situations where we abort
291     // turning off the screen.
292     private boolean mPendingScreenOff;
293 
294     // True if we have unfinished business and are holding a suspend blocker.
295     private boolean mUnfinishedBusiness;
296 
297     // The elapsed real time when the screen on was blocked.
298     private long mScreenOnBlockStartRealTime;
299     private long mScreenOffBlockStartRealTime;
300 
301     // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_SCREEN_* fields.
302     private int mReportedScreenStateToPolicy;
303 
304     // If the last recorded screen state was dozing or not.
305     private boolean mDozing;
306 
307     // Remembers whether certain kinds of brightness adjustments
308     // were recently applied so that we can decide how to transition.
309     private boolean mAppliedAutoBrightness;
310     private boolean mAppliedDimming;
311     private boolean mAppliedLowPower;
312     private boolean mAppliedScreenBrightnessOverride;
313     private boolean mAppliedTemporaryBrightness;
314     private boolean mAppliedTemporaryAutoBrightnessAdjustment;
315     private boolean mAppliedBrightnessBoost;
316 
317     // Reason for which the brightness was last changed. See {@link BrightnessReason} for more
318     // information.
319     // At the time of this writing, this value is changed within updatePowerState() only, which is
320     // limited to the thread used by DisplayControllerHandler.
321     private BrightnessReason mBrightnessReason = new BrightnessReason();
322     private BrightnessReason mBrightnessReasonTemp = new BrightnessReason();
323 
324     // Brightness animation ramp rates in brightness units per second
325     private final float mBrightnessRampRateSlow = 0.2352941f;
326     private final float mBrightnessRampRateFast = 0.7058823f;
327 
328 
329     // Whether or not to skip the initial brightness ramps into STATE_ON.
330     private final boolean mSkipScreenOnBrightnessRamp;
331 
332     // Display white balance components.
333     @Nullable
334     private final DisplayWhiteBalanceSettings mDisplayWhiteBalanceSettings;
335     @Nullable
336     private final DisplayWhiteBalanceController mDisplayWhiteBalanceController;
337 
338     // A record of state for skipping brightness ramps.
339     private int mSkipRampState = RAMP_STATE_SKIP_NONE;
340 
341     // The first autobrightness value set when entering RAMP_STATE_SKIP_INITIAL.
342     private float mInitialAutoBrightness;
343 
344     // The controller for the automatic brightness level.
345     private AutomaticBrightnessController mAutomaticBrightnessController;
346 
347     // The mapper between ambient lux, display backlight values, and display brightness.
348     @Nullable
349     private BrightnessMappingStrategy mBrightnessMapper;
350 
351     // The current brightness configuration.
352     @Nullable
353     private BrightnessConfiguration mBrightnessConfiguration;
354 
355     // The last brightness that was set by the user and not temporary. Set to
356     // PowerManager.BRIGHTNESS_INVALID_FLOAT when a brightness has yet to be recorded.
357     private float mLastUserSetScreenBrightness;
358 
359     // The screen brightness setting has changed but not taken effect yet. If this is different
360     // from the current screen brightness setting then this is coming from something other than us
361     // and should be considered a user interaction.
362     private float mPendingScreenBrightnessSetting;
363 
364     // The last observed screen brightness setting, either set by us or by the settings app on
365     // behalf of the user.
366     private float mCurrentScreenBrightnessSetting;
367 
368     // The temporary screen brightness. Typically set when a user is interacting with the
369     // brightness slider but hasn't settled on a choice yet. Set to
370     // PowerManager.BRIGHNTESS_INVALID_FLOAT when there's no temporary brightness set.
371     private float mTemporaryScreenBrightness;
372 
373     // The current screen brightness while in VR mode.
374     private float mScreenBrightnessForVr;
375 
376     // The last auto brightness adjustment that was set by the user and not temporary. Set to
377     // Float.NaN when an auto-brightness adjustment hasn't been recorded yet.
378     private float mAutoBrightnessAdjustment;
379 
380     // The pending auto brightness adjustment that will take effect on the next power state update.
381     private float mPendingAutoBrightnessAdjustment;
382 
383     // The temporary auto brightness adjustment. Typically set when a user is interacting with the
384     // adjustment slider but hasn't settled on a choice yet. Set to
385     // PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary adjustment set.
386     private float mTemporaryAutoBrightnessAdjustment;
387 
388     // Animators.
389     private ObjectAnimator mColorFadeOnAnimator;
390     private ObjectAnimator mColorFadeOffAnimator;
391     private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
392 
393     // The brightness synchronizer to allow changes in the int brightness value to be reflected in
394     // the float brightness value and vice versa.
395     @Nullable
396     private final BrightnessSynchronizer mBrightnessSynchronizer;
397 
398     /**
399      * Creates the display power controller.
400      */
DisplayPowerController(Context context, DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager, DisplayBlanker blanker, DisplayDevice displayDevice)401     public DisplayPowerController(Context context,
402             DisplayPowerCallbacks callbacks, Handler handler,
403             SensorManager sensorManager, DisplayBlanker blanker, DisplayDevice displayDevice) {
404         mHandler = new DisplayControllerHandler(handler.getLooper());
405         mBrightnessTracker = new BrightnessTracker(context, null);
406         mSettingsObserver = new SettingsObserver(mHandler);
407         mCallbacks = callbacks;
408         mBatteryStats = BatteryStatsService.getService();
409         mSensorManager = sensorManager;
410         mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
411         mBlanker = blanker;
412         mContext = context;
413         mBrightnessSynchronizer = new BrightnessSynchronizer(context);
414         mDisplayDevice = displayDevice;
415 
416         PowerManager pm =  context.getSystemService(PowerManager.class);
417         DisplayDeviceConfig displayDeviceConfig = mDisplayDevice.getDisplayDeviceConfig();
418 
419         final Resources resources = context.getResources();
420 
421         final float screenBrightnessSettingMinimumFloat = clampAbsoluteBrightness(
422                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM));
423 
424         // DOZE AND DIM SETTINGS
425         mScreenBrightnessDozeConfig = clampAbsoluteBrightness(
426                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DOZE));
427         mScreenBrightnessDimConfig = clampAbsoluteBrightness(
428                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DIM));
429 
430         // NORMAL SCREEN SETTINGS
431         mScreenBrightnessRangeMinimum =
432                 Math.min(screenBrightnessSettingMinimumFloat, mScreenBrightnessDimConfig);
433         mScreenBrightnessRangeMaximum = clampAbsoluteBrightness(
434                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM));
435         mScreenBrightnessDefault = clampAbsoluteBrightness(
436                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT));
437 
438         // VR SETTINGS
439         mScreenBrightnessForVrDefault = clampAbsoluteBrightness(
440                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR));
441         mScreenBrightnessForVrRangeMaximum = clampAbsoluteBrightness(
442                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR));
443         mScreenBrightnessForVrRangeMinimum = clampAbsoluteBrightness(
444                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR));
445 
446         mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
447                 com.android.internal.R.bool.config_automatic_brightness_available);
448 
449         mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
450                 com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
451 
452         mSkipScreenOnBrightnessRamp = resources.getBoolean(
453                 com.android.internal.R.bool.config_skipScreenOnBrightnessRamp);
454 
455         if (mUseSoftwareAutoBrightnessConfig) {
456             final float dozeScaleFactor = resources.getFraction(
457                     com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
458                     1, 1);
459 
460             int[] ambientBrighteningThresholds = resources.getIntArray(
461                     com.android.internal.R.array.config_ambientBrighteningThresholds);
462             int[] ambientDarkeningThresholds = resources.getIntArray(
463                     com.android.internal.R.array.config_ambientDarkeningThresholds);
464             int[] ambientThresholdLevels = resources.getIntArray(
465                     com.android.internal.R.array.config_ambientThresholdLevels);
466             HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels(
467                     ambientBrighteningThresholds, ambientDarkeningThresholds,
468                     ambientThresholdLevels);
469 
470             int[] screenBrighteningThresholds = resources.getIntArray(
471                     com.android.internal.R.array.config_screenBrighteningThresholds);
472             int[] screenDarkeningThresholds = resources.getIntArray(
473                     com.android.internal.R.array.config_screenDarkeningThresholds);
474             int[] screenThresholdLevels = resources.getIntArray(
475                     com.android.internal.R.array.config_screenThresholdLevels);
476             HysteresisLevels screenBrightnessThresholds = new HysteresisLevels(
477                     screenBrighteningThresholds, screenDarkeningThresholds, screenThresholdLevels);
478 
479             long brighteningLightDebounce = resources.getInteger(
480                     com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);
481             long darkeningLightDebounce = resources.getInteger(
482                     com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce);
483             boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean(
484                     com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
485 
486             int lightSensorWarmUpTimeConfig = resources.getInteger(
487                     com.android.internal.R.integer.config_lightSensorWarmupTime);
488             int lightSensorRate = resources.getInteger(
489                     com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
490             int initialLightSensorRate = resources.getInteger(
491                     com.android.internal.R.integer.config_autoBrightnessInitialLightSensorRate);
492             if (initialLightSensorRate == -1) {
493                 initialLightSensorRate = lightSensorRate;
494             } else if (initialLightSensorRate > lightSensorRate) {
495                 Slog.w(TAG, "Expected config_autoBrightnessInitialLightSensorRate ("
496                         + initialLightSensorRate + ") to be less than or equal to "
497                         + "config_autoBrightnessLightSensorRate (" + lightSensorRate + ").");
498             }
499 
500             String lightSensorType = resources.getString(
501                     com.android.internal.R.string.config_displayLightSensorType);
502             Sensor lightSensor = findDisplayLightSensor(lightSensorType);
503 
504             mBrightnessMapper = BrightnessMappingStrategy.create(resources);
505             if (mBrightnessMapper != null) {
506                 mAutomaticBrightnessController = new AutomaticBrightnessController(this,
507                         handler.getLooper(), sensorManager, lightSensor, mBrightnessMapper,
508                         lightSensorWarmUpTimeConfig, mScreenBrightnessRangeMinimum,
509                         mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
510                         initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
511                         autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
512                         screenBrightnessThresholds, context, displayDeviceConfig);
513             } else {
514                 mUseSoftwareAutoBrightnessConfig = false;
515             }
516         }
517 
518         mColorFadeEnabled = !ActivityManager.isLowRamDeviceStatic();
519         mColorFadeFadesConfig = resources.getBoolean(
520                 com.android.internal.R.bool.config_animateScreenLights);
521 
522         mDisplayBlanksAfterDozeConfig = resources.getBoolean(
523                 com.android.internal.R.bool.config_displayBlanksAfterDoze);
524 
525         mBrightnessBucketsInDozeConfig = resources.getBoolean(
526                 com.android.internal.R.bool.config_displayBrightnessBucketsInDoze);
527 
528         if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
529             mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
530             if (mProximitySensor != null) {
531                 mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
532                         TYPICAL_PROXIMITY_THRESHOLD);
533             }
534         }
535         mCurrentScreenBrightnessSetting = getScreenBrightnessSetting();
536         mScreenBrightnessForVr = getScreenBrightnessForVrSetting();
537         mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
538         mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
539         mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
540         mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
541         mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
542 
543         DisplayWhiteBalanceSettings displayWhiteBalanceSettings = null;
544         DisplayWhiteBalanceController displayWhiteBalanceController = null;
545         try {
546             displayWhiteBalanceSettings = new DisplayWhiteBalanceSettings(mContext, mHandler);
547             displayWhiteBalanceController = DisplayWhiteBalanceFactory.create(mHandler,
548                     mSensorManager, resources);
549             displayWhiteBalanceSettings.setCallbacks(this);
550             displayWhiteBalanceController.setCallbacks(this);
551         } catch (Exception e) {
552             Slog.e(TAG, "failed to set up display white-balance: " + e);
553         }
554         mDisplayWhiteBalanceSettings = displayWhiteBalanceSettings;
555         mDisplayWhiteBalanceController = displayWhiteBalanceController;
556     }
557 
findDisplayLightSensor(String sensorType)558     private Sensor findDisplayLightSensor(String sensorType) {
559         if (!TextUtils.isEmpty(sensorType)) {
560             List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
561             for (int i = 0; i < sensors.size(); i++) {
562                 Sensor sensor = sensors.get(i);
563                 if (sensorType.equals(sensor.getStringType())) {
564                     return sensor;
565                 }
566             }
567         }
568         return mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
569     }
570 
571     /**
572      * Returns true if the proximity sensor screen-off function is available.
573      */
isProximitySensorAvailable()574     public boolean isProximitySensorAvailable() {
575         return mProximitySensor != null;
576     }
577 
578     /**
579      * Get the {@link BrightnessChangeEvent}s for the specified user.
580      * @param userId userId to fetch data for
581      * @param includePackage if false will null out the package name in events
582      */
getBrightnessEvents( @serIdInt int userId, boolean includePackage)583     public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(
584             @UserIdInt int userId, boolean includePackage) {
585         return mBrightnessTracker.getEvents(userId, includePackage);
586     }
587 
onSwitchUser(@serIdInt int newUserId)588     public void onSwitchUser(@UserIdInt int newUserId) {
589         handleSettingsChange(true /* userSwitch */);
590         mBrightnessTracker.onSwitchUser(newUserId);
591     }
592 
getAmbientBrightnessStats( @serIdInt int userId)593     public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(
594             @UserIdInt int userId) {
595         return mBrightnessTracker.getAmbientBrightnessStats(userId);
596     }
597 
598     /**
599      * Persist the brightness slider events and ambient brightness stats to disk.
600      */
persistBrightnessTrackerState()601     public void persistBrightnessTrackerState() {
602         mBrightnessTracker.persistBrightnessTrackerState();
603     }
604 
605     /**
606      * Requests a new power state.
607      * The controller makes a copy of the provided object and then
608      * begins adjusting the power state to match what was requested.
609      *
610      * @param request The requested power state.
611      * @param waitForNegativeProximity If true, issues a request to wait for
612      * negative proximity before turning the screen back on, assuming the screen
613      * was turned off by the proximity sensor.
614      * @return True if display is ready, false if there are important changes that must
615      * be made asynchronously (such as turning the screen on), in which case the caller
616      * should grab a wake lock, watch for {@link DisplayPowerCallbacks#onStateChanged()}
617      * then try the request again later until the state converges.
618      */
requestPowerState(DisplayPowerRequest request, boolean waitForNegativeProximity)619     public boolean requestPowerState(DisplayPowerRequest request,
620             boolean waitForNegativeProximity) {
621         if (DEBUG) {
622             Slog.d(TAG, "requestPowerState: "
623                     + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
624         }
625 
626         synchronized (mLock) {
627             boolean changed = false;
628 
629             if (waitForNegativeProximity
630                     && !mPendingWaitForNegativeProximityLocked) {
631                 mPendingWaitForNegativeProximityLocked = true;
632                 changed = true;
633             }
634 
635             if (mPendingRequestLocked == null) {
636                 mPendingRequestLocked = new DisplayPowerRequest(request);
637                 changed = true;
638             } else if (!mPendingRequestLocked.equals(request)) {
639                 mPendingRequestLocked.copyFrom(request);
640                 changed = true;
641             }
642 
643             if (changed) {
644                 mDisplayReadyLocked = false;
645             }
646 
647             if (changed && !mPendingRequestChangedLocked) {
648                 mPendingRequestChangedLocked = true;
649                 sendUpdatePowerStateLocked();
650             }
651 
652             return mDisplayReadyLocked;
653         }
654     }
655 
getDefaultBrightnessConfiguration()656     public BrightnessConfiguration getDefaultBrightnessConfiguration() {
657         if (mAutomaticBrightnessController == null) {
658             return null;
659         }
660         return mAutomaticBrightnessController.getDefaultConfig();
661     }
662 
sendUpdatePowerState()663     private void sendUpdatePowerState() {
664         synchronized (mLock) {
665             sendUpdatePowerStateLocked();
666         }
667     }
668 
sendUpdatePowerStateLocked()669     private void sendUpdatePowerStateLocked() {
670         if (!mPendingUpdatePowerStateLocked) {
671             mPendingUpdatePowerStateLocked = true;
672             Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
673             mHandler.sendMessage(msg);
674         }
675     }
676 
initialize()677     private void initialize() {
678         // Initialize the power state object for the default display.
679         // In the future, we might manage multiple displays independently.
680         mPowerState = new DisplayPowerState(mBlanker,
681                 mColorFadeEnabled ? new ColorFade(Display.DEFAULT_DISPLAY) : null);
682 
683         if (mColorFadeEnabled) {
684             mColorFadeOnAnimator = ObjectAnimator.ofFloat(
685                     mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 0.0f, 1.0f);
686             mColorFadeOnAnimator.setDuration(COLOR_FADE_ON_ANIMATION_DURATION_MILLIS);
687             mColorFadeOnAnimator.addListener(mAnimatorListener);
688 
689             mColorFadeOffAnimator = ObjectAnimator.ofFloat(
690                     mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 1.0f, 0.0f);
691             mColorFadeOffAnimator.setDuration(COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS);
692             mColorFadeOffAnimator.addListener(mAnimatorListener);
693         }
694 
695         mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
696                 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS_FLOAT);
697         mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
698 
699         // Initialize screen state for battery stats.
700         try {
701             mBatteryStats.noteScreenState(mPowerState.getScreenState());
702             mBatteryStats.noteScreenBrightness(BrightnessSynchronizer.brightnessFloatToInt(mContext,
703                     mPowerState.getScreenBrightness()));
704         } catch (RemoteException ex) {
705             // same process
706         }
707         // Initialize all of the brightness tracking state
708         final float brightness = convertToNits(BrightnessSynchronizer.brightnessFloatToInt(mContext,
709                 mPowerState.getScreenBrightness()));
710         if (brightness >= 0.0f) {
711             mBrightnessTracker.start(brightness);
712         }
713         mContext.getContentResolver().registerContentObserver(
714                 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FLOAT),
715                 false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
716         mContext.getContentResolver().registerContentObserver(
717                 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT),
718                 false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
719         mContext.getContentResolver().registerContentObserver(
720                 Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
721                 false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
722     }
723 
724     private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
725         @Override
726         public void onAnimationStart(Animator animation) {
727         }
728         @Override
729         public void onAnimationEnd(Animator animation) {
730             sendUpdatePowerState();
731         }
732         @Override
733         public void onAnimationRepeat(Animator animation) {
734         }
735         @Override
736         public void onAnimationCancel(Animator animation) {
737         }
738     };
739 
740     private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
741         @Override
742         public void onAnimationEnd() {
743             sendUpdatePowerState();
744         }
745     };
746 
updatePowerState()747     private void updatePowerState() {
748         // Update the power state request.
749         final boolean mustNotify;
750         final int previousPolicy;
751         boolean mustInitialize = false;
752         int brightnessAdjustmentFlags = 0;
753         mBrightnessReasonTemp.set(null);
754 
755         synchronized (mLock) {
756             mPendingUpdatePowerStateLocked = false;
757             if (mPendingRequestLocked == null) {
758                 return; // wait until first actual power request
759             }
760 
761             if (mPowerRequest == null) {
762                 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
763                 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
764                 mPendingWaitForNegativeProximityLocked = false;
765                 mPendingRequestChangedLocked = false;
766                 mustInitialize = true;
767                 // Assume we're on and bright until told otherwise, since that's the state we turn
768                 // on in.
769                 previousPolicy = DisplayPowerRequest.POLICY_BRIGHT;
770             } else if (mPendingRequestChangedLocked) {
771                 previousPolicy = mPowerRequest.policy;
772                 mPowerRequest.copyFrom(mPendingRequestLocked);
773                 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
774                 mPendingWaitForNegativeProximityLocked = false;
775                 mPendingRequestChangedLocked = false;
776                 mDisplayReadyLocked = false;
777             } else {
778                 previousPolicy = mPowerRequest.policy;
779             }
780 
781             mustNotify = !mDisplayReadyLocked;
782         }
783 
784         // Initialize things the first time the power state is changed.
785         if (mustInitialize) {
786             initialize();
787         }
788 
789         // Compute the basic display state using the policy.
790         // We might override this below based on other factors.
791         // Initialise brightness as invalid.
792         int state;
793         float brightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
794         boolean performScreenOffTransition = false;
795         switch (mPowerRequest.policy) {
796             case DisplayPowerRequest.POLICY_OFF:
797                 state = Display.STATE_OFF;
798                 performScreenOffTransition = true;
799                 break;
800             case DisplayPowerRequest.POLICY_DOZE:
801                 if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
802                     state = mPowerRequest.dozeScreenState;
803                 } else {
804                     state = Display.STATE_DOZE;
805                 }
806                 if (!mAllowAutoBrightnessWhileDozingConfig) {
807                     brightnessState = mPowerRequest.dozeScreenBrightness;
808                     mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE);
809                 }
810                 break;
811             case DisplayPowerRequest.POLICY_VR:
812                 state = Display.STATE_VR;
813                 break;
814             case DisplayPowerRequest.POLICY_DIM:
815             case DisplayPowerRequest.POLICY_BRIGHT:
816             default:
817                 state = Display.STATE_ON;
818                 break;
819         }
820         assert(state != Display.STATE_UNKNOWN);
821 
822         // Apply the proximity sensor.
823         if (mProximitySensor != null) {
824             if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
825                 setProximitySensorEnabled(true);
826                 if (!mScreenOffBecauseOfProximity
827                         && mProximity == PROXIMITY_POSITIVE) {
828                     mScreenOffBecauseOfProximity = true;
829                     sendOnProximityPositiveWithWakelock();
830                 }
831             } else if (mWaitingForNegativeProximity
832                     && mScreenOffBecauseOfProximity
833                     && mProximity == PROXIMITY_POSITIVE
834                     && state != Display.STATE_OFF) {
835                 setProximitySensorEnabled(true);
836             } else {
837                 setProximitySensorEnabled(false);
838                 mWaitingForNegativeProximity = false;
839             }
840             if (mScreenOffBecauseOfProximity
841                     && mProximity != PROXIMITY_POSITIVE) {
842                 mScreenOffBecauseOfProximity = false;
843                 sendOnProximityNegativeWithWakelock();
844             }
845         } else {
846             mWaitingForNegativeProximity = false;
847         }
848         if (mScreenOffBecauseOfProximity) {
849             state = Display.STATE_OFF;
850         }
851 
852         // Animate the screen state change unless already animating.
853         // The transition may be deferred, so after this point we will use the
854         // actual state instead of the desired one.
855         final int oldState = mPowerState.getScreenState();
856         animateScreenStateChange(state, performScreenOffTransition);
857         state = mPowerState.getScreenState();
858 
859         if (state == Display.STATE_OFF) {
860             brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
861             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_SCREEN_OFF);
862         }
863 
864         // Always use the VR brightness when in the VR state.
865         if (state == Display.STATE_VR) {
866             brightnessState = mScreenBrightnessForVr;
867             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_VR);
868         }
869 
870         if ((Float.isNaN(brightnessState))
871                 && isValidBrightnessValue(mPowerRequest.screenBrightnessOverride)) {
872             brightnessState = mPowerRequest.screenBrightnessOverride;
873             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_OVERRIDE);
874             mAppliedScreenBrightnessOverride = true;
875         } else {
876             mAppliedScreenBrightnessOverride = false;
877         }
878 
879         final boolean autoBrightnessEnabledInDoze =
880                 mAllowAutoBrightnessWhileDozingConfig && Display.isDozeState(state);
881         final boolean autoBrightnessEnabled = mPowerRequest.useAutoBrightness
882                     && (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
883                     && Float.isNaN(brightnessState)
884                     && mAutomaticBrightnessController != null;
885 
886         final boolean userSetBrightnessChanged = updateUserSetScreenBrightness();
887 
888         // Use the temporary screen brightness if there isn't an override, either from
889         // WindowManager or based on the display state.
890         if (isValidBrightnessValue(mTemporaryScreenBrightness)) {
891             brightnessState = mTemporaryScreenBrightness;
892             mAppliedTemporaryBrightness = true;
893             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_TEMPORARY);
894         } else {
895             mAppliedTemporaryBrightness = false;
896         }
897 
898         final boolean autoBrightnessAdjustmentChanged = updateAutoBrightnessAdjustment();
899         if (autoBrightnessAdjustmentChanged) {
900             mTemporaryAutoBrightnessAdjustment = Float.NaN;
901         }
902 
903         // Use the autobrightness adjustment override if set.
904         final float autoBrightnessAdjustment;
905         if (!Float.isNaN(mTemporaryAutoBrightnessAdjustment)) {
906             autoBrightnessAdjustment = mTemporaryAutoBrightnessAdjustment;
907             brightnessAdjustmentFlags = BrightnessReason.ADJUSTMENT_AUTO_TEMP;
908             mAppliedTemporaryAutoBrightnessAdjustment = true;
909         } else {
910             autoBrightnessAdjustment = mAutoBrightnessAdjustment;
911             brightnessAdjustmentFlags = BrightnessReason.ADJUSTMENT_AUTO;
912             mAppliedTemporaryAutoBrightnessAdjustment = false;
913         }
914         // Apply brightness boost.
915         // We do this here after deciding whether auto-brightness is enabled so that we don't
916         // disable the light sensor during this temporary state.  That way when boost ends we will
917         // be able to resume normal auto-brightness behavior without any delay.
918         if (mPowerRequest.boostScreenBrightness
919                 && brightnessState != PowerManager.BRIGHTNESS_OFF_FLOAT) {
920             brightnessState = PowerManager.BRIGHTNESS_MAX;
921             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_BOOST);
922             mAppliedBrightnessBoost = true;
923         } else {
924             mAppliedBrightnessBoost = false;
925         }
926 
927         // If the brightness is already set then it's been overridden by something other than the
928         // user, or is a temporary adjustment.
929         boolean userInitiatedChange = (Float.isNaN(brightnessState))
930                 && (autoBrightnessAdjustmentChanged || userSetBrightnessChanged);
931         boolean hadUserBrightnessPoint = false;
932         // Configure auto-brightness.
933         if (mAutomaticBrightnessController != null) {
934             hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
935             mAutomaticBrightnessController.configure(autoBrightnessEnabled,
936                     mBrightnessConfiguration,
937                     mLastUserSetScreenBrightness,
938                     userSetBrightnessChanged, autoBrightnessAdjustment,
939                     autoBrightnessAdjustmentChanged, mPowerRequest.policy);
940         }
941 
942         if (mBrightnessTracker != null) {
943             mBrightnessTracker.setBrightnessConfiguration(mBrightnessConfiguration);
944         }
945 
946         // Apply auto-brightness.
947         boolean slowChange = false;
948         if (Float.isNaN(brightnessState)) {
949             float newAutoBrightnessAdjustment = autoBrightnessAdjustment;
950             if (autoBrightnessEnabled) {
951                 brightnessState = mAutomaticBrightnessController.getAutomaticScreenBrightness();
952                 newAutoBrightnessAdjustment =
953                         mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment();
954             }
955             if (isValidBrightnessValue(brightnessState)
956                     || brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT) {
957                 // Use current auto-brightness value and slowly adjust to changes.
958                 brightnessState = clampScreenBrightness(brightnessState);
959                 if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
960                     slowChange = true; // slowly adapt to auto-brightness
961                 }
962                 // Tell the rest of the system about the new brightness. Note that we do this
963                 // before applying the low power or dim transformations so that the slider
964                 // accurately represents the full possible range, even if they range changes what
965                 // it means in absolute terms.
966                 putScreenBrightnessSetting(brightnessState);
967                 mAppliedAutoBrightness = true;
968                 mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC);
969             } else {
970                 mAppliedAutoBrightness = false;
971             }
972             if (autoBrightnessAdjustment != newAutoBrightnessAdjustment) {
973                 // If the autobrightness controller has decided to change the adjustment value
974                 // used, make sure that's reflected in settings.
975                 putAutoBrightnessAdjustmentSetting(newAutoBrightnessAdjustment);
976             } else {
977                 // Adjustment values resulted in no change
978                 brightnessAdjustmentFlags = 0;
979             }
980         } else {
981             mAppliedAutoBrightness = false;
982             brightnessAdjustmentFlags = 0;
983         }
984         // Use default brightness when dozing unless overridden.
985         if ((Float.isNaN(brightnessState))
986                 && Display.isDozeState(state)) {
987             brightnessState = mScreenBrightnessDozeConfig;
988             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
989         }
990 
991         // Apply manual brightness.
992         if (Float.isNaN(brightnessState)) {
993             brightnessState = clampScreenBrightness(mCurrentScreenBrightnessSetting);
994             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
995         }
996 
997         // Apply dimming by at least some minimum amount when user activity
998         // timeout is about to expire.
999         if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
1000             if (brightnessState > mScreenBrightnessRangeMinimum) {
1001                 brightnessState = Math.max(Math.min(brightnessState
1002                                 - SCREEN_DIM_MINIMUM_REDUCTION_FLOAT,
1003                         mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
1004                 mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);
1005             }
1006             if (!mAppliedDimming) {
1007                 slowChange = false;
1008             }
1009             mAppliedDimming = true;
1010         } else if (mAppliedDimming) {
1011             slowChange = false;
1012             mAppliedDimming = false;
1013         }
1014         // If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
1015         // as long as it is above the minimum threshold.
1016         if (mPowerRequest.lowPowerMode) {
1017             if (brightnessState > mScreenBrightnessRangeMinimum) {
1018                 final float brightnessFactor =
1019                         Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
1020                 final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);
1021                 brightnessState = Math.max(lowPowerBrightnessFloat,
1022                         mScreenBrightnessRangeMinimum);
1023                 mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER);
1024             }
1025             if (!mAppliedLowPower) {
1026                 slowChange = false;
1027             }
1028             mAppliedLowPower = true;
1029         } else if (mAppliedLowPower) {
1030             slowChange = false;
1031             mAppliedLowPower = false;
1032         }
1033 
1034         // Animate the screen brightness when the screen is on or dozing.
1035         // Skip the animation when the screen is off or suspended or transition to/from VR.
1036         if (!mPendingScreenOff) {
1037             if (mSkipScreenOnBrightnessRamp) {
1038                 if (state == Display.STATE_ON) {
1039                     if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
1040                         mInitialAutoBrightness = brightnessState;
1041                         mSkipRampState = RAMP_STATE_SKIP_INITIAL;
1042                     } else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL
1043                             && mUseSoftwareAutoBrightnessConfig
1044                             && !BrightnessSynchronizer.floatEquals(brightnessState,
1045                             mInitialAutoBrightness)) {
1046                         mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;
1047                     } else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {
1048                         mSkipRampState = RAMP_STATE_SKIP_NONE;
1049                     }
1050                 } else {
1051                     mSkipRampState = RAMP_STATE_SKIP_NONE;
1052                 }
1053             }
1054 
1055             final boolean wasOrWillBeInVr =
1056                     (state == Display.STATE_VR || oldState == Display.STATE_VR);
1057             final boolean initialRampSkip =
1058                     state == Display.STATE_ON && mSkipRampState != RAMP_STATE_SKIP_NONE;
1059             // While dozing, sometimes the brightness is split into buckets. Rather than animating
1060             // through the buckets, which is unlikely to be smooth in the first place, just jump
1061             // right to the suggested brightness.
1062             final boolean hasBrightnessBuckets =
1063                     Display.isDozeState(state) && mBrightnessBucketsInDozeConfig;
1064             // If the color fade is totally covering the screen then we can change the backlight
1065             // level without it being a noticeable jump since any actual content isn't yet visible.
1066             final boolean isDisplayContentVisible =
1067                     mColorFadeEnabled && mPowerState.getColorFadeLevel() == 1.0f;
1068             final boolean brightnessIsTemporary =
1069                     mAppliedTemporaryBrightness || mAppliedTemporaryAutoBrightnessAdjustment;
1070             // We only want to animate the brightness if it is between 0.0f and 1.0f.
1071             // brightnessState can contain the values -1.0f and NaN, which we do not want to
1072             // animate to. To avoid this, we check the value first.
1073             // If the brightnessState is off (-1.0f) we still want to animate to the minimum
1074             // brightness (0.0f) to accommodate for LED displays, which can appear bright to the
1075             // user even when the display is all black.
1076             float animateValue = brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT
1077                     ? PowerManager.BRIGHTNESS_MIN : brightnessState;
1078             if (isValidBrightnessValue(animateValue)) {
1079                 if (initialRampSkip || hasBrightnessBuckets
1080                         || wasOrWillBeInVr || !isDisplayContentVisible || brightnessIsTemporary) {
1081                     animateScreenBrightness(animateValue, SCREEN_ANIMATION_RATE_MINIMUM);
1082                 } else {
1083                     animateScreenBrightness(animateValue,
1084                             slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
1085                 }
1086             }
1087 
1088             if (!brightnessIsTemporary) {
1089                 if (userInitiatedChange && (mAutomaticBrightnessController == null
1090                         || !mAutomaticBrightnessController.hasValidAmbientLux())) {
1091                     // If we don't have a valid lux reading we can't report a valid
1092                     // slider event so notify as if the system changed the brightness.
1093                     userInitiatedChange = false;
1094                 }
1095                 notifyBrightnessChanged(
1096                         BrightnessSynchronizer.brightnessFloatToInt(mContext, brightnessState),
1097                         userInitiatedChange, hadUserBrightnessPoint);
1098             }
1099 
1100         }
1101 
1102         // Log any changes to what is currently driving the brightness setting.
1103         if (!mBrightnessReasonTemp.equals(mBrightnessReason) || brightnessAdjustmentFlags != 0) {
1104             Slog.v(TAG, "Brightness [" + brightnessState + "] reason changing to: '"
1105                     + mBrightnessReasonTemp.toString(brightnessAdjustmentFlags)
1106                     + "', previous reason: '" + mBrightnessReason + "'.");
1107             mBrightnessReason.set(mBrightnessReasonTemp);
1108         }
1109 
1110         // Update display white-balance.
1111         if (mDisplayWhiteBalanceController != null) {
1112             if (state == Display.STATE_ON && mDisplayWhiteBalanceSettings.isEnabled()) {
1113                 mDisplayWhiteBalanceController.setEnabled(true);
1114                 mDisplayWhiteBalanceController.updateDisplayColorTemperature();
1115             } else {
1116                 mDisplayWhiteBalanceController.setEnabled(false);
1117             }
1118         }
1119 
1120         // Determine whether the display is ready for use in the newly requested state.
1121         // Note that we do not wait for the brightness ramp animation to complete before
1122         // reporting the display is ready because we only need to ensure the screen is in the
1123         // right power state even as it continues to converge on the desired brightness.
1124         final boolean ready = mPendingScreenOnUnblocker == null &&
1125                 (!mColorFadeEnabled ||
1126                         (!mColorFadeOnAnimator.isStarted() && !mColorFadeOffAnimator.isStarted()))
1127                 && mPowerState.waitUntilClean(mCleanListener);
1128         final boolean finished = ready
1129                 && !mScreenBrightnessRampAnimator.isAnimating();
1130 
1131         // Notify policy about screen turned on.
1132         if (ready && state != Display.STATE_OFF
1133                 && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
1134             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_ON);
1135             mWindowManagerPolicy.screenTurnedOn();
1136         }
1137 
1138         // Grab a wake lock if we have unfinished business.
1139         if (!finished && !mUnfinishedBusiness) {
1140             if (DEBUG) {
1141                 Slog.d(TAG, "Unfinished business...");
1142             }
1143             mCallbacks.acquireSuspendBlocker();
1144             mUnfinishedBusiness = true;
1145         }
1146 
1147         // Notify the power manager when ready.
1148         if (ready && mustNotify) {
1149             // Send state change.
1150             synchronized (mLock) {
1151                 if (!mPendingRequestChangedLocked) {
1152                     mDisplayReadyLocked = true;
1153 
1154                     if (DEBUG) {
1155                         Slog.d(TAG, "Display ready!");
1156                     }
1157                 }
1158             }
1159             sendOnStateChangedWithWakelock();
1160         }
1161 
1162         // Release the wake lock when we have no unfinished business.
1163         if (finished && mUnfinishedBusiness) {
1164             if (DEBUG) {
1165                 Slog.d(TAG, "Finished business...");
1166             }
1167             mUnfinishedBusiness = false;
1168             mCallbacks.releaseSuspendBlocker();
1169         }
1170 
1171         // Record if dozing for future comparison.
1172         mDozing = state != Display.STATE_ON;
1173 
1174         if (previousPolicy != mPowerRequest.policy) {
1175             logDisplayPolicyChanged(mPowerRequest.policy);
1176         }
1177     }
1178 
1179     @Override
updateBrightness()1180     public void updateBrightness() {
1181         sendUpdatePowerState();
1182     }
1183 
setBrightnessConfiguration(BrightnessConfiguration c)1184     public void setBrightnessConfiguration(BrightnessConfiguration c) {
1185         Message msg = mHandler.obtainMessage(MSG_CONFIGURE_BRIGHTNESS, c);
1186         msg.sendToTarget();
1187     }
1188 
setTemporaryBrightness(float brightness)1189     public void setTemporaryBrightness(float brightness) {
1190         Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_BRIGHTNESS,
1191                 Float.floatToIntBits(brightness), 0 /*unused*/);
1192         msg.sendToTarget();
1193     }
1194 
setTemporaryAutoBrightnessAdjustment(float adjustment)1195     public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
1196         Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT,
1197                 Float.floatToIntBits(adjustment), 0 /*unused*/);
1198         msg.sendToTarget();
1199     }
1200 
blockScreenOn()1201     private void blockScreenOn() {
1202         if (mPendingScreenOnUnblocker == null) {
1203             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
1204             mPendingScreenOnUnblocker = new ScreenOnUnblocker();
1205             mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
1206             Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
1207         }
1208     }
1209 
unblockScreenOn()1210     private void unblockScreenOn() {
1211         if (mPendingScreenOnUnblocker != null) {
1212             mPendingScreenOnUnblocker = null;
1213             long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
1214             Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
1215             Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
1216         }
1217     }
1218 
blockScreenOff()1219     private void blockScreenOff() {
1220         if (mPendingScreenOffUnblocker == null) {
1221             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_OFF_BLOCKED_TRACE_NAME, 0);
1222             mPendingScreenOffUnblocker = new ScreenOffUnblocker();
1223             mScreenOffBlockStartRealTime = SystemClock.elapsedRealtime();
1224             Slog.i(TAG, "Blocking screen off");
1225         }
1226     }
1227 
unblockScreenOff()1228     private void unblockScreenOff() {
1229         if (mPendingScreenOffUnblocker != null) {
1230             mPendingScreenOffUnblocker = null;
1231             long delay = SystemClock.elapsedRealtime() - mScreenOffBlockStartRealTime;
1232             Slog.i(TAG, "Unblocked screen off after " + delay + " ms");
1233             Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_OFF_BLOCKED_TRACE_NAME, 0);
1234         }
1235     }
1236 
setScreenState(int state)1237     private boolean setScreenState(int state) {
1238         return setScreenState(state, false /*reportOnly*/);
1239     }
1240 
setScreenState(int state, boolean reportOnly)1241     private boolean setScreenState(int state, boolean reportOnly) {
1242         final boolean isOff = (state == Display.STATE_OFF);
1243         if (mPowerState.getScreenState() != state) {
1244 
1245             // If we are trying to turn screen off, give policy a chance to do something before we
1246             // actually turn the screen off.
1247             if (isOff && !mScreenOffBecauseOfProximity) {
1248                 if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON) {
1249                     setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);
1250                     blockScreenOff();
1251                     mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker);
1252                     unblockScreenOff();
1253                 } else if (mPendingScreenOffUnblocker != null) {
1254                     // Abort doing the state change until screen off is unblocked.
1255                     return false;
1256                 }
1257             }
1258 
1259             if (!reportOnly) {
1260                 Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);
1261                 // TODO(b/153319140) remove when we can get this from the above trace invocation
1262                 SystemProperties.set("debug.tracing.screen_state", String.valueOf(state));
1263                 mPowerState.setScreenState(state);
1264                 // Tell battery stats about the transition.
1265                 try {
1266                     mBatteryStats.noteScreenState(state);
1267                 } catch (RemoteException ex) {
1268                     // same process
1269                 }
1270             }
1271         }
1272 
1273         // Tell the window manager policy when the screen is turned off or on unless it's due
1274         // to the proximity sensor.  We temporarily block turning the screen on until the
1275         // window manager is ready by leaving a black surface covering the screen.
1276         // This surface is essentially the final state of the color fade animation and
1277         // it is only removed once the window manager tells us that the activity has
1278         // finished drawing underneath.
1279         if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
1280                 && !mScreenOffBecauseOfProximity) {
1281             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
1282             unblockScreenOn();
1283             mWindowManagerPolicy.screenTurnedOff();
1284         } else if (!isOff
1285                 && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_OFF) {
1286 
1287             // We told policy already that screen was turning off, but now we changed our minds.
1288             // Complete the full state transition on -> turningOff -> off.
1289             unblockScreenOff();
1290             mWindowManagerPolicy.screenTurnedOff();
1291             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
1292         }
1293         if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
1294             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
1295             if (mPowerState.getColorFadeLevel() == 0.0f) {
1296                 blockScreenOn();
1297             } else {
1298                 unblockScreenOn();
1299             }
1300             mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
1301         }
1302 
1303         // Return true if the screen isn't blocked.
1304         return mPendingScreenOnUnblocker == null;
1305     }
1306 
setReportedScreenState(int state)1307     private void setReportedScreenState(int state) {
1308         Trace.traceCounter(Trace.TRACE_TAG_POWER, "ReportedScreenStateToPolicy", state);
1309         mReportedScreenStateToPolicy = state;
1310     }
1311 
clampScreenBrightnessForVr(float value)1312     private float clampScreenBrightnessForVr(float value) {
1313         return MathUtils.constrain(
1314                 value, mScreenBrightnessForVrRangeMinimum,
1315                 mScreenBrightnessForVrRangeMaximum);
1316     }
1317 
clampScreenBrightness(float value)1318     private float clampScreenBrightness(float value) {
1319         if (Float.isNaN(value)) {
1320             return mScreenBrightnessRangeMinimum;
1321         }
1322         return MathUtils.constrain(
1323                 value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
1324     }
1325 
1326     // Checks whether the brightness is within the valid brightness range, not including the off or
1327     // invalid states.
isValidBrightnessValue(float brightnessState)1328     private boolean isValidBrightnessValue(float brightnessState) {
1329         return brightnessState >= mScreenBrightnessRangeMinimum
1330                 && brightnessState <= mScreenBrightnessRangeMaximum;
1331     }
1332 
animateScreenBrightness(float target, float rate)1333     private void animateScreenBrightness(float target, float rate) {
1334         if (DEBUG) {
1335             Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
1336         }
1337         if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
1338             Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", (int) target);
1339             // TODO(b/153319140) remove when we can get this from the above trace invocation
1340             SystemProperties.set("debug.tracing.screen_brightness", String.valueOf(target));
1341             try {
1342                 // TODO(brightnessfloat): change BatteryStats to use float
1343                 mBatteryStats.noteScreenBrightness(
1344                         BrightnessSynchronizer.brightnessFloatToInt(
1345                         mContext, target));
1346             } catch (RemoteException ex) {
1347                 // same process
1348             }
1349         }
1350     }
1351 
animateScreenStateChange(int target, boolean performScreenOffTransition)1352     private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
1353         // If there is already an animation in progress, don't interfere with it.
1354         if (mColorFadeEnabled &&
1355                 (mColorFadeOnAnimator.isStarted() || mColorFadeOffAnimator.isStarted())) {
1356             if (target != Display.STATE_ON) {
1357                 return;
1358             }
1359             // If display state changed to on, proceed and stop the color fade and turn screen on.
1360             mPendingScreenOff = false;
1361         }
1362 
1363         if (mDisplayBlanksAfterDozeConfig
1364                 && Display.isDozeState(mPowerState.getScreenState())
1365                 && !Display.isDozeState(target)) {
1366             // Skip the screen off animation and add a black surface to hide the
1367             // contents of the screen.
1368             mPowerState.prepareColorFade(mContext,
1369                     mColorFadeFadesConfig ? ColorFade.MODE_FADE : ColorFade.MODE_WARM_UP);
1370             if (mColorFadeOffAnimator != null) {
1371                 mColorFadeOffAnimator.end();
1372             }
1373             // Some display hardware will blank itself on the transition between doze and non-doze
1374             // but still on display states. In this case we want to report to policy that the
1375             // display has turned off so it can prepare the appropriate power on animation, but we
1376             // don't want to actually transition to the fully off state since that takes
1377             // significantly longer to transition from.
1378             setScreenState(Display.STATE_OFF, target != Display.STATE_OFF /*reportOnly*/);
1379         }
1380 
1381         // If we were in the process of turning off the screen but didn't quite
1382         // finish.  Then finish up now to prevent a jarring transition back
1383         // to screen on if we skipped blocking screen on as usual.
1384         if (mPendingScreenOff && target != Display.STATE_OFF) {
1385             setScreenState(Display.STATE_OFF);
1386             mPendingScreenOff = false;
1387             mPowerState.dismissColorFadeResources();
1388         }
1389 
1390         if (target == Display.STATE_ON) {
1391             // Want screen on.  The contents of the screen may not yet
1392             // be visible if the color fade has not been dismissed because
1393             // its last frame of animation is solid black.
1394             if (!setScreenState(Display.STATE_ON)) {
1395                 return; // screen on blocked
1396             }
1397             if (USE_COLOR_FADE_ON_ANIMATION && mColorFadeEnabled && mPowerRequest.isBrightOrDim()) {
1398                 // Perform screen on animation.
1399                 if (mPowerState.getColorFadeLevel() == 1.0f) {
1400                     mPowerState.dismissColorFade();
1401                 } else if (mPowerState.prepareColorFade(mContext,
1402                         mColorFadeFadesConfig ?
1403                                 ColorFade.MODE_FADE :
1404                                         ColorFade.MODE_WARM_UP)) {
1405                     mColorFadeOnAnimator.start();
1406                 } else {
1407                     mColorFadeOnAnimator.end();
1408                 }
1409             } else {
1410                 // Skip screen on animation.
1411                 mPowerState.setColorFadeLevel(1.0f);
1412                 mPowerState.dismissColorFade();
1413             }
1414         } else if (target == Display.STATE_VR) {
1415             // Wait for brightness animation to complete beforehand when entering VR
1416             // from screen on to prevent a perceptible jump because brightness may operate
1417             // differently when the display is configured for dozing.
1418             if (mScreenBrightnessRampAnimator.isAnimating()
1419                     && mPowerState.getScreenState() == Display.STATE_ON) {
1420                 return;
1421             }
1422 
1423             // Set screen state.
1424             if (!setScreenState(Display.STATE_VR)) {
1425                 return; // screen on blocked
1426             }
1427 
1428             // Dismiss the black surface without fanfare.
1429             mPowerState.setColorFadeLevel(1.0f);
1430             mPowerState.dismissColorFade();
1431         } else if (target == Display.STATE_DOZE) {
1432             // Want screen dozing.
1433             // Wait for brightness animation to complete beforehand when entering doze
1434             // from screen on to prevent a perceptible jump because brightness may operate
1435             // differently when the display is configured for dozing.
1436             if (mScreenBrightnessRampAnimator.isAnimating()
1437                     && mPowerState.getScreenState() == Display.STATE_ON) {
1438                 return;
1439             }
1440 
1441             // Set screen state.
1442             if (!setScreenState(Display.STATE_DOZE)) {
1443                 return; // screen on blocked
1444             }
1445 
1446             // Dismiss the black surface without fanfare.
1447             mPowerState.setColorFadeLevel(1.0f);
1448             mPowerState.dismissColorFade();
1449         } else if (target == Display.STATE_DOZE_SUSPEND) {
1450             // Want screen dozing and suspended.
1451             // Wait for brightness animation to complete beforehand unless already
1452             // suspended because we may not be able to change it after suspension.
1453             if (mScreenBrightnessRampAnimator.isAnimating()
1454                     && mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
1455                 return;
1456             }
1457 
1458             // If not already suspending, temporarily set the state to doze until the
1459             // screen on is unblocked, then suspend.
1460             if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
1461                 if (!setScreenState(Display.STATE_DOZE)) {
1462                     return; // screen on blocked
1463                 }
1464                 setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
1465             }
1466 
1467             // Dismiss the black surface without fanfare.
1468             mPowerState.setColorFadeLevel(1.0f);
1469             mPowerState.dismissColorFade();
1470         } else if (target == Display.STATE_ON_SUSPEND) {
1471             // Want screen full-power and suspended.
1472             // Wait for brightness animation to complete beforehand unless already
1473             // suspended because we may not be able to change it after suspension.
1474             if (mScreenBrightnessRampAnimator.isAnimating()
1475                     && mPowerState.getScreenState() != Display.STATE_ON_SUSPEND) {
1476                 return;
1477             }
1478 
1479             // If not already suspending, temporarily set the state to on until the
1480             // screen on is unblocked, then suspend.
1481             if (mPowerState.getScreenState() != Display.STATE_ON_SUSPEND) {
1482                 if (!setScreenState(Display.STATE_ON)) {
1483                     return;
1484                 }
1485                 setScreenState(Display.STATE_ON_SUSPEND);
1486             }
1487 
1488             // Dismiss the black surface without fanfare.
1489             mPowerState.setColorFadeLevel(1.0f);
1490             mPowerState.dismissColorFade();
1491         } else {
1492             // Want screen off.
1493             mPendingScreenOff = true;
1494             if (!mColorFadeEnabled) {
1495                 mPowerState.setColorFadeLevel(0.0f);
1496             }
1497 
1498             if (mPowerState.getColorFadeLevel() == 0.0f) {
1499                 // Turn the screen off.
1500                 // A black surface is already hiding the contents of the screen.
1501                 setScreenState(Display.STATE_OFF);
1502                 mPendingScreenOff = false;
1503                 mPowerState.dismissColorFadeResources();
1504             } else if (performScreenOffTransition
1505                     && mPowerState.prepareColorFade(mContext,
1506                             mColorFadeFadesConfig ?
1507                                     ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
1508                     && mPowerState.getScreenState() != Display.STATE_OFF) {
1509                 // Perform the screen off animation.
1510                 mColorFadeOffAnimator.start();
1511             } else {
1512                 // Skip the screen off animation and add a black surface to hide the
1513                 // contents of the screen.
1514                 mColorFadeOffAnimator.end();
1515             }
1516         }
1517     }
1518 
1519     private final Runnable mCleanListener = new Runnable() {
1520         @Override
1521         public void run() {
1522             sendUpdatePowerState();
1523         }
1524     };
1525 
setProximitySensorEnabled(boolean enable)1526     private void setProximitySensorEnabled(boolean enable) {
1527         if (enable) {
1528             if (!mProximitySensorEnabled) {
1529                 // Register the listener.
1530                 // Proximity sensor state already cleared initially.
1531                 mProximitySensorEnabled = true;
1532                 mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
1533                         SensorManager.SENSOR_DELAY_NORMAL, mHandler);
1534             }
1535         } else {
1536             if (mProximitySensorEnabled) {
1537                 // Unregister the listener.
1538                 // Clear the proximity sensor state for next time.
1539                 mProximitySensorEnabled = false;
1540                 mProximity = PROXIMITY_UNKNOWN;
1541                 mPendingProximity = PROXIMITY_UNKNOWN;
1542                 mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
1543                 mSensorManager.unregisterListener(mProximitySensorListener);
1544                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
1545             }
1546         }
1547     }
1548 
handleProximitySensorEvent(long time, boolean positive)1549     private void handleProximitySensorEvent(long time, boolean positive) {
1550         if (mProximitySensorEnabled) {
1551             if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
1552                 return; // no change
1553             }
1554             if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
1555                 return; // no change
1556             }
1557 
1558             // Only accept a proximity sensor reading if it remains
1559             // stable for the entire debounce delay.  We hold a wake lock while
1560             // debouncing the sensor.
1561             mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
1562             if (positive) {
1563                 mPendingProximity = PROXIMITY_POSITIVE;
1564                 setPendingProximityDebounceTime(
1565                         time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
1566             } else {
1567                 mPendingProximity = PROXIMITY_NEGATIVE;
1568                 setPendingProximityDebounceTime(
1569                         time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
1570             }
1571 
1572             // Debounce the new sensor reading.
1573             debounceProximitySensor();
1574         }
1575     }
1576 
debounceProximitySensor()1577     private void debounceProximitySensor() {
1578         if (mProximitySensorEnabled
1579                 && mPendingProximity != PROXIMITY_UNKNOWN
1580                 && mPendingProximityDebounceTime >= 0) {
1581             final long now = SystemClock.uptimeMillis();
1582             if (mPendingProximityDebounceTime <= now) {
1583                 // Sensor reading accepted.  Apply the change then release the wake lock.
1584                 mProximity = mPendingProximity;
1585                 updatePowerState();
1586                 clearPendingProximityDebounceTime(); // release wake lock (must be last)
1587             } else {
1588                 // Need to wait a little longer.
1589                 // Debounce again later.  We continue holding a wake lock while waiting.
1590                 Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
1591                 mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
1592             }
1593         }
1594     }
1595 
clearPendingProximityDebounceTime()1596     private void clearPendingProximityDebounceTime() {
1597         if (mPendingProximityDebounceTime >= 0) {
1598             mPendingProximityDebounceTime = -1;
1599             mCallbacks.releaseSuspendBlocker(); // release wake lock
1600         }
1601     }
1602 
setPendingProximityDebounceTime(long debounceTime)1603     private void setPendingProximityDebounceTime(long debounceTime) {
1604         if (mPendingProximityDebounceTime < 0) {
1605             mCallbacks.acquireSuspendBlocker(); // acquire wake lock
1606         }
1607         mPendingProximityDebounceTime = debounceTime;
1608     }
1609 
sendOnStateChangedWithWakelock()1610     private void sendOnStateChangedWithWakelock() {
1611         mCallbacks.acquireSuspendBlocker();
1612         mHandler.post(mOnStateChangedRunnable);
1613     }
1614 
logDisplayPolicyChanged(int newPolicy)1615     private void logDisplayPolicyChanged(int newPolicy) {
1616         LogMaker log = new LogMaker(MetricsEvent.DISPLAY_POLICY);
1617         log.setType(MetricsEvent.TYPE_UPDATE);
1618         log.setSubtype(newPolicy);
1619         MetricsLogger.action(log);
1620     }
1621 
handleSettingsChange(boolean userSwitch)1622     private void handleSettingsChange(boolean userSwitch) {
1623         mPendingScreenBrightnessSetting = getScreenBrightnessSetting();
1624 
1625         if (userSwitch) {
1626             // Don't treat user switches as user initiated change.
1627             mCurrentScreenBrightnessSetting = mPendingScreenBrightnessSetting;
1628             if (mAutomaticBrightnessController != null) {
1629                 mAutomaticBrightnessController.resetShortTermModel();
1630             }
1631         }
1632         mPendingAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
1633         // We don't bother with a pending variable for VR screen brightness since we just
1634         // immediately adapt to it.
1635         mScreenBrightnessForVr = getScreenBrightnessForVrSetting();
1636         sendUpdatePowerState();
1637     }
1638 
getAutoBrightnessAdjustmentSetting()1639     private float getAutoBrightnessAdjustmentSetting() {
1640         final float adj = Settings.System.getFloatForUser(mContext.getContentResolver(),
1641                 Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f, UserHandle.USER_CURRENT);
1642         return Float.isNaN(adj) ? 0.0f : clampAutoBrightnessAdjustment(adj);
1643     }
1644 
getScreenBrightnessSetting()1645     private float getScreenBrightnessSetting() {
1646         final float brightness = Settings.System.getFloatForUser(mContext.getContentResolver(),
1647                 Settings.System.SCREEN_BRIGHTNESS_FLOAT, mScreenBrightnessDefault,
1648                 UserHandle.USER_CURRENT);
1649         return clampAbsoluteBrightness(brightness);
1650     }
1651 
getScreenBrightnessForVrSetting()1652     private float getScreenBrightnessForVrSetting() {
1653         final float brightnessFloat = Settings.System.getFloatForUser(mContext.getContentResolver(),
1654                 Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT, mScreenBrightnessForVrDefault,
1655                 UserHandle.USER_CURRENT);
1656         return clampScreenBrightnessForVr(brightnessFloat);
1657     }
1658 
putScreenBrightnessSetting(float brightnessValue)1659     private void putScreenBrightnessSetting(float brightnessValue) {
1660         mCurrentScreenBrightnessSetting = brightnessValue;
1661         Settings.System.putFloatForUser(mContext.getContentResolver(),
1662                 Settings.System.SCREEN_BRIGHTNESS_FLOAT, brightnessValue, UserHandle.USER_CURRENT);
1663     }
1664 
putAutoBrightnessAdjustmentSetting(float adjustment)1665     private void putAutoBrightnessAdjustmentSetting(float adjustment) {
1666         mAutoBrightnessAdjustment = adjustment;
1667         Settings.System.putFloatForUser(mContext.getContentResolver(),
1668                 Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adjustment, UserHandle.USER_CURRENT);
1669     }
1670 
updateAutoBrightnessAdjustment()1671     private boolean updateAutoBrightnessAdjustment() {
1672         if (Float.isNaN(mPendingAutoBrightnessAdjustment)) {
1673             return false;
1674         }
1675         if (mAutoBrightnessAdjustment == mPendingAutoBrightnessAdjustment) {
1676             mPendingAutoBrightnessAdjustment = Float.NaN;
1677             return false;
1678         }
1679         mAutoBrightnessAdjustment = mPendingAutoBrightnessAdjustment;
1680         mPendingAutoBrightnessAdjustment = Float.NaN;
1681         return true;
1682     }
1683 
updateUserSetScreenBrightness()1684     private boolean updateUserSetScreenBrightness() {
1685         if ((Float.isNaN(mPendingScreenBrightnessSetting)
1686                 || mPendingScreenBrightnessSetting < 0.0f)) {
1687             return false;
1688         }
1689         if (mCurrentScreenBrightnessSetting == mPendingScreenBrightnessSetting) {
1690             mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
1691             mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
1692             return false;
1693         }
1694         mCurrentScreenBrightnessSetting = mPendingScreenBrightnessSetting;
1695         mLastUserSetScreenBrightness = mPendingScreenBrightnessSetting;
1696         mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
1697         mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
1698         return true;
1699     }
1700 
notifyBrightnessChanged(int brightness, boolean userInitiated, boolean hadUserDataPoint)1701     private void notifyBrightnessChanged(int brightness, boolean userInitiated,
1702             boolean hadUserDataPoint) {
1703         final float brightnessInNits = convertToNits(brightness);
1704         if (mPowerRequest.useAutoBrightness && brightnessInNits >= 0.0f
1705                 && mAutomaticBrightnessController != null) {
1706             // We only want to track changes on devices that can actually map the display backlight
1707             // values into a physical brightness unit since the value provided by the API is in
1708             // nits and not using the arbitrary backlight units.
1709             final float powerFactor = mPowerRequest.lowPowerMode
1710                     ? mPowerRequest.screenLowPowerBrightnessFactor
1711                     : 1.0f;
1712             mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
1713                     powerFactor, hadUserDataPoint,
1714                     mAutomaticBrightnessController.isDefaultConfig());
1715         }
1716     }
1717 
convertToNits(int backlight)1718     private float convertToNits(int backlight) {
1719         if (mBrightnessMapper != null) {
1720             return mBrightnessMapper.convertToNits(backlight);
1721         } else {
1722             return -1.0f;
1723         }
1724     }
1725 
1726     private final Runnable mOnStateChangedRunnable = new Runnable() {
1727         @Override
1728         public void run() {
1729             mCallbacks.onStateChanged();
1730             mCallbacks.releaseSuspendBlocker();
1731         }
1732     };
1733 
sendOnProximityPositiveWithWakelock()1734     private void sendOnProximityPositiveWithWakelock() {
1735         mCallbacks.acquireSuspendBlocker();
1736         mHandler.post(mOnProximityPositiveRunnable);
1737     }
1738 
1739     private final Runnable mOnProximityPositiveRunnable = new Runnable() {
1740         @Override
1741         public void run() {
1742             mCallbacks.onProximityPositive();
1743             mCallbacks.releaseSuspendBlocker();
1744         }
1745     };
1746 
sendOnProximityNegativeWithWakelock()1747     private void sendOnProximityNegativeWithWakelock() {
1748         mCallbacks.acquireSuspendBlocker();
1749         mHandler.post(mOnProximityNegativeRunnable);
1750     }
1751 
1752     private final Runnable mOnProximityNegativeRunnable = new Runnable() {
1753         @Override
1754         public void run() {
1755             mCallbacks.onProximityNegative();
1756             mCallbacks.releaseSuspendBlocker();
1757         }
1758     };
1759 
dump(final PrintWriter pw)1760     public void dump(final PrintWriter pw) {
1761         synchronized (mLock) {
1762             pw.println();
1763             pw.println("Display Power Controller Locked State:");
1764             pw.println("  mDisplayReadyLocked=" + mDisplayReadyLocked);
1765             pw.println("  mPendingRequestLocked=" + mPendingRequestLocked);
1766             pw.println("  mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
1767             pw.println("  mPendingWaitForNegativeProximityLocked="
1768                     + mPendingWaitForNegativeProximityLocked);
1769             pw.println("  mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
1770         }
1771 
1772         pw.println();
1773         pw.println("Display Power Controller Configuration:");
1774         pw.println("  mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
1775         pw.println("  mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
1776         pw.println("  mScreenBrightnessDefault=" + mScreenBrightnessDefault);
1777         pw.println("  mScreenBrightnessForVrRangeMinimum=" + mScreenBrightnessForVrRangeMinimum);
1778         pw.println("  mScreenBrightnessForVrRangeMaximum=" + mScreenBrightnessForVrRangeMaximum);
1779         pw.println("  mScreenBrightnessForVrDefault=" + mScreenBrightnessForVrDefault);
1780         pw.println("  mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
1781         pw.println("  mAllowAutoBrightnessWhileDozingConfig=" +
1782                 mAllowAutoBrightnessWhileDozingConfig);
1783         pw.println("  mSkipScreenOnBrightnessRamp=" + mSkipScreenOnBrightnessRamp);
1784         pw.println("  mColorFadeFadesConfig=" + mColorFadeFadesConfig);
1785         pw.println("  mColorFadeEnabled=" + mColorFadeEnabled);
1786         pw.println("  mDisplayBlanksAfterDozeConfig=" + mDisplayBlanksAfterDozeConfig);
1787         pw.println("  mBrightnessBucketsInDozeConfig=" + mBrightnessBucketsInDozeConfig);
1788 
1789         mHandler.runWithScissors(new Runnable() {
1790             @Override
1791             public void run() {
1792                 dumpLocal(pw);
1793             }
1794         }, 1000);
1795     }
1796 
dumpLocal(PrintWriter pw)1797     private void dumpLocal(PrintWriter pw) {
1798         pw.println();
1799         pw.println("Display Power Controller Thread State:");
1800         pw.println("  mPowerRequest=" + mPowerRequest);
1801         pw.println("  mUnfinishedBusiness=" + mUnfinishedBusiness);
1802         pw.println("  mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
1803         pw.println("  mProximitySensor=" + mProximitySensor);
1804         pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
1805         pw.println("  mProximityThreshold=" + mProximityThreshold);
1806         pw.println("  mProximity=" + proximityToString(mProximity));
1807         pw.println("  mPendingProximity=" + proximityToString(mPendingProximity));
1808         pw.println("  mPendingProximityDebounceTime="
1809                 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
1810         pw.println("  mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
1811         pw.println("  mLastUserSetScreenBrightnessFloat=" + mLastUserSetScreenBrightness);
1812         pw.println("  mPendingScreenBrightnessSettingFloat="
1813                 + mPendingScreenBrightnessSetting);
1814         pw.println("  mTemporaryScreenBrightnessFloat=" + mTemporaryScreenBrightness);
1815         pw.println("  mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
1816         pw.println("  mBrightnessReason=" + mBrightnessReason);
1817         pw.println("  mTemporaryAutoBrightnessAdjustment=" + mTemporaryAutoBrightnessAdjustment);
1818         pw.println("  mPendingAutoBrightnessAdjustment=" + mPendingAutoBrightnessAdjustment);
1819         pw.println("  mScreenBrightnessForVrFloat=" + mScreenBrightnessForVr);
1820         pw.println("  mAppliedAutoBrightness=" + mAppliedAutoBrightness);
1821         pw.println("  mAppliedDimming=" + mAppliedDimming);
1822         pw.println("  mAppliedLowPower=" + mAppliedLowPower);
1823         pw.println("  mAppliedScreenBrightnessOverride=" + mAppliedScreenBrightnessOverride);
1824         pw.println("  mAppliedTemporaryBrightness=" + mAppliedTemporaryBrightness);
1825         pw.println("  mDozing=" + mDozing);
1826         pw.println("  mSkipRampState=" + skipRampStateToString(mSkipRampState));
1827         pw.println("  mScreenOnBlockStartRealTime=" + mScreenOnBlockStartRealTime);
1828         pw.println("  mScreenOffBlockStartRealTime=" + mScreenOffBlockStartRealTime);
1829         pw.println("  mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
1830         pw.println("  mPendingScreenOffUnblocker=" + mPendingScreenOffUnblocker);
1831         pw.println("  mPendingScreenOff=" + mPendingScreenOff);
1832         pw.println("  mReportedToPolicy=" +
1833                 reportedToPolicyToString(mReportedScreenStateToPolicy));
1834 
1835         if (mScreenBrightnessRampAnimator != null) {
1836             pw.println("  mScreenBrightnessRampAnimator.isAnimating()=" +
1837                     mScreenBrightnessRampAnimator.isAnimating());
1838         }
1839 
1840         if (mColorFadeOnAnimator != null) {
1841             pw.println("  mColorFadeOnAnimator.isStarted()=" +
1842                     mColorFadeOnAnimator.isStarted());
1843         }
1844         if (mColorFadeOffAnimator != null) {
1845             pw.println("  mColorFadeOffAnimator.isStarted()=" +
1846                     mColorFadeOffAnimator.isStarted());
1847         }
1848 
1849         if (mPowerState != null) {
1850             mPowerState.dump(pw);
1851         }
1852 
1853         if (mAutomaticBrightnessController != null) {
1854             mAutomaticBrightnessController.dump(pw);
1855         }
1856 
1857         if (mBrightnessTracker != null) {
1858             pw.println();
1859             mBrightnessTracker.dump(pw);
1860         }
1861 
1862         pw.println();
1863         if (mDisplayWhiteBalanceController != null) {
1864             mDisplayWhiteBalanceController.dump(pw);
1865             mDisplayWhiteBalanceSettings.dump(pw);
1866         }
1867     }
1868 
proximityToString(int state)1869     private static String proximityToString(int state) {
1870         switch (state) {
1871             case PROXIMITY_UNKNOWN:
1872                 return "Unknown";
1873             case PROXIMITY_NEGATIVE:
1874                 return "Negative";
1875             case PROXIMITY_POSITIVE:
1876                 return "Positive";
1877             default:
1878                 return Integer.toString(state);
1879         }
1880     }
1881 
reportedToPolicyToString(int state)1882     private static String reportedToPolicyToString(int state) {
1883         switch (state) {
1884             case REPORTED_TO_POLICY_SCREEN_OFF:
1885                 return "REPORTED_TO_POLICY_SCREEN_OFF";
1886             case REPORTED_TO_POLICY_SCREEN_TURNING_ON:
1887                 return "REPORTED_TO_POLICY_SCREEN_TURNING_ON";
1888             case REPORTED_TO_POLICY_SCREEN_ON:
1889                 return "REPORTED_TO_POLICY_SCREEN_ON";
1890             default:
1891                 return Integer.toString(state);
1892         }
1893     }
1894 
skipRampStateToString(int state)1895     private static String skipRampStateToString(int state) {
1896         switch (state) {
1897             case RAMP_STATE_SKIP_NONE:
1898                 return "RAMP_STATE_SKIP_NONE";
1899             case RAMP_STATE_SKIP_INITIAL:
1900                 return "RAMP_STATE_SKIP_INITIAL";
1901             case RAMP_STATE_SKIP_AUTOBRIGHT:
1902                 return "RAMP_STATE_SKIP_AUTOBRIGHT";
1903             default:
1904                 return Integer.toString(state);
1905         }
1906     }
1907 
clampAbsoluteBrightness(int value)1908     private static int clampAbsoluteBrightness(int value) {
1909         return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
1910     }
1911 
clampAbsoluteBrightness(float value)1912     private static float clampAbsoluteBrightness(float value) {
1913         return MathUtils.constrain(value, PowerManager.BRIGHTNESS_MIN,
1914                 PowerManager.BRIGHTNESS_MAX);
1915     }
1916 
clampAutoBrightnessAdjustment(float value)1917     private static float clampAutoBrightnessAdjustment(float value) {
1918         return MathUtils.constrain(value, -1.0f, 1.0f);
1919     }
1920 
1921     private final class DisplayControllerHandler extends Handler {
DisplayControllerHandler(Looper looper)1922         public DisplayControllerHandler(Looper looper) {
1923             super(looper, null, true /*async*/);
1924         }
1925 
1926         @Override
handleMessage(Message msg)1927         public void handleMessage(Message msg) {
1928             switch (msg.what) {
1929                 case MSG_UPDATE_POWER_STATE:
1930                     updatePowerState();
1931                     break;
1932 
1933                 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
1934                     debounceProximitySensor();
1935                     break;
1936 
1937                 case MSG_SCREEN_ON_UNBLOCKED:
1938                     if (mPendingScreenOnUnblocker == msg.obj) {
1939                         unblockScreenOn();
1940                         updatePowerState();
1941                     }
1942                     break;
1943                 case MSG_SCREEN_OFF_UNBLOCKED:
1944                     if (mPendingScreenOffUnblocker == msg.obj) {
1945                         unblockScreenOff();
1946                         updatePowerState();
1947                     }
1948                     break;
1949                 case MSG_CONFIGURE_BRIGHTNESS:
1950                     mBrightnessConfiguration = (BrightnessConfiguration)msg.obj;
1951                     updatePowerState();
1952                     break;
1953 
1954                 case MSG_SET_TEMPORARY_BRIGHTNESS:
1955                     // TODO: Should we have a a timeout for the temporary brightness?
1956                     mTemporaryScreenBrightness = Float.intBitsToFloat(msg.arg1);
1957                     updatePowerState();
1958                     break;
1959 
1960                 case MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT:
1961                     mTemporaryAutoBrightnessAdjustment = Float.intBitsToFloat(msg.arg1);
1962                     updatePowerState();
1963                     break;
1964             }
1965         }
1966     }
1967 
1968     private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
1969         @Override
1970         public void onSensorChanged(SensorEvent event) {
1971             if (mProximitySensorEnabled) {
1972                 final long time = SystemClock.uptimeMillis();
1973                 final float distance = event.values[0];
1974                 boolean positive = distance >= 0.0f && distance < mProximityThreshold;
1975                 handleProximitySensorEvent(time, positive);
1976             }
1977         }
1978 
1979         @Override
1980         public void onAccuracyChanged(Sensor sensor, int accuracy) {
1981             // Not used.
1982         }
1983     };
1984 
1985 
1986     private final class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler)1987         public SettingsObserver(Handler handler) {
1988             super(handler);
1989         }
1990 
1991         @Override
onChange(boolean selfChange, Uri uri)1992         public void onChange(boolean selfChange, Uri uri) {
1993             handleSettingsChange(false /* userSwitch */);
1994         }
1995     }
1996 
1997     private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
1998         @Override
onScreenOn()1999         public void onScreenOn() {
2000             Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
2001             mHandler.sendMessage(msg);
2002         }
2003     }
2004 
2005     private final class ScreenOffUnblocker implements WindowManagerPolicy.ScreenOffListener {
2006         @Override
onScreenOff()2007         public void onScreenOff() {
2008             Message msg = mHandler.obtainMessage(MSG_SCREEN_OFF_UNBLOCKED, this);
2009             mHandler.sendMessage(msg);
2010         }
2011     }
2012 
setAutoBrightnessLoggingEnabled(boolean enabled)2013     void setAutoBrightnessLoggingEnabled(boolean enabled) {
2014         if (mAutomaticBrightnessController != null) {
2015             mAutomaticBrightnessController.setLoggingEnabled(enabled);
2016         }
2017     }
2018 
2019     @Override // DisplayWhiteBalanceController.Callbacks
updateWhiteBalance()2020     public void updateWhiteBalance() {
2021         sendUpdatePowerState();
2022     }
2023 
setDisplayWhiteBalanceLoggingEnabled(boolean enabled)2024     void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
2025         if (mDisplayWhiteBalanceController != null) {
2026             mDisplayWhiteBalanceController.setLoggingEnabled(enabled);
2027             mDisplayWhiteBalanceSettings.setLoggingEnabled(enabled);
2028         }
2029     }
2030 
setAmbientColorTemperatureOverride(float cct)2031     void setAmbientColorTemperatureOverride(float cct) {
2032         if (mDisplayWhiteBalanceController != null) {
2033             mDisplayWhiteBalanceController.setAmbientColorTemperatureOverride(cct);
2034             // The ambient color temperature override is only applied when the ambient color
2035             // temperature changes or is updated, so it doesn't necessarily change the screen color
2036             // temperature immediately. So, let's make it!
2037             sendUpdatePowerState();
2038         }
2039     }
2040 
2041     /**
2042      * Stores data about why the brightness was changed.  Made up of one main
2043      * {@code BrightnessReason.REASON_*} reason and various {@code BrightnessReason.MODIFIER_*}
2044      * modifiers.
2045      */
2046     private final class BrightnessReason {
2047         static final int REASON_UNKNOWN = 0;
2048         static final int REASON_MANUAL = 1;
2049         static final int REASON_DOZE = 2;
2050         static final int REASON_DOZE_DEFAULT = 3;
2051         static final int REASON_AUTOMATIC = 4;
2052         static final int REASON_SCREEN_OFF = 5;
2053         static final int REASON_VR = 6;
2054         static final int REASON_OVERRIDE = 7;
2055         static final int REASON_TEMPORARY = 8;
2056         static final int REASON_BOOST = 9;
2057         static final int REASON_MAX = REASON_BOOST;
2058 
2059         static final int MODIFIER_DIMMED = 0x1;
2060         static final int MODIFIER_LOW_POWER = 0x2;
2061         static final int MODIFIER_MASK = 0x3;
2062 
2063         // ADJUSTMENT_*
2064         // These things can happen at any point, even if the main brightness reason doesn't
2065         // fundamentally change, so they're not stored.
2066 
2067         // Auto-brightness adjustment factor changed
2068         static final int ADJUSTMENT_AUTO_TEMP = 0x1;
2069         // Temporary adjustment to the auto-brightness adjustment factor.
2070         static final int ADJUSTMENT_AUTO = 0x2;
2071 
2072         // One of REASON_*
2073         public int reason;
2074         // Any number of MODIFIER_*
2075         public int modifier;
2076 
set(BrightnessReason other)2077         public void set(BrightnessReason other) {
2078             setReason(other == null ? REASON_UNKNOWN : other.reason);
2079             setModifier(other == null ? 0 : other.modifier);
2080         }
2081 
setReason(int reason)2082         public void setReason(int reason) {
2083             if (reason < REASON_UNKNOWN || reason > REASON_MAX) {
2084                 Slog.w(TAG, "brightness reason out of bounds: " + reason);
2085             } else {
2086                 this.reason = reason;
2087             }
2088         }
2089 
setModifier(int modifier)2090         public void setModifier(int modifier) {
2091             if ((modifier & ~MODIFIER_MASK) != 0) {
2092                 Slog.w(TAG, "brightness modifier out of bounds: 0x"
2093                         + Integer.toHexString(modifier));
2094             } else {
2095                 this.modifier = modifier;
2096             }
2097         }
2098 
addModifier(int modifier)2099         public void addModifier(int modifier) {
2100             setModifier(modifier | this.modifier);
2101         }
2102 
2103         @Override
equals(Object obj)2104         public boolean equals(Object obj) {
2105             if (obj == null || !(obj instanceof BrightnessReason)) {
2106                 return false;
2107             }
2108             BrightnessReason other = (BrightnessReason) obj;
2109             return other.reason == reason && other.modifier == modifier;
2110         }
2111 
2112         @Override
toString()2113         public String toString() {
2114             return toString(0);
2115         }
2116 
toString(int adjustments)2117         public String toString(int adjustments) {
2118             final StringBuilder sb = new StringBuilder();
2119             sb.append(reasonToString(reason));
2120             sb.append(" [");
2121             if ((adjustments & ADJUSTMENT_AUTO_TEMP) != 0) {
2122                 sb.append(" temp_adj");
2123             }
2124             if ((adjustments & ADJUSTMENT_AUTO) != 0) {
2125                 sb.append(" auto_adj");
2126             }
2127             if ((modifier & MODIFIER_LOW_POWER) != 0) {
2128                 sb.append(" low_pwr");
2129             }
2130             if ((modifier & MODIFIER_DIMMED) != 0) {
2131                 sb.append(" dim");
2132             }
2133             int strlen = sb.length();
2134             if (sb.charAt(strlen - 1) == '[') {
2135                 sb.setLength(strlen - 2);
2136             } else {
2137                 sb.append(" ]");
2138             }
2139             return sb.toString();
2140         }
2141 
reasonToString(int reason)2142         private String reasonToString(int reason) {
2143             switch (reason) {
2144                 case REASON_MANUAL: return "manual";
2145                 case REASON_DOZE: return "doze";
2146                 case REASON_DOZE_DEFAULT: return "doze_default";
2147                 case REASON_AUTOMATIC: return "automatic";
2148                 case REASON_SCREEN_OFF: return "screen_off";
2149                 case REASON_VR: return "vr";
2150                 case REASON_OVERRIDE: return "override";
2151                 case REASON_TEMPORARY: return "temporary";
2152                 case REASON_BOOST: return "boost";
2153                 default: return Integer.toString(reason);
2154             }
2155         }
2156     }
2157 }
2158