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