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